added ability for substitute aliases when mapping in YAML is on single line
This commit is contained in:
parent
c963178206
commit
675a3fe7f6
|
@ -491,6 +491,59 @@ class Parser
|
|||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Substitute from alias where is used a <<
|
||||
*
|
||||
* @param mixed $values Parsed YAML in which aliases are not substituted
|
||||
*
|
||||
* @return mixed YAML with substituted aliases
|
||||
*
|
||||
* @throws Exception\ParseException When indentation problem are detected
|
||||
*/
|
||||
private function substituteAliases($values)
|
||||
{
|
||||
if (is_array($values)) {
|
||||
$keys = array();
|
||||
foreach ($values as $key => $value) {
|
||||
if ($key ==='<<' && preg_grep('/^\*.+/', (array) $value) === array_values((array) $value)) {
|
||||
$values[$key] = array();
|
||||
foreach ((array) $value as $ref) {
|
||||
$refName = substr($ref, 1);
|
||||
if (!array_key_exists($refName, $this->refs)) {
|
||||
throw new ParseException(
|
||||
sprintf('Reference "%s" does not exist.', $refName),
|
||||
$this->getRealCurrentLineNb() + 1,
|
||||
$this->currentLine
|
||||
);
|
||||
}
|
||||
|
||||
$keys = array_merge(
|
||||
$keys,
|
||||
array_diff(array_keys($this->refs[$refName]), $keys)
|
||||
);
|
||||
$values[$key] = array_replace($this->refs[$refName], $values[$key]);
|
||||
}
|
||||
} elseif (!isset($result[$key]) || is_array($result[$key])) {
|
||||
$keys[] = $key;
|
||||
$values[$key] = $this->substituteAliases($value);
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($values['<<'])) {
|
||||
$values = array_replace($values['<<'], $values);
|
||||
unset($values['<<']);
|
||||
uksort(
|
||||
$values,
|
||||
function ($a, $b) use ($keys) {
|
||||
return array_search($a, $keys, true) - array_search($b, $keys, true);
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return $values;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses a YAML value.
|
||||
*
|
||||
|
@ -526,7 +579,7 @@ class Parser
|
|||
}
|
||||
|
||||
try {
|
||||
return Inline::parse($value, $exceptionOnInvalidType, $objectSupport, $objectForMap, $this->refs);
|
||||
return $this->substituteAliases(Inline::parse($value, $exceptionOnInvalidType, $objectSupport, $objectForMap, $this->refs));
|
||||
} catch (ParseException $e) {
|
||||
$e->setParsedLine($this->getRealCurrentLineNb() + 1);
|
||||
$e->setSnippet($this->currentLine);
|
||||
|
|
|
@ -22,6 +22,7 @@ yaml: |
|
|||
foo: bar
|
||||
foo: ignore
|
||||
bar: foo
|
||||
bar_inline: {a: before, d: other, <<: *foo, b: new, x: Oren, c: { foo: bar, foo: ignore, bar: foo}}
|
||||
duplicate:
|
||||
foo: bar
|
||||
foo: ignore
|
||||
|
@ -46,15 +47,20 @@ yaml: |
|
|||
p: 12345
|
||||
z:
|
||||
<<: *nestedref
|
||||
head_inline: &head_inline { <<: [ *foo , *dong , *foo2 ] }
|
||||
recursive_inline: { <<: *head_inline, c: { <<: *foo2 } }
|
||||
php: |
|
||||
array(
|
||||
'foo' => array('a' => 'Steve', 'b' => 'Clark', 'c' => 'Brian', 'e' => 'notnull'),
|
||||
'bar' => array('a' => 'before', 'd' => 'other', 'e' => null, 'b' => 'new', 'c' => array('foo' => 'bar', 'bar' => 'foo'), 'x' => 'Oren'),
|
||||
'bar_inline' => 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', 'e' => 'notnull', 'fi', 'fei', 'fo', 'fam', 'isit' => 'tested'),
|
||||
'head' => array('a' => 'Steve', 'b' => 'Clark', 'c' => 'Brian', 'e' => 'notnull', 'fi', 'fei', 'fo', 'fam'),
|
||||
'taz' => array('a' => 'Steve', 'w' => array('p' => 1234)),
|
||||
'nested' => array('a' => 'Steve', 'w' => array('p' => 12345), 'd' => 'Doug', 'z' => array('p' => 12345))
|
||||
'nested' => array('a' => 'Steve', 'w' => array('p' => 12345), 'd' => 'Doug', 'z' => array('p' => 12345)),
|
||||
'head_inline' => array('a' => 'Steve', 'b' => 'Clark', 'c' => 'Brian', 'fi', 'fei', 'fo', 'fam'),
|
||||
'recursive_inline' => array('a' => 'Steve', 'b' => 'Clark', 'c' => array('a' => 'Ballmer'), 'fi', 'fei', 'fo', 'fam')
|
||||
)
|
||||
|
|
|
@ -1207,6 +1207,18 @@ YAML;
|
|||
|
||||
$this->assertSame($expected, $this->parser->parse($yaml));
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \Symfony\Component\Yaml\Exception\ParseException
|
||||
* @expectedExceptionMessage Reference "foo" does not exist
|
||||
*/
|
||||
public function testEvalRefException()
|
||||
{
|
||||
$yaml = <<<EOE
|
||||
foo: { &foo { a: Steve, <<: *foo} }
|
||||
EOE;
|
||||
$this->parser->parse($yaml);
|
||||
}
|
||||
}
|
||||
|
||||
class B
|
||||
|
|
Reference in New Issue