Skip to content

Commit 675a3fe

Browse files
Michał Strzeleckixabbuh
authored andcommitted
added ability for substitute aliases when mapping in YAML is on single line
1 parent c963178 commit 675a3fe

File tree

3 files changed

+73
-2
lines changed

3 files changed

+73
-2
lines changed

src/Symfony/Component/Yaml/Parser.php

Lines changed: 54 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -491,6 +491,59 @@ private function moveToPreviousLine()
491491
return true;
492492
}
493493

494+
/**
495+
* Substitute from alias where is used a <<
496+
*
497+
* @param mixed $values Parsed YAML in which aliases are not substituted
498+
*
499+
* @return mixed YAML with substituted aliases
500+
*
501+
* @throws Exception\ParseException When indentation problem are detected
502+
*/
503+
private function substituteAliases($values)
504+
{
505+
if (is_array($values)) {
506+
$keys = array();
507+
foreach ($values as $key => $value) {
508+
if ($key ==='<<' && preg_grep('/^\*.+/', (array) $value) === array_values((array) $value)) {
509+
$values[$key] = array();
510+
foreach ((array) $value as $ref) {
511+
$refName = substr($ref, 1);
512+
if (!array_key_exists($refName, $this->refs)) {
513+
throw new ParseException(
514+
sprintf('Reference "%s" does not exist.', $refName),
515+
$this->getRealCurrentLineNb() + 1,
516+
$this->currentLine
517+
);
518+
}
519+
520+
$keys = array_merge(
521+
$keys,
522+
array_diff(array_keys($this->refs[$refName]), $keys)
523+
);
524+
$values[$key] = array_replace($this->refs[$refName], $values[$key]);
525+
}
526+
} elseif (!isset($result[$key]) || is_array($result[$key])) {
527+
$keys[] = $key;
528+
$values[$key] = $this->substituteAliases($value);
529+
}
530+
}
531+
532+
if (isset($values['<<'])) {
533+
$values = array_replace($values['<<'], $values);
534+
unset($values['<<']);
535+
uksort(
536+
$values,
537+
function ($a, $b) use ($keys) {
538+
return array_search($a, $keys, true) - array_search($b, $keys, true);
539+
}
540+
);
541+
}
542+
}
543+
544+
return $values;
545+
}
546+
494547
/**
495548
* Parses a YAML value.
496549
*
@@ -526,7 +579,7 @@ private function parseValue($value, $exceptionOnInvalidType, $objectSupport, $ob
526579
}
527580

528581
try {
529-
return Inline::parse($value, $exceptionOnInvalidType, $objectSupport, $objectForMap, $this->refs);
582+
return $this->substituteAliases(Inline::parse($value, $exceptionOnInvalidType, $objectSupport, $objectForMap, $this->refs));
530583
} catch (ParseException $e) {
531584
$e->setParsedLine($this->getRealCurrentLineNb() + 1);
532585
$e->setSnippet($this->currentLine);

src/Symfony/Component/Yaml/Tests/Fixtures/sfMergeKey.yml

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ yaml: |
2222
foo: bar
2323
foo: ignore
2424
bar: foo
25+
bar_inline: {a: before, d: other, <<: *foo, b: new, x: Oren, c: { foo: bar, foo: ignore, bar: foo}}
2526
duplicate:
2627
foo: bar
2728
foo: ignore
@@ -46,15 +47,20 @@ yaml: |
4647
p: 12345
4748
z:
4849
<<: *nestedref
50+
head_inline: &head_inline { <<: [ *foo , *dong , *foo2 ] }
51+
recursive_inline: { <<: *head_inline, c: { <<: *foo2 } }
4952
php: |
5053
array(
5154
'foo' => array('a' => 'Steve', 'b' => 'Clark', 'c' => 'Brian', 'e' => 'notnull'),
5255
'bar' => array('a' => 'before', 'd' => 'other', 'e' => null, 'b' => 'new', 'c' => array('foo' => 'bar', 'bar' => 'foo'), 'x' => 'Oren'),
56+
'bar_inline' => array('a' => 'before', 'd' => 'other', 'b' => 'new', 'c' => array('foo' => 'bar', 'bar' => 'foo'), 'x' => 'Oren'),
5357
'duplicate' => array('foo' => 'bar'),
5458
'foo2' => array('a' => 'Ballmer'),
5559
'ding' => array('fi', 'fei', 'fo', 'fam'),
5660
'check' => array('a' => 'Steve', 'b' => 'Clark', 'c' => 'Brian', 'e' => 'notnull', 'fi', 'fei', 'fo', 'fam', 'isit' => 'tested'),
5761
'head' => array('a' => 'Steve', 'b' => 'Clark', 'c' => 'Brian', 'e' => 'notnull', 'fi', 'fei', 'fo', 'fam'),
5862
'taz' => array('a' => 'Steve', 'w' => array('p' => 1234)),
59-
'nested' => array('a' => 'Steve', 'w' => array('p' => 12345), 'd' => 'Doug', 'z' => array('p' => 12345))
63+
'nested' => array('a' => 'Steve', 'w' => array('p' => 12345), 'd' => 'Doug', 'z' => array('p' => 12345)),
64+
'head_inline' => array('a' => 'Steve', 'b' => 'Clark', 'c' => 'Brian', 'fi', 'fei', 'fo', 'fam'),
65+
'recursive_inline' => array('a' => 'Steve', 'b' => 'Clark', 'c' => array('a' => 'Ballmer'), 'fi', 'fei', 'fo', 'fam')
6066
)

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

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1207,6 +1207,18 @@ public function testParseReferencesOnMergeKeys()
12071207

12081208
$this->assertSame($expected, $this->parser->parse($yaml));
12091209
}
1210+
1211+
/**
1212+
* @expectedException \Symfony\Component\Yaml\Exception\ParseException
1213+
* @expectedExceptionMessage Reference "foo" does not exist
1214+
*/
1215+
public function testEvalRefException()
1216+
{
1217+
$yaml = <<<EOE
1218+
foo: { &foo { a: Steve, <<: *foo} }
1219+
EOE;
1220+
$this->parser->parse($yaml);
1221+
}
12101222
}
12111223

12121224
class B

0 commit comments

Comments
 (0)