From 534eaed7aeaf52fbdcbcb8f666243de2c5aa352b Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Wed, 13 Sep 2017 19:40:55 +0200 Subject: [PATCH] parse merge keys with PARSE_OBJECT_FOR_MAP flag --- src/Symfony/Component/Yaml/Parser.php | 18 +++++++-- .../Component/Yaml/Tests/ParserTest.php | 37 +++++++++++++++++++ 2 files changed, 52 insertions(+), 3 deletions(-) diff --git a/src/Symfony/Component/Yaml/Parser.php b/src/Symfony/Component/Yaml/Parser.php index 81b5e0f7f6..54a5704daf 100644 --- a/src/Symfony/Component/Yaml/Parser.php +++ b/src/Symfony/Component/Yaml/Parser.php @@ -249,7 +249,7 @@ class Parser if ('<<' === $key) { $mergeNode = true; $allowOverwrite = true; - if (isset($values['value']) && 0 === strpos($values['value'], '*')) { + if (isset($values['value'][0]) && '*' === $values['value'][0]) { $refName = substr(rtrim($values['value']), 1); if (!array_key_exists($refName, $this->refs)) { throw new ParseException(sprintf('Reference "%s" does not exist.', $refName), $this->getRealCurrentLineNb() + 1, $this->currentLine); @@ -257,6 +257,10 @@ class Parser $refValue = $this->refs[$refName]; + if (Yaml::PARSE_OBJECT_FOR_MAP & $flags && $refValue instanceof \stdClass) { + $refValue = (array) $refValue; + } + if (!is_array($refValue)) { throw new ParseException('YAML merge keys used with a scalar value instead of an array.', $this->getRealCurrentLineNb() + 1, $this->currentLine); } @@ -270,6 +274,10 @@ class Parser } $parsed = $this->parseBlock($this->getRealCurrentLineNb() + 1, $value, $flags); + if (Yaml::PARSE_OBJECT_FOR_MAP & $flags && $parsed instanceof \stdClass) { + $parsed = (array) $parsed; + } + if (!is_array($parsed)) { throw new ParseException('YAML merge keys used with a scalar value instead of an array.', $this->getRealCurrentLineNb() + 1, $this->currentLine); } @@ -279,6 +287,10 @@ class Parser // and each of these nodes is merged in turn according to its order in the sequence. Keys in mapping nodes earlier // in the sequence override keys specified in later mapping nodes. foreach ($parsed as $parsedItem) { + if (Yaml::PARSE_OBJECT_FOR_MAP & $flags && $parsedItem instanceof \stdClass) { + $parsedItem = (array) $parsedItem; + } + if (!is_array($parsedItem)) { throw new ParseException('Merge items must be arrays.', $this->getRealCurrentLineNb() + 1, $parsedItem); } @@ -902,7 +914,7 @@ class Parser // remove leading comments $trimmedValue = preg_replace('#^(\#.*?\n)+#s', '', $value, -1, $count); - if (1 == $count) { + if (1 === $count) { // items have been removed, update the offset $this->offset += substr_count($value, "\n") - substr_count($trimmedValue, "\n"); $value = $trimmedValue; @@ -910,7 +922,7 @@ class Parser // remove start of the document marker (---) $trimmedValue = preg_replace('#^\-\-\-.*?\n#s', '', $value, -1, $count); - if (1 == $count) { + if (1 === $count) { // items have been removed, update the offset $this->offset += substr_count($value, "\n") - substr_count($trimmedValue, "\n"); $value = $trimmedValue; diff --git a/src/Symfony/Component/Yaml/Tests/ParserTest.php b/src/Symfony/Component/Yaml/Tests/ParserTest.php index 620eff32d9..ddf3213054 100644 --- a/src/Symfony/Component/Yaml/Tests/ParserTest.php +++ b/src/Symfony/Component/Yaml/Tests/ParserTest.php @@ -1865,6 +1865,43 @@ YAML; $this->assertSame($expected, $this->parser->parse($yaml, Yaml::PARSE_CONSTANT | Yaml::PARSE_KEYS_AS_STRINGS)); } + + public function testMergeKeysWhenMappingsAreParsedAsObjects() + { + $yaml = << (object) array( + 'bar' => 1, + ), + 'bar' => (object) array( + 'baz' => 2, + 'bar' => 1, + ), + 'baz' => (object) array( + 'baz_foo' => 3, + 'baz_bar' => 4, + ), + 'foobar' => (object) array( + 'bar' => null, + 'baz' => 2, + ), + ); + + $this->assertEquals($expected, $this->parser->parse($yaml, Yaml::PARSE_OBJECT_FOR_MAP)); + } } class B