diff --git a/src/Symfony/Component/Yaml/Dumper.php b/src/Symfony/Component/Yaml/Dumper.php index 52db38c3b032..67102ed62c03 100644 --- a/src/Symfony/Component/Yaml/Dumper.php +++ b/src/Symfony/Component/Yaml/Dumper.php @@ -29,6 +29,13 @@ class Dumper */ protected $indentation; + /** + * String of spaces with length equal to $this->indentation. + * + * @var string + */ + private $indentStr; + public function __construct(int $indentation = 4) { if ($indentation < 1) { @@ -36,6 +43,7 @@ public function __construct(int $indentation = 4) } $this->indentation = $indentation; + $this->indentStr = str_repeat(' ', $indentation); } /** @@ -50,93 +58,106 @@ public function __construct(int $indentation = 4) */ public function dump($input, int $inline = 0, int $indent = 0, int $flags = 0): string { - $output = ''; $prefix = $indent ? str_repeat(' ', $indent) : ''; - $dumpObjectAsInlineMap = true; - if (Yaml::DUMP_OBJECT_AS_MAP & $flags && ($input instanceof \ArrayObject || $input instanceof \stdClass)) { - $dumpObjectAsInlineMap = empty((array) $input); + $tag = null; + if ($input instanceof TaggedValue) { + $tag = $input->getTag(); + $input = $input->getValue(); + if ($input instanceof TaggedValue) { + throw new \InvalidArgumentException('Nested tags are not supported.'); + } } - if ($inline <= 0 || (!\is_array($input) && !$input instanceof TaggedValue && $dumpObjectAsInlineMap) || empty($input)) { - $output .= $prefix.Inline::dump($input, $flags); - } else { - $dumpAsMap = Inline::isHash($input); - - foreach ($input as $key => $value) { - if ('' !== $output && "\n" !== $output[-1]) { - $output .= "\n"; - } - - if (Yaml::DUMP_MULTI_LINE_LITERAL_BLOCK & $flags && \is_string($value) && false !== strpos($value, "\n") && false === strpos($value, "\r")) { - // If the first line starts with a space character, the spec requires a blockIndicationIndicator - // http://www.yaml.org/spec/1.2/spec.html#id2793979 - $blockIndentationIndicator = (' ' === substr($value, 0, 1)) ? (string) $this->indentation : ''; - - if (isset($value[-2]) && "\n" === $value[-2] && "\n" === $value[-1]) { - $blockChompingIndicator = '+'; - } elseif ("\n" === $value[-1]) { - $blockChompingIndicator = ''; - } else { - $blockChompingIndicator = '-'; - } + if ($this->shouldDumpAsInline($inline, $input, $flags)) { + return $prefix + .(null !== $tag ? '!'.$tag.' ' : '') + .Inline::dump($input, $flags) + ; + } - $output .= sprintf('%s%s%s |%s%s', $prefix, $dumpAsMap ? Inline::dump($key, $flags).':' : '-', '', $blockIndentationIndicator, $blockChompingIndicator); + $dumpAsMap = Inline::isHash($input); - foreach (explode("\n", $value) as $row) { - if ('' === $row) { - $output .= "\n"; - } else { - $output .= sprintf("\n%s%s%s", $prefix, str_repeat(' ', $this->indentation), $row); - } - } - - continue; - } + $output = ''; + foreach ($input as $key => $value) { + if ('' !== $output && "\n" !== $output[-1]) { + $output .= "\n"; + } + $output .= $prefix; + $output .= $dumpAsMap ? Inline::dump($key, $flags).':' : '-'; + $tagged = false; + if ($value instanceof TaggedValue) { + $output .= ' !'.$value->getTag(); + $value = $value->getValue(); if ($value instanceof TaggedValue) { - $output .= sprintf('%s%s !%s', $prefix, $dumpAsMap ? Inline::dump($key, $flags).':' : '-', $value->getTag()); + throw new \InvalidArgumentException('Nested tags are not supported.'); + } + $tagged = true; + } - if (Yaml::DUMP_MULTI_LINE_LITERAL_BLOCK & $flags && \is_string($value->getValue()) && false !== strpos($value->getValue(), "\n") && false === strpos($value->getValue(), "\r\n")) { - // If the first line starts with a space character, the spec requires a blockIndicationIndicator - // http://www.yaml.org/spec/1.2/spec.html#id2793979 - $blockIndentationIndicator = (' ' === substr($value->getValue(), 0, 1)) ? (string) $this->indentation : ''; - $output .= sprintf(' |%s', $blockIndentationIndicator); + if (Yaml::DUMP_MULTI_LINE_LITERAL_BLOCK & $flags && \is_string($value) && false !== strpos($value, "\n") && false === strpos($value, "\r")) { + $output .= ' |'; + // If the first line starts with a space character, the spec requires a blockIndicationIndicator + // http://www.yaml.org/spec/1.2/spec.html#id2793979 + if (' ' === substr($value, 0, 1)) { + $output .= $this->indentation; + } - foreach (explode("\n", $value->getValue()) as $row) { - $output .= sprintf("\n%s%s%s", $prefix, str_repeat(' ', $this->indentation), $row); - } + if (isset($value[-2]) && "\n" === $value[-2] && "\n" === $value[-1]) { + $output .= '+'; + } elseif ("\n" !== $value[-1]) { + $output .= '-'; + } - continue; + foreach (explode("\n", $value) as $row) { + $output .= "\n"; + if ('' !== $row) { + $output .= $prefix.$this->indentStr.$row; } + } - if ($inline - 1 <= 0 || null === $value->getValue() || \is_scalar($value->getValue())) { - $output .= ' '.$this->dump($value->getValue(), $inline - 1, 0, $flags)."\n"; - } else { - $output .= "\n"; - $output .= $this->dump($value->getValue(), $inline - 1, $dumpAsMap ? $indent + $this->indentation : $indent + 2, $flags); - } + continue; + } - continue; - } + $willBeInlined = $this->shouldDumpAsInline($inline - 1, $value, $flags); + + $output .= ($willBeInlined ? ' ' : "\n") + .$this->dump( + $value, + $inline - 1, + $willBeInlined + ? 0 + : $indent + ($tagged && !$dumpAsMap ? 2 : $this->indentation), + $flags) + .($willBeInlined ? "\n" : '') + ; + } + + if (null !== $tag) { + $output = '!'.$tag."\n".$output; + } - $dumpObjectAsInlineMap = true; + return $output; + } - if (Yaml::DUMP_OBJECT_AS_MAP & $flags && ($value instanceof \ArrayObject || $value instanceof \stdClass)) { - $dumpObjectAsInlineMap = empty((array) $value); - } + private function shouldDumpAsInline(int $inline, $value, int $flags): bool + { + if ($inline <= 0 || empty($value)) { + return true; + } - $willBeInlined = $inline - 1 <= 0 || !\is_array($value) && $dumpObjectAsInlineMap || empty($value); + if (\is_array($value)) { + return false; + } - $output .= sprintf('%s%s%s%s', - $prefix, - $dumpAsMap ? Inline::dump($key, $flags).':' : '-', - $willBeInlined ? ' ' : "\n", - $this->dump($value, $inline - 1, $willBeInlined ? 0 : $indent + $this->indentation, $flags) - ).($willBeInlined ? "\n" : ''); - } + if (Yaml::DUMP_OBJECT_AS_MAP & $flags + && ($value instanceof \ArrayObject || $value instanceof \stdClass) + && !empty((array) $value) + ) { + return false; } - return $output; + return true; } } diff --git a/src/Symfony/Component/Yaml/Tests/DumperTest.php b/src/Symfony/Component/Yaml/Tests/DumperTest.php index 59a47a8130f3..164b01c7e74b 100644 --- a/src/Symfony/Component/Yaml/Tests/DumperTest.php +++ b/src/Symfony/Component/Yaml/Tests/DumperTest.php @@ -443,20 +443,20 @@ public function testDumpingTaggedValueTopLevelAssocInline() public function testDumpingTaggedValueTopLevelAssoc() { $data = new TaggedValue('user', ['name' => 'jane']); + $expected = <<<'YAML' +!user +name: jane - // @todo Fix the dumper, the output should not be ''. - $expected = ''; - $yaml = $this->dumper->dump($data, 2); - $this->assertSame($expected, $yaml); +YAML; + $this->assertSame($expected, $this->dumper->dump($data, 2)); } public function testDumpingTaggedValueTopLevelMultiLine() { $data = new TaggedValue('text', "a\nb\n"); - - // @todo Fix the dumper, the output should not be ''. - $expected = ''; + $expected = '!text "a\\nb\\n"'; $this->assertSame($expected, $this->dumper->dump($data, 2, 0, Yaml::DUMP_MULTI_LINE_LITERAL_BLOCK)); + $this->assertEquals($data, $this->parser->parse($expected, Yaml::PARSE_CUSTOM_TAGS)); } public function testDumpingTaggedValueSpecialCharsInTag() @@ -588,7 +588,7 @@ public function testDumpingMultiLineStringAsScalarBlockTaggedValue() $data = [ 'foo' => new TaggedValue('bar', "foo\nline with trailing spaces:\n \nbar\ninteger like line:\n123456789\nempty line:\n\nbaz"), ]; - $expected = "foo: !bar |\n". + $expected = "foo: !bar |-\n". " foo\n". " line with trailing spaces:\n". " \n". @@ -596,7 +596,7 @@ public function testDumpingMultiLineStringAsScalarBlockTaggedValue() " integer like line:\n". " 123456789\n". " empty line:\n". - " \n". + "\n". ' baz'; $this->assertSame($expected, $this->dumper->dump($data, 2, 0, Yaml::DUMP_MULTI_LINE_LITERAL_BLOCK)); @@ -608,12 +608,12 @@ public function testDumpingTaggedMultiLineInList() $data = [ new TaggedValue('bar', "a\nb"), ]; - $expected = "- !bar |\n a\n b"; + $expected = "- !bar |-\n a\n b"; $this->assertSame($expected, $this->dumper->dump($data, 2, 0, Yaml::DUMP_MULTI_LINE_LITERAL_BLOCK)); // @todo Fix the parser, eliminate these exceptions. $this->expectException(ParseException::class); - $this->expectExceptionMessage('Unable to parse at line 3 (near "!bar |").'); + $this->expectExceptionMessage('Unable to parse at line 3 (near "!bar |-").'); $this->parser->parse($expected, Yaml::PARSE_CUSTOM_TAGS); } @@ -623,14 +623,11 @@ public function testDumpingTaggedMultiLineTrailingNewlinesInMap() $data = [ 'foo' => new TaggedValue('bar', "a\nb\n\n\n"), ]; - $expected = "foo: !bar |\n a\n b\n \n \n "; + $expected = "foo: !bar |+\n a\n b\n\n\n"; $this->assertSame($expected, $this->dumper->dump($data, 2, 0, Yaml::DUMP_MULTI_LINE_LITERAL_BLOCK)); - // @todo Fix the parser, the result should be identical to $data. $this->assertSameData( - [ - 'foo' => new TaggedValue('bar', "a\nb\n"), - ], + $data, $this->parser->parse($expected, Yaml::PARSE_CUSTOM_TAGS)); } @@ -639,12 +636,12 @@ public function testDumpingTaggedMultiLineTrailingNewlinesInList() $data = [ new TaggedValue('bar', "a\nb\n\n\n"), ]; - $expected = "- !bar |\n a\n b\n \n \n "; + $expected = "- !bar |+\n a\n b\n\n\n"; $this->assertSame($expected, $this->dumper->dump($data, 2, 0, Yaml::DUMP_MULTI_LINE_LITERAL_BLOCK)); // @todo Fix the parser, eliminate these exceptions. $this->expectException(ParseException::class); - $this->expectExceptionMessage('Unable to parse at line 6 (near "!bar |").'); + $this->expectExceptionMessage('Unable to parse at line 6 (near "!bar |+").'); $this->parser->parse($expected, Yaml::PARSE_CUSTOM_TAGS); } @@ -696,7 +693,7 @@ public function testDumpMultiLineStringAsScalarBlock() nested_inlined_multi_line_string: { inlined_multi_line: "foo\nbar\r\nempty line:\n\nbaz" } YAML -); + ); $this->assertSame($expected, $yml); $this->assertSame($data, $this->parser->parse($yml)); } pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy