From d54f6135f9ab496c2e9213cd2975486088cb6bd6 Mon Sep 17 00:00:00 2001 From: kenjis Date: Fri, 21 Jun 2024 12:45:05 +0900 Subject: [PATCH 1/4] test: add test for translateUriToCamelCase and Default Method Fallback --- .../system/Router/AutoRouterImprovedTest.php | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/tests/system/Router/AutoRouterImprovedTest.php b/tests/system/Router/AutoRouterImprovedTest.php index c60c978e4a3c..5975280bcdfd 100644 --- a/tests/system/Router/AutoRouterImprovedTest.php +++ b/tests/system/Router/AutoRouterImprovedTest.php @@ -277,6 +277,28 @@ public function testAutoRouteFallbackToDefaultMethod(): void ], $router->getPos()); } + public function testAutoRouteFallbackToDefaultMethodWithTranslateUriToCamelCase(): void + { + $config = config(Routing::class); + $config->translateUriToCamelCase = true; + Factories::injectMock('config', Routing::class, $config); + + $router = $this->createNewAutoRouter(); + + [$directory, $controller, $method, $params] + = $router->getRoute('index/15', Method::GET); + + $this->assertNull($directory); + $this->assertSame('\\' . Index::class, $controller); + $this->assertSame('getIndex', $method); + $this->assertSame(['15'], $params); + $this->assertSame([ + 'controller' => 0, + 'method' => null, + 'params' => 1, + ], $router->getPos()); + } + public function testAutoRouteFallbackToDefaultControllerOneParam(): void { $router = $this->createNewAutoRouter(); From 4882913cfd332234c3231162f9b0e196af7ab077 Mon Sep 17 00:00:00 2001 From: kenjis Date: Fri, 21 Jun 2024 12:46:32 +0900 Subject: [PATCH 2/4] fix: Auto Routing (Improved) Default Method Fallback does not work with $translateUriToCamelCase --- system/Router/AutoRouterImproved.php | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/system/Router/AutoRouterImproved.php b/system/Router/AutoRouterImproved.php index 0db5ebc1ddc2..57d5ca0ad610 100644 --- a/system/Router/AutoRouterImproved.php +++ b/system/Router/AutoRouterImproved.php @@ -519,7 +519,15 @@ private function checkUriForMethod(string $method): void return; } - if (! in_array($method, get_class_methods($this->controller), true)) { + // If `getSomeMethod()` exists, only `controller/some-method` should be + // accessible. But if a visitor navigates to `controller/somemethod`, + // `getSomemethod()` will be checked, and method_exists() will return true. + if ( + method_exists($this->controller, $method) + // We do not permit `controller/somemethod`, so check the exact method + // name. + && ! in_array($method, get_class_methods($this->controller), true) + ) { throw new PageNotFoundException( '"' . $this->controller . '::' . $method . '()" is not found.' ); From 96de786a0cb7f4c7a59dec9a75e5f276b9b2fc5a Mon Sep 17 00:00:00 2001 From: kenjis Date: Fri, 21 Jun 2024 13:01:01 +0900 Subject: [PATCH 3/4] refactor: rename method name --- system/Router/AutoRouterImproved.php | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/system/Router/AutoRouterImproved.php b/system/Router/AutoRouterImproved.php index 57d5ca0ad610..09a796ae0f3c 100644 --- a/system/Router/AutoRouterImproved.php +++ b/system/Router/AutoRouterImproved.php @@ -162,7 +162,7 @@ private function searchFirstController(): bool $segment = array_shift($segments); $controllerPos++; - $class = $this->translateURIDashes($segment); + $class = $this->translateURI($segment); // as soon as we encounter any segment that is not PSR-4 compliant, stop searching if (! $this->isValidSegment($class)) { @@ -209,7 +209,7 @@ private function searchLastDefaultController(): bool } $namespaces = array_map( - fn ($segment) => $this->translateURIDashes($segment), + fn ($segment) => $this->translateURI($segment), $segments ); @@ -307,7 +307,7 @@ public function getRoute(string $uri, string $httpVerb): array $method = ''; if ($methodParam !== null) { - $method = $httpVerb . $this->translateURIDashes($methodParam); + $method = $httpVerb . $this->translateURI($methodParam); $this->checkUriForMethod($method); } @@ -544,7 +544,10 @@ private function isValidSegment(string $segment): bool return (bool) preg_match('/^[a-zA-Z_\x80-\xff][a-zA-Z0-9_\x80-\xff]*$/', $segment); } - private function translateURIDashes(string $segment): string + /** + * Translates URI segment to CamelCase or replaces `-` with `_`. + */ + private function translateURI(string $segment): string { if ($this->translateUriToCamelCase) { if (strtolower($segment) !== $segment) { From d474187587290259d9f650bb301fac7c27909395 Mon Sep 17 00:00:00 2001 From: kenjis Date: Mon, 24 Jun 2024 09:40:52 +0900 Subject: [PATCH 4/4] docs: improve comment --- system/Router/AutoRouterImproved.php | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/system/Router/AutoRouterImproved.php b/system/Router/AutoRouterImproved.php index 09a796ae0f3c..63cdd7702635 100644 --- a/system/Router/AutoRouterImproved.php +++ b/system/Router/AutoRouterImproved.php @@ -519,13 +519,15 @@ private function checkUriForMethod(string $method): void return; } - // If `getSomeMethod()` exists, only `controller/some-method` should be - // accessible. But if a visitor navigates to `controller/somemethod`, - // `getSomemethod()` will be checked, and method_exists() will return true. if ( + // For example, if `getSomeMethod()` exists in the controller, only + // the URI `controller/some-method` should be accessible. But if a + // visitor navigates to the URI `controller/somemethod`, `getSomemethod()` + // will be checked, and `method_exists()` will return true because + // method names in PHP are case-insensitive. method_exists($this->controller, $method) - // We do not permit `controller/somemethod`, so check the exact method - // name. + // But we do not permit `controller/somemethod`, so check the exact + // method name. && ! in_array($method, get_class_methods($this->controller), true) ) { throw new PageNotFoundException(