Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 53d9b10

Browse files
committed
bug #39847 [Messenger] Fix merging PrototypedArrayNode associative values (svityashchuk)
This PR was squashed before being merged into the 4.4 branch. Discussion ---------- [Messenger] Fix merging PrototypedArrayNode associative values Now keys will not be considered as irrelevant. | Q | A | ------------- | --- | Branch? | 4.4 | Bug fix? | yes | New feature? | no | Deprecations? | no | Tickets | Fix #39846, fix #36874 | License | MIT | Doc PR | The problem was because in ConfigTree `options` are defined as `arrayNode` and has a `prototype('variable')`. So for combining config together `PrototypedArrayNode::mergeValues()` was called. And there was a trouble - for that `PrototypedArrayNode` `$rightSide` values were added without keys: `\Symfony\Component\Config\Definition\PrototypedArrayNode::mergeValues` ```php foreach ($rightSide as $k => $v) { // prototype, and key is irrelevant, append the element if (null === $this->keyAttribute) { $leftSide[] = $v; continue; } ``` Commits ------- 11128c9 [Messenger] Fix merging PrototypedArrayNode associative values
2 parents a76cdec + 11128c9 commit 53d9b10

File tree

4 files changed

+62
-7
lines changed

4 files changed

+62
-7
lines changed

composer.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,8 @@
4949
"symfony/polyfill-mbstring": "~1.0",
5050
"symfony/polyfill-php72": "~1.5",
5151
"symfony/polyfill-php73": "^1.11",
52-
"symfony/polyfill-php80": "^1.15"
52+
"symfony/polyfill-php80": "^1.15",
53+
"symfony/polyfill-php81": "^1.22"
5354
},
5455
"replace": {
5556
"symfony/asset": "self.version",

src/Symfony/Component/Config/Definition/PrototypedArrayNode.php

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -225,11 +225,11 @@ protected function normalizeValue($value)
225225

226226
$value = $this->remapXml($value);
227227

228-
$isAssoc = array_keys($value) !== range(0, \count($value) - 1);
228+
$isList = array_is_list($value);
229229
$normalized = [];
230230
foreach ($value as $k => $v) {
231231
if (null !== $this->keyAttribute && \is_array($v)) {
232-
if (!isset($v[$this->keyAttribute]) && \is_int($k) && !$isAssoc) {
232+
if (!isset($v[$this->keyAttribute]) && \is_int($k) && $isList) {
233233
$ex = new InvalidConfigurationException(sprintf('The attribute "%s" must be set for path "%s".', $this->keyAttribute, $this->getPath()));
234234
$ex->setPath($this->getPath());
235235

@@ -271,7 +271,7 @@ protected function normalizeValue($value)
271271
}
272272

273273
$prototype = $this->getPrototypeForChild($k);
274-
if (null !== $this->keyAttribute || $isAssoc) {
274+
if (null !== $this->keyAttribute || !$isList) {
275275
$normalized[$k] = $prototype->normalize($v);
276276
} else {
277277
$normalized[] = $prototype->normalize($v);
@@ -304,9 +304,10 @@ protected function mergeValues($leftSide, $rightSide)
304304
return $rightSide;
305305
}
306306

307+
$isList = array_is_list($rightSide);
307308
foreach ($rightSide as $k => $v) {
308-
// prototype, and key is irrelevant, append the element
309-
if (null === $this->keyAttribute) {
309+
// prototype, and key is irrelevant there are no named keys, append the element
310+
if (null === $this->keyAttribute && $isList) {
310311
$leftSide[] = $v;
311312
continue;
312313
}

src/Symfony/Component/Config/Tests/Definition/PrototypedArrayNodeTest.php

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -338,4 +338,56 @@ public function getDataForKeyRemovedLeftValueOnly()
338338
],
339339
];
340340
}
341+
342+
/**
343+
* @dataProvider getPrototypedArrayNodeDataToMerge
344+
*/
345+
public function testPrototypedArrayNodeMerge($left, $right, $expected)
346+
{
347+
$node = new PrototypedArrayNode('options');
348+
$node->setNormalizeKeys(false);
349+
$node->setPrototype(new VariableNode('value'));
350+
$node->setDefaultValue([]);
351+
352+
$result = $node->merge($left, $right);
353+
354+
self::assertSame($result, $expected);
355+
}
356+
357+
public function getPrototypedArrayNodeDataToMerge()
358+
{
359+
return [
360+
// data to merged is a plain array
361+
[
362+
['foo', 'bar'],
363+
['foo', 'baz', 'qux'],
364+
['foo', 'bar', 'foo', 'baz', 'qux'],
365+
],
366+
// data to be merged is an associative array
367+
[
368+
['option1' => true, 'option2' => 'foo'],
369+
[
370+
'option2' => 'bar',
371+
'option3' => 42,
372+
'option4' => [
373+
'option41' => 'baz',
374+
'option42' => [
375+
'option423' => 'qux',
376+
],
377+
],
378+
],
379+
[
380+
'option1' => true,
381+
'option2' => 'bar',
382+
'option3' => 42,
383+
'option4' => [
384+
'option41' => 'baz',
385+
'option42' => [
386+
'option423' => 'qux',
387+
],
388+
],
389+
],
390+
],
391+
];
392+
}
341393
}

src/Symfony/Component/Config/composer.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,8 @@
1818
"require": {
1919
"php": ">=7.1.3",
2020
"symfony/filesystem": "^3.4|^4.0|^5.0",
21-
"symfony/polyfill-ctype": "~1.8"
21+
"symfony/polyfill-ctype": "~1.8",
22+
"symfony/polyfill-php81": "^1.22"
2223
},
2324
"require-dev": {
2425
"symfony/event-dispatcher": "^3.4|^4.0|^5.0",

0 commit comments

Comments
 (0)