diff --git a/rector.php b/rector.php index 6cb5a5c7e451..cf6985af1488 100644 --- a/rector.php +++ b/rector.php @@ -26,6 +26,7 @@ use Rector\CodingStyle\Rector\ClassMethod\MakeInheritedMethodVisibilitySameAsParentRector; use Rector\CodingStyle\Rector\FuncCall\CountArrayToEmptyArrayComparisonRector; use Rector\Config\RectorConfig; +use Rector\DeadCode\Rector\ClassMethod\RemoveUnusedConstructorParamRector; use Rector\DeadCode\Rector\ClassMethod\RemoveUnusedPrivateMethodRector; use Rector\DeadCode\Rector\If_\UnwrapFutureCompatibleIfPhpVersionRector; use Rector\DeadCode\Rector\MethodCall\RemoveEmptyMethodCallRector; @@ -88,6 +89,11 @@ __DIR__ . '/tests/system/Test/ReflectionHelperTest.php', ], + RemoveUnusedConstructorParamRector::class => [ + // @TODO remove if deprecated $httpVerb is removed + __DIR__ . '/system/Router/AutoRouterImproved.php', + ], + // call on purpose for nothing happen check RemoveEmptyMethodCallRector::class => [ __DIR__ . '/tests', diff --git a/system/Router/AutoRouter.php b/system/Router/AutoRouter.php index 3c29ff8290d4..3096b3bbd6f9 100644 --- a/system/Router/AutoRouter.php +++ b/system/Router/AutoRouter.php @@ -80,7 +80,7 @@ public function __construct( * * @return array [directory_name, controller_name, controller_method, params] */ - public function getRoute(string $uri): array + public function getRoute(string $uri, string $httpVerb): array { $segments = explode('/', $uri); diff --git a/system/Router/AutoRouterImproved.php b/system/Router/AutoRouterImproved.php index 39b264ecf780..603c7f3620d7 100644 --- a/system/Router/AutoRouterImproved.php +++ b/system/Router/AutoRouterImproved.php @@ -58,11 +58,6 @@ final class AutoRouterImproved implements AutoRouterInterface */ private bool $translateURIDashes; - /** - * HTTP verb for the request. - */ - private string $httpVerb; - /** * The namespace for controllers. */ @@ -74,15 +69,17 @@ final class AutoRouterImproved implements AutoRouterInterface private string $defaultController; /** - * The name of the default method + * The name of the default method without HTTP verb prefix. */ private string $defaultMethod; /** * @param class-string[] $protectedControllers * @param string $defaultController Short classname + * + * @deprecated $httpVerb is deprecated. No longer used. */ - public function __construct( + public function __construct(// @phpstan-ignore-line array $protectedControllers, string $namespace, string $defaultController, @@ -93,13 +90,11 @@ public function __construct( $this->protectedControllers = $protectedControllers; $this->namespace = rtrim($namespace, '\\') . '\\'; $this->translateURIDashes = $translateURIDashes; - $this->httpVerb = $httpVerb; $this->defaultController = $defaultController; - $this->defaultMethod = $httpVerb . ucfirst($defaultMethod); + $this->defaultMethod = $defaultMethod; // Set the default values $this->controller = $this->defaultController; - $this->method = $this->defaultMethod; } /** @@ -107,8 +102,11 @@ public function __construct( * * @return array [directory_name, controller_name, controller_method, params] */ - public function getRoute(string $uri): array + public function getRoute(string $uri, string $httpVerb): array { + $defaultMethod = strtolower($httpVerb) . ucfirst($this->defaultMethod); + $this->method = $defaultMethod; + $segments = explode('/', $uri); // WARNING: Directories get shifted out of the segments array. @@ -144,10 +142,10 @@ public function getRoute(string $uri): array $methodSegment = $this->translateURIDashes(array_shift($nonDirSegments)); // Prefix HTTP verb - $this->method = $this->httpVerb . ucfirst($methodSegment); + $this->method = $httpVerb . ucfirst($methodSegment); // Prevent access to default method path - if (strtolower($this->method) === strtolower($this->defaultMethod)) { + if (strtolower($this->method) === strtolower($defaultMethod)) { throw new PageNotFoundException( 'Cannot access the default method "' . $this->method . '" with the method name URI path.' ); diff --git a/system/Router/AutoRouterInterface.php b/system/Router/AutoRouterInterface.php index 9ecdd3ec2b30..6d98aec4a5bf 100644 --- a/system/Router/AutoRouterInterface.php +++ b/system/Router/AutoRouterInterface.php @@ -21,5 +21,5 @@ interface AutoRouterInterface * * @return array [directory_name, controller_name, controller_method, params] */ - public function getRoute(string $uri): array; + public function getRoute(string $uri, string $httpVerb): array; } diff --git a/system/Router/RouteCollection.php b/system/Router/RouteCollection.php index 50b73616ea0e..66724935e31c 100644 --- a/system/Router/RouteCollection.php +++ b/system/Router/RouteCollection.php @@ -150,7 +150,7 @@ class RouteCollection implements RouteCollectionInterface /** * The current method that the script is being called by. * - * @var string + * @var string HTTP verb (lower case) like `get`,`post` or `*` */ protected $HTTPVerb = '*'; @@ -550,11 +550,13 @@ public function getHTTPVerb(): string * Sets the current HTTP verb. * Used primarily for testing. * + * @param string $verb HTTP verb + * * @return $this */ public function setHTTPVerb(string $verb) { - $this->HTTPVerb = $verb; + $this->HTTPVerb = strtolower($verb); return $this; } diff --git a/system/Router/Router.php b/system/Router/Router.php index 8dd35c656e39..f9299fa1dd0a 100644 --- a/system/Router/Router.php +++ b/system/Router/Router.php @@ -126,7 +126,7 @@ public function __construct(RouteCollectionInterface $routes, ?Request $request $this->controller = $this->collection->getDefaultController(); $this->method = $this->collection->getDefaultMethod(); - $this->collection->setHTTPVerb(strtolower($request->getMethod() ?? $_SERVER['REQUEST_METHOD'])); + $this->collection->setHTTPVerb($request->getMethod() ?? $_SERVER['REQUEST_METHOD']); $this->translateURIDashes = $this->collection->shouldTranslateURIDashes(); @@ -504,7 +504,7 @@ protected function checkRoutes(string $uri): bool public function autoRoute(string $uri) { [$this->directory, $this->controller, $this->method, $this->params] - = $this->autoRouter->getRoute($uri); + = $this->autoRouter->getRoute($uri, $this->collection->getHTTPVerb()); } /** diff --git a/tests/system/Router/AutoRouterImprovedTest.php b/tests/system/Router/AutoRouterImprovedTest.php index ec94676be121..5b2fdff532c1 100644 --- a/tests/system/Router/AutoRouterImprovedTest.php +++ b/tests/system/Router/AutoRouterImprovedTest.php @@ -57,7 +57,7 @@ public function testAutoRouteFindsDefaultControllerAndMethodGet() $router = $this->createNewAutoRouter(); [$directory, $controller, $method, $params] - = $router->getRoute('/'); + = $router->getRoute('/', 'get'); $this->assertNull($directory); $this->assertSame('\\' . Index::class, $controller); @@ -72,7 +72,7 @@ public function testAutoRouteFindsDefaultControllerAndMethodPost() $router = $this->createNewAutoRouter('post'); [$directory, $controller, $method, $params] - = $router->getRoute('/'); + = $router->getRoute('/', 'post'); $this->assertNull($directory); $this->assertSame('\\' . Index::class, $controller); @@ -85,7 +85,7 @@ public function testAutoRouteFindsControllerWithFileAndMethod() $router = $this->createNewAutoRouter(); [$directory, $controller, $method, $params] - = $router->getRoute('mycontroller/somemethod'); + = $router->getRoute('mycontroller/somemethod', 'get'); $this->assertNull($directory); $this->assertSame('\\' . Mycontroller::class, $controller); @@ -98,7 +98,7 @@ public function testFindsControllerAndMethodAndParam() $router = $this->createNewAutoRouter(); [$directory, $controller, $method, $params] - = $router->getRoute('mycontroller/somemethod/a'); + = $router->getRoute('mycontroller/somemethod/a', 'get'); $this->assertNull($directory); $this->assertSame('\\' . Mycontroller::class, $controller); @@ -115,7 +115,7 @@ public function testUriParamCountIsGreaterThanMethodParams() $router = $this->createNewAutoRouter(); - $router->getRoute('mycontroller/somemethod/a/b'); + $router->getRoute('mycontroller/somemethod/a/b', 'get'); } public function testAutoRouteFindsControllerWithFile() @@ -123,7 +123,7 @@ public function testAutoRouteFindsControllerWithFile() $router = $this->createNewAutoRouter(); [$directory, $controller, $method, $params] - = $router->getRoute('mycontroller'); + = $router->getRoute('mycontroller', 'get'); $this->assertNull($directory); $this->assertSame('\\' . Mycontroller::class, $controller); @@ -136,7 +136,7 @@ public function testAutoRouteFindsControllerWithSubfolder() $router = $this->createNewAutoRouter(); [$directory, $controller, $method, $params] - = $router->getRoute('subfolder/mycontroller/somemethod'); + = $router->getRoute('subfolder/mycontroller/somemethod', 'get'); $this->assertSame('Subfolder/', $directory); $this->assertSame('\\' . \CodeIgniter\Router\Controllers\Subfolder\Mycontroller::class, $controller); @@ -149,7 +149,7 @@ public function testAutoRouteFindsDashedSubfolder() $router = $this->createNewAutoRouter(); [$directory, $controller, $method, $params] - = $router->getRoute('dash-folder/mycontroller/somemethod'); + = $router->getRoute('dash-folder/mycontroller/somemethod', 'get'); $this->assertSame('Dash_folder/', $directory); $this->assertSame( @@ -165,7 +165,7 @@ public function testAutoRouteFindsDashedController() $router = $this->createNewAutoRouter(); [$directory, $controller, $method, $params] - = $router->getRoute('dash-folder/dash-controller/somemethod'); + = $router->getRoute('dash-folder/dash-controller/somemethod', 'get'); $this->assertSame('Dash_folder/', $directory); $this->assertSame('\\' . Dash_controller::class, $controller); @@ -178,7 +178,7 @@ public function testAutoRouteFindsDashedMethod() $router = $this->createNewAutoRouter(); [$directory, $controller, $method, $params] - = $router->getRoute('dash-folder/dash-controller/dash-method'); + = $router->getRoute('dash-folder/dash-controller/dash-method', 'get'); $this->assertSame('Dash_folder/', $directory); $this->assertSame('\\' . Dash_controller::class, $controller); @@ -191,7 +191,7 @@ public function testAutoRouteFindsDefaultDashFolder() $router = $this->createNewAutoRouter(); [$directory, $controller, $method, $params] - = $router->getRoute('dash-folder'); + = $router->getRoute('dash-folder', 'get'); $this->assertSame('Dash_folder/', $directory); $this->assertSame('\\' . Home::class, $controller); @@ -205,7 +205,7 @@ public function testAutoRouteRejectsSingleDot() $router = $this->createNewAutoRouter(); - $router->getRoute('.'); + $router->getRoute('.', 'get'); } public function testAutoRouteRejectsDoubleDot() @@ -214,7 +214,7 @@ public function testAutoRouteRejectsDoubleDot() $router = $this->createNewAutoRouter(); - $router->getRoute('..'); + $router->getRoute('..', 'get'); } public function testAutoRouteRejectsMidDot() @@ -223,7 +223,7 @@ public function testAutoRouteRejectsMidDot() $router = $this->createNewAutoRouter(); - $router->getRoute('foo.bar'); + $router->getRoute('foo.bar', 'get'); } public function testRejectsDefaultControllerPath() @@ -232,7 +232,7 @@ public function testRejectsDefaultControllerPath() $router = $this->createNewAutoRouter(); - $router->getRoute('home'); + $router->getRoute('home', 'get'); } public function testRejectsDefaultControllerAndDefaultMethodPath() @@ -241,7 +241,7 @@ public function testRejectsDefaultControllerAndDefaultMethodPath() $router = $this->createNewAutoRouter(); - $router->getRoute('home/index'); + $router->getRoute('home/index', 'get'); } public function testRejectsDefaultMethodPath() @@ -250,7 +250,7 @@ public function testRejectsDefaultMethodPath() $router = $this->createNewAutoRouter(); - $router->getRoute('mycontroller/index'); + $router->getRoute('mycontroller/index', 'get'); } public function testRejectsControllerWithRemapMethod() @@ -262,6 +262,6 @@ public function testRejectsControllerWithRemapMethod() $router = $this->createNewAutoRouter(); - $router->getRoute('remap/test'); + $router->getRoute('remap/test', 'get'); } } diff --git a/tests/system/Test/FeatureTestAutoRoutingImprovedTest.php b/tests/system/Test/FeatureTestAutoRoutingImprovedTest.php new file mode 100644 index 000000000000..897697146fb5 --- /dev/null +++ b/tests/system/Test/FeatureTestAutoRoutingImprovedTest.php @@ -0,0 +1,75 @@ + + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + +namespace CodeIgniter\Test; + +use CodeIgniter\Events\Events; +use Config\Feature; +use Config\Services; + +/** + * @group Others + * + * @internal + */ +final class FeatureTestAutoRoutingImprovedTest extends CIUnitTestCase +{ + use FeatureTestTrait; + + public static function setUpBeforeClass(): void + { + parent::setUpBeforeClass(); + + Events::simulate(true); + + self::initializeRouter(); + } + + public static function tearDownAfterClass(): void + { + parent::tearDownAfterClass(); + + Events::simulate(false); + + Services::reset(); + } + + private static function initializeRouter(): void + { + $routes = Services::routes(); + $routes->resetRoutes(); + $routes->loadRoutes(); + + $routes->setAutoRoute(true); + config(Feature::class)->autoRoutesImproved = true; + + $namespace = 'Tests\Support\Controllers'; + $routes->setDefaultNamespace($namespace); + + $router = Services::router($routes); + + Services::injectMock('router', $router); + } + + public function testCallGet() + { + $response = $this->get('newautorouting'); + + $response->assertSee('Hello'); + } + + public function testCallPost() + { + $response = $this->post('newautorouting/save/1/a/b'); + + $response->assertSee('Saved'); + } +} diff --git a/user_guide_src/source/changelogs/v4.3.6.rst b/user_guide_src/source/changelogs/v4.3.6.rst index 01fc0893d41d..34551c1ede03 100644 --- a/user_guide_src/source/changelogs/v4.3.6.rst +++ b/user_guide_src/source/changelogs/v4.3.6.rst @@ -19,6 +19,11 @@ Interface Changes or implemented these interfaces, all these changes are backward compatible and require no intervention. +AutoRouterInterface +------------------- + +Now ``AutoRouterInterface::getRoute()`` has the new second parameter ``string $httpVerb``. + ValidationInterface::check() ---------------------------- @@ -43,6 +48,9 @@ Changes Deprecations ************ +- **AutoRouterImproved:** The constructor parameter ``$httpVerb`` is deprecated. + No longer used. + Bugs Fixed ********** @@ -51,6 +59,8 @@ Bugs Fixed - **Validation:** Fixed a bug that ``check()`` cannot specify non-default database group. - **Database:** Fixed a bug where semicolon character (``;``) in one of the Postgre connection parameters would break the DSN string. +- **AutoRouting Improved:** Fixed a bug that feature testing may not find + controller/method. See the repo's `CHANGELOG.md `_ diff --git a/user_guide_src/source/installation/upgrade_436.rst b/user_guide_src/source/installation/upgrade_436.rst index 71efd80d9f85..7d4e99bb602a 100644 --- a/user_guide_src/source/installation/upgrade_436.rst +++ b/user_guide_src/source/installation/upgrade_436.rst @@ -18,6 +18,9 @@ Mandatory File Changes Breaking Changes **************** +- ``AutoRouterInterface::getRoute()`` has the new second parameter ``string $httpVerb``. + If you implement it, add the parameter. + Breaking Enhancements *********************