8000 [DI] [CompilerPass] [AutoWire] : fix order service definition problem · symfony/symfony@955a4b9 · GitHub
[go: up one dir, main page]

Skip to content

Commit 955a4b9

Browse files
committed
[DI] [CompilerPass] [AutoWire] : fix order service definition problem
1 parent a0e654d commit 955a4b9

File tree

2 files changed

+129
-2
lines changed

2 files changed

+129
-2
lines changed

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

Lines changed: 38 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ class AutowirePass implements CompilerPassInterface
2929
private $types;
3030
private $notGuessableTypes = array();
3131
private $usedTypes = array();
32+
private $secondPassDefinitions = array();
3233

3334
/**
3435
* {@inheritdoc}
@@ -46,6 +47,10 @@ public function process(ContainerBuilder $container)
4647
}
4748
}
4849

50+
foreach ($this->secondPassDefinitions as $id => $definition) {
51+
$this->completeDefinition($id, $definition);
52+
}
53+
4954
foreach ($this->usedTypes as $type => $id) {
5055
if (isset($this->usedTypes[$type]) && isset($this->notGuessableTypes[$type])) {
5156
$classOrInterface = class_exists($type) ? 'class' : 'interface';
@@ -67,6 +72,7 @@ public function process(ContainerBuilder $container)
6772
$this->types = null;
6873
$this->notGuessableTypes = array();
6974
$this->usedTypes = array();
75+
$this->secondPassDefinitions = array();
7076

7177
if (isset($e)) {
7278
throw $e;
@@ -94,7 +100,8 @@ private function completeDefinition($id, Definition $definition)
94100
}
95101

96102
$arguments = $definition->getArguments();
97-
foreach ($constructor->getParameters() as $index => $parameter) {
103+
$parameters = $this->getPriorityToInstantiableParameters($constructor->getParameters());
104+
foreach ($parameters as $index => $parameter) {
98105
if (array_key_exists($index, $arguments) && '' !== $arguments[$index]) {
99106
continue;
100107
}
@@ -131,7 +138,11 @@ private function completeDefinition($id, Definition $definition)
131138
} elseif ($parameter->isDefaultValueAvailable()) {
132139
$value = $parameter->getDefaultValue();
133140
} else {
134-
throw $e;
141+
if (isset($this->secondPassDefinitions[$id])) {
142+
throw $e;
143+
}
144+
$this->secondPassDefinitions[$id] = $definition;
145+
return;
135146
}
136147
}
137148
}
@@ -299,4 +310,29 @@ private function getReflectionClass($id, Definition $definition)
299310

300311
return $this->reflectionClasses[$id] = $reflector;
301312
}
313+
314+
/**
315+
* Priority for Instantiable parameters
316+
*
317+
* @param array $parameters
318+
* @return array
319+
*/
320+
private function getPriorityToInstantiableParameters(array $parameters)
321+
{
322+
$result = array();
323+
324+
foreach ($parameters as $index => $parameter) {
325+
try {
326+
if (($typeHint = $parameter->getClass()) && $typeHint->isInstantiable()) {
327+
$result = array($index => $parameter) + $result;
328+
} else {
329+
$result = $result + array($index => $parameter);
330+
}
331+
} catch (\Exception $e) {
332+
$result = $result + array($index => $parameter);
333+
}
334+
}
335+
336+
return $result;
337+
}
302338
}

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

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -486,6 +486,75 @@ public function provideAutodiscoveredAutowiringOrder()
486486
array('CannotBeAutowiredReverseOrder'),
487487
);
488488
}
489+
490+
public function testAutoDiscoverWithAnyOrderParameters()
491+
{
492+
$container = new ContainerBuilder();
493+
$container->register('a', __NAMESPACE__.'\\'.'Jordan')
494+
->setAutowired(true);
495+
496+
$pass = new AutowirePass();
497+
$pass->process($container);
498+
499+
$this->assertTrue($container->hasDefinition('a'));
500+
501+
$this->assertEquals(
502+
array(
503+
new Reference('autowired.symfony\component\dependencyinjection\tests\compiler\i'),
504+
new Reference('autowired.symfony\component\dependencyinjection\tests\compiler\i'),
505+
new Reference('autowired.symfony\component\dependencyinjection\tests\compiler\d'),
506+
new Reference('autowired.symfony\component\dependencyinjection\tests\compiler\j'),
507+
new Reference('autowired.symfony\component\dependencyinjection\tests\compiler\d'),
508+
new Reference('autowired.symfony\component\dependencyinjection\tests\compiler\j'),
509+
),
510+
$container->getDefinition('a')->getArguments()
511+
);
512+
}
513+
514+
public function testAutoDiscoverWithAnyOrderServices()
515+
{
516+
$container = new ContainerBuilder();
517+
$container->register('montreal', __NAMESPACE__.'\\'.'Montreal')
518+
->setAutowired(true);
519+
$container->register('paris', __NAMESPACE__.'\\'.'Paris')
520+
->setAutowired(true);
521+
522+
$pass = new AutowirePass();
523+
$pass->process($container);
524+
525+
$this->assertTrue($container->hasDefinition('montreal'));
526+
$this->assertTrue($container->hasDefinition('paris'));
527+
528+
$this->assertEquals(
529+
array(
530+
new Reference('autowired.symfony\component\dependencyinjection\tests\compiler\j'),
531+
new Reference('autowired.symfony\component\dependencyinjection\tests\compiler\d'),
532+
new Reference('autowired.symfony\component\dependencyinjection\tests\compiler\d'),
533+
),
534+
$container->getDefinition('montreal')->getArguments()
535+
);
536+
537+
$this->assertEquals(
538+
array(
539+
new Reference('autowired.symfony\component\dependencyinjection\tests\compiler\j'),
540+
),
541+
$container->getDefinition('paris')->getArguments()
542+
);
543+
}
544+
}
545+
546+
class Montreal
547+
{
548+
public function __construct(JInterface $j, DInterface $d, D $d2)
549+
{
550+
}
551+
}
552+
553+
class Paris
554+
{
555+
public function __construct(J $j)
556+
{
557+
}
489558
}
490559

491560
class Foo
@@ -522,6 +591,10 @@ interface EInterface extends DInterface
522591
{
523592
}
524593

594+
interface JInterface
595+
{
596+
}
597+
525598
interface IInterface
526599
{
527600
}
@@ -548,6 +621,24 @@ public function __construct(B $b, DInterface $d)
548621
}
549622
}
550623

624+
class D implements DInterface
625+
{
626+
627+
}
628+
629+
class J implements JInterface
630+
{
631+
632+
}
633+
634+
class Jordan
635+
{
636+
public function __construct(IInterface $i, I $i2, DInterface $d, JInterface $j, D $d2, J $j2)
637+
{
638+
}
639+
}
640+
641+
551642
interface CollisionInterface
552643
{
553644
}

0 commit comments

Comments
 (0)
0