From 4bc6bedfdb21f8de6cfcfd9860aa10490a321b95 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Tamarelle?= Date: Thu, 21 Mar 2024 18:35:14 +0100 Subject: [PATCH] Deprecate #[TaggedIterator] and #[TaggedLocator] --- UPGRADE-7.1.md | 1 + .../Attribute/TaggedIterator.php | 4 ++ .../Attribute/TaggedLocator.php | 4 ++ .../Tests/Compiler/IntegrationTest.php | 5 -- .../RegisterServiceSubscribersPassTest.php | 55 +++++++++++++++---- .../Fixtures/MultipleArgumentBindings.php | 15 ----- .../Fixtures/TaggedConsumerWithExclude.php | 8 +-- ...IteratorConsumerWithDefaultIndexMethod.php | 4 +- ...ndexMethodAndWithDefaultPriorityMethod.php | 4 +- ...ratorConsumerWithDefaultPriorityMethod.php | 4 +- .../Fixtures/TaggedLocatorConsumerFactory.php | 4 +- ...dLocatorConsumerWithDefaultIndexMethod.php | 3 +- ...ndexMethodAndWithDefaultPriorityMethod.php | 4 +- ...catorConsumerWithDefaultPriorityMethod.php | 3 +- ...edLocatorConsumerWithServiceSubscriber.php | 4 +- .../TaggedLocatorConsumerWithoutIndex.php | 4 +- .../includes/autowiring_classes_80.php | 8 +-- ...sterControllerArgumentLocatorsPassTest.php | 53 +++++++++++++++--- 18 files changed, 123 insertions(+), 64 deletions(-) delete mode 100644 src/Symfony/Component/DependencyInjection/Tests/Fixtures/MultipleArgumentBindings.php diff --git a/UPGRADE-7.1.md b/UPGRADE-7.1.md index 5c0e445ea1cc6..52e82191346fa 100644 --- a/UPGRADE-7.1.md +++ b/UPGRADE-7.1.md @@ -15,6 +15,7 @@ DependencyInjection ------------------- * [BC BREAK] When used in the `prependExtension()` method, the `ContainerConfigurator::import()` method now prepends the configuration instead of appending it + * Deprecate `#[TaggedIterator]` and `#[TaggedLocator]` attributes, use `#[AutowireIterator]` and `#[AutowireLocator]` instead DoctrineBridge -------------- diff --git a/src/Symfony/Component/DependencyInjection/Attribute/TaggedIterator.php b/src/Symfony/Component/DependencyInjection/Attribute/TaggedIterator.php index 60a67f69c1f26..cd558def31f55 100644 --- a/src/Symfony/Component/DependencyInjection/Attribute/TaggedIterator.php +++ b/src/Symfony/Component/DependencyInjection/Attribute/TaggedIterator.php @@ -13,6 +13,8 @@ /** * Autowires an iterator of services based on a tag name. + * + * @deprecated since Symfony 7.1, use {@see AutowireIterator} instead. */ #[\Attribute(\Attribute::TARGET_PARAMETER)] class TaggedIterator extends AutowireIterator @@ -33,6 +35,8 @@ public function __construct( public string|array $exclude = [], public bool $excludeSelf = true, ) { + trigger_deprecation('symfony/dependency-injection', '7.1', 'The "%s" attribute is deprecated, use "%s" instead.', self::class, AutowireIterator::class); + parent::__construct($tag, $indexAttribute, $defaultIndexMethod, $defaultPriorityMethod, $exclude, $excludeSelf); } } diff --git a/src/Symfony/Component/DependencyInjection/Attribute/TaggedLocator.php b/src/Symfony/Component/DependencyInjection/Attribute/TaggedLocator.php index 606394861587f..d122930f56eb8 100644 --- a/src/Symfony/Component/DependencyInjection/Attribute/TaggedLocator.php +++ b/src/Symfony/Component/DependencyInjection/Attribute/TaggedLocator.php @@ -13,6 +13,8 @@ /** * Autowires a locator of services based on a tag name. + * + * @deprecated since Symfony 7.1, use {@see AutowireLocator} instead. */ #[\Attribute(\Attribute::TARGET_PARAMETER)] class TaggedLocator extends AutowireLocator @@ -33,6 +35,8 @@ public function __construct( public string|array $exclude = [], public bool $excludeSelf = true, ) { + trigger_deprecation('symfony/dependency-injection', '7.1', 'The "%s" attribute is deprecated, use "%s" instead.', self::class, AutowireLocator::class); + parent::__construct($tag, $indexAttribute, $defaultIndexMethod, $defaultPriorityMethod, $exclude, $excludeSelf); } } diff --git a/src/Symfony/Component/DependencyInjection/Tests/Compiler/IntegrationTest.php b/src/Symfony/Component/DependencyInjection/Tests/Compiler/IntegrationTest.php index f68b546ab75c7..8d74e817356ab 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Compiler/IntegrationTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Compiler/IntegrationTest.php @@ -58,7 +58,6 @@ use Symfony\Component\DependencyInjection\Tests\Fixtures\TaggedService3Configurator; use Symfony\Component\DependencyInjection\Tests\Fixtures\TaggedService4; use Symfony\Component\DependencyInjection\Tests\Fixtures\TaggedService5; -use Symfony\Contracts\Service\Attribute\SubscribedService; use Symfony\Contracts\Service\ServiceProviderInterface; use Symfony\Contracts\Service\ServiceSubscriberInterface; @@ -395,10 +394,6 @@ public function testTaggedServiceWithIndexAttributeAndDefaultMethod() public function testLocatorConfiguredViaAttribute() { - if (!property_exists(SubscribedService::class, 'type')) { - $this->markTestSkipped('Requires symfony/service-contracts >= 3.2'); - } - $container = new ContainerBuilder(); $container->setParameter('some.parameter', 'foo'); $container->register(BarTagClass::class) diff --git a/src/Symfony/Component/DependencyInjection/Tests/Compiler/RegisterServiceSubscribersPassTest.php b/src/Symfony/Component/DependencyInjection/Tests/Compiler/RegisterServiceSubscribersPassTest.php index fbaef1ce09e5d..9e1d6065587b6 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Compiler/RegisterServiceSubscribersPassTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Compiler/RegisterServiceSubscribersPassTest.php @@ -411,18 +411,12 @@ public static function getSubscribedServices(): array public function testSubscribedServiceWithAttributes() { - if (!property_exists(SubscribedService::class, 'attributes')) { - $this->markTestSkipped('Requires symfony/service-contracts 3.2+'); - } - $container = new ContainerBuilder(); $subscriber = new class() implements ServiceSubscriberInterface { public static function getSubscribedServices(): array { return [ - new SubscribedService('tagged.iterator', 'iterable', attributes: new TaggedIterator('tag')), - new SubscribedService('tagged.locator', PsrContainerInterface::class, attributes: new TaggedLocator('tag')), new SubscribedService('autowired', 'stdClass', attributes: new Autowire(service: 'service.id')), new SubscribedService('autowired.nullable', 'stdClass', nullable: true, attributes: new Autowire(service: 'service.id')), new SubscribedService('autowired.parameter', 'string', attributes: new Autowire('%parameter.1%')), @@ -444,8 +438,6 @@ public static function getSubscribedServices(): array $locator = $container->getDefinition((string) $foo->getMethodCalls()[0][1][0]); $expected = [ - 'tagged.iterator' => new ServiceClosureArgument(new TypedReference('iterable', 'iterable', ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE, 'tagged.iterator', [new TaggedIterator('tag')])), - 'tagged.locator' => new ServiceClosureArgument(new TypedReference(PsrContainerInterface::class, PsrContainerInterface::class, ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE, 'tagged.locator', [new TaggedLocator('tag')])), 'autowired' => new ServiceClosureArgument(new TypedReference('stdClass', 'stdClass', ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE, 'autowired', [new Autowire(service: 'service.id')])), 'autowired.nullable' => new ServiceClosureArgument(new TypedReference('stdClass', 'stdClass', ContainerInterface::IGNORE_ON_INVALID_REFERENCE, 'autowired.nullable', [new Autowire(service: 'service.id')])), 'autowired.parameter' => new ServiceClosureArgument(new TypedReference('string', 'string', ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE, 'autowired.parameter', [new Autowire(service: '%parameter.1%')])), @@ -457,17 +449,58 @@ public static function getSubscribedServices(): array (new AutowirePass())->process($container); $expected = [ - 'tagged.iterator' => new ServiceClosureArgument(new TaggedIteratorArgument('tag')), - 'tagged.locator' => new ServiceClosureArgument(new ServiceLocatorArgument(new TaggedIteratorArgument('tag', 'tag', needsIndexes: true))), 'autowired' => new ServiceClosureArgument(new TypedReference('service.id', 'stdClass', ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE, 'autowired', [new Autowire(service: 'service.id')])), 'autowired.nullable' => new ServiceClosureArgument(new TypedReference('service.id', 'stdClass', ContainerInterface::IGNORE_ON_INVALID_REFERENCE, 'autowired.nullable', [new Autowire(service: 'service.id')])), 'autowired.parameter' => new ServiceClosureArgument('foobar'), - 'autowire.decorated' => new ServiceClosureArgument(new Reference('.service_locator.420ES7z.inner', ContainerInterface::NULL_ON_INVALID_REFERENCE)), + 'autowire.decorated' => new ServiceClosureArgument(new Reference('.service_locator.4qmCWv..inner', ContainerInterface::NULL_ON_INVALID_REFERENCE)), 'target' => new ServiceClosureArgument(new TypedReference('stdClass', 'stdClass', ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE, 'target', [new Target('someTarget')])), ]; $this->assertEquals($expected, $container->getDefinition((string) $locator->getFactory()[0])->getArgument(0)); } + /** + * @group legacy + */ + public function testSubscribedServiceWithLegacyAttributes() + { + $container = new ContainerBuilder(); + + $subscriber = new class() implements ServiceSubscriberInterface { + public static function getSubscribedServices(): array + { + return [ + new SubscribedService('tagged.iterator', 'iterable', attributes: new TaggedIterator('tag')), + new SubscribedService('tagged.locator', PsrContainerInterface::class, attributes: new TaggedLocator('tag')), + ]; + } + }; + + $container->setParameter('parameter.1', 'foobar'); + $container->register('foo', $subscriber::class) + ->addMethodCall('setContainer', [new Reference(PsrContainerInterface::class)]) + ->addTag('container.service_subscriber'); + + (new RegisterServiceSubscribersPass())->process($container); + (new ResolveServiceSubscribersPass())->process($container); + + $foo = $container->getDefinition('foo'); + $locator = $container->getDefinition((string) $foo->getMethodCalls()[0][1][0]); + + $expected = [ + 'tagged.iterator' => new ServiceClosureArgument(new TypedReference('iterable', 'iterable', ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE, 'tagged.iterator', [new TaggedIterator('tag')])), + 'tagged.locator' => new ServiceClosureArgument(new TypedReference(PsrContainerInterface::class, PsrContainerInterface::class, ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE, 'tagged.locator', [new TaggedLocator('tag')])), + ]; + $this->assertEquals($expected, $container->getDefinition((string) $locator->getFactory()[0])->getArgument(0)); + + (new AutowirePass())->process($container); + + $expected = [ + 'tagged.iterator' => new ServiceClosureArgument(new TaggedIteratorArgument('tag')), + 'tagged.locator' => new ServiceClosureArgument(new ServiceLocatorArgument(new TaggedIteratorArgument('tag', 'tag', needsIndexes: true))), + ]; + $this->assertEquals($expected, $container->getDefinition((string) $locator->getFactory()[0])->getArgument(0)); + } + public function testBinding() { $container = new ContainerBuilder(); diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/MultipleArgumentBindings.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/MultipleArgumentBindings.php deleted file mode 100644 index 4442a6bc08c74..0000000000000 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/MultipleArgumentBindings.php +++ /dev/null @@ -1,15 +0,0 @@ - new AutowireDecorated(), - 'iterator' => new TaggedIterator('foo'), - 'locator' => new TaggedLocator('foo'), + 'iterator' => new AutowireIterator('foo'), + 'locator' => new AutowireLocator('foo'), 'service' => new Autowire(service: 'bar') ])] array $options) { diff --git a/src/Symfony/Component/HttpKernel/Tests/DependencyInjection/RegisterControllerArgumentLocatorsPassTest.php b/src/Symfony/Component/HttpKernel/Tests/DependencyInjection/RegisterControllerArgumentLocatorsPassTest.php index e34a808625831..6e261dae7a195 100644 --- a/src/Symfony/Component/HttpKernel/Tests/DependencyInjection/RegisterControllerArgumentLocatorsPassTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/DependencyInjection/RegisterControllerArgumentLocatorsPassTest.php @@ -502,6 +502,9 @@ public function testAutowireAttribute() $this->assertFalse($locator->has('service2')); } + /** + * @group legacy + */ public function testTaggedIteratorAndTaggedLocatorAttributes() { $container = new ContainerBuilder(); @@ -524,16 +527,12 @@ public function testTaggedIteratorAndTaggedLocatorAttributes() /** @var ServiceLocator $locator */ $locator = $container->get($locatorId)->get('foo::fooAction'); - $this->assertCount(6, $locator->getProvidedServices()); + $this->assertCount(2, $locator->getProvidedServices()); $this->assertTrue($locator->has('iterator1')); $this->assertInstanceOf(RewindableGenerator::class, $argIterator = $locator->get('iterator1')); $this->assertCount(2, $argIterator); - $this->assertTrue($locator->has('iterator2')); - $this->assertInstanceOf(RewindableGenerator::class, $argIterator = $locator->get('iterator2')); - $this->assertCount(2, $argIterator); - $this->assertTrue($locator->has('locator1')); $this->assertInstanceOf(ServiceLocator::class, $argLocator = $locator->get('locator1')); $this->assertCount(2, $argLocator); @@ -541,9 +540,38 @@ public function testTaggedIteratorAndTaggedLocatorAttributes() $this->assertTrue($argLocator->has('baz')); $this->assertSame(iterator_to_array($argIterator), [$argLocator->get('bar'), $argLocator->get('baz')]); + } + + public function testAutowireIteratorAndAutowireLocatorAttributes() + { + $container = new ContainerBuilder(); + $container->setParameter('some.parameter', 'bar'); + $resolver = $container->register('argument_resolver.service', \stdClass::class)->addArgument([]); + + $container->register('bar', \stdClass::class)->addTag('foobar'); + $container->register('baz', \stdClass::class)->addTag('foobar'); + + $container->register('foo', WithAutowireIteratorAndAutowireLocator::class) + ->addTag('controller.service_arguments'); + + (new RegisterControllerArgumentLocatorsPass())->process($container); + + $locatorId = (string) $resolver->getArgument(0); + $container->getDefinition($locatorId)->setPublic(true); + + $container->compile(); + + /** @var ServiceLocator $locator */ + $locator = $container->get($locatorId)->get('foo::fooAction'); + + $this->assertCount(4, $locator->getProvidedServices()); - $this->assertTrue($locator->has('locator2')); - $this->assertInstanceOf(ServiceLocator::class, $argLocator = $locator->get('locator2')); + $this->assertTrue($locator->has('iterator1')); + $this->assertInstanceOf(RewindableGenerator::class, $argIterator = $locator->get('iterator1')); + $this->assertCount(2, $argIterator); + + $this->assertTrue($locator->has('locator1')); + $this->assertInstanceOf(ServiceLocator::class, $argLocator = $locator->get('locator1')); $this->assertCount(2, $argLocator); $this->assertTrue($argLocator->has('bar')); $this->assertTrue($argLocator->has('baz')); @@ -724,9 +752,16 @@ class WithTaggedIteratorAndTaggedLocator { public function fooAction( #[TaggedIterator('foobar')] iterable $iterator1, - #[AutowireIterator('foobar')] iterable $iterator2, #[TaggedLocator('foobar')] ServiceLocator $locator1, - #[AutowireLocator('foobar')] ServiceLocator $locator2, + ) { + } +} + +class WithAutowireIteratorAndAutowireLocator +{ + public function fooAction( + #[AutowireIterator('foobar')] iterable $iterator1, + #[AutowireLocator('foobar')] ServiceLocator $locator1, #[AutowireLocator(['bar', 'baz'])] ContainerInterface $container1, #[AutowireLocator(['foo' => new Autowire('%some.parameter%')])] ContainerInterface $container2, ) {