@@ -156,17 +156,18 @@ public function dump(array $options = array())
156
156
}
157
157
158
158
(new AnalyzeServiceReferencesPass (false , !$ this ->getProxyDumper () instanceof NullDumper))->process ($ this ->container );
159
+ $ checkedNodes = array ();
159
160
$ this ->circularReferences = array ();
160
- foreach (array (true , false ) as $ byConstructor ) {
161
- foreach ($ this ->container ->getCompiler ()->getServiceReferenceGraph ()->getNodes () as $ id => $ node ) {
162
- if (!$ node ->getValue () instanceof Definition) {
163
- continue ;
164
- }
165
- $ currentPath = array ($ id => true );
166
- $ this ->analyzeCircularReferences ($ node ->getOutEdges (), $ currentPath , $ id , $ byConstructor );
161
+ foreach ($ this ->container ->getCompiler ()->getServiceReferenceGraph ()->getNodes () as $ id => $ node ) {
162
+ if (!$ node ->getValue () instanceof Definition) {
163
+ continue ;
164
+ }
165
+ if (!isset ($ checkedNodes [$ id ])) {
166
+ $ this ->analyzeCircularReferences ($ id , $ node ->getOutEdges (), $ checkedNodes );
167
167
}
168
168
}
169
169
$ this ->container ->getCompiler ()->getServiceReferenceGraph ()->clear ();
170
+ $ checkedNodes = array ();
170
171
171
172
$ this ->docStar = $ options ['debug ' ] ? '* ' : '' ;
172
173
@@ -307,12 +308,12 @@ private function getProxyDumper(): ProxyDumper
307
308
return $ this ->proxyDumper ;
308
309
}
309
310
310
- private function analyzeCircularReferences (array $ edges , &$ currentPath , $ sourceId , $ byConstructor )
311
+ private function analyzeCircularReferences ($ sourceId , array $ edges , &$ checkedNodes , & $ currentPath = array () )
311
312
{
313
+ $ checkedNodes [$ sourceId ] = true ;
314
+ $ currentPath [$ sourceId ] = $ sourceId ;
315
+
312
316
foreach ($ edges as $ edge ) {
313
- if ($ byConstructor && !$ edge ->isReferencedByConstructor ()) {
314
- continue ;
315
- }
316
317
$ node = $ edge ->getDestNode ();
317
318
$ id = $ node ->getId ();
318
319
@@ -321,20 +322,42 @@ private function analyzeCircularReferences(array $edges, &$currentPath, $sourceI
321
322
} elseif (isset ($ currentPath [$ id ])) {
322
323
$ currentId = $ id ;
323
324
foreach (array_reverse ($ currentPath ) as $ parentId ) {
324
- if (!isset ($ this ->circularReferences [$ parentId ][$ currentId ])) {
325
- $ this ->circularReferences [$ parentId ][$ currentId ] = $ byConstructor ;
325
+ $ this ->circularReferences [$ parentId ][$ currentId ] = $ currentId ;
326
+ if ($ parentId === $ id ) {
327
+ break ;
326
328
}
329
+ $ currentId = $ parentId ;
330
+ }
331
+ } elseif (!isset ($ checkedNodes [$ id ])) {
332
+ $ this ->analyzeCircularReferences ($ id , $ node ->getOutEdges (), $ checkedNodes , $ currentPath );
333
+ } elseif (isset ($ this ->circularReferences [$ id ])) {
334
+ $ this ->connectCircularReferences ($ id , $ currentPath );
335
+ }
336
+ }
337
+ unset($ currentPath [$ sourceId ]);
338
+ }
339
+
340
+ private function connectCircularReferences ($ sourceId , &$ currentPath , &$ subPath = array ())
341
+ {
342
+ $ subPath [$ sourceId ] = $ sourceId ;
343
+ $ currentPath [$ sourceId ] = $ sourceId ;
344
+
345
+ foreach ($ this ->circularReferences [$ sourceId ] as $ id ) {
346
+ if (isset ($ currentPath [$ id ])) {
347
+ $ currentId = $ id ;
348
+ foreach (array_reverse ($ currentPath ) as $ parentId ) {
349
+ $ this ->circularReferences [$ parentId ][$ currentId ] = $ currentId ;
327
350
if ($ parentId === $ id ) {
328
351
break ;
329
352
}
330
353
$ currentId = $ parentId ;
331
354
}
332
- } else {
333
- $ currentPath [$ id ] = $ id ;
334
- $ this ->analyzeCircularReferences ($ node ->getOutEdges (), $ currentPath , $ id , $ byConstructor );
335
- unset($ currentPath [$ id ]);
355
+ } elseif (!isset ($ subPath [$ id ]) && isset ($ this ->circularReferences [$ id ])) {
356
+ $ this ->connectCircularReferences ($ id , $ currentPath , $ subPath );
336
357
}
337
358
}
359
+ unset($ currentPath [$ sourceId ]);
360
+ unset($ subPath [$ sourceId ]);
338
361
}
339
362
340
363
private function collectLineage ($ class , array &$ lineage )
@@ -539,8 +562,11 @@ private function addServiceConfigurator(Definition $definition, string $variable
539
562
540
563
if (\is_array ($ callable )) {
541
564
if ($ callable [0 ] instanceof Reference
542
- || ($ callable [0 ] instanceof Definition && $ this ->definitionVariables ->contains ($ callable [0 ]))) {
543
- return sprintf (" %s->%s( \$%s); \n" , $ this ->dumpValue ($ callable [0 ]), $ callable [1 ], $ variableName );
565
+ || ($ callable [0 ] instanceof Definition && $ this ->definitionVariables ->contains ($ callable [0 ]))
566
+ ) {
567
+ $ callable [0 ] = $ this ->dumpValue ($ callable [0 ]);
568
+
569
+ return sprintf (' ' .('$ ' === $ callable [0 ][0 ] ? '%s ' : '(%s) ' )."->%s( \$%s); \n" , $ callable [0 ], $ callable [1 ], $ variableName );
544
570
}
545
571
546
572
$ class = $ this ->dumpValue ($ callable [0 ]);
@@ -691,7 +717,7 @@ private function addInlineReference(string $id, Definition $definition, string $
691
717
692
718
$ hasSelfRef = isset ($ this ->circularReferences [$ id ][$ targetId ]);
693
719
$ forConstructor = $ forConstructor && !isset ($ this ->definitionVariables [$ definition ]);
694
- $ code = $ hasSelfRef && $ this -> circularReferences [ $ id ][ $ targetId ] && !$ forConstructor ? $ this ->addInlineService ($ id , $ definition , $ definition ) : '' ;
720
+ $ code = $ hasSelfRef && !$ forConstructor ? $ this ->addInlineService ($ id , $ definition , $ definition ) : '' ;
695
721
696
722
if (isset ($ this ->referenceVariables [$ targetId ]) || (2 > $ callCount && (!$ hasSelfRef || !$ forConstructor ))) {
697
723
return $ code ;
0 commit comments