Skip to content

Commit

Permalink
Add tests and cover more cases
Browse files Browse the repository at this point in the history
  • Loading branch information
alamirault committed Nov 11, 2022
1 parent e2ff6b3 commit 27618ce
Show file tree
Hide file tree
Showing 4 changed files with 209 additions and 17 deletions.
17 changes: 12 additions & 5 deletions src/Symfony/Component/Yaml/Dumper.php
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,13 @@ public function dump(mixed $input, int $inline = 0, int $indent = 0, int $flags
if ($inline <= 0 || (!\is_array($input) && !$input instanceof TaggedValue && $dumpObjectAsInlineMap) || empty($input)) {
$output .= $prefix.Inline::dump($input, $flags);
} else {
if (Yaml::DUMP_NUMERIC_KEY_AS_STRING & $flags) {
$keyFlags = $flags;
$valueFlags = $flags - Yaml::DUMP_NUMERIC_KEY_AS_STRING;
} else {
$keyFlags = $valueFlags = $flags;
}

$dumpAsMap = Inline::isHash($input);

foreach ($input as $key => $value) {
Expand All @@ -77,7 +84,7 @@ public function dump(mixed $input, int $inline = 0, int $indent = 0, int $flags
$blockChompingIndicator = '-';
}

$output .= sprintf('%s%s%s |%s%s', $prefix, $dumpAsMap ? Inline::dump($key, $flags).':' : '-', '', $blockIndentationIndicator, $blockChompingIndicator);
$output .= sprintf('%s%s%s |%s%s', $prefix, $dumpAsMap ? Inline::dump($key, $keyFlags).':' : '-', '', $blockIndentationIndicator, $blockChompingIndicator);

foreach (explode("\n", $value) as $row) {
if ('' === $row) {
Expand All @@ -91,7 +98,7 @@ public function dump(mixed $input, int $inline = 0, int $indent = 0, int $flags
}

if ($value instanceof TaggedValue) {
$output .= sprintf('%s%s !%s', $prefix, $dumpAsMap ? Inline::dump($key, $flags).':' : '-', $value->getTag());
$output .= sprintf('%s%s !%s', $prefix, $dumpAsMap ? Inline::dump($key, $keyFlags).':' : '-', $value->getTag());

if (Yaml::DUMP_MULTI_LINE_LITERAL_BLOCK & $flags && \is_string($value->getValue()) && str_contains($value->getValue(), "\n") && !str_contains($value->getValue(), "\r\n")) {
// If the first line starts with a space character, the spec requires a blockIndicationIndicator
Expand All @@ -107,7 +114,7 @@ public function dump(mixed $input, int $inline = 0, int $indent = 0, int $flags
}

if ($inline - 1 <= 0 || null === $value->getValue() || \is_scalar($value->getValue())) {
$output .= ' '.$this->dump($value->getValue(), $inline - 1, 0, $flags)."\n";
$output .= ' '.$this->dump($value->getValue(), $inline - 1, 0, \is_int($value->getValue()) ? $valueFlags : $keyFlags)."\n";
} else {
$output .= "\n";
$output .= $this->dump($value->getValue(), $inline - 1, $dumpAsMap ? $indent + $this->indentation : $indent + 2, $flags);
Expand All @@ -126,9 +133,9 @@ public function dump(mixed $input, int $inline = 0, int $indent = 0, int $flags

$output .= sprintf('%s%s%s%s',
$prefix,
$dumpAsMap ? Inline::dump($key, $flags).':' : '-',
$dumpAsMap ? Inline::dump($key, $keyFlags).':' : '-',
$willBeInlined ? ' ' : "\n",
$this->dump($value, $inline - 1, $willBeInlined ? 0 : $indent + $this->indentation, $flags)
$this->dump($value, $inline - 1, $willBeInlined ? 0 : $indent + $this->indentation, \is_int($value) ? $valueFlags : $keyFlags)
).($willBeInlined ? "\n" : '');
}
}
Expand Down
32 changes: 24 additions & 8 deletions src/Symfony/Component/Yaml/Inline.php
Original file line number Diff line number Diff line change
Expand Up @@ -114,16 +114,23 @@ public static function dump(mixed $value, int $flags = 0): string
case $value instanceof \UnitEnum:
return sprintf('!php/const %s::%s', $value::class, $value->name);
case \is_object($value):
if (Yaml::DUMP_NUMERIC_KEY_AS_STRING & $flags) {
$keyFlags = $flags;
$valueFlags = $flags - Yaml::DUMP_NUMERIC_KEY_AS_STRING;
} else {
$keyFlags = $valueFlags = $flags;
}

if ($value instanceof TaggedValue) {
return '!'.$value->getTag().' '.self::dump($value->getValue(), $flags);
return '!'.$value->getTag().' '.self::dump($value->getValue(), $valueFlags);
}

if (Yaml::DUMP_OBJECT & $flags) {
return '!php/object '.self::dump(serialize($value));
}

if (Yaml::DUMP_OBJECT_AS_MAP & $flags && ($value instanceof \stdClass || $value instanceof \ArrayObject)) {
return self::dumpHashArray($value, $flags);
return self::dumpHashArray($value, $keyFlags, $valueFlags);
}

if (Yaml::DUMP_EXCEPTION_ON_INVALID_TYPE & $flags) {
Expand Down Expand Up @@ -220,30 +227,39 @@ public static function isHash(array|\ArrayObject|\stdClass $value): bool
*/
private static function dumpArray(array $value, int $flags): string
{
$numericKeysAsString = Yaml::DUMP_NUMERIC_KEY_AS_STRING & $flags;
if ($numericKeysAsString) {
$keyFlags = $flags;
$valueFlags = $flags - Yaml::DUMP_NUMERIC_KEY_AS_STRING;
} else {
$keyFlags = $valueFlags = $flags;
}

// array
if (($value || Yaml::DUMP_EMPTY_ARRAY_AS_SEQUENCE & $flags) && !self::isHash($value)) {
$output = [];
foreach ($value as $val) {
$output[] = self::dump($val, $flags);
$output[] = self::dump($val, $valueFlags);
}

return sprintf('[%s]', implode(', ', $output));
}

return self::dumpHashArray($value, $flags);
return self::dumpHashArray($value, $keyFlags, $valueFlags);
}

/**
* Dumps hash array to a YAML string.
*
* @param array|\ArrayObject|\stdClass $value The hash array to dump
* @param int $flags A bit field of Yaml::DUMP_* constants to customize the dumped YAML string
* @param array|\ArrayObject|\stdClass $value The hash array to dump
* @param int $keyFlags A bit field of Yaml::DUMP_* constants to customize the dumped YAML string
* @param int $valueFlags A bit field of Yaml::DUMP_* constants to customize the dumped YAML string
*/
private static function dumpHashArray(array|\ArrayObject|\stdClass $value, int $flags): string
private static function dumpHashArray(array|\ArrayObject|\stdClass $value, int $keyFlags, int $valueFlags): string
{
$output = [];
foreach ($value as $key => $val) {
$output[] = sprintf('%s: %s', self::dump($key, $flags), self::dump($val, $flags));
$output[] = sprintf('%s: %s', self::dump($key, $keyFlags), self::dump($val, \is_int($val) ? $valueFlags : $keyFlags));
}

return sprintf('{ %s }', implode(', ', $output));
Expand Down
62 changes: 60 additions & 2 deletions src/Symfony/Component/Yaml/Tests/DumperTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -804,9 +804,67 @@ public function testDumpNullAsTilde()
$this->assertSame('{ foo: ~ }', $this->dumper->dump(['foo' => null], 0, 0, Yaml::DUMP_NULL_AS_TILDE));
}

public function testDumpNumericKeyAsString()
/**
* @dataProvider getNumericKeyData
*/
public function testDumpInlineNumericKeyAsString(array $input, bool $inline, int $flags, string $expected)
{
$this->assertSame($expected, $this->dumper->dump($input, $inline ? 0 : 4, 0, $flags));
}

public function getNumericKeyData()
{
$this->assertSame("{ '200': foo }", $this->dumper->dump([200 => 'foo'], 0, 0, Yaml::DUMP_NUMERIC_KEY_AS_STRING));
yield 'Int key with flag ineline' => [
[200 => 'foo'],
true,
Yaml::DUMP_NUMERIC_KEY_AS_STRING,
"{ '200': foo }",
];

yield 'Int key without flag ineline' => [
[200 => 'foo'],
true,
0,
'{ 200: foo }',
];

$expected = <<<YAML
'200': foo
YAML;

yield 'Int key with flag' => [
[200 => 'foo'],
false,
Yaml::DUMP_NUMERIC_KEY_AS_STRING,
$expected,
];

$expected = <<<YAML
200: foo
YAML;

yield 'Int key without flag' => [
[200 => 'foo'],
false,
0,
$expected,
];

$expected = <<<YAML
count: !number 5
YAML;

yield 'Int tagged value with flag' => [
[
'count' => new TaggedValue('number', 5),
],
false,
Yaml::DUMP_NUMERIC_KEY_AS_STRING,
$expected,
];
}

public function testDumpIdeographicSpaces()
Expand Down
115 changes: 113 additions & 2 deletions src/Symfony/Component/Yaml/Tests/InlineTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -617,9 +617,120 @@ public function testDumpDateTime($dateTime, $expected)
$this->assertSame($expected, Inline::dump($dateTime));
}

public function testDumpNumericKeyAsString()
/**
* @dataProvider getNumericKeyData
*/
public function testDumpNumericKeyAsString(array|int $input, int $flags, string $expected)
{
$this->assertSame($expected, Inline::dump($input, $flags));
}

public function getNumericKeyData()
{
$this->assertSame("'200'", Inline::dump(200, Yaml::DUMP_NUMERIC_KEY_AS_STRING));
yield 'Int with flag' => [
200,
Yaml::DUMP_NUMERIC_KEY_AS_STRING,
"'200'",
];

yield 'Int without flag' => [
200,
0,
'200',
];

yield 'Int key with flag' => [
[200 => 'foo'],
Yaml::DUMP_NUMERIC_KEY_AS_STRING,
"{ '200': foo }",
];

yield 'String key with flag' => [
['200' => 'foo'],
Yaml::DUMP_NUMERIC_KEY_AS_STRING,
"{ '200': foo }",
];

yield 'Bool key with flag' => [
[true => 'foo'],
Yaml::DUMP_NUMERIC_KEY_AS_STRING,
"{ '1': foo }",
];

yield 'null key with flag' => [
[null => 'foo'],
Yaml::DUMP_NUMERIC_KEY_AS_STRING,
"{ '': foo }",
];

yield 'Int key without flag' => [
[200 => 'foo'],
0,
'{ 200: foo }',
];

yield 'Int value with flag' => [
[200 => 200],
Yaml::DUMP_NUMERIC_KEY_AS_STRING,
"{ '200': 200 }",
];

yield 'Mixed with flag' => [
[42 => 'a', 'b' => 'c', 'd' => 43],
Yaml::DUMP_NUMERIC_KEY_AS_STRING,
"{ '42': a, b: c, d: 43 }",
];

yield 'Auto-index with flag' => [
['a', 'b', 42],
Yaml::DUMP_NUMERIC_KEY_AS_STRING,
'[a, b, 42]',
];

yield 'Complex mixed array with flag' => [
[
42 => [
'foo' => 43,
44 => 'bar',
],
45 => 'baz',
46,
],
Yaml::DUMP_NUMERIC_KEY_AS_STRING,
"{ '42': { foo: 43, '44': bar }, '45': baz, '46': 46 }",
];

yield 'Int tagged value with flag' => [
[
'count' => new TaggedValue('number', 5),
],
Yaml::DUMP_NUMERIC_KEY_AS_STRING,
'{ count: !number 5 }',
];

yield 'Array tagged value with flag' => [
[
'user' => new TaggedValue('metadata', [
'john',
42,
]),
],
Yaml::DUMP_NUMERIC_KEY_AS_STRING,
'{ user: !metadata [john, 42] }',
];

$arrayObject = new \ArrayObject();
$arrayObject['foo'] = 'bar';
$arrayObject[42] = 'baz';
$arrayObject['baz'] = 43;

yield 'Object value with flag' => [
[
'user' => $arrayObject,
],
Yaml::DUMP_NUMERIC_KEY_AS_STRING | Yaml::DUMP_OBJECT_AS_MAP,
"{ user: { foo: bar, '42': baz, baz: 43 } }",
];
}

public function testDumpUnitEnum()
Expand Down

0 comments on commit 27618ce

Please sign in to comment.