From 4f5c14979880ce0c07fbb98ebeaa20b601c22485 Mon Sep 17 00:00:00 2001 From: Asmir Mustafic Date: Wed, 12 Apr 2017 12:55:45 +0200 Subject: [PATCH 1/2] Test case for not in-lined map-objects --- .../Component/Yaml/Tests/DumperTest.php | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/src/Symfony/Component/Yaml/Tests/DumperTest.php b/src/Symfony/Component/Yaml/Tests/DumperTest.php index 844177dbcd107..4533c6050c35e 100644 --- a/src/Symfony/Component/Yaml/Tests/DumperTest.php +++ b/src/Symfony/Component/Yaml/Tests/DumperTest.php @@ -206,6 +206,25 @@ public function testInlineLevel() $this->assertEquals($expected, $this->dumper->dump($this->array, 10), '->dump() takes an inline level argument'); } + public function testArrayObjectAsMapNotInLined() + { + $deep = new \ArrayObject(array('deep1' => 'd', 'deep2' => 'e')); + $inner = new \ArrayObject(array('inner1' => 'b', 'inner2' => 'c', 'inner3' => $deep)); + $outer = new \ArrayObject(array('outer1' => 'a', 'outer1' => $inner)); + + $yaml = $this->dumper->dump($outer, 2, 0, Yaml::DUMP_OBJECT_AS_MAP); + + $expected = <<assertEquals($expected, $yaml); + } + public function testObjectSupportEnabled() { $dump = $this->dumper->dump(array('foo' => new A(), 'bar' => 1), 0, 0, Yaml::DUMP_OBJECT); From 3cca48c715bb016825c96aae7957d66afb7f8562 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Wed, 12 Apr 2017 21:41:43 +0200 Subject: [PATCH 2/2] respect inline level when dumping objects as maps --- src/Symfony/Component/Yaml/Dumper.php | 21 +++- src/Symfony/Component/Yaml/Inline.php | 10 +- .../Component/Yaml/Tests/DumperTest.php | 106 ++++++++++++++---- 3 files changed, 110 insertions(+), 27 deletions(-) diff --git a/src/Symfony/Component/Yaml/Dumper.php b/src/Symfony/Component/Yaml/Dumper.php index 98d82434c2388..a38bce014279a 100644 --- a/src/Symfony/Component/Yaml/Dumper.php +++ b/src/Symfony/Component/Yaml/Dumper.php @@ -81,15 +81,20 @@ public function dump($input, $inline = 0, $indent = 0, $flags = 0) $output = ''; $prefix = $indent ? str_repeat(' ', $indent) : ''; + $dumpObjectAsInlineMap = true; - if ($inline <= 0 || !is_array($input) || empty($input)) { + if (Yaml::DUMP_OBJECT_AS_MAP & $flags && ($input instanceof \ArrayObject || $input instanceof \stdClass)) { + $dumpObjectAsInlineMap = empty((array) $input); + } + + if ($inline <= 0 || (!is_array($input) && $dumpObjectAsInlineMap) || empty($input)) { $output .= $prefix.Inline::dump($input, $flags); } else { - $isAHash = Inline::isHash($input); + $dumpAsMap = Inline::isHash($input); foreach ($input as $key => $value) { if ($inline >= 1 && Yaml::DUMP_MULTI_LINE_LITERAL_BLOCK & $flags && is_string($value) && false !== strpos($value, "\n")) { - $output .= sprintf("%s%s%s |\n", $prefix, $isAHash ? Inline::dump($key, $flags).':' : '-', ''); + $output .= sprintf("%s%s%s |\n", $prefix, $dumpAsMap ? Inline::dump($key, $flags).':' : '-', ''); foreach (preg_split('/\n|\r\n/', $value) as $row) { $output .= sprintf("%s%s%s\n", $prefix, str_repeat(' ', $this->indentation), $row); @@ -98,11 +103,17 @@ public function dump($input, $inline = 0, $indent = 0, $flags = 0) continue; } - $willBeInlined = $inline - 1 <= 0 || !is_array($value) || empty($value); + $dumpObjectAsInlineMap = true; + + if (Yaml::DUMP_OBJECT_AS_MAP & $flags && ($value instanceof \ArrayObject || $value instanceof \stdClass)) { + $dumpObjectAsInlineMap = empty((array) $value); + } + + $willBeInlined = $inline - 1 <= 0 || !is_array($value) && $dumpObjectAsInlineMap || empty($value); $output .= sprintf('%s%s%s%s', $prefix, - $isAHash ? Inline::dump($key, $flags).':' : '-', + $dumpAsMap ? Inline::dump($key, $flags).':' : '-', $willBeInlined ? ' ' : "\n", $this->dump($value, $inline - 1, $willBeInlined ? 0 : $indent + $this->indentation, $flags) ).($willBeInlined ? "\n" : ''); diff --git a/src/Symfony/Component/Yaml/Inline.php b/src/Symfony/Component/Yaml/Inline.php index eb3ffed6f3690..b2cf9d4930f72 100644 --- a/src/Symfony/Component/Yaml/Inline.php +++ b/src/Symfony/Component/Yaml/Inline.php @@ -164,7 +164,7 @@ public static function dump($value, $flags = 0) } if (Yaml::DUMP_OBJECT_AS_MAP & $flags && ($value instanceof \stdClass || $value instanceof \ArrayObject)) { - return self::dumpArray((array) $value, $flags); + return self::dumpArray($value, $flags); } if (Yaml::DUMP_EXCEPTION_ON_INVALID_TYPE & $flags) { @@ -224,12 +224,16 @@ public static function dump($value, $flags = 0) * * @internal * - * @param array $value The PHP array to check + * @param array|\ArrayObject|\stdClass $value The PHP array or array-like object to check * * @return bool true if value is hash array, false otherwise */ - public static function isHash(array $value) + public static function isHash($value) { + if ($value instanceof \stdClass || $value instanceof \ArrayObject) { + return true; + } + $expectedKey = 0; foreach ($value as $key => $val) { diff --git a/src/Symfony/Component/Yaml/Tests/DumperTest.php b/src/Symfony/Component/Yaml/Tests/DumperTest.php index 4533c6050c35e..de49f46dded92 100644 --- a/src/Symfony/Component/Yaml/Tests/DumperTest.php +++ b/src/Symfony/Component/Yaml/Tests/DumperTest.php @@ -206,25 +206,6 @@ public function testInlineLevel() $this->assertEquals($expected, $this->dumper->dump($this->array, 10), '->dump() takes an inline level argument'); } - public function testArrayObjectAsMapNotInLined() - { - $deep = new \ArrayObject(array('deep1' => 'd', 'deep2' => 'e')); - $inner = new \ArrayObject(array('inner1' => 'b', 'inner2' => 'c', 'inner3' => $deep)); - $outer = new \ArrayObject(array('outer1' => 'a', 'outer1' => $inner)); - - $yaml = $this->dumper->dump($outer, 2, 0, Yaml::DUMP_OBJECT_AS_MAP); - - $expected = <<assertEquals($expected, $yaml); - } - public function testObjectSupportEnabled() { $dump = $this->dumper->dump(array('foo' => new A(), 'bar' => 1), 0, 0, Yaml::DUMP_OBJECT); @@ -352,6 +333,93 @@ public function objectAsMapProvider() return $tests; } + public function testDumpingArrayObjectInstancesRespectsInlineLevel() + { + $deep = new \ArrayObject(array('deep1' => 'd', 'deep2' => 'e')); + $inner = new \ArrayObject(array('inner1' => 'b', 'inner2' => 'c', 'inner3' => $deep)); + $outer = new \ArrayObject(array('outer1' => 'a', 'outer2' => $inner)); + + $yaml = $this->dumper->dump($outer, 2, 0, Yaml::DUMP_OBJECT_AS_MAP); + + $expected = <<assertSame($expected, $yaml); + } + + public function testDumpingArrayObjectInstancesWithNumericKeysInlined() + { + $deep = new \ArrayObject(array('d', 'e')); + $inner = new \ArrayObject(array('b', 'c', $deep)); + $outer = new \ArrayObject(array('a', $inner)); + + $yaml = $this->dumper->dump($outer, 0, 0, Yaml::DUMP_OBJECT_AS_MAP); + $expected = <<assertSame($expected, $yaml); + } + + public function testDumpingArrayObjectInstancesWithNumericKeysRespectsInlineLevel() + { + $deep = new \ArrayObject(array('d', 'e')); + $inner = new \ArrayObject(array('b', 'c', $deep)); + $outer = new \ArrayObject(array('a', $inner)); + $yaml = $this->dumper->dump($outer, 2, 0, Yaml::DUMP_OBJECT_AS_MAP); + $expected = <<assertEquals($expected, $yaml); + } + + public function testDumpEmptyArrayObjectInstanceAsMap() + { + $this->assertSame('{ }', $this->dumper->dump(new \ArrayObject(), 2, 0, Yaml::DUMP_OBJECT_AS_MAP)); + } + + public function testDumpEmptyStdClassInstanceAsMap() + { + $this->assertSame('{ }', $this->dumper->dump(new \stdClass(), 2, 0, Yaml::DUMP_OBJECT_AS_MAP)); + } + + public function testDumpingStdClassInstancesRespectsInlineLevel() + { + $deep = new \stdClass(); + $deep->deep1 = 'd'; + $deep->deep2 = 'e'; + + $inner = new \stdClass(); + $inner->inner1 = 'b'; + $inner->inner2 = 'c'; + $inner->inner3 = $deep; + + $outer = new \stdClass(); + $outer->outer1 = 'a'; + $outer->outer2 = $inner; + + $yaml = $this->dumper->dump($outer, 2, 0, Yaml::DUMP_OBJECT_AS_MAP); + + $expected = <<assertSame($expected, $yaml); + } + public function testDumpMultiLineStringAsScalarBlock() { $data = array(