From 806d7d5f04f8cf4802151c47893efcfc0273f5ca Mon Sep 17 00:00:00 2001 From: Kevin Bond Date: Sun, 27 Feb 2022 12:08:02 -0500 Subject: [PATCH] [DependencyInjection] add `Service` attribute --- .../DependencyInjection/Attribute/Service.php | 23 +++++++++++++++++++ .../DependencyInjection/CHANGELOG.md | 1 + .../Compiler/AutowirePass.php | 8 +++++++ .../Tests/Compiler/AutowirePassTest.php | 19 +++++++++++++++ .../includes/autowiring_classes_80.php | 8 +++++++ 5 files changed, 59 insertions(+) create mode 100644 src/Symfony/Component/DependencyInjection/Attribute/Service.php diff --git a/src/Symfony/Component/DependencyInjection/Attribute/Service.php b/src/Symfony/Component/DependencyInjection/Attribute/Service.php new file mode 100644 index 0000000000000..569fa5cceaac3 --- /dev/null +++ b/src/Symfony/Component/DependencyInjection/Attribute/Service.php @@ -0,0 +1,23 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Attribute; + +/** + * @author Kevin Bond + */ +#[\Attribute(\Attribute::TARGET_PARAMETER)] +final class Service +{ + public function __construct(public string $id) + { + } +} diff --git a/src/Symfony/Component/DependencyInjection/CHANGELOG.md b/src/Symfony/Component/DependencyInjection/CHANGELOG.md index b2a997ad4f4b6..68e8154cbc36e 100644 --- a/src/Symfony/Component/DependencyInjection/CHANGELOG.md +++ b/src/Symfony/Component/DependencyInjection/CHANGELOG.md @@ -7,6 +7,7 @@ CHANGELOG * Add `$exclude` to `TaggedIterator` and `TaggedLocator` attributes * Add `$exclude` to `tagged_iterator` and `tagged_locator` configurator * Add an `env` function to the expression language provider + * Add a `Service` attribute to explicitly choose the injected service id 6.0 --- diff --git a/src/Symfony/Component/DependencyInjection/Compiler/AutowirePass.php b/src/Symfony/Component/DependencyInjection/Compiler/AutowirePass.php index a6f1dbc5b95be..dba6a910fd96c 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/AutowirePass.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/AutowirePass.php @@ -14,6 +14,7 @@ use Symfony\Component\Config\Resource\ClassExistenceResource; use Symfony\Component\DependencyInjection\Argument\ServiceLocatorArgument; use Symfony\Component\DependencyInjection\Argument\TaggedIteratorArgument; +use Symfony\Component\DependencyInjection\Attribute\Service; use Symfony\Component\DependencyInjection\Attribute\TaggedIterator; use Symfony\Component\DependencyInjection\Attribute\TaggedLocator; use Symfony\Component\DependencyInjection\Attribute\Target; @@ -22,6 +23,7 @@ use Symfony\Component\DependencyInjection\Exception\AutowiringFailedException; use Symfony\Component\DependencyInjection\Exception\RuntimeException; use Symfony\Component\DependencyInjection\LazyProxy\ProxyHelper; +use Symfony\Component\DependencyInjection\Reference; use Symfony\Component\DependencyInjection\TypedReference; /** @@ -256,6 +258,12 @@ private function autowireMethod(\ReflectionFunctionAbstract $reflectionMethod, a $arguments[$index] = new ServiceLocatorArgument(new TaggedIteratorArgument($attribute->tag, $attribute->indexAttribute, $attribute->defaultIndexMethod, true, $attribute->defaultPriorityMethod, (array) $attribute->exclude)); break; } + + if (Service::class === $attribute->getName()) { + $attribute = $attribute->newInstance(); + $arguments[$index] = new Reference($attribute->id); + break; + } } if ('' !== ($arguments[$index] ?? '')) { diff --git a/src/Symfony/Component/DependencyInjection/Tests/Compiler/AutowirePassTest.php b/src/Symfony/Component/DependencyInjection/Tests/Compiler/AutowirePassTest.php index 0dd57a8065748..d23a2ea57a703 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Compiler/AutowirePassTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Compiler/AutowirePassTest.php @@ -1121,4 +1121,23 @@ public function testDecorationWithServiceAndAliasedInterface() static::assertInstanceOf(DecoratedDecorator::class, $container->get(DecoratorInterface::class)); static::assertInstanceOf(DecoratedDecorator::class, $container->get(DecoratorImpl::class)); } + + public function testServiceAttributeParameter() + { + $container = new ContainerBuilder(); + + $container->register(AutowireServiceParameter::class) + ->setAutowired(true) + ; + + $container->register('some.id', \stdClass::class); + + (new ResolveClassPass())->process($container); + (new AutowirePass())->process($container); + + $definition = $container->getDefinition(AutowireServiceParameter::class); + + $this->assertCount(1, $definition->getArguments()); + $this->assertSame('some.id', (string) $definition->getArgument(0)); + } } diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/includes/autowiring_classes_80.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/includes/autowiring_classes_80.php index e22ae85169e5a..07555210886e8 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/includes/autowiring_classes_80.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/includes/autowiring_classes_80.php @@ -2,6 +2,7 @@ namespace Symfony\Component\DependencyInjection\Tests\Compiler; +use Symfony\Component\DependencyInjection\Attribute\Service; use Symfony\Contracts\Service\Attribute\Required; class AutowireSetter @@ -26,3 +27,10 @@ class AutowireProperty #[Required] public Foo $foo; } + +class AutowireServiceParameter +{ + public function __construct(#[Service('some.id')] $service) + { + } +}