Merge pull request #3172 from michalsn/router_regex

Add Unicode support for regular expressions in router
This commit is contained in:
MGatner 2020-07-01 09:14:02 -04:00 committed by GitHub
commit 458e2d4bc5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 49 additions and 5 deletions

View File

@ -1348,7 +1348,7 @@ class RouteCollection implements RouteCollectionInterface
// the expected param type.
$pos = strpos($from, $pattern);
if (preg_match('#' . $pattern . '#', $params[$index]))
if (preg_match('#^' . $pattern . '$#u', $params[$index]))
{
$from = substr_replace($from, $params[$index], $pos, strlen($pattern));
}

View File

@ -171,6 +171,9 @@ class Router implements RouterInterface
: $this->controller;
}
// Decode URL-encoded string
$uri = urldecode($uri);
if ($this->checkRoutes($uri))
{
if ($this->collection->isFiltered($this->matchedRoute[0]))
@ -420,12 +423,12 @@ class Router implements RouterInterface
// Replace it with a regex so it
// will actually match.
$key = str_replace('/', '\/', $key);
$key = str_replace('/', '\/', $key);
$key = str_replace('{locale}', '[^\/]+', $key);
}
// Does the RegEx match?
if (preg_match('#^' . $key . '$#', $uri, $matches))
if (preg_match('#^' . $key . '$#u', $uri, $matches))
{
// Is this route supposed to redirect to another?
if ($this->collection->isRedirect($key))
@ -470,12 +473,12 @@ class Router implements RouterInterface
if (strpos($val, '$') !== false && strpos($key, '(') !== false && strpos($key, '/') !== false)
{
$replacekey = str_replace('/(.*)', '', $key);
$val = preg_replace('#^' . $key . '$#', $val, $uri);
$val = preg_replace('#^' . $key . '$#u', $val, $uri);
$val = str_replace($replacekey, str_replace('/', '\\', $replacekey), $val);
}
elseif (strpos($val, '$') !== false && strpos($key, '(') !== false)
{
$val = preg_replace('#^' . $key . '$#', $val, $uri);
$val = preg_replace('#^' . $key . '$#u', $val, $uri);
}
elseif (strpos($val, '/') !== false)
{

View File

@ -531,4 +531,45 @@ class RouterTest extends \CodeIgniter\Test\CIUnitTestCase
$this->assertEquals('Home', $router->controllerName());
$this->assertEquals('index', $router->methodName());
}
//--------------------------------------------------------------------
/**
* @see https://github.com/codeigniter4/CodeIgniter4/issues/3169
*/
public function testRegularExpressionWithUnicode()
{
$this->collection->get('news/([a-z0-9\x{0980}-\x{09ff}-]+)', 'News::view/$1');
$router = new Router($this->collection, $this->request);
$router->handle('news/a0%E0%A6%80%E0%A7%BF-');
$this->assertEquals('\News', $router->controllerName());
$this->assertEquals('view', $router->methodName());
$expected = [
'a0ঀ৿-',
];
$this->assertEquals($expected, $router->params());
}
/**
* @see https://github.com/codeigniter4/CodeIgniter4/issues/3169
*/
public function testRegularExpressionPlaceholderWithUnicode()
{
$this->collection->addPlaceholder('custom', '[a-z0-9\x{0980}-\x{09ff}-]+');
$this->collection->get('news/(:custom)', 'News::view/$1');
$router = new Router($this->collection, $this->request);
$router->handle('news/a0%E0%A6%80%E0%A7%BF-');
$this->assertEquals('\News', $router->controllerName());
$this->assertEquals('view', $router->methodName());
$expected = [
'a0ঀ৿-',
];
$this->assertEquals($expected, $router->params());
}
}