Skip to content

Commit 9f42e31

Browse files
authored
Merge pull request #6644 from kenjis/fix-routes-processing
fix: routes registration bug
2 parents ac753fc + daa1b7c commit 9f42e31

3 files changed

Lines changed: 85 additions & 8 deletions

File tree

system/Router/RouteCollection.php

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ class RouteCollection implements RouteCollectionInterface
110110
* verb => [
111111
* routeName => [
112112
* 'route' => [
113-
* routeKey => handler,
113+
* routeKey(or from) => handler,
114114
* ]
115115
* ]
116116
* ],
@@ -133,6 +133,14 @@ class RouteCollection implements RouteCollectionInterface
133133
* Array of routes options
134134
*
135135
* @var array
136+
*
137+
* [
138+
* verb => [
139+
* routeKey(or from) => [
140+
* key => value,
141+
* ]
142+
* ],
143+
* ]
136144
*/
137145
protected $routesOptions = [];
138146

@@ -1239,12 +1247,15 @@ protected function create(string $verb, string $from, $to, ?array $options = nul
12391247

12401248
$name = $options['as'] ?? $from;
12411249

1250+
helper('array');
1251+
12421252
// Don't overwrite any existing 'froms' so that auto-discovered routes
12431253
// do not overwrite any app/Config/Routes settings. The app
12441254
// routes should always be the "source of truth".
12451255
// this works only because discovered routes are added just prior
12461256
// to attempting to route the request.
1247-
if (isset($this->routes[$verb][$name]) && ! $overwrite) {
1257+
$fromExists = dot_array_search('*.route.' . $from, $this->routes[$verb] ?? []) !== null;
1258+
if ((isset($this->routes[$verb][$name]) || $fromExists) && ! $overwrite) {
12481259
return;
12491260
}
12501261

tests/system/HTTP/RedirectResponseTest.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -73,12 +73,12 @@ public function testRedirectRoute()
7373
$this->assertTrue($response->hasHeader('Location'));
7474
$this->assertSame('http://example.com/index.php/exampleRoute', $response->getHeaderLine('Location'));
7575

76-
$this->routes->add('exampleRoute', 'Home::index', ['as' => 'home']);
76+
$this->routes->add('exampleRoute2', 'Home::index', ['as' => 'home']);
7777

7878
$response->route('home');
7979

8080
$this->assertTrue($response->hasHeader('Location'));
81-
$this->assertSame('http://example.com/index.php/exampleRoute', $response->getHeaderLine('Location'));
81+
$this->assertSame('http://example.com/index.php/exampleRoute2', $response->getHeaderLine('Location'));
8282
}
8383

8484
public function testRedirectRouteBadNamedRoute()

tests/system/Router/RouteCollectionTest.php

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

1212
namespace CodeIgniter\Router;
1313

14-
use App\Controllers\Home;
1514
use CodeIgniter\Config\Services;
1615
use CodeIgniter\Test\CIUnitTestCase;
1716
use Config\Modules;
@@ -1189,6 +1188,73 @@ static function () {},
11891188
$this->assertSame($options, ['as' => 'admin', 'foo' => 'baz']);
11901189
}
11911190

1191+
/**
1192+
* @dataProvider optionsProvider
1193+
*/
1194+
public function testRoutesOptionsWithSameFromTwoRoutes(array $options1, array $options2)
1195+
{
1196+
$routes = $this->getCollector();
1197+
1198+
// This is the first route for `administrator`.
1199+
$routes->get(
1200+
'administrator',
1201+
static function () {},
1202+
$options1
1203+
);
1204+
// The second route for `administrator` should be ignored.
1205+
$routes->get(
1206+
'administrator',
1207+
static function () {},
1208+
$options2
1209+
);
1210+
1211+
$options = $routes->getRoutesOptions('administrator');
1212+
1213+
$this->assertSame($options, $options1);
1214+
}
1215+
1216+
public function optionsProvider()
1217+
{
1218+
yield from [
1219+
[
1220+
[
1221+
'foo' => 'options1',
1222+
],
1223+
[
1224+
'foo' => 'options2',
1225+
],
1226+
],
1227+
[
1228+
[
1229+
'as' => 'admin',
1230+
'foo' => 'options1',
1231+
],
1232+
[
1233+
'foo' => 'options2',
1234+
],
1235+
],
1236+
[
1237+
[
1238+
'foo' => 'options1',
1239+
],
1240+
[
1241+
'as' => 'admin',
1242+
'foo' => 'options2',
1243+
],
1244+
],
1245+
[
1246+
[
1247+
'as' => 'admin',
1248+
'foo' => 'options1',
1249+
],
1250+
[
1251+
'as' => 'admin',
1252+
'foo' => 'options2',
1253+
],
1254+
],
1255+
];
1256+
}
1257+
11921258
public function testRoutesOptionsForDifferentVerbs()
11931259
{
11941260
$routes = $this->getCollector();
@@ -1460,12 +1526,12 @@ public function testRouteOverwritingTwoRules()
14601526
$routes->setDefaultController('Home');
14611527
$routes->setDefaultMethod('index');
14621528

1529+
// The subdomain of the current URL is `doc`, so this route is registered.
14631530
$routes->get('/', '\App\Controllers\Site\CDoc::index', ['subdomain' => 'doc', 'as' => 'doc_index']);
1531+
// The subdomain route is already registered, so this route is not registered.
14641532
$routes->get('/', 'Home::index');
14651533

1466-
// the second rule applies, so overwrites the first
1467-
$expects = '\\' . Home::class;
1468-
1534+
$expects = '\App\Controllers\Site\CDoc';
14691535
$this->assertSame($expects, $router->handle('/'));
14701536
}
14711537

0 commit comments

Comments
 (0)