diff --git a/src/Symfony/Component/Routing/Requirement/EnumRequirement.php b/src/Symfony/Component/Routing/Requirement/EnumRequirement.php index ba5078cda3f8a..2a369845c4eb4 100644 --- a/src/Symfony/Component/Routing/Requirement/EnumRequirement.php +++ b/src/Symfony/Component/Routing/Requirement/EnumRequirement.php @@ -15,36 +15,42 @@ final class EnumRequirement implements \Stringable { - /** - * @var string[] - */ - private readonly array $values; + private string $requirement; /** * @template T of \BackedEnum - * @param class-string $enum - * @param T ...$cases + * + * @param class-string|list $cases */ - public function __construct(string $enum, \BackedEnum ...$cases) + public function __construct(string|array $cases = []) { - if (!\is_subclass_of($enum, \BackedEnum::class, true)) { - throw new InvalidArgumentException(sprintf('"%s" is not a \BackedEnum class.', $enum)); - } + if (\is_string($cases)) { + if (!is_subclass_of($cases, \BackedEnum::class, true)) { + throw new InvalidArgumentException(sprintf('"%s" is not a "BackedEnum" class.', $cases)); + } + + $cases = $cases::cases(); + } else { + $class = null; + + foreach ($cases as $case) { + if (!$case instanceof \BackedEnum) { + throw new InvalidArgumentException(sprintf('Case must be a "BackedEnum" instance, "%s" given.', get_debug_type($case))); + } + + $class ??= \get_class($case); - foreach ($cases as $case) { - if (!$case instanceof $enum) { - throw new InvalidArgumentException(sprintf('"%s::%s" is not a case of "%s".', \get_class($case), $case->name, $enum)); + if (!$case instanceof $class) { + throw new InvalidArgumentException(sprintf('"%s::%s" is not a case of "%s".', get_debug_type($case), $case->name, $class)); + } } } - $this->values = array_map( - static fn (\BackedEnum $e): string => $e->value, - $cases ?: $enum::cases(), - ); + $this->requirement = implode('|', array_map(static fn ($e) => preg_quote($e->value), $cases)); } public function __toString(): string { - return implode('|', array_map(preg_quote(...), $this->values)); + return $this->requirement; } } diff --git a/src/Symfony/Component/Routing/Tests/Requirement/EnumRequirementTest.php b/src/Symfony/Component/Routing/Tests/Requirement/EnumRequirementTest.php index 18484c03d142a..75613f4985575 100644 --- a/src/Symfony/Component/Routing/Tests/Requirement/EnumRequirementTest.php +++ b/src/Symfony/Component/Routing/Tests/Requirement/EnumRequirementTest.php @@ -25,25 +25,33 @@ class EnumRequirementTest extends TestCase public function testNotABackedEnum() { $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessage('"Symfony\Component\Routing\Tests\Fixtures\Enum\TestUnitEnum" is not a \BackedEnum class.'); + $this->expectExceptionMessage('"Symfony\Component\Routing\Tests\Fixtures\Enum\TestUnitEnum" is not a "BackedEnum" class.'); new EnumRequirement(TestUnitEnum::class); } + public function testCaseNotABackedEnum() + { + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage('Case must be a "BackedEnum" instance, "string" given.'); + + new EnumRequirement(['wrong']); + } + public function testCaseFromAnotherEnum() { $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('"Symfony\Component\Routing\Tests\Fixtures\Enum\TestStringBackedEnum2::Spades" is not a case of "Symfony\Component\Routing\Tests\Fixtures\Enum\TestStringBackedEnum".'); - new EnumRequirement(TestStringBackedEnum::class, TestStringBackedEnum::Diamonds, TestStringBackedEnum2::Spades); + new EnumRequirement([TestStringBackedEnum::Diamonds, TestStringBackedEnum2::Spades]); } /** * @dataProvider provideToString */ - public function testToString(string $expected, string $enum, \BackedEnum ...$cases) + public function testToString(string $expected, string|array $cases = []) { - $this->assertSame($expected, (string) new EnumRequirement($enum, ...$cases)); + $this->assertSame($expected, (string) new EnumRequirement($cases)); } public function provideToString() @@ -51,7 +59,8 @@ public function provideToString() return [ ['hearts|diamonds|clubs|spades', TestStringBackedEnum::class], ['10|20|30|40', TestIntBackedEnum::class], - ['diamonds|spades', TestStringBackedEnum::class, TestStringBackedEnum::Diamonds, TestStringBackedEnum::Spades], + ['diamonds|spades', [TestStringBackedEnum::Diamonds, TestStringBackedEnum::Spades]], + ['diamonds', [TestStringBackedEnum::Diamonds]], ['hearts|diamonds|clubs|spa\|des', TestStringBackedEnum2::class], ]; }