10000 [DI] [CompilerPass] [AutoWire] : fix order service definition problem · symfony/symfony@8eb5053 · GitHub
[go: up one dir, main page]

Skip to content

Commit 8eb5053

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

File tree

2 files changed

+128
-2
lines changed

2 files changed

+128
-2
lines changed

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

Lines changed: 40 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,12 @@ 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+
146+
return;
135147
}
136148
}
137149
}
@@ -299,4 +311,30 @@ private function getReflectionClass($id, Definition $definition)
299311

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

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

Lines changed: 88 additions & 0 deletions
486
Original file line numberDiff line numberDiff line change
@@ -486,6 +486,75 @@ public function provideAutodiscoveredAutowiringOrder()
486
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+< F438 div class="diff-text-inner"> );
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,21 @@ public function __construct(B $b, DInterface $d)
548621
}
549622
}
550623

624+
class D implements DInterface
625+
{
626+
}
627+
628+
class J implements JInterface
629+
{
630+
}
631+
632< 77D5 code class="diff-text syntax-highlighted-line addition">+
class Jordan
633+
{
634+
public function __construct(IInterface $i, I $i2, DInterface $d, JInterface $j, D $d2, J $j2)
635+
{
636+
}
637+
}
638+
551639
interface CollisionInterface
552640
{
553641
}

0 commit comments

Comments
 (0)
0