@@ -44,11 +44,8 @@ class AutowirePass extends AbstractRecursivePass
44
44
private bool $ throwOnAutowiringException ;
45
45
private ?string $ decoratedClass = null ;
46
46
private ?string $ decoratedId = null ;
47
- private ?array $ methodCalls = null ;
48
47
private object $ defaultArgument ;
49
- private ?\Closure $ getPreviousValue = null ;
50
- private ?int $ decoratedMethodIndex = null ;
51
- private ?int $ decoratedMethodArgumentIndex = null ;
48
+ private ?\Closure $ restorePreviousValue = null ;
52
49
private ?self $ typesClone = null ;
53
50
54
51
public function __construct (bool $ throwOnAutowireException = true )
@@ -79,12 +76,9 @@ public function process(ContainerBuilder $container): void
79
76
} finally {
80
77
$ this ->decoratedClass = null ;
81
78
$ this ->decoratedId = null ;
82
- $ this ->methodCalls = null ;
83
79
$ this ->defaultArgument ->bag = null ;
84
80
$ this ->defaultArgument ->names = null ;
85
- $ this ->getPreviousValue = null ;
86
- $ this ->decoratedMethodIndex = null ;
87
- $ this ->decoratedMethodArgumentIndex = null ;
81
+ $ this ->restorePreviousValue = null ;
88
82
$ this ->typesClone = null ;
89
83
}
90
84
}
@@ -155,7 +149,7 @@ private function doProcessValue(mixed $value, bool $isRoot = false): mixed
155
149
return $ value ;
156
150
}
157
151
158
- $ this -> methodCalls = $ value ->getMethodCalls ();
152
+ $ methodCalls = $ value ->getMethodCalls ();
159
153
160
154
try {
161
155
$ constructor = $ this ->getConstructor ($ value , false );
@@ -164,40 +158,42 @@ private function doProcessValue(mixed $value, bool $isRoot = false): mixed
164
158
}
165
159
166
160
if ($ constructor ) {
167
- array_unshift ($ this -> methodCalls , [$ constructor , $ value ->getArguments ()]);
161
+ array_unshift ($ methodCalls , [$ constructor , $ value ->getArguments ()]);
168
162
}
169
163
170
164
$ checkAttributes = !$ value ->hasTag ('container.ignore_attributes ' );
171
- $ this -> methodCalls = $ this ->autowireCalls ($ reflectionClass , $ isRoot , $ checkAttributes );
165
+ $ methodCalls = $ this ->autowireCalls ($ methodCalls , $ reflectionClass , $ isRoot , $ checkAttributes );
172
166
173
167
if ($ constructor ) {
174
- [, $ arguments ] = array_shift ($ this -> methodCalls );
168
+ [, $ arguments ] = array_shift ($ methodCalls );
175
169
176
170
if ($ arguments !== $ value ->getArguments ()) {
177
171
$ value ->setArguments ($ arguments );
178
172
}
179
173
}
180
174
181
- if ($ this -> methodCalls !== $ value ->getMethodCalls ()) {
182
- $ value ->setMethodCalls ($ this -> methodCalls );
175
+ if ($ methodCalls !== $ value ->getMethodCalls ()) {
176
+ $ value ->setMethodCalls ($ methodCalls );
183
177
}
184
178
185
179
return $ value ;
186
180
}
187
181
188
- private function autowireCalls (\ReflectionClass $ reflectionClass , bool $ isRoot , bool $ checkAttributes ): array
182
+ private function autowireCalls (array $ methodCalls , \ReflectionClass $ reflectionClass , bool $ isRoot , bool $ checkAttributes ): array
189
183
{
190
- $ this ->decoratedId = null ;
191
- $ this ->decoratedClass = null ;
192
- $ this ->getPreviousValue = null ;
184
+ if ($ isRoot ) {
185
+ $ this ->decoratedId = null ;
186
+ $ this ->decoratedClass = null ;
187
+ $ this ->restorePreviousValue = null ;
193
188
194
- if ($ isRoot && ($ definition = $ this ->container ->getDefinition ($ this ->currentId )) && null !== ($ this ->decoratedId = $ definition ->innerServiceId ) && $ this ->container ->has ($ this ->decoratedId )) {
195
- $ this ->decoratedClass = $ this ->container ->findDefinition ($ this ->decoratedId )->getClass ();
189
+ if (($ definition = $ this ->container ->getDefinition ($ this ->currentId )) && null !== ($ this ->decoratedId = $ definition ->innerServiceId ) && $ this ->container ->has ($ this ->decoratedId )) {
190
+ $ this ->decoratedClass = $ this ->container ->findDefinition ($ this ->decoratedId )->getClass ();
191
+ }
196
192
}
197
193
198
194
$ patchedIndexes = [];
199
195
200
- foreach ($ this -> methodCalls as $ i => $ call ) {
196
+ foreach ($ methodCalls as $ i => $ call ) {
201
197
[$ method , $ arguments ] = $ call ;
202
198
203
199
if ($ method instanceof \ReflectionFunctionAbstract) {
@@ -214,18 +210,18 @@ private function autowireCalls(\ReflectionClass $reflectionClass, bool $isRoot,
214
210
}
215
211
}
216
212
217
- $ arguments = $ this ->autowireMethod ($ reflectionMethod , $ arguments , $ checkAttributes, $ i );
213
+ $ arguments = $ this ->autowireMethod ($ reflectionMethod , $ arguments , $ checkAttributes );
218
214
219
215
if ($ arguments !== $ call [1 ]) {
220
- $ this -> methodCalls [$ i ][1 ] = $ arguments ;
216
+ $ methodCalls [$ i ][1 ] = $ arguments ;
221
217
$ patchedIndexes [] = $ i ;
222
218
}
223
219
}
224
220
225
221
// use named arguments to skip complex default values
226
222
foreach ($ patchedIndexes as $ i ) {
227
223
$ namedArguments = null ;
228
- $ arguments = $ this -> methodCalls [$ i ][1 ];
224
+ $ arguments = $ methodCalls [$ i ][1 ];
229
225
230
226
foreach ($ arguments as $ j => $ value ) {
231
227
if ($ namedArguments && !$ value instanceof $ this ->defaultArgument ) {
@@ -248,29 +244,30 @@ private function autowireCalls(\ReflectionClass $reflectionClass, bool $isRoot,
248
244
}
249
245
}
250
246
251
- $ this -> methodCalls [$ i ][1 ] = $ arguments ;
247
+ $ methodCalls [$ i ][1 ] = $ arguments ;
252
248
}
253
249
254
- return $ this -> methodCalls ;
250
+ return $ methodCalls ;
255
251
}
256
252
257
253
/**
258
254
* Autowires the constructor or a method.
259
255
*
260
256
* @throws AutowiringFailedException
261
257
*/
262
- private function autowireMethod (\ReflectionFunctionAbstract $ reflectionMethod , array $ arguments , bool $ checkAttributes, int $ methodIndex ): array
258
+ private function autowireMethod (\ReflectionFunctionAbstract $ reflectionMethod , array $ arguments , bool $ checkAttributes ): array
263
259
{
264
260
$ class = $ reflectionMethod instanceof \ReflectionMethod ? $ reflectionMethod ->class : $ this ->currentId ;
265
261
$ method = $ reflectionMethod ->name ;
266
262
$ parameters = $ reflectionMethod ->getParameters ();
267
263
if ($ reflectionMethod ->isVariadic ()) {
268
264
array_pop ($ parameters );
269
265
}
270
- $ this ->defaultArgument ->names = new \ArrayObject ();
266
+ $ defaultArgument = clone $ this ->defaultArgument ;
267
+ $ defaultArgument ->names = new \ArrayObject ();
271
268
272
269
foreach ($ parameters as $ index => $ parameter ) {
273
- $ this -> defaultArgument ->names [$ index ] = $ parameter ->name ;
270
+ $ defaultArgument ->names [$ index ] = $ parameter ->name ;
274
271
275
272
if (\array_key_exists ($ parameter ->name , $ arguments )) {
276
273
$ arguments [$ index ] = $ arguments [$ parameter ->name ];
@@ -284,15 +281,16 @@ private function autowireMethod(\ReflectionFunctionAbstract $reflectionMethod, a
284
281
$ target = null ;
285
282
$ name = Target::parseName ($ parameter , $ target );
286
283
$ target = $ target ? [$ target ] : [];
284
+ $ currentId = $ this ->currentId ;
287
285
288
- $ getValue = function () use ($ type , $ parameter , $ class , $ method , $ name , $ target ) {
286
+ $ getValue = function () use ($ type , $ parameter , $ class , $ method , $ name , $ target, $ defaultArgument , $ currentId ) {
289
287
if (!$ value = $ this ->getAutowiredReference ($ ref = new TypedReference ($ type , $ type , ContainerBuilder::EXCEPTION_ON_INVALID_REFERENCE , $ name , $ target ), false )) {
290
- $ failureMessage = $ this ->createTypeNotFoundMessageCallback ($ ref , sprintf ('argument "$%s" of method "%s()" ' , $ parameter ->name , $ class !== $ this -> currentId ? $ class .':: ' .$ method : $ method ));
288
+ $ failureMessage = $ this ->createTypeNotFoundMessageCallback ($ ref , sprintf ('argument "$%s" of method "%s()" ' , $ parameter ->name , $ class !== $ currentId ? $ class .':: ' .$ method : $ method ));
291
289
292
290
if ($ parameter ->isDefaultValueAvailable ()) {
293
- $ value = $ this -> defaultArgument ->withValue ($ parameter );
291
+ $ value = $ defaultArgument ->withValue ($ parameter );
294
292
} elseif (!$ parameter ->allowsNull ()) {
295
- throw new AutowiringFailedException ($ this -> currentId , $ failureMessage );
293
+ throw new AutowiringFailedException ($ currentId , $ failureMessage );
296
294
}
297
295
}
298
296
@@ -316,14 +314,15 @@ private function autowireMethod(\ReflectionFunctionAbstract $reflectionMethod, a
316
314
if (!$ parameter ->isDefaultValueAvailable ()) {
317
315
throw new AutowiringFailedException ($ this ->currentId , $ e ->getMessage (), 0 , $ e );
318
316
}
319
- $ arguments [$ index ] = clone $ this -> defaultArgument ;
317
+ $ arguments [$ index ] = clone $ defaultArgument ;
320
318
$ arguments [$ index ]->value = $ parameter ->getDefaultValue ();
321
319
322
320
continue 2 ;
323
321
}
324
322
325
323
if ($ attribute instanceof AutowireCallable) {
326
324
$ value = $ attribute ->buildDefinition ($ value , $ type , $ parameter );
325
+ $ value = $ this ->doProcessValue ($ value );
327
326
} elseif ($ lazy = $ attribute ->lazy ) {
328
327
$ definition = (new Definition ($ type ))
329
328
->setFactory ('current ' )
@@ -385,25 +384,24 @@ private function autowireMethod(\ReflectionFunctionAbstract $reflectionMethod, a
385
384
}
386
385
387
386
// specifically pass the default value
388
- $ arguments [$ index ] = $ this -> defaultArgument ->withValue ($ parameter );
387
+ $ arguments [$ index ] = $ defaultArgument ->withValue ($ parameter );
389
388
390
389
continue ;
391
390
}
392
391
393
392
if ($ this ->decoratedClass && is_a ($ this ->decoratedClass , $ type , true )) {
394
- if ($ this ->getPreviousValue ) {
393
+ if ($ this ->restorePreviousValue ) {
395
394
// The inner service is injected only if there is only 1 argument matching the type of the decorated class
396
395
// across all arguments of all autowired methods.
397
396
// If a second matching argument is found, the default behavior is restored.
398
-
399
- $ getPreviousValue = $ this ->getPreviousValue ;
400
- $ this ->methodCalls [$ this ->decoratedMethodIndex ][1 ][$ this ->decoratedMethodArgumentIndex ] = $ getPreviousValue ();
401
- $ this ->decoratedClass = null ; // Prevent further checks
397
+ ($ this ->restorePreviousValue )();
398
+ $ this ->decoratedClass = $ this ->restorePreviousValue = null ; // Prevent further checks
402
399
} else {
403
400
$ arguments [$ index ] = new TypedReference ($ this ->decoratedId , $ this ->decoratedClass );
404
- $ this ->getPreviousValue = $ getValue ;
405
- $ this ->decoratedMethodIndex = $ methodIndex ;
406
- $ this ->decoratedMethodArgumentIndex = $ index ;
401
+ $ argumentAtIndex = &$ arguments [$ index ];
402
+ $ this ->restorePreviousValue = static function () use (&$ argumentAtIndex , $ getValue ) {
403
+ $ argumentAtIndex = $ getValue ();
404
+ };
407
405
408
406
continue ;
409
407
}
@@ -414,7 +412,7 @@ private function autowireMethod(\ReflectionFunctionAbstract $reflectionMethod, a
414
412
415
413
if ($ parameters && !isset ($ arguments [++$ index ])) {
416
414
while (0 <= --$ index ) {
417
- if (!$ arguments [$ index ] instanceof $ this -> defaultArgument ) {
415
+ if (!$ arguments [$ index ] instanceof $ defaultArgument ) {
418
416
break ;
419
417
}
420
418
unset($ arguments [$ index ]);
0 commit comments