8000 feature #17132 [DependencyInjection] Properly ignore invalid referenc… · symfony/symfony@e9e4869 · GitHub
[go: up one dir, main page]

Skip to content

Commit e9e4869

Browse files
committed
feature #17132 [DependencyInjection] Properly ignore invalid reference arguments in collection arguments (ogizanagi)
This PR was merged into the 3.1-dev branch. Discussion ---------- [DependencyInjection] Properly ignore invalid reference arguments in collection arguments | Q | A | ------------- | --- | Bug fix? | no | New feature? | yes | BC breaks? | no | Deprecations? | no | Tests pass? | yes | Fixed tickets | - | License | MIT | Doc PR | - With this new feature, the following configuration: ```xml <service id="baz" class="Baz"/> <service id="foo" class="Foo"> <argument type="collection"> <argument type="service" id="bar" on-invalid="ignore" /> <argument type="service" id="baz" /> <argument type="service" id="moo" on-invalid="null" /> </argument> <argument type="service" id="bar" on-invalid="ignore" /> <argument type="service" id="baz" /> <argument type="service" id="moo" on-invalid="null" /> <call method="foo"> <argument type="service" id="bar" on-invalid="ignore" /> </call> <call method="fooCollection"> <argument type="collection"> <argument type="service" id="bar" on-invalid="ignore" /> <argument type="service" id="baz" /> <argument type="service" id="moo" on-invalid="null" /> </argument> </call> </service> ``` will result into the following `Definition`: ```php Definition {#64 ▼ -class: "Foo" // […] -calls: array:1 [▼ 0 => array:2 [▼ 0 => "fooCollection" 1 => array:1 [▼ 0 => array:2 [▼ 0 => Reference {#59 ▼ -id: "baz" -invalidBehavior: 1 } 1 => null ] ] ] ] // […] #arguments: array:4 [▼ 0 => array:2 [▼ 0 => Reference {#63 ▼ -id: "baz" -invalidBehavior: 1 } 1 => null ] 1 => null 2 => Reference {#56 ▼ -id: "baz" -invalidBehavior: 1 } 3 => null ] } ``` Invalid references are ignored instead of replaced by `null` when they are part of a collection argument. If the collection argument is part of a method call and contains an invalid reference, the method call is kept, but the invalid reference removed. The behavior stays the same as before for non-collection arguments. :christmas_tree: Commits ------- cfc4879 [DependencyInjection] Properly ignore invalid reference arguments in collection arguments
2 parents d55114e + cfc4879 commit e9e4869

File tree

2 files changed

+62
-4
lines changed

2 files changed

+62
-4
lines changed

src/Symfony/Component/DependencyInjection/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
}

src/Symfony/Component/DependencyInjection/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+
6D40
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)
0