@@ -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,107 +35,90 @@ 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
- }
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
- }
70
+ $ container ->setDefinition ($ definitionId , $ definition );
71
+ $ container ->removeDefinition ($ targetId );
72
+ $ replacements [$ targetId ] = $ definitionId ;
86
73
}
87
74
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 ->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 ->setFactory ($ this ->updateFactoryReference ($ replacements , $ definition ->getFactory ()));
104
81
}
105
82
}
106
83
107
84
/**
108
- * Updates argument references.
85
+ * Recursively updates references in an array .
109
86
*
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
87
+ * @param array $replacements Table of aliases to replace
88
+ * @param string $definitionId Identifier of this definition
89
+ * @param array $arguments Where to replace the aliases
113
90
*
114
91
* @return array
115
92
*/
116
- private function updateArgumentReferences (array $ arguments , $ currentId , $ newId )
93
+ private function updateArgumentReferences (array $ replacements , $ definitionId , array $ arguments )
117
94
{
118
95
foreach ($ arguments as $ k => $ argument ) {
96
+ // Handle recursion step
119
97
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
- }
98
+ $ arguments [$ k ] = $ this ->updateArgumentReferences ($ replacements , $ definitionId , $ argument );
99
+ continue ;
100
+ }
101
+ // Skip arguments that don't need replacement
102
+ if (! $ argument instanceof Reference) {
103
+ continue ;
126
104
}
105
+ $ referenceId = (string ) $ argument ;
106
+ if (!isset ($ replacements [$ referenceId ])) {
107
+ continue ;
108
+ }
109
+ // Perform the replacement
110
+ $ newId = $ replacements [$ referenceId ];
111
+ $ arguments [$ k ] = new Reference ($ newId , $ argument ->getInvalidBehavior ());
112
+ $ this ->compiler ->addLogMessage ($ this ->formatter ->formatUpdateReference ($ this , $ definitionId , $ referenceId , $ newId ));
127
113
}
128
114
129
115
return $ arguments ;
130
116
}
131
117
132
- private function updateFactoryReference ($ factory , $ currentId , $ newId )
118
+ private function updateFactoryReference (array $ replacements , $ factory )
133
119
{
134
- if (null === $ factory || !is_array ($ factory ) || !$ factory [0 ] instanceof Reference) {
135
- return $ factory ;
136
- }
137
-
138
- if ($ currentId === (string ) $ factory [0 ]) {
139
- $ factory [0 ] = new Reference ($ newId , $ factory [0 ]->getInvalidBehavior ());
120
+ if (is_array ($ factory ) && $ factory [0 ] instanceof Reference && isset ($ replacements [$ referenceId = (string ) $ factory [0 ]])) {
121
+ $ factory [0 ] = new Reference ($ replacements [$ referenceId ], $ factory [0 ]->getInvalidBehavior ());
140
122
}
141
123
142
124
return $ factory ;
0 commit comments