1717use Symfony \Component \DependencyInjection \Variable ;
1818use Symfony \Component \DependencyInjection \Definition ;
1919use Symfony \Component \DependencyInjection \Compiler \AnalyzeServiceReferencesPass ;
20+ use Symfony \Component \DependencyInjection \Compiler \ServiceReferenceGraphNode ;
2021use Symfony \Component \DependencyInjection \ContainerBuilder ;
2122use Symfony \Component \DependencyInjection \Container ;
2223use Symfony \Component \DependencyInjection \ContainerInterface ;
@@ -68,6 +69,7 @@ class PhpDumper extends Dumper
6869 private $ inlineRequires ;
6970 private $ inlinedRequires = array ();
7071 private $ circularReferences = array ();
72+ private $ singleUsePrivateIds = array ();
7173
7274 /**
7375 * @var ProxyDumper
@@ -141,10 +143,14 @@ public function dump(array $options = array())
141143
142144 (new AnalyzeServiceReferencesPass ())->process ($ this ->container );
143145 $ this ->circularReferences = array ();
146+ $ this ->singleUsePrivateIds = array ();
144147 $ checkedNodes = array ();
145148 foreach ($ this ->container ->getCompiler ()->getServiceReferenceGraph ()->getNodes () as $ id => $ node ) {
146149 $ currentPath = array ($ id => $ id );
147150 $ this ->analyzeCircularReferences ($ node ->getOutEdges (), $ checkedNodes , $ currentPath );
151+ if ($ this ->isSingleUsePrivateNode ($ node )) {
152+ $ this ->singleUsePrivateIds [$ id ] = $ id ;
153+ }
148154 }
149155 $ this ->container ->getCompiler ()->getServiceReferenceGraph ()->clear ();
150156
@@ -526,7 +532,7 @@ private function addServiceInstance(string $id, Definition $definition, string $
526532 $ isProxyCandidate = $ this ->getProxyDumper ()->isProxyCandidate ($ definition );
527533 $ instantiation = '' ;
528534
529- if (!$ isProxyCandidate && $ definition ->isShared ()) {
535+ if (!$ isProxyCandidate && $ definition ->isShared () && ! isset ( $ this -> singleUsePrivateIds [ $ id ]) ) {
530536 $ instantiation = sprintf ('$this->%s[ \'%s \'] = %s ' , $ this ->container ->getDefinition ($ id )->isPublic () ? 'services ' : 'privates ' , $ id , $ isSimpleInstance ? '' : '$instance ' );
531537 } elseif (!$ isSimpleInstance ) {
532538 $ instantiation = '$instance ' ;
@@ -819,7 +825,7 @@ private function generateServiceFiles()
819825 $ definitions = $ this ->container ->getDefinitions ();
820826 ksort ($ definitions );
821827 foreach ($ definitions as $ id => $ definition ) {
822- if (!$ definition ->isSynthetic () && !$ this ->isHotPath ($ definition )) {
828+ if (!$ definition ->isSynthetic () && !$ this ->isHotPath ($ definition ) && ( $ definition -> isPublic () || ! $ this -> isTrivialInstance ( $ definition )) ) {
823829 $ code = $ this ->addService ($ id , $ definition , $ file );
824830
825831 if (!$ definition ->isShared ()) {
@@ -1662,7 +1668,7 @@ private function getServiceCall(string $id, Reference $reference = null): string
16621668 $ code = 'null ' ;
16631669 } elseif ($ this ->isTrivialInstance ($ definition )) {
16641670 $ code = substr ($ this ->addNewInstance ($ definition , '' , '' , $ id ), 8 , -2 );
1665- if ($ definition ->isShared ()) {
1671+ if ($ definition ->isShared () && ! isset ( $ this -> singleUsePrivateIds [ $ id ]) ) {
16661672 $ code = sprintf ('$this->%s[ \'%s \'] = %s ' , $ definition ->isPublic () ? 'services ' : 'privates ' , $ id , $ code );
16671673 }
16681674 } elseif ($ this ->asFiles && !$ this ->isHotPath ($ definition )) {
@@ -1674,7 +1680,7 @@ private function getServiceCall(string $id, Reference $reference = null): string
16741680 } else {
16751681 $ code = sprintf ('$this->%s() ' , $ this ->generateMethodName ($ id ));
16761682 }
1677- if ($ definition ->isShared ()) {
1683+ if ($ definition ->isShared () && ! isset ( $ this -> singleUsePrivateIds [ $ id ]) ) {
16781684 $ code = sprintf ('($this->%s[ \'%s \'] ?? %s) ' , $ definition ->isPublic () ? 'services ' : 'privates ' , $ id , $ code );
16791685 }
16801686
@@ -1798,6 +1804,22 @@ private function isHotPath(Definition $definition)
17981804 return $ this ->hotPathTag && $ definition ->hasTag ($ this ->hotPathTag ) && !$ definition ->isDeprecated ();
17991805 }
18001806
1807+ private function isSingleUsePrivateNode (ServiceReferenceGraphNode $ node ): bool
1808+ {
1809+ if ($ node ->getValue ()->isPublic ()) {
1810+ return false ;
1811+ }
1812+ $ ids = array ();
1813+ foreach ($ node ->getInEdges () as $ edge ) {
1814+ if ($ edge ->isLazy () || !$ edge ->getSourceNode ()->getValue ()->isShared ()) {
1815+ return false ;
1816+ }
1817+ $ ids [$ edge ->getSourceNode ()->getId ()] = true ;
1818+ }
1819+
1820+ return 1 === \count ($ ids );
1821+ }
1822+
18011823 private function export ($ value )
18021824 {
18031825 if (null !== $ this ->targetDirRegex && is_string ($ value ) && preg_match ($ this ->targetDirRegex , $ value , $ matches , PREG_OFFSET_CAPTURE )) {
0 commit comments