Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit f71e4ab

Browse files
[Yaml] Add support for !php/enum *->value syntax
1 parent bbf25d6 commit f71e4ab

File tree

4 files changed

+103
-2
lines changed

4 files changed

+103
-2
lines changed

src/Symfony/Component/Yaml/CHANGELOG.md

+5
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
CHANGELOG
22
=========
33

4+
6.2
5+
---
6+
7+
* Add support for `!php/enum` and `!php/enum *->value`
8+
49
6.1
510
---
611

src/Symfony/Component/Yaml/Inline.php

+36-2
Original file line numberDiff line numberDiff line change
@@ -432,7 +432,7 @@ private static function parseMapping(string $mapping, int $flags, int &$i = 0, a
432432
throw new ParseException('Missing mapping key.', self::$parsedLineNumber + 1, $mapping);
433433
}
434434

435-
if ('!php/const' === $key) {
435+
if ('!php/const' === $key || '!php/enum' === $key) {
436436
$key .= ' '.self::parseScalar($mapping, $flags, [':'], $i, false);
437437
$key = self::evaluateScalar($key, $flags);
438438
}
@@ -623,6 +623,40 @@ private static function evaluateScalar(string $scalar, int $flags, array &$refer
623623
throw new ParseException(sprintf('The string "%s" could not be parsed as a constant. Did you forget to pass the "Yaml::PARSE_CONSTANT" flag to the parser?', $scalar), self::$parsedLineNumber + 1, $scalar, self::$parsedFilename);
624624
}
625625

626+
return null;
627+
case str_starts_with($scalar, '!php/enum'):
628+
if (self::$constantSupport) {
629+
if (!isset($scalar[11])) {
630+
throw new ParseException('Missing value for tag "!php/enum".', self::$parsedLineNumber + 1, $scalar, self::$parsedFilename);
631+
}
632+
633+
$i = 0;
634+
$enum = self::parseScalar(substr($scalar, 10), 0, null, $i, false);
635+
if ($useValue = str_ends_with($enum, '->value')) {
636+
$enum = substr($enum, 0, -7);
637+
}
638+
if (!\defined($enum)) {
639+
throw new ParseException(sprintf('The enum "%s" is not defined.', $enum), self::$parsedLineNumber + 1, $scalar, self::$parsedFilename);
640+
}
641+
642+
$value = \constant($enum);
643+
644+
if (!$value instanceof \UnitEnum) {
645+
throw new ParseException(sprintf('The string "%s" is not the name of a valid enum.', $enum), self::$parsedLineNumber + 1, $scalar, self::$parsedFilename);
646+
}
647+
if (!$useValue) {
648+
return $value;
649+
}
650+
if (!$value instanceof \BackedEnum) {
651+
throw new ParseException(sprintf('The enum "%s" defines no value next to its name.', $enum), self::$parsedLineNumber + 1, $scalar, self::$parsedFilename);
652+
}
653+
654+
return $value->value;
655+
}
656+
if (self::$exceptionOnInvalidType) {
657+
throw new ParseException(sprintf('The string "%s" could not be parsed as an enum. Did you forget to pass the "Yaml::PARSE_CONSTANT" flag to the parser?', $scalar), self::$parsedLineNumber + 1, $scalar, self::$parsedFilename);
658+
}
659+
626660
return null;
627661
case str_starts_with($scalar, '!!float '):
628662
return (float) substr($scalar, 8);
@@ -703,7 +737,7 @@ private static function parseTag(string $value, int &$i, int $flags): ?string
703737
}
704738

