Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 69677cf

Browse files
[DI] fix auto-binding service providers to their service subscribers
1 parent 624f2e3 commit 69677cf

File tree

3 files changed

+46
-1
lines changed

3 files changed

+46
-1
lines changed

src/Symfony/Component/DependencyInjection/Compiler/RegisterServiceSubscribersPass.php

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,14 @@
1111

1212
namespace Symfony\Component\DependencyInjection\Compiler;
1313

14+
use Psr\Container\ContainerInterface as PsrContainerInterface;
15+
use Symfony\Component\DependencyInjection\Argument\BoundArgument;
1416
use Symfony\Component\DependencyInjection\ContainerInterface;
1517
use Symfony\Component\DependencyInjection\Definition;
1618
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
1719
use Symfony\Component\DependencyInjection\Reference;
1820
use Symfony\Component\DependencyInjection\TypedReference;
21+
use Symfony\Contracts\Service\ServiceProviderInterface;
1922
use Symfony\Contracts\Service\ServiceSubscriberInterface;
2023

2124
/**
@@ -105,7 +108,14 @@ protected function processValue($value, $isRoot = false)
105108
throw new InvalidArgumentException(sprintf('Service %s not exist in the map returned by "%s::getSubscribedServices()" for service "%s".', $message, $class, $this->currentId));
106109
}
107110

108-
$value->addTag('container.service_subscriber.locator', ['id' => (string) ServiceLocatorTagPass::register($this->container, $subscriberMap, $this->currentId)]);
111+
$locatorRef = ServiceLocatorTagPass::register($this->container, $subscriberMap, $this->currentId);
112+
113+
$value->addTag('container.service_subscriber.locator', ['id' => (string) $locatorRef]);
114+
115+
$value->setBindings([
116+
PsrContainerInterface::class => new BoundArgument($locatorRef, false),
117+
ServiceProviderInterface::class => new BoundArgument($locatorRef, false),
118+
] + $value->getBindings());
109119

110120
return parent::processValue($value);
111121
}

src/Symfony/Component/DependencyInjection/Tests/Compiler/RegisterServiceSubscribersPassTest.php

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument;
1717
use Symfony\Component\DependencyInjection\Compiler\AutowirePass;
1818
use Symfony\Component\DependencyInjection\Compiler\RegisterServiceSubscribersPass;
19+
use Symfony\Component\DependencyInjection\Compiler\ResolveBindingsPass;
1920
use Symfony\Component\DependencyInjection\Compiler\ResolveServiceSubscribersPass;
2021
use Symfony\Component\DependencyInjection\ContainerBuilder;
2122
use Symfony\Component\DependencyInjection\ContainerInterface;
@@ -235,4 +236,33 @@ public static function getSubscribedServices()
235236
];
236237
$this->assertEquals($expected, $container->getDefinition((string) $locator->getFactory()[0])->getArgument(0));
237238
}
239+
240+
public function testBinding()
241+
{
242+
$container = new ContainerBuilder();
243+
244+
$container->register('foo', TestServiceSubscriber::class)
245+
->addMethodCall('setServiceProvider')
246+
->addTag('container.service_subscriber')
247+
;
248+
249+
(new RegisterServiceSubscribersPass())->process($container);
250+
(new ResolveBindingsPass())->process($container);
251+
252+
$foo = $container->getDefinition('foo');
253+
$locator = $container->getDefinition((string) $foo->getMethodCalls()[0][1][0]);
254+
255+
$this->assertFalse($locator->isPublic());
256+
$this->assertSame(ServiceLocator::class, $locator->getClass());
257+
258+
$expected = [
259+
TestServiceSubscriber::class => new ServiceClosureArgument(new TypedReference(TestServiceSubscriber::class, TestServiceSubscriber::class)),
260+
CustomDefinition::class => new ServiceClosureArgument(new TypedReference(CustomDefinition::class, CustomDefinition::class, ContainerInterface::IGNORE_ON_INVALID_REFERENCE)),
261+
'bar' => new ServiceClosureArgument(new TypedReference(CustomDefinition::class, CustomDefinition::class, ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE, 'bar')),
262+
'baz' => new ServiceClosureArgument(new TypedReference(CustomDefinition::class, CustomDefinition::class, ContainerInterface::IGNORE_ON_INVALID_REFERENCE, 'baz')),
263+
];
264+
265+
$this->assertEquals($expected, $container->getDefinition((string) $locator->getFactory()[0])->getArgument(0));
266+
}
267+
238268
}

src/Symfony/Component/DependencyInjection/Tests/Fixtures/TestServiceSubscriber.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
namespace Symfony\Component\DependencyInjection\Tests\Fixtures;
44

5+
use Symfony\Contracts\Service\ServiceProviderInterface;
56
use Symfony\Contracts\Service\ServiceSubscriberInterface;
67

78
class TestServiceSubscriber implements ServiceSubscriberInterface
@@ -10,6 +11,10 @@ public function __construct($container)
1011
{
1112
}
1213

14+
public function setServiceProvider(ServiceProviderInterface $container)
15+
{
16+
}
17+
1318
public static function getSubscribedServices()
1419
{
1520
return [

0 commit comments

Comments
 (0)