diff --git a/src/Symfony/Component/DependencyInjection/Attribute/Target.php b/src/Symfony/Component/DependencyInjection/Attribute/Target.php index 7751b3813bada..b935500e9737d 100644 --- a/src/Symfony/Component/DependencyInjection/Attribute/Target.php +++ b/src/Symfony/Component/DependencyInjection/Attribute/Target.php @@ -28,13 +28,15 @@ public function __construct(string $name) $this->name = lcfirst(str_replace(' ', '', ucwords(preg_replace('/[^a-zA-Z0-9\x7f-\xff]++/', ' ', $name)))); } - public static function parseName(\ReflectionParameter $parameter): string + public static function parseName(\ReflectionParameter $parameter, self &$attribute = null): string { + $attribute = null; if (!$target = $parameter->getAttributes(self::class)[0] ?? null) { return $parameter->name; } - $name = $target->newInstance()->name; + $attribute = $target->newInstance(); + $name = $attribute->name; if (!preg_match('/^[a-zA-Z_\x7f-\xff]/', $name)) { if (($function = $parameter->getDeclaringFunction()) instanceof \ReflectionMethod) { diff --git a/src/Symfony/Component/DependencyInjection/CHANGELOG.md b/src/Symfony/Component/DependencyInjection/CHANGELOG.md index e1d0dda20d6ff..81dec56e681f3 100644 --- a/src/Symfony/Component/DependencyInjection/CHANGELOG.md +++ b/src/Symfony/Component/DependencyInjection/CHANGELOG.md @@ -9,6 +9,7 @@ CHANGELOG * Add `RemoveBuildParametersPass`, which removes parameters starting with a dot during compilation * Add support for nesting autowiring-related attributes into `#[Autowire(...)]` * Deprecate undefined and numeric keys with `service_locator` config + * Fail if Target attribute does not exist during compilation 6.2 --- diff --git a/src/Symfony/Component/DependencyInjection/Compiler/AutowirePass.php b/src/Symfony/Component/DependencyInjection/Compiler/AutowirePass.php index 09b0490adf4c8..66a175d76c267 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/AutowirePass.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/AutowirePass.php @@ -128,7 +128,7 @@ private function doProcessValue(mixed $value, bool $isRoot = false): mixed return $this->processAttribute($attribute, ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE !== $value->getInvalidBehavior()); } - $value = new TypedReference($value->getType(), $value->getType(), $value->getInvalidBehavior(), $attribute->name); + $value = new TypedReference($value->getType(), $value->getType(), $value->getInvalidBehavior(), $attribute->name, [$attribute]); } if ($ref = $this->getAutowiredReference($value, true)) { return $ref; @@ -332,7 +332,8 @@ private function autowireMethod(\ReflectionFunctionAbstract $reflectionMethod, a } $getValue = function () use ($type, $parameter, $class, $method) { - if (!$value = $this->getAutowiredReference($ref = new TypedReference($type, $type, ContainerBuilder::EXCEPTION_ON_INVALID_REFERENCE, Target::parseName($parameter)), false)) { + $name = Target::parseName($parameter, $target); + if (!$value = $this->getAutowiredReference($ref = new TypedReference($type, $type, ContainerBuilder::EXCEPTION_ON_INVALID_REFERENCE, $name, $target ? [$target] : []), false)) { $failureMessage = $this->createTypeNotFoundMessageCallback($ref, sprintf('argument "$%s" of method "%s()"', $parameter->name, $class !== $this->currentId ? $class.'::'.$method : $method)); if ($parameter->isDefaultValueAvailable()) { @@ -420,6 +421,10 @@ private function getAutowiredReference(TypedReference $reference, bool $filterTy } } } + + if ($reference->getAttributes()) { + return null; + } } if ($this->container->has($type) && !$this->container->findDefinition($type)->isAbstract()) { @@ -544,6 +549,9 @@ private function createTypeNotFoundMessage(TypedReference $reference, string $la } $message = sprintf('has type "%s" but this class %s.', $type, $parentMsg ? sprintf('is missing a parent class (%s)', $parentMsg) : 'was not found'); + } elseif ($reference->getAttributes()) { + $message = $label; + $label = sprintf('"#[Target(\'%s\')" on', $reference->getName()); } else { $alternatives = $this->createTypeAlternatives($this->container, $reference); $message = $this->container->has($type) ? 'this service is abstract' : 'no such service exists'; diff --git a/src/Symfony/Component/DependencyInjection/Tests/Compiler/AutowirePassTest.php b/src/Symfony/Component/DependencyInjection/Tests/Compiler/AutowirePassTest.php index c766bed6aefa4..8224150357dda 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Compiler/AutowirePassTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Compiler/AutowirePassTest.php @@ -1142,6 +1142,21 @@ public function testArgumentWithTarget() $this->assertSame(BarInterface::class.' $imageStorage', (string) $container->getDefinition('with_target')->getArgument(0)); } + public function testArgumentWithTypoTarget() + { + $container = new ContainerBuilder(); + + $container->register(BarInterface::class, BarInterface::class); + $container->register(BarInterface::class.' $iamgeStorage', BarInterface::class); + $container->register('with_target', WithTarget::class) + ->setAutowired(true); + + $this->expectException(AutowiringFailedException::class); + $this->expectExceptionMessage('Cannot autowire service "with_target": "#[Target(\'imageStorage\')" on argument "$bar" of method "Symfony\Component\DependencyInjection\Tests\Fixtures\WithTarget::__construct()"'); + + (new AutowirePass())->process($container); + } + public function testDecorationWithServiceAndAliasedInterface() { $container = new ContainerBuilder(); diff --git a/src/Symfony/Component/DependencyInjection/Tests/Compiler/RegisterServiceSubscribersPassTest.php b/src/Symfony/Component/DependencyInjection/Tests/Compiler/RegisterServiceSubscribersPassTest.php index 0f8fff4eed26f..ba979be80bc04 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Compiler/RegisterServiceSubscribersPassTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Compiler/RegisterServiceSubscribersPassTest.php @@ -463,7 +463,7 @@ public static function getSubscribedServices(): array 'autowired.nullable' => new ServiceClosureArgument(new Reference('service.id', ContainerInterface::NULL_ON_INVALID_REFERENCE)), 'autowired.parameter' => new ServiceClosureArgument('foobar'), 'map.decorated' => new ServiceClosureArgument(new Reference('.service_locator.oZHAdom.inner', ContainerInterface::NULL_ON_INVALID_REFERENCE)), - 'target' => new ServiceClosureArgument(new TypedReference('stdClass', 'stdClass', ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE, 'someTarget')), + 'target' => new ServiceClosureArgument(new TypedReference('stdClass', 'stdClass', ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE, 'someTarget', [new Target('someTarget')])), ]; $this->assertEquals($expected, $container->getDefinition((string) $locator->getFactory()[0])->getArgument(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