@@ -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,105 +35,99 @@ 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
-
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 ()));
104
80
}
105
81
}
106
82
107
83
/**
108
- * Updates argument references.
84
+ * Recursively updates references in an array .
109
85
*
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
113
89
*
114
90
* @return array
115
91
*/
116
- private function updateArgumentReferences (array $ arguments , $ currentId , $ newId )
92
+ private function updateArgumentReferences (array $ replacements , $ definitionId , array $ arguments )
117
93
{
118
94
foreach ($ arguments as $ k => $ argument ) {
95
+ // Handle recursion step
119
96
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 ;
126
99
}
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 ));
127
112
}
128
113
129
114
return $ arguments ;
130
115
}
131
116
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 )
133
126
{
134
- if (null === $ factoryService ) {
127
+ if (null === $ referenceId ) {
135
128
return ;
136
129
}
137
130
138
- return $ currentId === $ factoryService ? $ newId : $ factoryService ;
131
+ return isset ( $ replacements [ $ referenceId ]) ? $ replacements [ $ referenceId ] : $ referenceId ;
139
132
}
140
133
}
0 commit comments