@@ -171,21 +171,22 @@ public function dump(array $options = array())
171
171
}
172
172
173
173
(new AnalyzeServiceReferencesPass (false , !$ this ->getProxyDumper () instanceof NullDumper))->process ($ this ->container );
174
+ $ checkedNodes = array ();
174
175
$ this ->circularReferences = array ();
175
176
$ this ->singleUsePrivateIds = array ();
176
- foreach (array (true , false ) as $ byConstructor ) {
177
- foreach ($ this ->container ->getCompiler ()->getServiceReferenceGraph ()->getNodes () as $ id => $ node ) {
178
- if (!$ node ->getValue () instanceof Definition) {
179
- continue ;
180
- }
181
- $ currentPath = array ($ id => $ id );
182
- $ this ->analyzeCircularReferences ($ node ->getOutEdges (), $ currentPath , $ id , $ byConstructor );
183
- if ($ this ->isSingleUsePrivateNode ($ node )) {
184
- $ this ->singleUsePrivateIds [$ id ] = $ id ;
185
- }
177
+ foreach ($ this ->container ->getCompiler ()->getServiceReferenceGraph ()->getNodes () as $ id => $ node ) {
178
+ if (!$ node ->getValue () instanceof Definition) {
179
+ continue ;
180
+ }
181
+ if (!isset ($ checkedNodes [$ id ])) {
182
+ $ this ->analyzeCircularReferences ($ id , $ node ->getOutEdges (), $ checkedNodes );
183
+ }
184
+ if ($ this ->isSingleUsePrivateNode ($ node )) {
185
+ $ this ->singleUsePrivateIds [$ id ] = $ id ;
186
186
}
187
187
}
188
188
$ this ->container ->getCompiler ()->getServiceReferenceGraph ()->clear ();
189
+ $ checkedNodes = array ();
189
190
190
191
$ this ->docStar = $ options ['debug ' ] ? '* ' : '' ;
191
192
@@ -337,12 +338,12 @@ private function getProxyDumper(): ProxyDumper
337
338
return $ this ->proxyDumper ;
338
339
}
339
340
340
- private function analyzeCircularReferences (array $ edges , &$ currentPath , $ sourceId , $ byConstructor )
341
+ private function analyzeCircularReferences ($ sourceId , array $ edges , &$ checkedNodes , & $ currentPath = array () )
341
342
{
343
+ $ checkedNodes [$ sourceId ] = true ;
344
+ $ currentPath [$ sourceId ] = $ sourceId ;
345
+
342
346
foreach ($ edges as $ edge ) {
343
- if ($ byConstructor && !$ edge ->isReferencedByConstructor ()) {
344
- continue ;
345
- }
346
347
$ node = $ edge ->getDestNode ();
347
348
$ id = $ node ->getId ();
348
349
@@ -351,20 +352,42 @@ private function analyzeCircularReferences(array $edges, &$currentPath, $sourceI
351
352
} elseif (isset ($ currentPath [$ id ])) {
352
353
$ currentId = $ id ;
353
354
foreach (array_reverse ($ currentPath ) as $ parentId ) {
354
- if (!isset ($ this ->circularReferences [$ parentId ][$ currentId ])) {
355
- $ this ->circularReferences [$ parentId ][$ currentId ] = $ byConstructor ;
355
+ $ this ->circularReferences [$ parentId ][$ currentId ] = $ currentId ;
356
+ if ($ parentId === $ id ) {
357
+ break ;
356
358
}
359
+ $ currentId = $ parentId ;
360
+ }
361
+ } elseif (!isset ($ checkedNodes [$ id ])) {
362
+ $ this ->analyzeCircularReferences ($ id , $ node ->getOutEdges (), $ checkedNodes , $ currentPath );
363
+ } elseif (isset ($ this ->circularReferences [$ id ])) {
364
+ $ this ->connectCircularReferences ($ id , $ currentPath );
365
+ }
366
+ }
367
+ unset($ currentPath [$ sourceId ]);
368
+ }
369
+
370
+ private function connectCircularReferences ($ sourceId , &$ currentPath , &$ subPath = array ())
371
+ {
372
+ $ subPath [$ sourceId ] = $ sourceId ;
373
+ $ currentPath [$ sourceId ] = $ sourceId ;
374
+
375
+ foreach ($ this ->circularReferences [$ sourceId ] as $ id ) {
376
+ if (isset ($ currentPath [$ id ])) {
377
+ $ currentId = $ id ;
378
+ foreach (array_reverse ($ currentPath ) as $ parentId ) {
379
+ $ this ->circularReferences [$ parentId ][$ currentId ] = $ currentId ;
357
380
if ($ parentId === $ id ) {
358
381
break ;
359
382
}
360
383
$ currentId = $ parentId ;
361
384
}
362
- } else {
363
- $ currentPath [$ id ] = $ id ;
364
- $ this ->analyzeCircularReferences ($ node ->getOutEdges (), $ currentPath , $ id , $ byConstructor );
365
- unset($ currentPath [$ id ]);
385
+ } elseif (!isset ($ subPath [$ id ]) && isset ($ this ->circularReferences [$ id ])) {
386
+ $ this ->connectCircularReferences ($ id , $ currentPath , $ subPath );
366
387
}
367
388
}
389
+ unset($ currentPath [$ sourceId ]);
390
+ unset($ subPath [$ sourceId ]);
368
391
}
369
392
370
393
private function collectLineage ($ class , array &$ lineage )
@@ -572,8 +595,11 @@ private function addServiceConfigurator(Definition $definition, string $variable
572
595
573
596
if (\is_array ($ callable )) {
574
597
if ($ callable [0 ] instanceof Reference
575
- || ($ callable [0 ] instanceof Definition && $ this ->definitionVariables ->contains ($ callable [0 ]))) {
576
- return sprintf (" %s->%s( \$%s); \n" , $ this ->dumpValue ($ callable [0 ]), $ callable [1 ], $ variableName );
598
+ || ($ callable [0 ] instanceof Definition && $ this ->definitionVariables ->contains ($ callable [0 ]))
599
+ ) {
600
+ $ callable [0 ] = $ this ->dumpValue ($ callable [0 ]);
601
+
602
+ return sprintf (' ' .('$ ' === $ callable [0 ][0 ] ? '%s ' : '(%s) ' )."->%s( \$%s); \n" , $ callable [0 ], $ callable [1 ], $ variableName );
577
603
}
578
604
579
605
$ class = $ this ->dumpValue ($ callable [0 ]);
@@ -719,7 +745,7 @@ private function addInlineReference(string $id, Definition $definition, string $
719
745
720
746
$ hasSelfRef = isset ($ this ->circularReferences [$ id ][$ targetId ]);
721
747
$ forConstructor = $ forConstructor && !isset ($ this ->definitionVariables [$ definition ]);
722
- $ code = $ hasSelfRef && $ this -> circularReferences [ $ id ][ $ targetId ] && !$ forConstructor ? $ this ->addInlineService ($ id , $ definition , $ definition ) : '' ;
748
+ $ code = $ hasSelfRef && !$ forConstructor ? $ this ->addInlineService ($ id , $ definition , $ definition ) : '' ;
723
749
724
750
if (isset ($ this ->referenceVariables [$ targetId ]) || (2 > $ callCount && (!$ hasSelfRef || !$ forConstructor ))) {
725
751
return $ code ;
0 commit comments