From abf457a5cfb1ef54f758c27a4606616a3e6c72b3 Mon Sep 17 00:00:00 2001 From: Dmitrii Derepko Date: Sat, 6 Jan 2024 18:27:43 +0700 Subject: [PATCH] Support unicode files and classes --- src/FileRouter.php | 11 +++---- tests/FileRouterTest.php | 33 +++++++++++++++++++ ...0\276\320\273\320\273\320\265\321\200.php" | 26 +++++++++++++++ 3 files changed, 64 insertions(+), 6 deletions(-) create mode 100644 "tests/Support/App4/\320\232\320\276\320\275\321\202\321\200\320\276\320\273\320\273\320\265\321\200\321\213/\320\237\320\276\320\273\321\214\320\267\320\276\320\262\320\260\321\202\320\265\320\273\321\214/\320\223\320\273\320\260\320\262\320\275\321\213\320\271\320\232\320\276\320\275\321\202\321\200\320\276\320\273\320\273\320\265\321\200.php" diff --git a/src/FileRouter.php b/src/FileRouter.php index 5bfdb76..b0f79c3 100644 --- a/src/FileRouter.php +++ b/src/FileRouter.php @@ -60,15 +60,14 @@ public function process(ServerRequestInterface $request, RequestHandlerInterface } /** @psalm-suppress InvalidPropertyFetch */ - $actions = $controllerClass::$actions ?? [ + $action = $possibleAction ?? ($controllerClass::$actions ?? [ 'HEAD' => 'head', 'OPTIONS' => 'options', 'GET' => 'index', 'POST' => 'create', 'PUT' => 'update', 'DELETE' => 'delete', - ]; - $action = $possibleAction ?? $actions[$request->getMethod()] ?? null; + ])[$request->getMethod()] ?? null; if ($action === null) { continue; @@ -93,7 +92,7 @@ public function process(ServerRequestInterface $request, RequestHandlerInterface private function parseRequestPath(ServerRequestInterface $request): iterable { $possibleAction = null; - $path = $request->getUri()->getPath(); + $path = urldecode($request->getUri()->getPath()); if ($path === '/') { $controllerName = 'Index'; @@ -107,8 +106,8 @@ private function parseRequestPath(ServerRequestInterface $request): iterable } $controllerName = preg_replace_callback( - '#(/.)#', - fn(array $matches) => strtoupper($matches[1]), + '#(/.)#u', + fn(array $matches) => mb_strtoupper($matches[1]), $path, ); diff --git a/tests/FileRouterTest.php b/tests/FileRouterTest.php index 37fd463..4b68ff2 100644 --- a/tests/FileRouterTest.php +++ b/tests/FileRouterTest.php @@ -14,6 +14,7 @@ use Yiisoft\FileRouter\Tests\Support\App1; use Yiisoft\FileRouter\Tests\Support\App2; use Yiisoft\FileRouter\Tests\Support\App3; +use Yiisoft\FileRouter\Tests\Support\App4; use Yiisoft\FileRouter\Tests\Support\HeaderMiddleware; use Yiisoft\Middleware\Dispatcher\MiddlewareDispatcher; use Yiisoft\Middleware\Dispatcher\MiddlewareFactory; @@ -267,6 +268,36 @@ public static function dataRoutesCollision(): iterable ]; } + #[DataProvider('dataUnicodeRoutes')] + public function testTestUnicodeRoutes(string $method, string $uri, string $expectedResponse): void + { + $router = $this->createRouter(); + $router = $router + ->withNamespace('Yiisoft\FileRouter\Tests\Support\App4') + ->withClassPostfix('Контроллер') + ->withBaseControllerDirectory('Контроллеры'); + + $handler = $this->createExceptionHandler(); + $request = new ServerRequest( + method: $method, + uri: $uri, + ); + + $response = $router->process($request, $handler); + + $this->assertEquals(200, $response->getStatusCode()); + $this->assertEquals($expectedResponse, (string) $response->getBody()); + } + + public static function dataUnicodeRoutes(): iterable + { + yield 'direct' => [ + 'GET', + '/пользователь/главный', + 'Привет, Контроллеры/Пользователь/ГлавныйКонтроллер!', + ]; + } + private function createRouter(): FileRouter { $container = new SimpleContainer([ @@ -280,6 +311,8 @@ private function createRouter(): FileRouter App3\Controller\UserController::class => new App3\Controller\UserController(), App3\Controller\User\IndexController::class => new App3\Controller\User\IndexController(), + + App4\Контроллеры\Пользователь\ГлавныйКонтроллер::class => new App4\Контроллеры\Пользователь\ГлавныйКонтроллер(), ]); return new FileRouter( diff --git "a/tests/Support/App4/\320\232\320\276\320\275\321\202\321\200\320\276\320\273\320\273\320\265\321\200\321\213/\320\237\320\276\320\273\321\214\320\267\320\276\320\262\320\260\321\202\320\265\320\273\321\214/\320\223\320\273\320\260\320\262\320\275\321\213\320\271\320\232\320\276\320\275\321\202\321\200\320\276\320\273\320\273\320\265\321\200.php" "b/tests/Support/App4/\320\232\320\276\320\275\321\202\321\200\320\276\320\273\320\273\320\265\321\200\321\213/\320\237\320\276\320\273\321\214\320\267\320\276\320\262\320\260\321\202\320\265\320\273\321\214/\320\223\320\273\320\260\320\262\320\275\321\213\320\271\320\232\320\276\320\275\321\202\321\200\320\276\320\273\320\273\320\265\321\200.php" new file mode 100644 index 0000000..e5287b3 --- /dev/null +++ "b/tests/Support/App4/\320\232\320\276\320\275\321\202\321\200\320\276\320\273\320\273\320\265\321\200\321\213/\320\237\320\276\320\273\321\214\320\267\320\276\320\262\320\260\321\202\320\265\320\273\321\214/\320\223\320\273\320\260\320\262\320\275\321\213\320\271\320\232\320\276\320\275\321\202\321\200\320\276\320\273\320\273\320\265\321\200.php" @@ -0,0 +1,26 @@ + 'главный', + ]; + public static array $middlewares = [ + 'index' => [ + HeaderMiddleware::class, + ], + ]; + + public function главный(): ResponseInterface + { + return new TextResponse('Привет, Контроллеры/Пользователь/ГлавныйКонтроллер!'); + } +}