705739
// Is followed by a scalar and is a built-in tag
706-
if ('' !== $tag && (!isset($value[$nextOffset]) || !\in_array($value[$nextOffset], ['[', '{'], true)) && ('!' === $tag[0] || 'str' === $tag || 'php/const' === $tag || 'php/object' === $tag)) {
740+
if ('' !== $tag && (!isset($value[$nextOffset]) || !\in_array($value[$nextOffset], ['[', '{'], true)) && ('!' === $tag[0] || \in_array($tag, ['str', 'php/const', 'php/enum', 'php/object'], true))) {
707741
// Manage in {@link self::evaluateScalar()}
708742
return null;
709743
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<?php
2+
3+
namespace Symfony\Component\Yaml\Tests\Fixtures;
4+
5+
enum FooBackedEnum: string
6+
{
7+
case BAR = 'bar';
8+
}

src/Symfony/Component/Yaml/Tests/InlineTest.php

+54
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
use Symfony\Component\Yaml\Exception\ParseException;
1616
use Symfony\Component\Yaml\Inline;
1717
use Symfony\Component\Yaml\Tag\TaggedValue;
18+
use Symfony\Component\Yaml\Tests\Fixtures\FooBackedEnum;
1819
use Symfony\Component\Yaml\Tests\Fixtures\FooUnitEnum;
1920
use Symfony\Component\Yaml\Yaml;
2021

@@ -72,13 +73,45 @@ public function testParsePhpConstantThrowsExceptionWhenUndefined()
7273
Inline::parse('!php/const WRONG_CONSTANT', Yaml::PARSE_CONSTANT);
7374
}
7475

76+
public function testParsePhpEnumThrowsExceptionWhenUndefined()
77+
{
78+
$this->expectException(ParseException::class);
79+
$this->expectExceptionMessage('The enum "SomeEnum::Foo" is not defined');
80+
Inline::parse('!php/enum SomeEnum::Foo', Yaml::PARSE_CONSTANT);
81+
}
82+
83+
public function testParsePhpEnumThrowsExceptionWhenNotAnEnum()
84+
{
85+
$this->expectException(ParseException::class);
86+
$this->expectExceptionMessage('The string "PHP_INT_MAX" is not the name of a valid enum');
87+
Inline::parse('!php/enum PHP_INT_MAX', Yaml::PARSE_CONSTANT);
88+
}
89+
90+
public function testParsePhpEnumThrowsExceptionWhenNotBacked()
91+
{
92+
$this->expectException(ParseException::class);
93+
$this->expectExceptionMessage('The enum "Symfony\Component\Yaml\Tests\Fixtures\FooUnitEnum::BAR" defines no value next to its name');
94+
Inline::parse('!php/enum Symfony\Component\Yaml\Tests\Fixtures\FooUnitEnum::BAR->value', Yaml::PARSE_CONSTANT);
95+
}
96+
7597
public function testParsePhpConstantThrowsExceptionOnInvalidType()
7698
{
99+
$this->assertNull(Inline::parse('!php/const PHP_INT_MAX'));
100+
77101
$this->expectException(ParseException::class);
78102
$this->expectExceptionMessageMatches('#The string "!php/const PHP_INT_MAX" could not be parsed as a constant.*#');
79103
Inline::parse('!php/const PHP_INT_MAX', Yaml::PARSE_EXCEPTION_ON_INVALID_TYPE);
80104
}
81105

106+
public function testParsePhpEnumThrowsExceptionOnInvalidType()
107+
{
108+
$this->assertNull(Inline::parse('!php/enum SomeEnum::Foo'));
109+
110+
$this->expectException(ParseException::class);
111+
$this->expectExceptionMessageMatches('#The string "!php/enum SomeEnum::Foo" could not be parsed as an enum.*#');
112+
Inline::parse('!php/enum SomeEnum::Foo', Yaml::PARSE_EXCEPTION_ON_INVALID_TYPE);
113+
}
114+
82115
/**
83116
* @dataProvider getTestsForDump
84117
*/
@@ -589,6 +622,16 @@ public function testDumpUnitEnum()
589622
$this->assertSame("!php/const Symfony\Component\Yaml\Tests\Fixtures\FooUnitEnum::BAR", Inline::dump(FooUnitEnum::BAR));
590623
}
591624

625+
public function testParseUnitEnum()
626+
{
627+
$this->assertSame(FooUnitEnum::BAR, Inline::parse("!php/enum Symfony\Component\Yaml\Tests\Fixtures\FooUnitEnum::BAR", Yaml::PARSE_CONSTANT));
628+
}
629+
630+
public function testParseBackedEnumValue()
631+
{
632+
$this->assertSame(FooBackedEnum::BAR->value, Inline::parse("!php/enum Symfony\Component\Yaml\Tests\Fixtures\FooBackedEnum::BAR->value", Yaml::PARSE_CONSTANT));
633+
}
634+
592635
public function getDateTimeDumpTests()
593636
{
594637
$tests = [];
@@ -818,6 +861,17 @@ public function testPhpConstTagWithEmptyValue(string $value)
818861
Inline::parse($value, Yaml::PARSE_CONSTANT);
819862
}
820863

864+
/**
865+
* @dataProvider phpConstTagWithEmptyValueProvider
866+
*/
867+
public function testPhpEnumTagWithEmptyValue(string $value)
868+
{
869+
$this->expectException(ParseException::class);
870+
$this->expectExceptionMessage('Missing value for tag "!php/enum" at line 1 (near "!php/enum").');
871+
872+
Inline::parse(str_replace('!php/const', '!php/enum', $value), Yaml::PARSE_CONSTANT);
873+
}
874+
821875
public function phpConstTagWithEmptyValueProvider()
822876
{
823877
return [

0 commit comments

Comments
 (0)