diff --git a/src/Symfony/Component/Yaml/CHANGELOG.md b/src/Symfony/Component/Yaml/CHANGELOG.md index b1e9decbcc1ed..364bf66dfd68f 100644 --- a/src/Symfony/Component/Yaml/CHANGELOG.md +++ b/src/Symfony/Component/Yaml/CHANGELOG.md @@ -5,6 +5,7 @@ CHANGELOG --- * Add compact nested mapping support by using the `Yaml::DUMP_COMPACT_NESTED_MAPPING` flag + * Add the `Yaml::DUMP_FORCE_DOUBLE_QUOTES_ON_VALUES` flag to enforce double quotes around string values 7.2 --- diff --git a/src/Symfony/Component/Yaml/Inline.php b/src/Symfony/Component/Yaml/Inline.php index c310fe12b2829..bfa910c745b1c 100644 --- a/src/Symfony/Component/Yaml/Inline.php +++ b/src/Symfony/Component/Yaml/Inline.php @@ -173,6 +173,7 @@ public static function dump(mixed $value, int $flags = 0, bool $rootLevel = fals case self::isBinaryString($value): return '!!binary '.base64_encode($value); case Escaper::requiresDoubleQuoting($value): + case Yaml::DUMP_FORCE_DOUBLE_QUOTES_ON_VALUES & $flags: return Escaper::escapeWithDoubleQuotes($value); case Escaper::requiresSingleQuoting($value): $singleQuoted = Escaper::escapeWithSingleQuotes($value); @@ -242,12 +243,13 @@ private static function dumpArray(array $value, int $flags): string private static function dumpHashArray(array|\ArrayObject|\stdClass $value, int $flags): string { $output = []; + $keyFlags = $flags &~ Yaml::DUMP_FORCE_DOUBLE_QUOTES_ON_VALUES; foreach ($value as $key => $val) { if (\is_int($key) && Yaml::DUMP_NUMERIC_KEY_AS_STRING & $flags) { $key = (string) $key; } - $output[] = \sprintf('%s: %s', self::dump($key, $flags), self::dump($val, $flags)); + $output[] = \sprintf('%s: %s', self::dump($key, $keyFlags), self::dump($val, $flags)); } return \sprintf('{ %s }', implode(', ', $output)); diff --git a/src/Symfony/Component/Yaml/Tests/DumperTest.php b/src/Symfony/Component/Yaml/Tests/DumperTest.php index fe07e10a71130..cb163b677fff0 100644 --- a/src/Symfony/Component/Yaml/Tests/DumperTest.php +++ b/src/Symfony/Component/Yaml/Tests/DumperTest.php @@ -910,6 +910,87 @@ public function testDumpNullAsTilde() $this->assertSame('{ foo: ~ }', $this->dumper->dump(['foo' => null], 0, 0, Yaml::DUMP_NULL_AS_TILDE)); } + /** + * @dataProvider getForceQuotesOnValuesData + */ + public function testCanForceQuotesOnValues(array $input, string $expected) + { + $this->assertSame($expected, $this->dumper->dump($input, 0, 0, Yaml::DUMP_FORCE_DOUBLE_QUOTES_ON_VALUES)); + } + + public function getForceQuotesOnValuesData(): iterable + { + yield 'empty string' => [ + ['foo' => ''], + '{ foo: \'\' }', + ]; + + yield 'double quote' => [ + ['foo' => '"'], + '{ foo: "\"" }', + ]; + + yield 'single quote' => [ + ['foo' => "'"], + '{ foo: "\'" }', + ]; + + yield 'line break' => [ + ['foo' => "line\nbreak"], + '{ foo: "line\nbreak" }', + ]; + + yield 'tab character' => [ + ['foo' => "tab\tcharacter"], + '{ foo: "tab\tcharacter" }', + ]; + + yield 'backslash' => [ + ['foo' => "back\\slash"], + '{ foo: "back\\\\slash" }', + ]; + + yield 'colon' => [ + ['foo' => 'colon: value'], + '{ foo: "colon: value" }', + ]; + + yield 'dash' => [ + ['foo' => '- dash'], + '{ foo: "- dash" }', + ]; + + yield 'numeric' => [ + ['foo' => 23], + '{ foo: 23 }', + ]; + + yield 'boolean' => [ + ['foo' => true], + '{ foo: true }', + ]; + + yield 'null' => [ + ['foo' => null], + '{ foo: null }', + ]; + + yield 'nested' => [ + ['foo' => ['bar' => 'bat', 'baz' => 23]], + '{ foo: { bar: "bat", baz: 23 } }', + ]; + + yield 'mix of values' => [ + ['foo' => 'bat', 'bar' => 23, 'baz' => true, 'qux' => "line\nbreak"], + '{ foo: "bat", bar: 23, baz: true, qux: "line\nbreak" }', + ]; + + yield 'special YAML characters' => [ + ['foo' => 'colon: value', 'bar' => '- dash', 'baz' => '? question', 'qux' => '# hash'], + '{ foo: "colon: value", bar: "- dash", baz: "? question", qux: "# hash" }', + ]; + } + /** * @dataProvider getNumericKeyData */ diff --git a/src/Symfony/Component/Yaml/Yaml.php b/src/Symfony/Component/Yaml/Yaml.php index 0a156ae21cee8..57625a5337ebb 100644 --- a/src/Symfony/Component/Yaml/Yaml.php +++ b/src/Symfony/Component/Yaml/Yaml.php @@ -37,6 +37,7 @@ class Yaml public const DUMP_NUMERIC_KEY_AS_STRING = 4096; public const DUMP_NULL_AS_EMPTY = 8192; public const DUMP_COMPACT_NESTED_MAPPING = 16384; + public const DUMP_FORCE_DOUBLE_QUOTES_ON_VALUES = 32768; /** * Parses a YAML file into a PHP value.