From 93f181d8b32a3aeec0a25845cd07b22a80efd2a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9o=20FIDRY?= Date: Mon, 2 Jan 2017 13:35:05 +0000 Subject: [PATCH 1/3] Add interface FQCN as a valid service name to avoid collisions --- .../Compiler/AutowirePass.php | 8 +++-- .../Tests/Compiler/AutowirePassTest.php | 32 +++++++++++++++++++ 2 files changed, 38 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Component/DependencyInjection/Compiler/AutowirePass.php b/src/Symfony/Component/DependencyInjection/Compiler/AutowirePass.php index 7aa2d2a64e80d..8817cd19fb770 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/AutowirePass.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/AutowirePass.php @@ -338,11 +338,15 @@ private function set($type, $id) */ private function createAutowiredDefinition(\ReflectionClass $typeHint, $id) { - if (isset($this->ambiguousServiceTypes[$typeHint->name])) { + if (isset($this->ambiguousServiceTypes[$typeHintName = $typeHint->name])) { + if ($this->container->has($typeHintName)) { + return new Reference($typeHintName); + } + $classOrInterface = $typeHint->isInterface() ? 'interface' : 'class'; $matchingServices = implode(', ', $this->ambiguousServiceTypes[$typeHint->name]); - throw new RuntimeException(sprintf('Unable to autowire argument of type "%s" for the service "%s". Multiple services exist for this %s (%s).', $typeHint->name, $id, $classOrInterface, $matchingServices), 1); + throw new RuntimeException(sprintf('Unable to autowire argument of type "%s" for the service "%s". Multiple services exist for this %s (%s).', $typeHintName, $id, $classOrInterface, $matchingServices)); } if (!$typeHint->isInstantiable()) { diff --git a/src/Symfony/Component/DependencyInjection/Tests/Compiler/AutowirePassTest.php b/src/Symfony/Component/DependencyInjection/Tests/Compiler/AutowirePassTest.php index 0b8ab9374afe4..a0763954790e4 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Compiler/AutowirePassTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Compiler/AutowirePassTest.php @@ -119,6 +119,28 @@ public function testTypeCollision() $pass->process($container); } + public function testTypeCollisionWithInterfaceAsServiceId() + { + $container = new ContainerBuilder(); + + $container->register('c1', __NAMESPACE__.'\CollisionA'); + $container->register('c2', __NAMESPACE__.'\CollisionB'); + $container->register('c3', __NAMESPACE__.'\CollisionB'); + + $container->register(__NAMESPACE__.'\CollisionInterface', 'c3'); + + $aDefinition = $container->register('a', __NAMESPACE__.'\AutowiredInterface'); + $aDefinition->setAutowired(true); + + $pass = new AutowirePass(); + $pass->process($container); + + $aDefinition = $container->getDefinition('a'); + + $this->assertCount(1, $aDefinition->getArguments()); + $this->assertEquals(new Reference(__NAMESPACE__.'\CollisionInterface'), $aDefinition->getArgument(0)); + } + /** * @expectedException \Symfony\Component\DependencyInjection\Exception\RuntimeException * @expectedExceptionMessage Unable to autowire argument of type "Symfony\Component\DependencyInjection\Tests\Compiler\Foo" for the service "a". Multiple services exist for this class (a1, a2). @@ -656,6 +678,16 @@ public function __construct(CollisionInterface $collision) } } +class AutowiredInterface +{ + public $collision; + + public function __construct(CollisionInterface $collision) + { + $this->collision = $collision; + } +} + class Lille { } From 6a8306f68133d829c91ca8e6dbc3ec9a34c80a3a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9o=20FIDRY?= Date: Tue, 3 Jan 2017 09:18:31 +0000 Subject: [PATCH 2/3] Address comments --- .../DependencyInjection/Compiler/AutowirePass.php | 8 ++++---- .../Tests/Compiler/AutowirePassTest.php | 10 +++++----- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/Symfony/Component/DependencyInjection/Compiler/AutowirePass.php b/src/Symfony/Component/DependencyInjection/Compiler/AutowirePass.php index 8817cd19fb770..afecb46483dc5 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/AutowirePass.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/AutowirePass.php @@ -338,15 +338,15 @@ private function set($type, $id) */ private function createAutowiredDefinition(\ReflectionClass $typeHint, $id) { - if (isset($this->ambiguousServiceTypes[$typeHintName = $typeHint->name])) { - if ($this->container->has($typeHintName)) { - return new Reference($typeHintName); + if (isset($this->ambiguousServiceTypes[$typeHint->name])) { + if ($this->container->has($typeHint->name)) { + return new Reference($typeHint->name); } $classOrInterface = $typeHint->isInterface() ? 'interface' : 'class'; $matchingServices = implode(', ', $this->ambiguousServiceTypes[$typeHint->name]); - throw new RuntimeException(sprintf('Unable to autowire argument of type "%s" for the service "%s". Multiple services exist for this %s (%s).', $typeHintName, $id, $classOrInterface, $matchingServices)); + throw new RuntimeException(sprintf('Unable to autowire argument of type "%s" for the service "%s". Multiple services exist for this %s (%s).', $typeHint->name, $id, $classOrInterface, $matchingServices)); } if (!$typeHint->isInstantiable()) { diff --git a/src/Symfony/Component/DependencyInjection/Tests/Compiler/AutowirePassTest.php b/src/Symfony/Component/DependencyInjection/Tests/Compiler/AutowirePassTest.php index a0763954790e4..79e7e3431b0c1 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Compiler/AutowirePassTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Compiler/AutowirePassTest.php @@ -123,13 +123,13 @@ public function testTypeCollisionWithInterfaceAsServiceId() { $container = new ContainerBuilder(); - $container->register('c1', __NAMESPACE__.'\CollisionA'); - $container->register('c2', __NAMESPACE__.'\CollisionB'); - $container->register('c3', __NAMESPACE__.'\CollisionB'); + $container->register('c1', CollisionA::class); + $container->register('c2', CollisionB::class); + $container->register('c3', CollisionB::class); - $container->register(__NAMESPACE__.'\CollisionInterface', 'c3'); + $container->register(CollisionInterface::class, 'c3'); - $aDefinition = $container->register('a', __NAMESPACE__.'\AutowiredInterface'); + $aDefinition = $container->register('a', AutowiredInterface::class); $aDefinition->setAutowired(true); $pass = new AutowirePass(); From 24d3ff4fcd9916f38a936ef62a2192c534256630 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9o=20FIDRY?= Date: Fri, 6 Jan 2017 10:01:13 +0000 Subject: [PATCH 3/3] Revert the change to the exception --- .../Component/DependencyInjection/Compiler/AutowirePass.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/DependencyInjection/Compiler/AutowirePass.php b/src/Symfony/Component/DependencyInjection/Compiler/AutowirePass.php index afecb46483dc5..cea19ddfa0cc6 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/AutowirePass.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/AutowirePass.php @@ -346,7 +346,7 @@ private function createAutowiredDefinition(\ReflectionClass $typeHint, $id) $classOrInterface = $typeHint->isInterface() ? 'interface' : 'class'; $matchingServices = implode(', ', $this->ambiguousServiceTypes[$typeHint->name]); - throw new RuntimeException(sprintf('Unable to autowire argument of type "%s" for the service "%s". Multiple services exist for this %s (%s).', $typeHint->name, $id, $classOrInterface, $matchingServices)); + throw new RuntimeException(sprintf('Unable to autowire argument of type "%s" for the service "%s". Multiple services exist for this %s (%s).', $typeHint->name, $id, $classOrInterface, $matchingServices), 1); } if (!$typeHint->isInstantiable()) {