8000 [DependencyInjection] Fix parsing named autowiring aliases that conta… · symfony/symfony@69a115c · GitHub
[go: up one dir, main page]

Skip to content

Commit 69a115c

Browse files
[DependencyInjection] Fix parsing named autowiring aliases that contain underscores
1 parent e3e3d5f commit 69a115c

File tree

7 files changed

+55
-14
lines changed

7 files changed

+55
-14
lines changed

src/Symfony/Component/DependencyInjection/Attribute/Target.php

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,10 +36,12 @@ public function getParsedName(): string
3636
return lcfirst(str_replace(' ', '', ucwords(preg_replace('/[^a-zA-Z0-9\x7f-\xff]++/', ' ', $this->name))));
3737
}
3838

39-
public static function parseName(\ReflectionParameter $parameter, self &$attribute = null): string
39+
public static function parseName(\ReflectionParameter $parameter, self &$attribute = null, string &$parsedName = null): string
4040
{
4141
$attribute = null;
4242
if (!$target = $parameter->getAttributes(self::class)[0] ?? null) {
43+
$parsedName = (new self($parameter->name))->getParsedName();
44+
4345
return $parameter->name;
4446
}
4547

@@ -57,6 +59,6 @@ public static function parseName(\ReflectionParameter $parameter, self &$attribu
5759
throw new InvalidArgumentException(sprintf('Invalid #[Target] name "%s" on parameter "$%s" of "%s()": the first character must be a letter.', $name, $parameter->name, $function));
5860
}
5961

60-
return $parsedName;
62+
return preg_match('/^[a-zA-Z0-9_\x7f-\xff]++$/', $name) ? $name : $parsedName;
6163
}
6264
}

