Skip to content

Commit b84bd14

Browse files
authored
Merge pull request #7690 from kenjis/fix-auto-routing-legacy-cli-routes
fix: auto routing legacy and $route->add()
2 parents 0c7e178 + bed018a commit b84bd14

7 files changed

Lines changed: 54 additions & 32 deletions

File tree

phpstan-baseline.neon.dist

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -197,16 +197,11 @@ parameters:
197197

198198
-
199199
message: "#^Call to an undefined method CodeIgniter\\\\Router\\\\RouteCollectionInterface\\:\\:getRegisteredControllers\\(.*\\)\\.$#"
200-
count: 2
201-
path: system/Router/Router.php
202-
203-
-
204-
message: "#^Expression on left side of \\?\\? is not nullable\\.$#"
205200
count: 1
206201
path: system/Router/Router.php
207202

208203
-
209-
message: "#^Method CodeIgniter\\\\Router\\\\RouteCollectionInterface\\:\\:getRoutes\\(\\) invoked with 1 parameter, 0 required\\.$#"
204+
message: "#^Expression on left side of \\?\\? is not nullable\\.$#"
210205
count: 1
211206
path: system/Router/Router.php
212207

system/Router/AutoRouter.php

Lines changed: 33 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
namespace CodeIgniter\Router;
1313

14+
use Closure;
1415
use CodeIgniter\Exceptions\PageNotFoundException;
1516

1617
/**
@@ -19,11 +20,11 @@
1920
final class AutoRouter implements AutoRouterInterface
2021
{
2122
/**
22-
* List of controllers registered for the CLI verb that should not be accessed in the web.
23+
* List of CLI routes that do not contain '*' routes.
2324
*
24-
* @var class-string[]
25+
* @var array<string, Closure|string> [routeKey => handler]
2526
*/
26-
private array $protectedControllers;
27+
private array $cliRoutes;
2728

