[Yaml] fix overwriting of keys after merged map

fixes symfony/symfony#11142
This commit is contained in:
Tobias Schultze 2014-06-18 19:47:01 +02:00
parent 8c621ab4b5
commit dee15623ae
2 changed files with 26 additions and 11 deletions

View File

@ -66,6 +66,7 @@ class Parser
$data = array(); $data = array();
$context = null; $context = null;
$allowOverwrite = false;
while ($this->moveToNextLine()) { while ($this->moveToNextLine()) {
if ($this->isCurrentLineEmpty()) { if ($this->isCurrentLineEmpty()) {
continue; continue;
@ -133,6 +134,7 @@ class Parser
if ('<<' === $key) { if ('<<' === $key) {
$mergeNode = true; $mergeNode = true;
$allowOverwrite = true;
if (isset($values['value']) && 0 === strpos($values['value'], '*')) { if (isset($values['value']) && 0 === strpos($values['value'], '*')) {
$refName = substr($values['value'], 1); $refName = substr($values['value'], 1);
if (!array_key_exists($refName, $this->refs)) { if (!array_key_exists($refName, $this->refs)) {
@ -202,9 +204,8 @@ class Parser
// if next line is less indented or equal, then it means that the current value is null // if next line is less indented or equal, then it means that the current value is null
if (!$this->isNextLineIndented() && !$this->isNextLineUnIndentedCollection()) { if (!$this->isNextLineIndented() && !$this->isNextLineUnIndentedCollection()) {
// Spec: Keys MUST be unique; first one wins. // Spec: Keys MUST be unique; first one wins.
// Parser cannot abort this mapping earlier, since lines // But overwriting is allowed when a merge node is used in current block.
// are processed sequentially. if ($allowOverwrite || !isset($data[$key])) {
if (!isset($data[$key])) {
$data[$key] = null; $data[$key] = null;
} }
} else { } else {
@ -213,18 +214,16 @@ class Parser
$parser->refs =& $this->refs; $parser->refs =& $this->refs;
$value = $parser->parse($this->getNextEmbedBlock(), $exceptionOnInvalidType, $objectSupport); $value = $parser->parse($this->getNextEmbedBlock(), $exceptionOnInvalidType, $objectSupport);
// Spec: Keys MUST be unique; first one wins. // Spec: Keys MUST be unique; first one wins.
// Parser cannot abort this mapping earlier, since lines // But overwriting is allowed when a merge node is used in current block.
// are processed sequentially. if ($allowOverwrite || !isset($data[$key])) {
if (!isset($data[$key])) {
$data[$key] = $value; $data[$key] = $value;
} }
} }
} else { } else {
$value = $this->parseValue($values['value'], $exceptionOnInvalidType, $objectSupport); $value = $this->parseValue($values['value'], $exceptionOnInvalidType, $objectSupport);
// Spec: Keys MUST be unique; first one wins. // Spec: Keys MUST be unique; first one wins.
// Parser cannot abort this mapping earlier, since lines // But overwriting is allowed when a merge node is used in current block.
// are processed sequentially. if ($allowOverwrite || !isset($data[$key])) {
if (!isset($data[$key])) {
$data[$key] = $value; $data[$key] = $value;
} }
} }

View File

@ -10,11 +10,19 @@ yaml: |
a: Steve a: Steve
b: Clark b: Clark
c: Brian c: Brian
bar: &bar bar:
a: before a: before
d: other d: other
<<: *foo <<: *foo
b: new
x: Oren x: Oren
c:
foo: bar
foo: ignore
bar: foo
duplicate:
foo: bar
foo: ignore
foo2: &foo2 foo2: &foo2
a: Ballmer a: Ballmer
ding: &dong [ fi, fei, fo, fam] ding: &dong [ fi, fei, fo, fam]
@ -26,4 +34,12 @@ yaml: |
head: head:
<<: [ *foo , *dong , *foo2 ] <<: [ *foo , *dong , *foo2 ]
php: | php: |
array('foo' => array('a' => 'Steve', 'b' => 'Clark', 'c' => 'Brian'), 'bar' => array('a' => 'before', 'd' => 'other', 'b' => 'Clark', 'c' => 'Brian', 'x' => 'Oren'), 'foo2' => array('a' => 'Ballmer'), 'ding' => array('fi', 'fei', 'fo', 'fam'), 'check' => array('a' => 'Steve', 'b' => 'Clark', 'c' => 'Brian', 'fi', 'fei', 'fo', 'fam', 'isit' => 'tested'), 'head' => array('a' => 'Steve', 'b' => 'Clark', 'c' => 'Brian', 'fi', 'fei', 'fo', 'fam')) array(
'foo' => array('a' => 'Steve', 'b' => 'Clark', 'c' => 'Brian'),
'bar' => array('a' => 'before', 'd' => 'other', 'b' => 'new', 'c' => array('foo' => 'bar', 'bar' => 'foo'), 'x' => 'Oren'),
'duplicate' => array('foo' => 'bar'),
'foo2' => array('a' => 'Ballmer'),
'ding' => array('fi', 'fei', 'fo', 'fam'),
'check' => array('a' => 'Steve', 'b' => 'Clark', 'c' => 'Brian', 'fi', 'fei', 'fo', 'fam', 'isit' => 'tested'),
'head' => array('a' => 'Steve', 'b' => 'Clark', 'c' => 'Brian', 'fi', 'fei', 'fo', 'fam')
)