src/Symfony/Component/DependencyInjection/Compiler/AutowirePass.php

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -454,20 +454,30 @@ private function getAutowiredReference(TypedReference $reference, bool $filterTy
454454
$name = $target = (array_filter($reference->getAttributes(), static fn ($a) => $a instanceof Target)[0] ?? null)?->name;
455455

456456
if (null !== $name ??= $reference->getName()) {
457+
if ($this->container->has($alias = $type.' $'.$name) && !$this->container->findDefinition($alias)->isAbstract()) {
458+
return new TypedReference($alias, $type, $reference->getInvalidBehavior());
459+
}
460+
461+
if (null !== ($alias = $this->getCombinedAlias($type, $name)) && !$this->container->findDefinition($alias)->isAbstract()) {
462+
return new TypedReference($alias, $type, $reference->getInvalidBehavior());
463+
}
464+
457465
$parsedName = (new Target($name))->getParsedName();
458466

459467
if ($this->container->has($alias = $type.' $'.$parsedName) && !$this->container->findDefinition($alias)->isAbstract()) {
460468
return new TypedReference($alias, $type, $reference->getInvalidBehavior());
461469
}
462470

463-
if (null !== ($alias = $this->getCombinedAlias($type, $parsedName) ?? null) && !$this->container->findDefinition($alias)->isAbstract()) {
471+
if (null !== ($alias = $this->getCombinedAlias($type, $parsedName)) && !$this->container->findDefinition($alias)->isAbstract()) {
464472
return new TypedReference($alias, $type, $reference->getInvalidBehavior());
465473
}
466474

467-
if ($this->container->has($name) && !$this->container->findDefinition($name)->isAbstract()) {
475+
if (($this->container->has($n = $name) && !$this->container->findDefinition($n)->isAbstract())
476+
|| ($this->container->has($n = $parsedName) && !$this->container->findDefinition($n)->isAbstract())
477+
) {
468478
foreach ($this->container->getAliases() as $id => $alias) {
469-
if ($name === (string) $alias && str_starts_with($id, $type.' $')) {
470-
return new TypedReference($name, $type, $reference->getInvalidBehavior());
479+
if ($n === (string) $alias && str_starts_with($id, $type.' $')) {
480+
return new TypedReference($n, $type, $reference->getInvalidBehavior());
471481
}
472482
}
473483
}
@@ -481,7 +491,7 @@ private function getAutowiredReference(TypedReference $reference, bool $filterTy
481491
return new TypedReference($type, $type, $reference->getInvalidBehavior());
482492
}
483493

484-
if (null !== ($alias = $this->getCombinedAlias($type) ?? null) && !$this->container->findDefinition($alias)->isAbstract()) {
494+
if (null !== ($alias = $this->getCombinedAlias($type)) && !$this->container->findDefinition($alias)->isAbstract()) {
485495
return new TypedReference($alias, $type, $reference->getInvalidBehavior());
486496
}
487497

src/Symfony/Component/DependencyInjection/Compiler/ResolveBindingsPass.php

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -190,16 +190,19 @@ protected function processValue(mixed $value, bool $isRoot = false): mixed
190190

191191
$typeHint = ltrim(ProxyHelper::exportType($parameter) ?? '', '?');
192192

193-
$name = Target::parseName($parameter);
193+
$name = Target::parseName($parameter, parsedName: $parsedName);
194194

195-
if ($typeHint && \array_key_exists($k = preg_replace('/(^|[(|&])\\\\/', '\1', $typeHint).' $'.$name, $bindings)) {
195+
if ($typeHint && (
196+
\array_key_exists($k = preg_replace('/(^|[(|&])\\\\/', '\1', $typeHint).' $'.$name, $bindings)
197+
|| \array_key_exists($k = preg_replace('/(^|[(|&])\\\\/', '\1', $typeHint).' $'.$parsedName, $bindings)
198+
)) {
196199
$arguments[$key] = $this->getBindingValue($bindings[$k]);
197200

198201
continue;
199202
}
200203

201-
if (\array_key_exists('$'.$name, $bindings)) {
202-
$arguments[$key] = $this->getBindingValue($bindings['$'.$name]);
204+
if (\array_key_exists($k = '$'.$name, $bindings) || \array_key_exists($k = '$'.$parsedName, $bindings)) {
205+
$arguments[$key] = $this->getBindingValue($bindings[$k]);
203206

204207
continue;
205208
}
@@ -210,7 +213,7 @@ protected function processValue(mixed $value, bool $isRoot = false): mixed
210213
continue;
211214
}
212215

213-
if (isset($bindingNames[$name]) || isset($bindingNames[$parameter->name])) {
216+
if (isset($bindingNames[$name]) || isset($bindingNames[$parsedName]) || isset($bindingNames[$parameter->name])) {
214217
$bindingKey = array_search($binding, $bindings, true);
215218
$argumentType = substr($bindingKey, 0, strpos($bindingKey, ' '));
216219
$this->errorMessages[] = sprintf('Did you forget to add the type "%s" to argument "$%s" of method "%s::%s()"?', $argumentType, $parameter->name, $reflectionMethod->class, $reflectionMethod->name);

src/Symfony/Component/DependencyInjection/Tests/Compiler/AutowirePassTest.php

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1301,6 +1301,18 @@ public function testAutowireWithNamedArgs()
13011301
$this->assertEquals([new TypedReference(A::class, A::class), 'abc'], $container->getDefinition('foo')->getArguments());
13021302
}
13031303

1304+
public function testAutowireUnderscoreNamedArgument()
1305+
{
1306+
$container = new ContainerBuilder();
1307+
1308+
$container->autowire(\DateTimeImmutable::class.' $now_datetime', \DateTimeImmutable::class);
1309+
$container->autowire('foo', UnderscoreNamedArgument::class)->setPublic(true);
1310+
1311+
(new AutowirePass())->process($container);
1312+
1313+
$this->assertInstanceOf(\DateTimeImmutable::class, $container->get('foo')->now_datetime);
1314+
}
1315+
13041316
public function testAutowireDefaultValueParametersLike()
13051317
{
13061318
$container = new ContainerBuilder();

src/Symfony/Component/DependencyInjection/Tests/Compiler/RegisterServiceSubscribersPassTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -403,7 +403,7 @@ public static function getSubscribedServices(): array
403403

404404
$expected = [
405405
'some.service' => new ServiceClosureArgument(new TypedReference('stdClass $someService', 'stdClass')),
406-
'some_service' => new ServiceClosureArgument(new TypedReference('stdClass $someService', 'stdClass')),
406+
'some_service' => new ServiceClosureArgument(new TypedReference('stdClass $some_service', 'stdClass')),
407407
'another_service' => new ServiceClosureArgument(new TypedReference('stdClass $anotherService', 'stdClass')),
408408
];
409409
$this->assertEquals($expected, $container->getDefinition((string) $locator->getFactory()[0])->getArgument(0));

src/Symfony/Component/DependencyInjection/Tests/Fixtures/includes/autowiring_classes.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -227,6 +227,14 @@ public function __construct(A $a, Lille $lille, $foo = 'some_val')
227227
}
228228
}
229229

230+
class UnderscoreNamedArgument
231+
{
232+
public function __construct(
233+
public \DateTimeImmutable $now_datetime,
234+
) {
235+
}
236+
}
237+
230238
/*
231239
* Classes used for testing createResourceForClass
232240
*/

src/Symfony/Component/HttpKernel/DependencyInjection/RegisterControllerArgumentLocatorsPass.php

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,8 @@ public function process(ContainerBuilder $container)
128128
$type = preg_replace('/(^|[(|&])\\\\/', '\1', $target = ltrim(ProxyHelper::exportType($p) ?? '', '?'));
129129
$invalidBehavior = ContainerInterface::IGNORE_ON_INVALID_REFERENCE;
130130
$autowireAttributes = $autowire ? $emptyAutowireAttributes : [];
131+
$parsedName = $p->name;
132+
$k = null;
131133

132134
if (isset($arguments[$r->name][$p->name])) {
133135
$target = $arguments[$r->name][$p->name];
@@ -138,7 +140,11 @@ public function process(ContainerBuilder $container)
138140
} elseif ($p->allowsNull() && !$p->isOptional()) {
139141
$invalidBehavior = ContainerInterface::NULL_ON_INVALID_REFERENCE;
140142
}
141-
} elseif (isset($bindings[$bindingName = $type.' $'.$name = Target::parseName($p)]) || isset($bindings[$bindingName = '$'.$name]) || isset($bindings[$bindingName = $type])) {
143+
} elseif (isset($bindings[$bindingName = $type.' $'.$name = Target::parseName($p, $k, $parsedName)])
144+
|| isset($bindings[$bindingName = $type.' $'.$parsedName])
145+
|| isset($bindings[$bindingName = '$'.$name])
146+
|| isset($bindings[$bindingName = $type])
147+
) {
142 4A3A 148
$binding = $bindings[$bindingName];
143149

144150
[$bindingValue, $bindingId, , $bindingType, $bindingFile] = $binding->getValues();

0 commit comments

Comments
 (0)
0