From 6c2ceb0c44ab4a6de36de31c4192e2aa30de4b30 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Mon, 16 Dec 2019 19:31:23 +0100 Subject: [PATCH] [DI] fix auto-binding service providers to their service subscribers --- .../RegisterServiceSubscribersPass.php | 12 +++++++- .../RegisterServiceSubscribersPassTest.php | 29 +++++++++++++++++++ .../Tests/Fixtures/TestServiceSubscriber.php | 5 ++++ 3 files changed, 45 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Component/DependencyInjection/Compiler/RegisterServiceSubscribersPass.php b/src/Symfony/Component/DependencyInjection/Compiler/RegisterServiceSubscribersPass.php index aeb96418112c9..14bf000863c9d 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/RegisterServiceSubscribersPass.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/RegisterServiceSubscribersPass.php @@ -11,11 +11,14 @@ namespace Symfony\Component\DependencyInjection\Compiler; +use Psr\Container\ContainerInterface as PsrContainerInterface; +use Symfony\Component\DependencyInjection\Argument\BoundArgument; use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\DependencyInjection\Definition; use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; use Symfony\Component\DependencyInjection\Reference; use Symfony\Component\DependencyInjection\TypedReference; +use Symfony\Contracts\Service\ServiceProviderInterface; use Symfony\Contracts\Service\ServiceSubscriberInterface; /** @@ -105,7 +108,14 @@ protected function processValue($value, $isRoot = false) throw new InvalidArgumentException(sprintf('Service %s not exist in the map returned by "%s::getSubscribedServices()" for service "%s".', $message, $class, $this->currentId)); } - $value->addTag('container.service_subscriber.locator', ['id' => (string) ServiceLocatorTagPass::register($this->container, $subscriberMap, $this->currentId)]); + $locatorRef = ServiceLocatorTagPass::register($this->container, $subscriberMap, $this->currentId); + + $value->addTag('container.service_subscriber.locator', ['id' => (string) $locatorRef]); + + $value->setBindings([ + PsrContainerInterface::class => new BoundArgument($locatorRef, false), + ServiceProviderInterface::class => new BoundArgument($locatorRef, false), + ] + $value->getBindings()); return parent::processValue($value); } diff --git a/src/Symfony/Component/DependencyInjection/Tests/Compiler/RegisterServiceSubscribersPassTest.php b/src/Symfony/Component/DependencyInjection/Tests/Compiler/RegisterServiceSubscribersPassTest.php index e78d468d66d90..212bd11ec01a4 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Compiler/RegisterServiceSubscribersPassTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Compiler/RegisterServiceSubscribersPassTest.php @@ -16,6 +16,7 @@ use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument; use Symfony\Component\DependencyInjection\Compiler\AutowirePass; use Symfony\Component\DependencyInjection\Compiler\RegisterServiceSubscribersPass; +use Symfony\Component\DependencyInjection\Compiler\ResolveBindingsPass; use Symfony\Component\DependencyInjection\Compiler\ResolveServiceSubscribersPass; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\ContainerInterface; @@ -235,4 +236,32 @@ public static function getSubscribedServices() ]; $this->assertEquals($expected, $container->getDefinition((string) $locator->getFactory()[0])->getArgument(0)); } + + public function testBinding() + { + $container = new ContainerBuilder(); + + $container->register('foo', TestServiceSubscriber::class) + ->addMethodCall('setServiceProvider') + ->addTag('container.service_subscriber') + ; + + (new RegisterServiceSubscribersPass())->process($container); + (new ResolveBindingsPass())->process($container); + + $foo = $container->getDefinition('foo'); + $locator = $container->getDefinition((string) $foo->getMethodCalls()[0][1][0]); + + $this->assertFalse($locator->isPublic()); + $this->assertSame(ServiceLocator::class, $locator->getClass()); + + $expected = [ + TestServiceSubscriber::class => new ServiceClosureArgument(new TypedReference(TestServiceSubscriber::class, TestServiceSubscriber::class)), + CustomDefinition::class => new ServiceClosureArgument(new TypedReference(CustomDefinition::class, CustomDefinition::class, ContainerInterface::IGNORE_ON_INVALID_REFERENCE)), + 'bar' => new ServiceClosureArgument(new TypedReference(CustomDefinition::class, CustomDefinition::class, ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE, 'bar')), + 'baz' => new ServiceClosureArgument(new TypedReference(CustomDefinition::class, CustomDefinition::class, ContainerInterface::IGNORE_ON_INVALID_REFERENCE, 'baz')), + ]; + + $this->assertEquals($expected, $container->getDefinition((string) $locator->getFactory()[0])->getArgument(0)); + } } diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/TestServiceSubscriber.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/TestServiceSubscriber.php index 7fc3842af3a49..e040dec0a945e 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/TestServiceSubscriber.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/TestServiceSubscriber.php @@ -2,6 +2,7 @@ namespace Symfony\Component\DependencyInjection\Tests\Fixtures; +use Symfony\Contracts\Service\ServiceProviderInterface; use Symfony\Contracts\Service\ServiceSubscriberInterface; class TestServiceSubscriber implements ServiceSubscriberInterface @@ -10,6 +11,10 @@ public function __construct($container) { } + public function setServiceProvider(ServiceProviderInterface $container) + { + } + public static function getSubscribedServices() { return [ 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