bug #17729 [Yaml] properly parse lists in object maps (xabbuh)

This PR was merged into the 2.8 branch.

Discussion
----------

[Yaml] properly parse lists in object maps

| Q             | A
| ------------- | ---
| Bug fix?      | yes
| New feature?  | no
| BC breaks?    | no
| Deprecations? | no
| Tests pass?   | yes
| Fixed tickets | #17709, #17710, #17711
| License       | MIT
| Doc PR        |
* do not cast parsed sequences to objects
* properly handle numeric mapping keys

Commits
-------

ee9ca93 [Yaml] properly parse lists in object maps
This commit is contained in:
Fabien Potencier 2016-02-14 11:09:04 +01:00
commit f6ffc4e744
2 changed files with 66 additions and 20 deletions

View File

@ -303,8 +303,14 @@ class Parser
mb_internal_encoding($mbEncoding);
}
if ($objectForMap && !is_object($data)) {
$data = (object) $data;
if ($objectForMap && !is_object($data) && 'mapping' === $context) {
$object = new \stdClass();
foreach ($data as $key => $value) {
$object->$key = $value;
}
$data = $object;
}
return empty($data) ? null : $data;

View File

@ -442,35 +442,75 @@ EOF;
$this->assertEquals(array('foo' => null, 'bar' => 1), $this->parser->parse($input), '->parse() does not parse objects');
}
public function testObjectForMapEnabledWithMapping()
/**
* @dataProvider getObjectForMapTests
*/
public function testObjectForMap($yaml, $expected)
{
$this->assertEquals($expected, $this->parser->parse($yaml, false, false, true));
}
public function getObjectForMapTests()
{
$tests = array();
$yaml = <<<EOF
foo:
fiz: [cat]
EOF;
$result = $this->parser->parse($yaml, false, false, true);
$expected = new \stdClass();
$expected->foo = new \stdClass();
$expected->foo->fiz = array('cat');
$tests['mapping'] = array($yaml, $expected);
$this->assertInstanceOf('stdClass', $result);
$this->assertInstanceOf('stdClass', $result->foo);
$this->assertEquals(array('cat'), $result->foo->fiz);
}
$yaml = '{ "foo": "bar", "fiz": "cat" }';
$expected = new \stdClass();
$expected->foo = 'bar';
$expected->fiz = 'cat';
$tests['inline-mapping'] = array($yaml, $expected);
public function testObjectForMapEnabledWithInlineMapping()
{
$result = $this->parser->parse('{ "foo": "bar", "fiz": "cat" }', false, false, true);
$this->assertInstanceOf('stdClass', $result);
$this->assertEquals('bar', $result->foo);
$this->assertEquals('cat', $result->fiz);
}
public function testObjectForMapIsAppliedAfterParsing()
{
$yaml = "foo: bar\nbaz: foobar";
$expected = new \stdClass();
$expected->foo = 'bar';
$expected->baz = 'foobar';
$tests['object-for-map-is-applied-after-parsing'] = array($yaml, $expected);
$this->assertEquals($expected, $this->parser->parse("foo: bar\nbaz: foobar", false, false, true));
$yaml = <<<EOT
array:
- key: one
- key: two
EOT;
$expected = new \stdClass();
$expected->array = array();
$expected->array[0] = new \stdClass();
$expected->array[0]->key = 'one';
$expected->array[1] = new \stdClass();
$expected->array[1]->key = 'two';
$tests['nest-map-and-sequence'] = array($yaml, $expected);
$yaml = <<<YAML
map:
1: one
2: two
YAML;
$expected = new \stdClass();
$expected->map = new \stdClass();
$expected->map->{1} = 'one';
$expected->map->{2} = 'two';
$tests['numeric-keys'] = array($yaml, $expected);
$yaml = <<<YAML
map:
0: one
1: two
YAML;
$expected = new \stdClass();
$expected->map = new \stdClass();
$expected->map->{0} = 'one';
$expected->map->{1} = 'two';
$tests['zero-indexed-numeric-keys'] = array($yaml, $expected);
return $tests;
}
/**