@@ -25,7 +25,6 @@ class ReplaceAliasByActualDefinitionPass implements CompilerPassInterface
2525{
2626 private $ compiler ;
2727 private $ formatter ;
28- private $ sourceId ;
2928
3029 /**
3130 * Process the Container to replace aliases with service definitions.
@@ -36,105 +35,99 @@ class ReplaceAliasByActualDefinitionPass implements CompilerPassInterface
3635 */
3736 public function process (ContainerBuilder $ container )
3837 {
38+ // Setup
3939 $ this ->compiler = $ container ->getCompiler ();
4040 $ this ->formatter = $ this ->compiler ->getLoggingFormatter ();
41-
42- foreach ($ container ->getAliases () as $ id => $ alias ) {
43- $ aliasId = (string ) $ alias ;
44-
45- if ('service_container ' === $ aliasId ) {
41+ // First collect all alias targets that need to be replaced
42+ $ seenAliasTargets = array ();
43+ $ replacements = array ();
44+ foreach ($ container ->getAliases () as $ definitionId => $ target ) {
45+ $ targetId = (string ) $ target ;
46+ // Special case: leave this target alone
47+ if ('service_container ' === $ targetId ) {
4648 continue ;
4749 }
48-
50+ // Check if target needs to be replaces
51+ if (isset ($ replacements [$ targetId ])) {
52+ $ container ->setAlias ($ definitionId , $ replacements [$ targetId ]);
53+ }
54+ // No neeed to process the same target twice
55+ if (isset ($ seenAliasTargets [$ targetId ])) {
56+ continue ;
57+ }
58+ // Process new target
59+ $ seenAliasTargets [$ targetId ] = true ;
4960 try {
50- $ definition = $ container ->getDefinition ($ aliasId );
61+ $ definition = $ container ->getDefinition ($ targetId );
5162 } catch (InvalidArgumentException $ e ) {
52- throw new InvalidArgumentException (sprintf ('Unable to replace alias "%s" with actual definition "%s". ' , $ id , $ alias ), null , $ e );
63+ throw new InvalidArgumentException (sprintf ('Unable to replace alias "%s" with actual definition "%s". ' , $ definitionId , $ targetId ), null , $ e );
5364 }
54-
5565 if ($ definition ->isPublic ()) {
5666 continue ;
5767 }
58-
68+ // Remove private definition and schedule for replacement
5969 $ definition ->setPublic (true );
60- $ container ->setDefinition ($ id , $ definition );
61- $ container ->removeDefinition ($ aliasId );
62-
63- $ this ->updateReferences ($ container , $ aliasId , $ id );
64-
65- // we have to restart the process due to concurrent modification of
66- // the container
67- $ this ->process ($ container );
68-
69- break ;
70+ $ container ->setDefinition ($ definitionId , $ definition );
71+ $ container ->removeDefinition ($ targetId );
72+ $ replacements [$ targetId ] = $ definitionId ;
7073 }
71- }
72-
73- /**
74- * Updates references to remove aliases.
75- *
76- * @param ContainerBuilder $container The container
77- * @param string $currentId The alias identifier being replaced
78- * @param string $newId The id of the service the alias points to
79- */
80- private function updateReferences ($ container , $ currentId , $ newId )
81- {
82- foreach ($ container ->getAliases () as $ id => $ alias ) {
83- if ($ currentId === (string ) $ alias ) {
84- $ container ->setAlias ($ id , $ newId );
85- }
86- }
87-
88- foreach ($ container ->getDefinitions () as $ id => $ definition ) {
89- $ this ->sourceId = $ id ;
90-
91- $ definition ->setArguments (
92- $ this ->updateArgumentReferences ($ definition ->getArguments (), $ currentId , $ newId )
93- );
94-
95- $ definition ->setMethodCalls (
96- $ this ->updateArgumentReferences ($ definition ->getMethodCalls (), $ currentId , $ newId )
97- );
98-
99- $ definition ->setProperties (
100- $ this ->updateArgumentReferences ($ definition ->getProperties (), $ currentId , $ newId )
101- );
102-
103- $ definition ->setFactoryService ($ this ->updateFactoryServiceReference ($ definition ->getFactoryService (), $ currentId , $ newId ));
74+ // Now replace target instances in all definitions
75+ foreach ($ container ->getDefinitions () as $ definitionId => $ definition ) {
76+ $ definition ->setArguments ($ this ->updateArgumentReferences ($ replacements , $ definitionId , $ definition ->getArguments ()));
77+ $ definition ->setMethodCalls ($ this ->updateArgumentReferences ($ replacements , $ definitionId , $ definition ->getMethodCalls ()));
78+ $ definition ->setProperties ($ this ->updateArgumentReferences ($ replacements , $ definitionId , $ definition ->getProperties ()));
79+ $ definition ->setFactoryService ($ this ->updateFactoryReferenceId ($ replacements , $ definition ->getFactoryService ()));
10480 }
10581 }
10682
10783 /**
108- * Updates argument references.
84+ * Recursively updates references in an array .
10985 *
110- * @param array $arguments An array of Arguments
111- * @param string $currentId The alias identifier
112- * @param string $newId The identifier the alias points to
86+ * @param array $replacements Table of aliases to replace
87+ * @param string $definitionId Identifier of this definition
88+ * @param array $arguments Where to replace the aliases
11389 *
11490 * @return array
11591 */
116- private function updateArgumentReferences (array $ arguments , $ currentId , $ newId )
92+ private function updateArgumentReferences (array $ replacements , $ definitionId , array $ arguments )
11793 {
11894 foreach ($ arguments as $ k => $ argument ) {
95+ // Handle recursion step
11996 if (is_array ($ argument )) {
120- $ arguments [$ k ] = $ this ->updateArgumentReferences ($ argument , $ currentId , $ newId );
121- } elseif ($ argument instanceof Reference) {
122- if ($ currentId === (string ) $ argument ) {
123- $ arguments [$ k ] = new Reference ($ newId , $ argument ->getInvalidBehavior ());
124- $ this ->compiler ->addLogMessage ($ this ->formatter ->formatUpdateReference ($ this , $ this ->sourceId , $ currentId , $ newId ));
125- }
97+ $ arguments [$ k ] = $ this ->updateArgumentReferences ($ replacements , $ definitionId , $ argument );
98+ continue ;
12699 }
100+ // Skip arguments that don't need replacement
101+ if (!$ argument instanceof Reference) {
102+ continue ;
103+ }
104+ $ referenceId = (string ) $ argument ;
105+ if (!isset ($ replacements [$ referenceId ])) {
106+ continue ;
107+ }
108+ // Perform the replacement
109+ $ newId = $ replacements [$ referenceId ];
110+ $ arguments [$ k ] = new Reference ($ newId , $ argument ->getInvalidBehavior ());
111+ $ this ->compiler ->addLogMessage ($ this ->formatter ->formatUpdateReference ($ this , $ definitionId , $ referenceId , $ newId ));
127112 }
128113
129114 return $ arguments ;
130115 }
131116
132- private function updateFactoryServiceReference ($ factoryService , $ currentId , $ newId )
117+ /**
118+ * Returns the updated reference for the factory service.
119+ *
120+ * @param array $replacements Table of aliases to replace
121+ * @param string|null $referenceId Factory service reference identifier
122+ *
123+ * @return string|null
124+ */
125+ private function updateFactoryReferenceId (array $ replacements , $ referenceId )
133126 {
134- if (null === $ factoryService ) {
127+ if (null === $ referenceId ) {
135128 return ;
136129 }
137130
138- return $ currentId === $ factoryService ? $ newId : $ factoryService ;
131+ return isset ( $ replacements [ $ referenceId ]) ? $ replacements [ $ referenceId ] : $ referenceId ;
139132 }
140133}
0 commit comments