@@ -25,7 +25,6 @@ class ReplaceAliasByActualDefinitionPass implements CompilerPassInterface
25
25
{
26
26
private $ compiler ;
27
27
private $ formatter ;
28
- private $ sourceId ;
29
28
30
29
/**
31
30
* Process the Container to replace aliases with service definitions.
@@ -36,118 +35,110 @@ class ReplaceAliasByActualDefinitionPass implements CompilerPassInterface
36
35
*/
37
36
public function process (ContainerBuilder $ container )
38
37
{
38
+ // Setup
39
39
$ this ->compiler = $ container ->getCompiler ();
40
40
$ 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 ) {
46
48
continue ;
47
49
}
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 ;
49
60
try {
50
- $ definition = $ container ->getDefinition ($ aliasId );
61
+ $ definition = $ container ->getDefinition ($ targetId );
51
62
} 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 );
53
64
}
54
-
55
65
if ($ definition ->isPublic ()) {
56
66
continue ;
57
67
}
58
-
68
+ // Remove private definition and schedule for replacement
59
69
$ 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 ;
70
73
}
71
- }
72
74
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 (false ), $ currentId , $ newId ), false );
104
- $ definition ->setFactory ($ this ->updateFactoryReference ($ definition ->getFactory (), $ currentId , $ newId ));
75
+ // Now replace target instances in all definitions
76
+ foreach ($ container ->getDefinitions () as $ definitionId => $ definition ) {
77
+ $ definition ->setArguments ($ this ->updateArgumentReferences ($ replacements , $ definitionId , $ definition ->getArguments ()));
78
+ $ definition ->setMethodCalls ($ this ->updateArgumentReferences ($ replacements , $ definitionId , $ definition ->getMethodCalls ()));
79
+ $ definition ->setProperties ($ this ->updateArgumentReferences ($ replacements , $ definitionId , $ definition ->getProperties ()));
80
+ $ definition ->setFactoryService ($ this ->updateFactoryReferenceId ($ replacements , $ definition ->getFactoryService (false )), false );
81
+ $ definition ->setFactory ($ this ->updateFactoryReference ($ replacements , $ definition ->getFactory ()));
105
82
}
106
83
}
107
84
108
85
/**
109
- * Updates argument references.
86
+ * Recursively updates references in an array .
110
87
*
111
- * @param array $arguments An array of Arguments
112
- * @param string $currentId The alias identifier
113
- * @param string $newId The identifier the alias points to
88
+ * @param array $replacements Table of aliases to replace
89
+ * @param string $definitionId Identifier of this definition
90
+ * @param array $arguments Where to replace the aliases
114
91
*
115
92
* @return array
116
93
*/
117
- private function updateArgumentReferences (array $ arguments , $ currentId , $ newId )
94
+ private function updateArgumentReferences (array $ replacements , $ definitionId , array $ arguments )
118
95
{
119 96
foreach ($ arguments as $ k => $ argument ) {
97
+ // Handle recursion step
120
98
if (is_array ($ argument )) {
121
- $ arguments [$ k ] = $ this ->updateArgumentReferences ($ argument , $ currentId , $ newId );
122
- } elseif ($ argument instanceof Reference) {
123
- if ($ currentId === (string ) $ argument ) {
124
- $ arguments [$ k ] = new Reference ($ newId , $ argument ->getInvalidBehavior ());
125
- $ this ->compiler ->addLogMessage ($ this ->formatter ->formatUpdateReference ($ this , $ this ->sourceId , $ currentId , $ newId ));
126
- }
99
+ $ arguments [$ k ] = $ this ->updateArgumentReferences ($ replacements , $ definitionId , $ argument );
100
+ continue ;
101
+ }
102
+ // Skip arguments that don't need replacement
103
+ if (!$ argument instanceof Reference) {
104
+ continue ;
105
+ }
106
+ $ referenceId = (string ) $ argument ;
107
+ if (!isset ($ replacements [$ referenceId ])) {
108
+ continue ;
127
109
}
110
+ // Perform the replacement
111
+ $ newId = $ replacements [$ referenceId ];
112
+ $ arguments [$ k ] = new Reference ($ newId , $ argument ->getInvalidBehavior ());
113
+ $ this ->compiler ->addLogMessage ($ this ->formatter ->formatUpdateReference ($ this , $ definitionId , $ referenceId , $ newId ));
128
114
}
129
115
130
116
return $ arguments ;
131
117
}
132
118
133
- private function updateFactoryServiceReference ($ factoryService , $ currentId , $ newId )
119
+ /**
120
+ * Returns the updated reference for the factory service.
121
+ *
122
+ * @param array $replacements Table of aliases to replace
123
+ * @param string|null $referenceId Factory service reference identifier
124
+ *
125
+ * @return string|null
126
+ */
127
+ private function updateFactoryReferenceId (array $ replacements , $ referenceId )
134
128
{
135
- if (null === $ factoryService ) {
129
+ if (null === $ referenceId ) {
136
130
return ;
137
131
}
138
132
139
- return $ currentId === $ factoryService ? $ newId : $ factoryService ;
133
+ return isset ( $ replacements [ $ referenceId ]) ? $ replacements [ $ referenceId ] : $ referenceId ;
140
134
}
141
135
142
- private function updateFactoryReference ($ factory , $ currentId , $ newId )
136
+ private function updateFactoryReference (array $ replacements , $ factory )
143
137
{
144
- if (null === $ factory || ! is_array ($ factory ) || ! $ factory [0 ] instanceof Reference) {
145
- return $ factory ;
138
+ if (is_array ($ factory ) && $ factory [0 ] instanceof Reference && isset ( $ replacements [ $ referenceId = ( string ) $ factory [ 0 ]]) ) {
139
+ $ factory [ 0 ] = new Reference ( $ replacements [ $ referenceId ], $ factory[ 0 ]-> getInvalidBehavior ()) ;
146
140
}
147
141
148
- if ($ currentId === (string ) $ factory [0 ]) {
149
- $ factory [0 ] = new Reference ($ newId , $ factory [0 ]->getInvalidBehavior ());
150
- }
151
142
152
143
return $ factory ;
153
144
}
0 commit comments