From 2f37c60f956d70792b43061e264424b1f15f2457 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20Lundb=C3=B8l?= Date: Thu, 16 Mar 2023 00:48:03 +0100 Subject: [PATCH] Cast enums with optional parameters --- .../Routing/ImplicitRouteBinding.php | 2 +- src/Illuminate/Support/Reflector.php | 8 ++++++-- tests/Routing/ImplicitRouteBindingTest.php | 18 ++++++++++++++++++ tests/Routing/RoutingRouteTest.php | 14 ++++++++++++++ 4 files changed, 39 insertions(+), 3 deletions(-) diff --git a/src/Illuminate/Routing/ImplicitRouteBinding.php b/src/Illuminate/Routing/ImplicitRouteBinding.php index d9978af3193a..d3590de1d707 100644 --- a/src/Illuminate/Routing/ImplicitRouteBinding.php +++ b/src/Illuminate/Routing/ImplicitRouteBinding.php @@ -84,7 +84,7 @@ protected static function resolveBackedEnumsForRoute($route, $parameters) $parameterValue = $parameters[$parameterName]; - $backedEnumClass = (string) $parameter->getType(); + $backedEnumClass = $parameter->getType()?->getName(); $backedEnum = $backedEnumClass::tryFrom((string) $parameterValue); diff --git a/src/Illuminate/Support/Reflector.php b/src/Illuminate/Support/Reflector.php index 0282378631d7..72609b90db6e 100644 --- a/src/Illuminate/Support/Reflector.php +++ b/src/Illuminate/Support/Reflector.php @@ -148,9 +148,13 @@ public static function isParameterSubclassOf($parameter, $className) */ public static function isParameterBackedEnumWithStringBackingType($parameter) { - $backedEnumClass = (string) $parameter->getType(); + $backedEnumClass = $parameter->getType(); - if (enum_exists($backedEnumClass)) { + if (null === $backedEnumClass) { + return false; + } + + if (enum_exists($backedEnumClass->getName())) { $reflectionBackedEnum = new ReflectionEnum($backedEnumClass); return $reflectionBackedEnum->isBacked() diff --git a/tests/Routing/ImplicitRouteBindingTest.php b/tests/Routing/ImplicitRouteBindingTest.php index 909af4be3e78..675196a11364 100644 --- a/tests/Routing/ImplicitRouteBindingTest.php +++ b/tests/Routing/ImplicitRouteBindingTest.php @@ -31,6 +31,24 @@ public function test_it_can_resolve_the_implicit_backed_enum_route_bindings_for_ $this->assertSame('fruits', $route->parameter('category')->value); } + public function test_it_can_resolve_the_implicit_backed_enum_route_bindings_for_the_given_route_with_optional_parameter() + { + $action = ['uses' => function (?CategoryBackedEnum $category = null) { + return $category->value; + }]; + + $route = new Route('GET', '/test', $action); + $route->parameters = ['category' => 'fruits']; + + $route->prepareForSerialization(); + + $container = Container::getInstance(); + + ImplicitRouteBinding::resolveForRoute($container, $route); + + $this->assertSame('fruits', $route->parameter('category')->value); + } + public function test_it_does_not_resolve_implicit_non_backed_enum_route_bindings_for_the_given_route() { $action = ['uses' => function (CategoryEnum $category) { diff --git a/tests/Routing/RoutingRouteTest.php b/tests/Routing/RoutingRouteTest.php index 5a1a675d5cf5..eeceb390169d 100644 --- a/tests/Routing/RoutingRouteTest.php +++ b/tests/Routing/RoutingRouteTest.php @@ -1893,6 +1893,20 @@ public function testImplicitBindingsWithOptionalParameterWithNoKeyInUri() $router->dispatch(Request::create('foo', 'GET'))->getContent(); } + public function testImplicitBindingsWithOptionalParameterUsingEnumIsAlwaysCastedToEnum() + { + include 'enums.php'; + + $router = $this->getRouter(); + $router->get('foo/{bar?}', [ + 'middleware' => SubstituteBindings::class, + 'uses' => function (?\Illuminate\Tests\Routing\CategoryBackedEnum $bar = null) { + $this->assertInstanceOf(CategoryBackedEnum::class, $bar); + }, + ]); + $router->dispatch(Request::create('foo/people', 'GET'))->getContent(); + } + public function testImplicitBindingsWithOptionalParameterWithNonExistingKeyInUri() { $this->expectException(ModelNotFoundException::class);