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

Skip to content

Commit 81cd56f

Browse files
committed
enable union services in ServiceSubscriberInterface
1 parent 0abd898 commit 81cd56f

File tree

3 files changed

+53
-1
lines changed

3 files changed

+53
-1
lines changed

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ protected function processValue($value, bool $isRoot = false)
7272
$subscriberMap = [];
7373

7474
foreach ($class::getSubscribedServices() as $key => $type) {
75-
if (!\is_string($type) || !preg_match('/^\??[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*+(?:\\\\[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*+)*+$/', $type)) {
75+
if (!\is_string($type) || !preg_match('/(?(DEFINE)(?<cn>[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*+))(?(DEFINE)(?<fqcn>(?&cn)(?:\\\\(?&cn))*+))^\??(?&fqcn)(?:(?:\|(?&fqcn))*+|(?:&(?&fqcn))*+)$/', $type)) {
7676
throw new InvalidArgumentException(sprintf('"%s::getSubscribedServices()" must return valid PHP types for service "%s" key "%s", "%s" returned.', $class, $this->currentId, $key, \is_string($type) ? $type : get_debug_type($type)));
7777
}
7878
if ($optionalBehavior = '?' === $type[0]) {

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

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
use Symfony\Component\DependencyInjection\Tests\Fixtures\TestServiceSubscriber;
3333
use Symfony\Component\DependencyInjection\Tests\Fixtures\TestServiceSubscriberChild;
3434
use Symfony\Component\DependencyInjection\Tests\Fixtures\TestServiceSubscriberParent;
35+
use Symfony\Component\DependencyInjection\Tests\Fixtures\TestServiceSubscriberUnion;
3536
use Symfony\Component\DependencyInjection\TypedReference;
3637
use Symfony\Contracts\Service\Attribute\SubscribedService;
3738
use Symfony\Contracts\Service\ServiceSubscriberInterface;
@@ -129,6 +130,36 @@ public function testWithAttributes()
129130
$this->assertEquals($expected, $container->getDefinition((string) $locator->getFactory()[0])->getArgument(0));
130131
}
131132

133+
/**
134+
* @requires PHP 8
135+
*/
136+
public function testUnionServices()
137+
{
138+
$container = new ContainerBuilder();
139+
140+
$container->register('foo', TestServiceSubscriberUnion::class)
141+
->addArgument(new Reference(PsrContainerInterface::class))
142+
->addTag('container.service_subscriber')
143+
;
144+
145+
(new RegisterServiceSubscribersPass())->process($container);
146+
(new ResolveServiceSubscribersPass())->process($container);
147+
148+
$foo = $container->getDefinition('foo');
149+
$locator = $container->getDefinition((string) $foo->getArgument(0));
150+
151+
$this->assertFalse($locator->isPublic());
152+
$this->assertSame(ServiceLocator::class, $locator->getClass());
153+
154+
$expected = [
155+
TestDefinition1::class.'|'.TestDefinition2::class => new ServiceClosureArgument(new TypedReference(TestDefinition1::class.'|'.TestDefinition2::class, TestDefinition1::class.'|'.TestDefinition2::class)),
156+
'bar' => new ServiceClosureArgument(new TypedReference(TestDefinition1::class.'|'.TestDefinition2::class, TestDefinition1::class.'|'.TestDefinition2::class, ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE, 'bar')),
157+
'baz' => new ServiceClosureArgument(new TypedReference(TestDefinition1::class.'|'.TestDefinition2::class, TestDefinition1::class.'|'.TestDefinition2::class, ContainerInterface::IGNORE_ON_INVALID_REFERENCE, 'baz')),
158+
];
159+
160+
$this->assertEquals($expected, $container->getDefinition((string) $locator->getFactory()[0])->getArgument(0));
161+
}
162+
132163
public function testExtraServiceSubscriber()
133164
{
134165
$this->expectException(InvalidArgumentException::class);
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<?php
2+
3+
namespace Symfony\Component\DependencyInjection\Tests\Fixtures;
4+
5+
use Symfony\Contracts\Service\ServiceSubscriberInterface;
6+
7+
class TestServiceSubscriberUnion implements ServiceSubscriberInterface
8+
{
9+
public function __construct($container)
10+
{
11+
}
12+
13+
public static function getSubscribedServices(): array
14+
{
15+
return [
16+
TestDefinition1::class.'|'.TestDefinition2::class,
17+
'bar' => TestDefinition1::class.'|'.TestDefinition2::class,
18+
'baz' => '?'.TestDefinition1::class.'|'.TestDefinition2::class,
19+
];
20+
}
21+
}

0 commit comments

Comments
 (0)