2829
/**
2930
* Sub-directory that contains the requested controller class.
@@ -58,17 +59,17 @@ final class AutoRouter implements AutoRouterInterface
5859
private string $defaultNamespace;
5960

6061
public function __construct(
61-
array $protectedControllers,
62+
array $cliRoutes,
6263
string $defaultNamespace,
6364
string $defaultController,
6465
string $defaultMethod,
6566
bool $translateURIDashes,
6667
string $httpVerb
6768
) {
68-
$this->protectedControllers = $protectedControllers;
69-
$this->defaultNamespace = $defaultNamespace;
70-
$this->translateURIDashes = $translateURIDashes;
71-
$this->httpVerb = $httpVerb;
69+
$this->cliRoutes = $cliRoutes;
70+
$this->defaultNamespace = $defaultNamespace;
71+
$this->translateURIDashes = $translateURIDashes;
72+
$this->httpVerb = $httpVerb;
7273

7374
$this->controller = $defaultController;
7475
$this->method = $defaultMethod;
@@ -126,18 +127,31 @@ public function getRoute(string $uri, string $httpVerb): array
126127
$controller .= $controllerName;
127128

128129
$controller = strtolower($controller);
129-
130-
foreach ($this->protectedControllers as $controllerInRoute) {
131-
if (! is_string($controllerInRoute)) {
132-
continue;
133-
}
134-
if (strtolower($controllerInRoute) !== $controller) {
135-
continue;
130+
$methodName = strtolower($this->methodName());
131+
132+
foreach ($this->cliRoutes as $handler) {
133+
if (is_string($handler)) {
134+
$handler = strtolower($handler);
135+
136+
// Like $routes->cli('hello/(:segment)', 'Home::$1')
137+
if (strpos($handler, '::$') !== false) {
138+
throw new PageNotFoundException(
139+
'Cannot access CLI Route: ' . $uri
140+
);
141+
}
142+
143+
if (strpos($handler, $controller . '::' . $methodName) === 0) {
144+
throw new PageNotFoundException(
145+
'Cannot access CLI Route: ' . $uri
146+
);
147+
}
148+
149+
if ($handler === $controller) {
150+
throw new PageNotFoundException(
151+
'Cannot access CLI Route: ' . $uri
152+
);
153+
}
136154
}
137-
138-
throw new PageNotFoundException(
139-
'Cannot access the controller in a CLI Route. Controller: ' . $controllerInRoute
140-
);
141155
}
142156
}
143157

system/Router/RouteCollection.php

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -484,8 +484,10 @@ public function shouldAutoRoute(): bool
484484

485485
/**
486486
* Returns the raw array of available routes.
487+
*
488+
* @param bool $includeWildcard Whether to include '*' routes.
487489
*/
488-
public function getRoutes(?string $verb = null): array
490+
public function getRoutes(?string $verb = null, bool $includeWildcard = true): array
489491
{
490492
if (empty($verb)) {
491493
$verb = $this->getHTTPVerb();
@@ -501,7 +503,7 @@ public function getRoutes(?string $verb = null): array
501503
if (isset($this->routes[$verb])) {
502504
// Keep current verb's routes at the beginning, so they're matched
503505
// before any of the generic, "add" routes.
504-
$collection = $this->routes[$verb] + ($this->routes['*'] ?? []);
506+
$collection = $includeWildcard ? $this->routes[$verb] + ($this->routes['*'] ?? []) : $this->routes[$verb];
505507

506508
foreach ($collection as $r) {
507509
$key = key($r['route']);

system/Router/Router.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,7 @@ public function __construct(RouteCollectionInterface $routes, ?Request $request
145145
);
146146
} else {
147147
$this->autoRouter = new AutoRouter(
148-
$this->collection->getRegisteredControllers('cli'),
148+
$this->collection->getRoutes('cli', false), // @phpstan-ignore-line
149149
$this->collection->getDefaultNamespace(),
150150
$this->collection->getDefaultController(),
151151
$this->collection->getDefaultMethod(),
@@ -393,6 +393,7 @@ public function getLocale()
393393
*/
394394
protected function checkRoutes(string $uri): bool
395395
{
396+
// @phpstan-ignore-next-line
396397
$routes = $this->collection->getRoutes($this->collection->getHTTPVerb());
397398

398399
// Don't waste any time

tests/system/Test/FeatureTestTraitTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -325,7 +325,7 @@ public function provideRoutesData()
325325
public function testOpenCliRoutesFromHttpGot404($from, $to, $httpGet)
326326
{
327327
$this->expectException(PageNotFoundException::class);
328-
$this->expectExceptionMessage('Cannot access the controller in a CLI Route.');
328+
$this->expectExceptionMessage('Cannot access CLI Route: ');
329329

330330
$collection = Services::routes();
331331
$collection->setAutoRoute(true);

user_guide_src/source/changelogs/v4.3.7.rst

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,10 @@ Release Date: Unreleased
1212
BREAKING
1313
********
1414

15+
- **RouteCollection:** The second parameter ``bool $includeWildcard = true`` has
16+
been added to the ``RouteCollection::getRoutes()`` method.
17+
- **AutoRouting Legacy:** The first parameter of the ``AutoRouter::__construct()``
18+
has been changed from ``$protectedControllers`` to ``$cliRoutes``.
1519
- **FeatureTestTrait:** When using :ref:`withBodyFormat() <feature-formatting-the-request>`,
1620
the priority of the request body has been changed.
1721
See :ref:`Upgrading Guide <upgrade-437-feature-testing>` for details.
@@ -28,6 +32,10 @@ Deprecations
2832
Bugs Fixed
2933
**********
3034

35+
- **AutoRouting Legacy:** Fixed a bug that when you added a route with
36+
``$routes->add()``, the controller's other methods were inaccessible from the
37+
web browser.
38+
3139
See the repo's
3240
`CHANGELOG.md <https://github.com/codeigniter4/CodeIgniter4/blob/develop/CHANGELOG.md>`_
3341
for a complete list of bugs fixed.

user_guide_src/source/incoming/routing.rst

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -324,10 +324,12 @@ Command-Line Only Routes
324324
.. note:: It is recommended to use Spark Commands for CLI scripts instead of calling controllers via CLI.
325325
See the :doc:`../cli/cli_commands` page for detailed information.
326326

327-
You can create routes that work only from the command-line, and are inaccessible from the web browser, with the
328-
``cli()`` method. Any route created by any of the HTTP-verb-based
327+
Any route created by any of the HTTP-verb-based
329328
route methods will also be inaccessible from the CLI, but routes created by the ``add()`` method will still be
330-
available from the command line:
329+
available from the command line.
330+
331+
You can create routes that work only from the command-line, and are inaccessible from the web browser, with the
332+
``cli()`` method:
331333

332334
.. literalinclude:: routing/032.php
333335

0 commit comments

Comments
 (0)