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

Skip to content

Commit 3cfd04b

Browse files
committed
bug #21665 [DependencyInjection] Fix autowiring collisions detection (nicolas-grekas, GuilhemN)
This PR was merged into the 2.8 branch. Discussion ---------- [DependencyInjection] Fix autowiring collisions detection | Q | A | ------------- | --- | Branch? | 2.8 | Bug fix? | yes | New feature? | no | BC breaks? | no | Deprecations? | no | Tests pass? | yes | Fixed tickets | - | License | MIT | Doc PR | Fixes #21658 by implementing the second proposal of #21658 (comment): > Another idea: store the types used previously and check that new services registered don't implement them. Commits ------- bb70472 [DependencyInjection] Fix autowiring collisions detection 6f578ee [DI] Bug in autowiring collisions detection
2 parents 0e1596d + bb70472 commit 3cfd04b

File tree

2 files changed

+52
-0
lines changed

2 files changed

+52
-0
lines changed

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

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ class AutowirePass implements CompilerPassInterface
2828
private $definedTypes = array();
2929
private $types;
3030
private $notGuessableTypes = array();
31+
private $usedTypes = array();
3132

3233
/**
3334
* {@inheritdoc}
@@ -44,6 +45,15 @@ public function process(ContainerBuilder $container)
4445
$this->completeDefinition($id, $definition);
4546
}
4647
}
48+
49+
foreach ($this->usedTypes as $type => $id) {
50+
if (isset($this->usedTypes[$type]) && isset($this->notGuessableTypes[$type])) {
51+
$classOrInterface = class_exists($type) ? 'class' : 'interface';
52+
$matchingServices = implode(', ', $this->types[$type]);
53+
54+
throw new RuntimeException(sprintf('Unable to autowire argument of type "%s" for the service "%s". Multiple services exist for this %s (%s).', $type, $id, $classOrInterface, $matchingServices));
55+
}
56+
}
4757
} catch (\Exception $e) {
4858
} catch (\Throwable $e) {
4959
}
@@ -56,6 +66,7 @@ public function process(ContainerBuilder $container)
5666
$this->definedTypes = array();
5767
$this->types = null;
5868
$this->notGuessableTypes = array();
69+
$this->usedTypes = array();
5970

6071
if (isset($e)) {
6172
throw $e;
@@ -109,9 +120,11 @@ private function completeDefinition($id, Definition $definition)
109120

110121
if (isset($this->types[$typeHint->name]) && !isset($this->notGuessableTypes[$typeHint->name])) {
111122
$value = new Reference($this->types[$typeHint->name]);
123+
$this->usedTypes[$typeHint->name] = $id;
112124
} else {
113125
try {
114126
$value = $this->createAutowiredDefinition($typeHint, $id);
127+
$this->usedTypes[$typeHint->name] = $id;
115128
} catch (RuntimeException $e) {
116129
if ($parameter->allowsNull()) {
117130
$value = null;

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

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -459,6 +459,31 @@ public function testEmptyStringIsKept()
459459

460460
$this->assertEquals(array(new Reference('a'), '', new Reference('lille')), $container->getDefinition('foo')->getArguments());
461461
}
462+
463+
/**
464+
* @dataProvider provideAutodiscoveredAutowiringOrder
465+
*
466+
* @expectedException \Symfony\Component\DependencyInjection\Exception\RuntimeException
467+
* @expectedExceptionMEssage Unable to autowire argument of type "Symfony\Component\DependencyInjection\Tests\Compiler\CollisionInterface" for the service "a". Multiple services exist for this interface (autowired.Symfony\Component\DependencyInjection\Tests\Compiler\CollisionA, autowired.Symfony\Component\DependencyInjection\Tests\Compiler\CollisionB).
468+
*/
469+
public function testAutodiscoveredAutowiringOrder($class)
470+
{
471+
$container = new ContainerBuilder();
472+
473+
$container->register('a', __NAMESPACE__.'\\'.$class)
474+
->setAutowired(true);
475+
476+
$pass = new AutowirePass();
477+
$pass->process($container);
478+
}
479+
480+
public function provideAutodiscoveredAutowiringOrder()
481+
{
482+
return array(
483+
array('CannotBeAutowiredForwardOrder'),
484+
array('CannotBeAutowiredReverseOrder'),
485+
);
486+
}
462487
}
463488

464489
class Foo
@@ -540,6 +565,20 @@ public function __construct(CollisionInterface $collision)
540565
}
541566
}
542567

568+
class CannotBeAutowiredForwardOrder
569+
{
570+
public function __construct(CollisionA $a, CollisionInterface $b, CollisionB $c)
571+
{
572+
}
573+
}
574+
575+
class CannotBeAutowiredReverseOrder
576+
{
577+
public function __construct(CollisionA $a, CollisionB $c, CollisionInterface $b)
578+
{
579+
}
580+
}
581+
543582
class Lille
544583
{
545584
}

0 commit comments

Comments
 (0)