Skip to content

Commit 4e897a2

Browse files
Merge branch '2.7' into 2.8
* 2.7: [Yaml] parse references on merge keys
2 parents 8f41e33 + cb14798 commit 4e897a2

File tree

2 files changed

+38
-6
lines changed

2 files changed

+38
-6
lines changed

src/Symfony/Component/Yaml/Parser.php

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -181,7 +181,7 @@ private function doParse($value, $exceptionOnInvalidType = false, $objectSupport
181181
$key = (string) $key;
182182
}
183183

184-
if ('<<' === $key) {
184+
if ('<<' === $key && (!isset($values['value']) || !self::preg_match('#^&(?P<ref>[^ ]+)#u', $values['value'], $refMatches))) {
185185
$mergeNode = true;
186186
$allowOverwrite = true;
187187
if (isset($values['value']) && 0 === strpos($values['value'], '*')) {
@@ -226,14 +226,14 @@ private function doParse($value, $exceptionOnInvalidType = false, $objectSupport
226226
$data += $parsed; // array union
227227
}
228228
}
229-
} elseif (isset($values['value']) && self::preg_match('#^&(?P<ref>[^ ]+) *(?P<value>.*)#u', $values['value'], $matches)) {
229+
} elseif ('<<' !== $key && isset($values['value']) && self::preg_match('#^&(?P<ref>[^ ]+) *(?P<value>.*)#u', $values['value'], $matches)) {
230230
$isRef = $matches['ref'];
231231
$values['value'] = $matches['value'];
232232
}
233233

234234
if ($mergeNode) {
235235
// Merge keys
236-
} elseif (!isset($values['value']) || '' == trim($values['value'], ' ') || 0 === strpos(ltrim($values['value'], ' '), '#')) {
236+
} elseif (!isset($values['value']) || '' == trim($values['value'], ' ') || 0 === strpos(ltrim($values['value'], ' '), '#') || '<<' === $key) {
237237
// hash
238238
// if next line is less indented or equal, then it means that the current value is null
239239
if (!$this->isNextLineIndented() && !$this->isNextLineUnIndentedCollection()) {
@@ -244,9 +244,13 @@ private function doParse($value, $exceptionOnInvalidType = false, $objectSupport
244244
}
245245
} else {
246246
$value = $this->parseBlock($this->getRealCurrentLineNb() + 1, $this->getNextEmbedBlock(), $exceptionOnInvalidType, $objectSupport, $objectForMap);
247-
// Spec: Keys MUST be unique; first one wins.
248-
// But overwriting is allowed when a merge node is used in current block.
249-
if ($allowOverwrite || !isset($data[$key])) {
247+
248+
if ('<<' === $key) {
249+
$this->refs[$refMatches['ref']] = $value;
250+
$data += $value;
251+
} elseif ($allowOverwrite || !isset($data[$key])) {
252+
// Spec: Keys MUST be unique; first one wins.
253+
// But overwriting is allowed when a merge node is used in current block.
250254
$data[$key] = $value;
251255
}
252256
}

src/Symfony/Component/Yaml/Tests/ParserTest.php

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1252,6 +1252,34 @@ public function testParserCleansUpReferencesBetweenRuns()
12521252
YAML;
12531253
$this->parser->parse($yaml);
12541254
}
1255+
1256+
public function testParseReferencesOnMergeKeys()
1257+
{
1258+
$yaml = <<<YAML
1259+
mergekeyrefdef:
1260+
a: foo
1261+
<<: &quux
1262+
b: bar
1263+
c: baz
1264+
mergekeyderef:
1265+
d: quux
1266+
<<: *quux
1267+
YAML;
1268+
$expected = array(
1269+
'mergekeyrefdef' => array(
1270+
'a' => 'foo',
1271+
'b' => 'bar',
1272+
'c' => 'baz',
1273+
),
1274+
'mergekeyderef' => array(
1275+
'd' => 'quux',
1276+
'b' => 'bar',
1277+
'c' => 'baz',
1278+
),
1279+
);
1280+
1281+
$this->assertSame($expected, $this->parser->parse($yaml));
1282+
}
12551283
}
12561284

12571285
class B

0 commit comments

Comments
 (0)