Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 955a4b9

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

File tree

2 files changed

+129
-2
lines changed
Filter options

2 files changed

+129
-2
lines changed

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

Copy file name to clipboardExpand all lines: src/Symfony/Component/DependencyInjection/Compiler/AutowirePass.php
+38-2Lines 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

Copy file name to clipboardExpand all lines: src/Symfony/Component/DependencyInjection/Tests/Compiler/AutowirePassTest.php
+91Lines 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)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.