11
11
12
12
namespace Symfony \Component \HttpKernel \DependencyInjection ;
13
13
14
+ use Symfony \Component \DependencyInjection \Argument \ServiceLocatorArgument ;
15
+ use Symfony \Component \DependencyInjection \Argument \TaggedIteratorArgument ;
14
16
use Symfony \Component \DependencyInjection \Attribute \Autowire ;
17
+ use Symfony \Component \DependencyInjection \Attribute \TaggedIterator ;
18
+ use Symfony \Component \DependencyInjection \Attribute \TaggedLocator ;
15
19
use Symfony \Component \DependencyInjection \Attribute \Target ;
16
20
use Symfony \Component \DependencyInjection \ChildDefinition ;
17
21
use Symfony \Component \DependencyInjection \Compiler \CompilerPassInterface ;
@@ -52,8 +56,6 @@ public function process(ContainerBuilder $container)
52
56
}
53
57
}
54
58
55
- $ emptyAutowireAttributes = class_exists (Autowire::class) ? null : [];
56
-
57
59
foreach ($ container ->findTaggedServiceIds ('controller.service_arguments ' , true ) as $ id => $ tags ) {
58
60
$ def = $ container ->getDefinition ($ id );
59
61
$ def ->setPublic (true );
@@ -126,7 +128,7 @@ public function process(ContainerBuilder $container)
126
128
/** @var \ReflectionParameter $p */
127
129
$ type = preg_replace ('/(^|[(|&]) \\\\/ ' , '\1 ' , $ target = ltrim (ProxyHelper::exportType ($ p ) ?? '' , '? ' ));
128
130
$ invalidBehavior = ContainerInterface::IGNORE_ON_INVALID_REFERENCE ;
129
- $ autowireAttributes = $ autowire ? $ emptyAutowireAttributes : [];
131
+ $ parameterAttributes = $ autowire ? null : [];
130
132
131
133
if (isset ($ arguments [$ r ->name ][$ p ->name ])) {
132
134
$ target = $ arguments [$ r ->name ][$ p ->name ];
@@ -146,7 +148,7 @@ public function process(ContainerBuilder $container)
146
148
$ args [$ p ->name ] = $ bindingValue ;
147
149
148
150
continue ;
149
- } elseif (!$ autowire || (!($ autowireAttributes ??= $ p -> getAttributes (Autowire::class, \ReflectionAttribute:: IS_INSTANCEOF )) && (!$ type || '\\' !== $ target [0 ]))) {
151
+ } elseif (!$ autowire || (!($ parameterAttributes ??= $ this -> getParameterAttributes ( $ p )) && (!$ type || '\\' !== $ target [0 ]))) {
150
152
continue ;
151
153
} elseif (is_subclass_of ($ type , \UnitEnum::class)) {
152
154
// do not attempt to register enum typed arguments if not already present in bindings
@@ -159,16 +161,24 @@ public function process(ContainerBuilder $container)
159
161
continue ;
160
162
}
161
163
162
- if ($ autowireAttributes ) {
163
- $ value = $ autowireAttributes [0 ]->newInstance ()-> value ;
164
+ if ($ parameterAttributes ) {
165
+ $ attributeInstance = $ parameterAttributes [0 ]->newInstance ();
164
166
165
- if ($ value instanceof Reference) {
166
- $ args [$ p ->name ] = $ type ? new TypedReference ($ value , $ type , $ invalidBehavior , $ p ->name ) : new Reference ($ value , $ invalidBehavior );
167
+ if ($ attributeInstance instanceof TaggedIterator) {
168
+ $ args [$ p ->name ] = new TaggedIteratorArgument ($ attributeInstance ->tag , $ attributeInstance ->indexAttribute , $ attributeInstance ->defaultIndexMethod , false , $ attributeInstance ->defaultPriorityMethod , (array ) $ attributeInstance ->exclude , $ attributeInstance ->excludeSelf );
169
+ } elseif ($ attributeInstance instanceof TaggedLocator) {
170
+ $ args [$ p ->name ] = new ServiceLocatorArgument (new TaggedIteratorArgument ($ attributeInstance ->tag , $ attributeInstance ->indexAttribute , $ attributeInstance ->defaultIndexMethod , true , $ attributeInstance ->defaultPriorityMethod , (array ) $ attributeInstance ->exclude , $ attributeInstance ->excludeSelf ));
167
171
} else {
168
- $ args [$ p ->name ] = new Reference ('.value. ' .$ container ->hash ($ value ));
169
- $ container ->register ((string ) $ args [$ p ->name ], 'mixed ' )
170
- ->setFactory ('current ' )
171
- ->addArgument ([$ value ]);
172
+ $ value = $ attributeInstance ->value ;
173
+
174
+ if ($ value instanceof Reference) {
175
+ $ args [$ p ->name ] = $ type ? new TypedReference ($ value , $ type , $ invalidBehavior , $ p ->name ) : new Reference ($ value , $ invalidBehavior );
176
+ } else {
177
+ $ args [$ p ->name ] = new Reference ('.value. ' .$ container ->hash ($ value ));
178
+ $ container ->register ((string ) $ args [$ p ->name ], 'mixed ' )
179
+ ->setFactory ('current ' )
180
+ ->addArgument ([$ value ]);
181
+ }
172
182
}
173
183
174
184
continue ;
@@ -216,4 +226,15 @@ public function process(ContainerBuilder $container)
216
226
217
227
$ container ->setAlias ('argument_resolver.controller_locator ' , (string ) $ controllerLocatorRef );
218
228
}
229
+
230
+ private function getParameterAttributes (\ReflectionParameter $ parameter ): array
231
+ {
232
+ foreach ([TaggedIterator::class, TaggedLocator::class, Autowire::class] as $ attributeClass ) {
233
+ if ($ attributes = $ parameter ->getAttributes ($ attributeClass , Autowire::class === $ attributeClass ? \ReflectionAttribute::IS_INSTANCEOF : 0 )) {
234
+ return $ attributes ;
235
+ }
236
+ }
237
+
238
+ return [];
239
+ }
219
240
}
0 commit comments