25
25
use Symfony \Component \DependencyInjection \Reference ;
26
26
use Symfony \Component \DependencyInjection \TypedReference ;
27
27
use Symfony \Component \VarExporter \ProxyHelper ;
28
- use Symfony \Contracts \Service \Attribute \SubscribedService ;
29
28
30
29
/**
31
30
* Inspects existing service definitions and wires the autowired ones using the type hints of their classes.
@@ -106,18 +105,19 @@ protected function processValue(mixed $value, bool $isRoot = false): mixed
106
105
private function doProcessValue (mixed $ value , bool $ isRoot = false ): mixed
107
106
{
108
107
if ($ value instanceof TypedReference) {
109
- if ($ attributes = $ value ->getAttributes ()) {
110
- $ attribute = array_pop ($ attributes );
111
-
112
- if ($ attributes ) {
113
- throw new AutowiringFailedException ($ this ->currentId , sprintf ('Using multiple attributes with "%s" is not supported. ' , SubscribedService::class));
108
+ foreach ($ value ->getAttributes () as $ attribute ) {
109
+ if ($ attribute === $ v = $ this ->processValue ($ attribute )) {
110
+ continue ;
114
111
}
115
-
116
- if (!$ attribute instanceof Target) {
117
- return $ this ->processAttribute ($ attribute , ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE !== $ value ->getInvalidBehavior ());
112
+ if (!$ attribute instanceof Autowire || !$ v instanceof Reference) {
113
+ return $ v ;
118
114
}
119
115
120
- $ value = new TypedReference ($ value ->getType (), $ value ->getType (), $ value ->getInvalidBehavior (), $ attribute ->name , [$ attribute ]);
116
+ $ invalidBehavior = ContainerBuilder::EXCEPTION_ON_INVALID_REFERENCE !== $ v ->getInvalidBehavior () ? $ v ->getInvalidBehavior () : $ value ->getInvalidBehavior ();
117
+ $ value = $ v instanceof TypedReference
118
+ ? new TypedReference ($ v , $ v ->getType (), $ invalidBehavior , $ v ->getName () ?? $ value ->getName (), array_merge ($ v ->getAttributes (), $ value ->getAttributes ()))
119
+ : new TypedReference ($ v , $ value ->getType (), $ invalidBehavior , $ value ->getName (), $ value ->getAttributes ());
120
+ break ;
121
121
}
122
122
if ($ ref = $ this ->getAutowiredReference ($ value , true )) {
123
123
return $ ref ;
@@ -173,22 +173,6 @@ private function doProcessValue(mixed $value, bool $isRoot = false): mixed
173
173
return $ value ;
174
174
}
175
175
176
- private function processAttribute (object $ attribute , bool $ isOptional = false ): mixed
177
- {
178
- switch (true ) {
179
- case $ attribute instanceof Autowire:
180
- if ($ isOptional && $ attribute ->value instanceof Reference) {
181
- return new Reference ($ attribute ->value , ContainerInterface::NULL_ON_INVALID_REFERENCE );
182
- }
183
- // no break
184
- case $ attribute instanceof AutowireDecorated:
185
- case $ attribute instanceof MapDecorated:
186
- return $ this ->processValue ($ attribute );
187
- }
188
-
189
- throw new AutowiringFailedException ($ this ->currentId , sprintf ('"%s" is an unsupported attribute. ' , $ attribute ::class));
190
- }
191
-
192
176
private function autowireCalls (\ReflectionClass $ reflectionClass , bool $ isRoot , bool $ checkAttributes ): array
193
177
{
194
178
$ this ->decoratedId = null ;
@@ -285,7 +269,9 @@ private function autowireMethod(\ReflectionFunctionAbstract $reflectionMethod, a
285
269
if ($ checkAttributes ) {
286
270
foreach ($ parameter ->getAttributes (Autowire::class, \ReflectionAttribute::IS_INSTANCEOF ) as $ attribute ) {
287
271
$ attribute = $ attribute ->newInstance ();
288
- $ value = $ this ->processAttribute ($ attribute , $ parameter ->allowsNull ());
272
+ $ name = Target::parseName ($ parameter , $ target );
273
+ $ invalidBehavior = $ parameter ->allowsNull () ? ContainerInterface::NULL_ON_INVALID_REFERENCE : ContainerBuilder::EXCEPTION_ON_INVALID_REFERENCE ;
274
+ $ value = $ this ->processValue (new TypedReference ($ type ?: '? ' , $ type ?: 'mixed ' , $ invalidBehavior , $ name , [$ attribute , ...($ target ? [$ target ] : [])]));
289
275
290
276
if ($ attribute instanceof AutowireCallable || 'Closure ' === $ type && \is_array ($ value )) {
291
277
$ value = (new Definition ('Closure ' ))
@@ -299,13 +285,13 @@ private function autowireMethod(\ReflectionFunctionAbstract $reflectionMethod, a
299
285
}
300
286
301
287
foreach ($ parameter ->getAttributes (AutowireDecorated::class) as $ attribute ) {
302
- $ arguments [$ index ] = $ this ->processAttribute ($ attribute ->newInstance (), $ parameter -> allowsNull ());
288
+ $ arguments [$ index ] = $ this ->processValue ($ attribute ->newInstance ());
303
289
304
290
continue 2 ;
305
291
}
306
292
307
293
foreach ($ parameter ->getAttributes (MapDecorated::class) as $ attribute ) {
308
- $ arguments [$ index ] = $ this ->processAttribute ($ attribute ->newInstance (), $ parameter -> allowsNull ());
294
+ $ arguments [$ index ] = $ this ->processValue ($ attribute ->newInstance ());
309
295
310
296
continue 2 ;
311
297
}
@@ -354,7 +340,7 @@ private function autowireMethod(\ReflectionFunctionAbstract $reflectionMethod, a
354
340
return $ value ;
355
341
};
356
342
357
- if ($ this ->decoratedClass && $ isDecorated = is_a ($ this ->decoratedClass , $ type , true )) {
343
+ if ($ this ->decoratedClass && is_a ($ this ->decoratedClass , $ type , true )) {
358
344
if ($ this ->getPreviousValue ) {
359
345
// The inner service is injected only if there is only 1 argument matching the type of the decorated class
360
346
// across all arguments of all autowired methods.
@@ -412,7 +398,9 @@ private function getAutowiredReference(TypedReference $reference, bool $filterTy
412
398
$ type = implode ($ m [0 ], $ types );
413
399
}
414
400
415
- if (null !== $ name = $ reference ->getName ()) {
401
+ $ name = (array_filter ($ reference ->getAttributes (), static fn ($ a ) => $ a instanceof Target)[0 ] ?? null )?->name;
402
+
403
+ if (null !== $ name ??= $ reference ->getName ()) {
416
404
if ($ this ->container ->has ($ alias = $ type .' $ ' .$ name ) && !$ this ->container ->findDefinition ($ alias )->isAbstract ()) {
417
405
return new TypedReference ($ alias , $ type , $ reference ->getInvalidBehavior ());
418
406
}
0 commit comments