Skip to content

Commit 45f817b

Browse files
bug #52836 [DependencyInjection] Fix parsing named autowiring aliases that contain underscores (nicolas-grekas)
This PR was merged into the 6.4 branch. Discussion ---------- [DependencyInjection] Fix parsing named autowiring aliases that contain underscores | Q | A | ------------- | --- | Branch? | 6.4 | Bug fix? | yes | New feature? | no | Deprecations? | no | Issues | Fix #52815 | License | MIT Fixing a regression introduced in #50718 Commits ------- 69a115c [DependencyInjection] Fix parsing named autowiring aliases that contain underscores
2 parents 9c27c32 + 69a115c commit 45f817b

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+
) {
142148
$binding = $bindings[$bindingName];
143149

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

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy