Skip to content

Commit 68b20be

Browse files
committed
[DependencyInjection] Properly ignore invalid reference arguments in collection arguments
1 parent 38122b2 commit 68b20be

File tree

2 files changed

+62
-4
lines changed

2 files changed

+62
-4
lines changed

Compiler/ResolveInvalidReferencesPass.php

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -71,16 +71,19 @@ public function process(ContainerBuilder $container)
7171
*
7272
* @param array $arguments An array of Reference objects
7373
* @param bool $inMethodCall
74+
* @param bool $inCollection
7475
*
7576
* @return array
7677
*
7778
* @throws RuntimeException When the config is invalid
7879
*/
79-
private function processArguments(array $arguments, $inMethodCall = false)
80+
private function processArguments(array $arguments, $inMethodCall = false, $inCollection = false)
8081
{
82+
$isNumeric = array_keys($arguments) === range(0, count($arguments) - 1);
83+
8184
foreach ($arguments as $k => $argument) {
8285
if (is_array($argument)) {
83-
$arguments[$k] = $this->processArguments($argument, $inMethodCall);
86+
$arguments[$k] = $this->processArguments($argument, $inMethodCall, true);
8487
} elseif ($argument instanceof Reference) {
8588
$id = (string) $argument;
8689

@@ -91,6 +94,10 @@ private function processArguments(array $arguments, $inMethodCall = false)
9194
if (!$exists && ContainerInterface::NULL_ON_INVALID_REFERENCE === $invalidBehavior) {
9295
$arguments[$k] = null;
9396
} elseif (!$exists && ContainerInterface::IGNORE_ON_INVALID_REFERENCE === $invalidBehavior) {
97+
if ($inCollection) {
98+
unset($arguments[$k]);
99+
continue;
100+
}
94101
if ($inMethodCall) {
95102
throw new RuntimeException('Method shouldn\'t be called.');
96103
}
@@ -100,6 +107,11 @@ private function processArguments(array $arguments, $inMethodCall = false)
100107
}
101108
}
102109

110+
// Ensure numerically indexed arguments have sequential numeric keys.
111+
if ($isNumeric) {
112+
$arguments = array_values($arguments);
113+
}
114+
103115
return $arguments;
104116
}
105117
}

Tests/Compiler/ResolveInvalidReferencesPassTest.php

Lines changed: 48 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,17 +23,63 @@ public function testProcess()
2323
$container = new ContainerBuilder();
2424
$def = $container
2525
->register('foo')
26-
->setArguments(array(new Reference('bar', ContainerInterface::NULL_ON_INVALID_REFERENCE)))
26+
->setArguments(array(
27+
new Reference('bar', ContainerInterface::NULL_ON_INVALID_REFERENCE),
28+
new Reference('baz', ContainerInterface::IGNORE_ON_INVALID_REFERENCE),
29+
))
2730
->addMethodCall('foo', array(new Reference('moo', ContainerInterface::IGNORE_ON_INVALID_REFERENCE)))
2831
;
2932

3033
$this->process($container);
3134

3235
$arguments = $def->getArguments();
33-
$this->assertNull($arguments[0]);
36+
$this->assertSame(array(null, null), $arguments);
3437
$this->assertCount(0, $def->getMethodCalls());
3538
}
3639

40+
public function testProcessIgnoreInvalidArgumentInCollectionArgument()
41+
{
42+
$container = new ContainerBuilder();
43+
$container->register('baz');
44+
$def = $container
45+
->register('foo')
46+
->setArguments(array(
47+
array(
48+
new Reference('bar', ContainerInterface::IGNORE_ON_INVALID_REFERENCE),
49+
$baz = new Reference('baz', ContainerInterface::IGNORE_ON_INVALID_REFERENCE),
50+
new Reference('moo', ContainerInterface::NULL_ON_INVALID_REFERENCE),
51+
),
52+
))
53+
;
54+
55+
$this->process($container);
56+
57+
$arguments = $def->getArguments();
58+
$this->assertSame(array($baz, null), $arguments[0]);
59+
}
60+
61+
public function testProcessKeepMethodCallOnInvalidArgumentInCollectionArgument()
62+
{
63+
$container = new ContainerBuilder();
64+
$container->register('baz');
65+
$def = $container
66+
->register('foo')
67+
->addMethodCall('foo', array(
68+
array(
69+
new Reference('bar', ContainerInterface::IGNORE_ON_INVALID_REFERENCE),
70+
$baz = new Reference('baz', ContainerInterface::IGNORE_ON_INVALID_REFERENCE),
71+
new Reference('moo', ContainerInterface::NULL_ON_INVALID_REFERENCE),
72+
),
73+
))
74+
;
75+
76+
$this->process($container);
77+
78+
$calls = $def->getMethodCalls();
79+
$this->assertCount(1, $def->getMethodCalls());
80+
$this->assertSame(array($baz, null), $calls[0][1][0]);
81+
}
82+
3783
public function testProcessIgnoreNonExistentServices()
3884
{
3985
$container = new ContainerBuilder();

0 commit comments

Comments
 (0)