[DependencyInjection] throw proper exception when decorating a synthetic service

This commit is contained in:
Nicolas Grekas 2021-06-22 10:35:27 +02:00
parent 63e42698d9
commit b763a29514
2 changed files with 25 additions and 0 deletions

View File

@ -14,6 +14,7 @@ namespace Symfony\Component\DependencyInjection\Compiler;
use Symfony\Component\DependencyInjection\Alias;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
use Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException;
use Symfony\Component\DependencyInjection\Reference;
@ -59,6 +60,7 @@ class DecoratorServicePass implements CompilerPassInterface
$public = $alias->isPublic();
$private = $alias->isPrivate();
$container->setAlias($renamedId, new Alias((string) $alias, false));
$decoratedDefinition = $container->findDefinition($alias);
} elseif ($container->hasDefinition($inner)) {
$decoratedDefinition = $container->getDefinition($inner);
$public = $decoratedDefinition->isPublic();
@ -72,10 +74,15 @@ class DecoratorServicePass implements CompilerPassInterface
} elseif (ContainerInterface::NULL_ON_INVALID_REFERENCE === $invalidBehavior) {
$public = $definition->isPublic();
$private = $definition->isPrivate();
$decoratedDefinition = null;
} else {
throw new ServiceNotFoundException($inner, $id);
}
if ($decoratedDefinition && $decoratedDefinition->isSynthetic()) {
throw new InvalidArgumentException(sprintf('A synthetic service cannot be decorated: service "%s" cannot decorate "%s".', $id, $inner));
}
if (isset($decoratingDefinitions[$inner])) {
$decoratingDefinition = $decoratingDefinitions[$inner];

View File

@ -16,6 +16,7 @@ use Symfony\Component\DependencyInjection\Alias;
use Symfony\Component\DependencyInjection\Compiler\DecoratorServicePass;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
use Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException;
class DecoratorServicePassTest extends TestCase
@ -262,6 +263,23 @@ class DecoratorServicePassTest extends TestCase
$this->assertEquals(['bar' => ['attr' => 'baz'], 'foobar' => ['attr' => 'bar']], $container->getDefinition('baz')->getTags());
}
public function testCannotDecorateSyntheticService()
{
$container = new ContainerBuilder();
$container
->register('foo')
->setSynthetic(true)
;
$container
->register('baz')
->setDecoratedService('foo')
;
$this->expectException(InvalidArgumentException::class);
$this->expectExceptionMessage('A synthetic service cannot be decorated: service "baz" cannot decorate "foo".');
$this->process($container);
}
protected function process(ContainerBuilder $container)
{
$repeatedPass = new DecoratorServicePass();