bug #35214 [DI] DecoratorServicePass should keep container.service_locator on the decorated definition (malarzm)

This PR was merged into the 4.3 branch.

Discussion
----------

[DI] DecoratorServicePass should keep container.service_locator on the decorated definition

| Q             | A
| ------------- | ---
| Branch?       | 4.3
| Bug fix?      | yes
| New feature?  | no
| Deprecations? | no
| Tickets       | Fix https://github.com/symfony/symfony/pull/33670#issuecomment-569917301
| License       | MIT
| Doc PR        | -

`container.service_locator` is special because it tells how the arguments of the constructor should be interpreted.

/cc @malarzm

Commits
-------

99dab87ada [DI] DecoratorServicePass should keep container.service_locator on the decorated definition
This commit is contained in:
Nicolas Grekas 2020-01-06 13:55:46 +01:00
commit 6fb2d52077
2 changed files with 31 additions and 2 deletions

View File

@ -64,8 +64,18 @@ class DecoratorServicePass implements CompilerPassInterface
if (isset($decoratingDefinitions[$inner])) {
$decoratingDefinition = $decoratingDefinitions[$inner];
$definition->setTags(array_merge($decoratingDefinition->getTags(), $definition->getTags()));
$decoratingDefinition->setTags([]);
$decoratingTags = $decoratingDefinition->getTags();
$resetTags = [];
if (isset($decoratingTags['container.service_locator'])) {
// container.service_locator has special logic and it must not be transferred out to decorators
$resetTags = ['container.service_locator' => $decoratingTags['container.service_locator']];
unset($decoratingTags['container.service_locator']);
}
$definition->setTags(array_merge($decoratingTags, $definition->getTags()));
$decoratingDefinition->setTags($resetTags);
$decoratingDefinitions[$inner] = $definition;
}

View File

@ -167,6 +167,25 @@ class DecoratorServicePassTest extends TestCase
$this->assertEquals(['bar' => ['attr' => 'baz']], $container->getDefinition('deco2')->getTags());
}
public function testProcessLeavesServiceLocatorTagOnOriginalDefinition()
{
$container = new ContainerBuilder();
$container
->register('foo')
->setTags(['container.service_locator' => [0 => []], 'bar' => ['attr' => 'baz']])
;
$container
->register('baz')
->setTags(['foobar' => ['attr' => 'bar']])
->setDecoratedService('foo')
;
$this->process($container);
$this->assertEquals(['container.service_locator' => [0 => []]], $container->getDefinition('baz.inner')->getTags());
$this->assertEquals(['bar' => ['attr' => 'baz'], 'foobar' => ['attr' => 'bar']], $container->getDefinition('baz')->getTags());
}
protected function process(ContainerBuilder $container)
{
$repeatedPass = new DecoratorServicePass();