Skip to content

Commit 6c2ceb0

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

File tree

3 files changed

+45
-1
lines changed

3 files changed

+45
-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: 29 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,32 @@ 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+
}
238267
}

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)
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