Skip to content

Commit 458e2d4

Browse files
authored
Merge pull request #3172 from michalsn/router_regex
Add Unicode support for regular expressions in router
2 parents d9864e3 + 6203e42 commit 458e2d4

3 files changed

Lines changed: 49 additions & 5 deletions

File tree

system/Router/RouteCollection.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1348,7 +1348,7 @@ protected function fillRouteParams(string $from, array $params = null): string
13481348
// the expected param type.
13491349
$pos = strpos($from, $pattern);
13501350

1351-
if (preg_match('#' . $pattern . '#', $params[$index]))
1351+
if (preg_match('#^' . $pattern . '$#u', $params[$index]))
13521352
{
13531353
$from = substr_replace($from, $params[$index], $pos, strlen($pattern));
13541354
}

system/Router/Router.php

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,9 @@ public function handle(string $uri = null)
171171
: $this->controller;
172172
}
173173

174+
// Decode URL-encoded string
175+
$uri = urldecode($uri);
176+
174177
if ($this->checkRoutes($uri))
175178
{
176179
if ($this->collection->isFiltered($this->matchedRoute[0]))
@@ -420,12 +423,12 @@ protected function checkRoutes(string $uri): bool
420423

421424
// Replace it with a regex so it
422425
// will actually match.
423-
$key = str_replace('/', '\/', $key);
426+
$key = str_replace('/', '\/', $key);
424427
$key = str_replace('{locale}', '[^\/]+', $key);
425428
}
426429

427430
// Does the RegEx match?
428-
if (preg_match('#^' . $key . '$#', $uri, $matches))
431+
if (preg_match('#^' . $key . '$#u', $uri, $matches))
429432
{
430433
// Is this route supposed to redirect to another?
431434
if ($this->collection->isRedirect($key))
@@ -470,12 +473,12 @@ protected function checkRoutes(string $uri): bool
470473
if (strpos($val, '$') !== false && strpos($key, '(') !== false && strpos($key, '/') !== false)
471474
{
472475
$replacekey = str_replace('/(.*)', '', $key);
473-
$val = preg_replace('#^' . $key . '$#', $val, $uri);
476+
$val = preg_replace('#^' . $key . '$#u', $val, $uri);
474477
$val = str_replace($replacekey, str_replace('/', '\\', $replacekey), $val);
475478
}
476479
elseif (strpos($val, '$') !== false && strpos($key, '(') !== false)
477480
{
478-
$val = preg_replace('#^' . $key . '$#', $val, $uri);
481+
$val = preg_replace('#^' . $key . '$#u', $val, $uri);
479482
}
480483
elseif (strpos($val, '/') !== false)
481484
{

tests/system/Router/RouterTest.php

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -531,4 +531,45 @@ public function testAutoRouteMethodEmpty()
531531
$this->assertEquals('Home', $router->controllerName());
532532
$this->assertEquals('index', $router->methodName());
533533
}
534+
535+
//--------------------------------------------------------------------
536+
537+
/**
538+
* @see https://github.com/codeigniter4/CodeIgniter4/issues/3169
539+
*/
540+
public function testRegularExpressionWithUnicode()
541+
{
542+
$this->collection->get('news/([a-z0-9\x{0980}-\x{09ff}-]+)', 'News::view/$1');
543+
544+
$router = new Router($this->collection, $this->request);
545+
546+
$router->handle('news/a0%E0%A6%80%E0%A7%BF-');
547+
$this->assertEquals('\News', $router->controllerName());
548+
$this->assertEquals('view', $router->methodName());
549+
550+
$expected = [
551+
'a0ঀ৿-',
552+
];
553+
$this->assertEquals($expected, $router->params());
554+
}
555+
556+
/**
557+
* @see https://github.com/codeigniter4/CodeIgniter4/issues/3169
558+
*/
559+
public function testRegularExpressionPlaceholderWithUnicode()
560+
{
561+
$this->collection->addPlaceholder('custom', '[a-z0-9\x{0980}-\x{09ff}-]+');
562+
$this->collection->get('news/(:custom)', 'News::view/$1');
563+
564+
$router = new Router($this->collection, $this->request);
565+
566+
$router->handle('news/a0%E0%A6%80%E0%A7%BF-');
567+
$this->assertEquals('\News', $router->controllerName());
568+
$this->assertEquals('view', $router->methodName());
569+
570+
$expected = [
571+
'a0ঀ৿-',
572+
];
573+
$this->assertEquals($expected, $router->params());
574+
}
534575
}

0 commit comments

Comments
 (0)