@@ -187,6 +187,7 @@ public function dump(array $options = [])
187
187
}
188
188
$ this ->container ->getCompiler ()->getServiceReferenceGraph ()->clear ();
189
189
$ checkedNodes = [];
190
+ $ this ->singleUsePrivateIds = array_diff_key ($ this ->singleUsePrivateIds , $ this ->circularReferences );
190
191
191
192
$ this ->docStar = $ options ['debug ' ] ? '* ' : '' ;
192
193
@@ -339,10 +340,10 @@ private function getProxyDumper(): ProxyDumper
339
340
return $ this ->proxyDumper ;
340
341
}
341
342
342
- private function analyzeCircularReferences ($ sourceId , array $ edges , &$ checkedNodes , &$ currentPath = [])
343
+ private function analyzeCircularReferences ($ sourceId , array $ edges , &$ checkedNodes , &$ currentPath = [], $ byConstructor = true )
343
344
{
344
345
$ checkedNodes [$ sourceId ] = true ;
345
- $ currentPath [$ sourceId ] = $ sourceId ;
346
+ $ currentPath [$ sourceId ] = $ byConstructor ;
346
347
347
348
foreach ($ edges as $ edge ) {
348
349
$ node = $ edge ->getDestNode ();
@@ -351,44 +352,52 @@ private function analyzeCircularReferences($sourceId, array $edges, &$checkedNod
351
352
if (!$ node ->getValue () instanceof Definition || $ sourceId === $ id || $ edge ->isLazy () || $ edge ->isWeak ()) {
352
353
// no-op
353
354
} elseif (isset ($ currentPath [$ id ])) {
354
- $ currentId = $ id ;
355
- foreach (array_reverse ($ currentPath ) as $ parentId ) {
356
- $ this ->circularReferences [$ parentId ][$ currentId ] = $ currentId ;
357
- if ($ parentId === $ id ) {
358
- break ;
359
- }
360
- $ currentId = $ parentId ;
361
- }
355
+ $ this ->addCircularReferences ($ id , $ currentPath , $ edge ->isReferencedByConstructor ());
362
356
} elseif (!isset ($ checkedNodes [$ id ])) {
363
- $ this ->analyzeCircularReferences ($ id , $ node ->getOutEdges (), $ checkedNodes , $ currentPath );
357
+ $ this ->analyzeCircularReferences ($ id , $ node ->getOutEdges (), $ checkedNodes , $ currentPath, $ edge -> isReferencedByConstructor () );
364
358
} elseif (isset ($ this ->circularReferences [$ id ])) {
365
- $ this ->connectCircularReferences ($ id , $ currentPath );
359
+ $ this ->connectCircularReferences ($ id , $ currentPath, $ edge -> isReferencedByConstructor () );
366
360
}
367
361
}
368
362
unset($ currentPath [$ sourceId ]);
369
363
}
370
364
371
- private function connectCircularReferences ($ sourceId , &$ currentPath , &$ subPath = [])
365
+ private function connectCircularReferences ($ sourceId , &$ currentPath , $ byConstructor , &$ subPath = [])
372
366
{
373
- $ subPath [$ sourceId ] = $ sourceId ;
374
- $ currentPath [$ sourceId ] = $ sourceId ;
367
+ $ currentPath [$ sourceId ] = $ subPath [$ sourceId ] = $ byConstructor ;
375
368
376
- foreach ($ this ->circularReferences [$ sourceId ] as $ id ) {
369
+ foreach ($ this ->circularReferences [$ sourceId ] as $ id => $ byConstructor ) {
377
370
if (isset ($ currentPath [$ id ])) {
378
- $ currentId = $ id ;
379
- foreach (array_reverse ($ currentPath ) as $ parentId ) {
380
- $ this ->circularReferences [$ parentId ][$ currentId ] = $ currentId ;
381
- if ($ parentId === $ id ) {
382
- break ;
383
- }
384
- $ currentId = $ parentId ;
385
- }
371
+ $ this ->addCircularReferences ($ id , $ currentPath , $ byConstructor );
386
372
} elseif (!isset ($ subPath [$ id ]) && isset ($ this ->circularReferences [$ id ])) {
387
- $ this ->connectCircularReferences ($ id , $ currentPath , $ subPath );
373
+ $ this ->connectCircularReferences ($ id , $ currentPath , $ byConstructor , $ subPath );
388
374
}
389
375
}
390
- unset($ currentPath [$ sourceId ]);
391
- unset($ subPath [$ sourceId ]);
376
+ unset($ currentPath [$ sourceId ], $ subPath [$ sourceId ]);
377
+ }
378
+
379
+ private function addCircularReferences ($ id , $ currentPath , $ byConstructor )
380
+ {
381
+ $ currentPath [$ id ] = $ byConstructor ;
382
+ $ circularRefs = [];
383
+
384
+ foreach (array_reverse ($ currentPath ) as $ parentId => $ v ) {
385
+ $ byConstructor = $ byConstructor && $ v ;
386
+ $ circularRefs [] = $ parentId ;
387
+
388
+ if ($ parentId === $ id ) {
389
+ break ;
390
+ }
391
+ }
392
+
393
+ $ currentId = $ id ;
394
+ foreach ($ circularRefs as $ parentId ) {
395
+ if (empty ($ this ->circularReferences [$ parentId ][$ currentId ])) {
396
+ $ this ->circularReferences [$ parentId ][$ currentId ] = $ byConstructor ;
397
+ }
398
+
399
+ $ currentId = $ parentId ;
400
+ }
392
401
}
393
402
394
403
private function collectLineage ($ class , array &$ lineage )
@@ -679,7 +688,6 @@ private function addService(string $id, Definition $definition): array
679
688
$ autowired = $ definition ->isAutowired () ? ' autowired ' : '' ;
680
689
681
690
if ($ definition ->isLazy ()) {
682
- unset($ this ->circularReferences [$ id ]);
683
691
$ lazyInitialization = '$lazyLoad = true ' ;
684
692
} else {
685
693
$ lazyInitialization = '' ;
@@ -755,12 +763,12 @@ private function addInlineVariables(string $id, Definition $definition, array $a
755
763
756
764
private function addInlineReference (string $ id , Definition $ definition , string $ targetId , bool $ forConstructor ): string
757
765
{
758
- list ($ callCount , $ behavior ) = $ this ->serviceCalls [$ targetId ];
759
-
760
766
while ($ this ->container ->hasAlias ($ targetId )) {
761
767
$ targetId = (string ) $ this ->container ->getAlias ($ targetId );
762
768
}
763
769
770
+ list ($ callCount , $ behavior ) = $ this ->serviceCalls [$ targetId ];
771
+
764
772
if ($ id === $ targetId ) {
765
773
return $ this ->addInlineService ($ id , $ definition , $ definition );
766
774
}
@@ -769,9 +777,13 @@ private function addInlineReference(string $id, Definition $definition, string $
769
777
return '' ;
770
778
}
771
779
772
- $ hasSelfRef = isset ($ this ->circularReferences [$ id ][$ targetId ]);
773
- $ forConstructor = $ forConstructor && !isset ($ this ->definitionVariables [$ definition ]);
774
- $ code = $ hasSelfRef && !$ forConstructor ? $ this ->addInlineService ($ id , $ definition , $ definition ) : '' ;
780
+ $ hasSelfRef = isset ($ this ->circularReferences [$ id ][$ targetId ]) && !isset ($ this ->definitionVariables [$ definition ]);
781
+
782
+ if ($ hasSelfRef && !$ forConstructor && !$ forConstructor = !$ this ->circularReferences [$ id ][$ targetId ]) {
783
+ $ code = $ this ->addInlineService ($ id , $ definition , $ definition );
784
+ } else {
785
+ $ code = '' ;
786
+ }
775
787
776
788
if (isset ($ this ->referenceVariables [$ targetId ]) || (2 > $ callCount && (!$ hasSelfRef || !$ forConstructor ))) {
777
789
return $ code ;
@@ -804,15 +816,23 @@ private function addInlineReference(string $id, Definition $definition, string $
804
816
805
817
private function addInlineService (string $ id , Definition $ definition , Definition $ inlineDef = null , bool $ forConstructor = true ): string
806
818
{
807
- $ isSimpleInstance = $ isRootInstance = null === $ inlineDef ;
819
+ $ code = '' ;
820
+
821
+ if ($ isSimpleInstance = $ isRootInstance = null === $ inlineDef ) {
822
+ foreach ($ this ->serviceCalls as $ targetId => list ($ callCount , $ behavior , $ byConstructor )) {
823
+ if ($ byConstructor && isset ($ this ->circularReferences [$ id ][$ targetId ]) && !$ this ->circularReferences [$ id ][$ targetId ]) {
824
+ $ code .= $ this ->addInlineReference ($ id , $ definition , $ targetId , $ forConstructor );
825
+ }
826
+ }
827
+ }
808
828
809
829
if (isset ($ this ->definitionVariables [$ inlineDef = $ inlineDef ?: $ definition ])) {
810
- return '' ;
830
+ return $ code ;
811
831
}
812
832
813
833
$ arguments = [$ inlineDef ->getArguments (), $ inlineDef ->getFactory ()];
814
834
815
- $ code = $ this ->addInlineVariables ($ id , $ definition , $ arguments , $ forConstructor );
835
+ $ code . = $ this ->addInlineVariables ($ id , $ definition , $ arguments , $ forConstructor );
816
836
817
837
if ($ arguments = array_filter ([$ inlineDef ->getProperties (), $ inlineDef ->getMethodCalls (), $ inlineDef ->getConfigurator ()])) {
818
838
$ isSimpleInstance = false ;
@@ -1473,20 +1493,24 @@ private function getServiceConditionals($value): string
1473
1493
return implode (' && ' , $ conditions );
1474
1494
}
1475
1495
1476
- private function getDefinitionsFromArguments (array $ arguments , \SplObjectStorage $ definitions = null , array &$ calls = []): \SplObjectStorage
1496
+ private function getDefinitionsFromArguments (array $ arguments , \SplObjectStorage $ definitions = null , array &$ calls = [], bool $ byConstructor = null ): \SplObjectStorage
1477
1497
{
1478
1498
if (null === $ definitions ) {
1479
1499
$ definitions = new \SplObjectStorage ();
1480
1500
}
1481
1501
1482
1502
foreach ($ arguments as $ argument ) {
1483
1503
if (\is_array ($ argument )) {
1484
- $ this ->getDefinitionsFromArguments ($ argument , $ definitions , $ calls );
1504
+ $ this ->getDefinitionsFromArguments ($ argument , $ definitions , $ calls, $ byConstructor );
1485
1505
} elseif ($ argument instanceof Reference) {
1486
1506
$ id = (string ) $ argument ;
1487
1507
1508
+ while ($ this ->container ->hasAlias ($ id )) {
1509
+ $ id = (string ) $ this ->container ->getAlias ($ id );
1510
+ }
1511
+
1488
1512
if (!isset ($ calls [$ id ])) {
1489
- $ calls [$ id ] = [0 , $ argument ->getInvalidBehavior ()];
1513
+ $ calls [$ id ] = [0 , $ argument ->getInvalidBehavior (), $ byConstructor ];
1490
1514
} else {
1491
1515
$ calls [$ id ][1 ] = min ($ calls [$ id ][1 ], $ argument ->getInvalidBehavior ());
1492
1516
}
@@ -1498,8 +1522,10 @@ private function getDefinitionsFromArguments(array $arguments, \SplObjectStorage
1498
1522
$ definitions [$ argument ] = 1 + $ definitions [$ argument ];
1499
1523
} else {
1500
1524
$ definitions [$ argument ] = 1 ;
1501
- $ arguments = [$ argument ->getArguments (), $ argument ->getFactory (), $ argument ->getProperties (), $ argument ->getMethodCalls (), $ argument ->getConfigurator ()];
1502
- $ this ->getDefinitionsFromArguments ($ arguments , $ definitions , $ calls );
1525
+ $ arguments = [$ argument ->getArguments (), $ argument ->getFactory ()];
1526
+ $ this ->getDefinitionsFromArguments ($ arguments , $ definitions , $ calls , null === $ byConstructor || $ byConstructor );
1527
+ $ arguments = [$ argument ->getProperties (), $ argument ->getMethodCalls (), $ argument ->getConfigurator ()];
1528
+ $ this ->getDefinitionsFromArguments ($ arguments , $ definitions , $ calls , null !== $ byConstructor && $ byConstructor );
1503
1529
}
1504
1530
}
1505
1531
@@ -1620,6 +1646,11 @@ private function dumpValue($value, bool $interpolate = true): string
1620
1646
return '$ ' .$ value ;
1621
1647
} elseif ($ value instanceof Reference) {
1622
1648
$ id = (string ) $ value ;
1649
+
1650
+ while ($ this ->container ->hasAlias ($ id )) {
1651
+ $ id = (string ) $ this ->container ->getAlias ($ id );
1652
+ }
1653
+
1623
1654
if (null !== $ this ->referenceVariables && isset ($ this ->referenceVariables [$ id ])) {
1624
1655
return $ this ->dumpValue ($ this ->referenceVariables [$ id ], $ interpolate );
1625
1656
}
0 commit comments