diff --git a/src/Dispatcher.php b/src/Dispatcher.php index b785142b..8a87a99d 100644 --- a/src/Dispatcher.php +++ b/src/Dispatcher.php @@ -24,6 +24,7 @@ final class Dispatcher HttpHelper $httpHelper, AuthService $authService, TokenService $tokenService, + RouteRepository $routeRepository, ControllerRepository $controllerRepository) { $this->router = $router; @@ -38,6 +39,8 @@ final class Dispatcher foreach ($controllerRepository->getControllers() as $controller) $controller->registerRoutes($router); + + $routeRepository->injectRoutes($router); } public function run($requestMethod, $requestUri) diff --git a/src/RouteRepository.php b/src/RouteRepository.php new file mode 100644 index 00000000..dc754041 --- /dev/null +++ b/src/RouteRepository.php @@ -0,0 +1,29 @@ +routes = $routes; + } + + public function getRoutes() + { + return $this->routes; + } + + public function injectRoutes(Router $router) + { + foreach ($this->routes as $route) + { + foreach ($route->getMethods() as $method) + { + $method = strtolower($method); + $router->$method($route->getUrl(), [$route, 'work']); + } + } + } +} diff --git a/src/Routes/AbstractRoute.php b/src/Routes/AbstractRoute.php new file mode 100644 index 00000000..efae6d59 --- /dev/null +++ b/src/Routes/AbstractRoute.php @@ -0,0 +1,11 @@ +tokenViewProxy = $tokenViewProxy; } - public function registerRoutes(Router $router) + public function getMethods() { - $router->post('/api/login', [$this, 'login']); - $router->put('/api/login', [$this, 'login']); + return ['POST', 'PUT']; } - public function login() + public function getUrl() + { + return '/api/login'; + } + + public function work() { if (isset($this->inputReader->userNameOrEmail) && isset($this->inputReader->password)) { diff --git a/src/di.php b/src/di.php index b43799a0..49fe2d2d 100644 --- a/src/di.php +++ b/src/di.php @@ -11,6 +11,7 @@ $publicDataDirectory = __DIR__ return [ \Szurubooru\Config::class => DI\object()->constructor($dataDirectory, $publicDataDirectory), + \Szurubooru\RouteRepository::class => DI\object()->constructor(DI\link('routes')), \Szurubooru\ControllerRepository::class => DI\object()->constructor(DI\link('controllers')), \Szurubooru\Upgrades\UpgradeRepository::class => DI\object()->constructor(DI\link('upgrades')), @@ -56,7 +57,6 @@ return [ 'controllers' => DI\factory(function (DI\container $container) { return [ - $container->get(\Szurubooru\Controllers\AuthController::class), $container->get(\Szurubooru\Controllers\UserController::class), $container->get(\Szurubooru\Controllers\UserAvatarController::class), $container->get(\Szurubooru\Controllers\PostController::class), @@ -70,4 +70,10 @@ return [ $container->get(\Szurubooru\Controllers\TagController::class), ]; }), + + 'routes' => DI\factory(function (DI\container $container) { + return [ + $container->get(\Szurubooru\Routes\Login::class), + ]; + }), ]; diff --git a/tests/DispatcherTest.php b/tests/DispatcherTest.php index ea603433..228a893c 100644 --- a/tests/DispatcherTest.php +++ b/tests/DispatcherTest.php @@ -3,6 +3,7 @@ namespace Szurubooru\Tests; use Szurubooru\ControllerRepository; use Szurubooru\Dispatcher; use Szurubooru\Helpers\HttpHelper; +use Szurubooru\RouteRepository; use Szurubooru\Router; use Szurubooru\Services\AuthService; use Szurubooru\Services\TokenService; @@ -16,6 +17,7 @@ final class DispatcherTest extends AbstractDatabaseTestCase private $authServiceMock; private $tokenServiceMock; private $controllerRepositoryMock; + private $routeRepositoryMock; public function setUp() { @@ -26,6 +28,7 @@ final class DispatcherTest extends AbstractDatabaseTestCase $this->authServiceMock = $this->mock(AuthService::class); $this->tokenServiceMock = $this->mock(TokenService::class); $this->controllerRepositoryMock = $this->mock(ControllerRepository::class); + $this->routeRepositoryMock = $this->mock(RouteRepository::class); $this->configMock->set('misc/dumpSqlIntoQueries', 0); } @@ -39,6 +42,7 @@ final class DispatcherTest extends AbstractDatabaseTestCase ->withConsecutive([$this->equalTo(500)], [$this->equalTo(200)]); $this->routerMock->expects($this->once())->method('handle')->willReturn($expected); $this->controllerRepositoryMock->method('getControllers')->willReturn([]); + $this->routeRepositoryMock->expects($this->once())->method('injectRoutes'); $dispatcher = $this->getDispatcher(); $actual = $dispatcher->run('GET', '/'); @@ -55,6 +59,7 @@ final class DispatcherTest extends AbstractDatabaseTestCase $this->routerMock->expects($this->once())->method('handle')->willReturn($classData); $this->controllerRepositoryMock->method('getControllers')->willReturn([]); + $this->routeRepositoryMock->expects($this->once())->method('injectRoutes'); $dispatcher = $this->getDispatcher(); $actual = $dispatcher->run('GET', '/'); @@ -68,6 +73,7 @@ final class DispatcherTest extends AbstractDatabaseTestCase $this->httpHelperMock->expects($this->once())->method('getRequestHeader')->with($this->equalTo('X-Authorization-Token'))->willReturn('test'); $this->tokenServiceMock->expects($this->once())->method('getByName'); $this->controllerRepositoryMock->method('getControllers')->willReturn([]); + $this->routeRepositoryMock->expects($this->once())->method('injectRoutes'); $dispatcher = $this->getDispatcher(); $dispatcher->run('GET', '/'); @@ -82,6 +88,7 @@ final class DispatcherTest extends AbstractDatabaseTestCase $this->httpHelperMock, $this->authServiceMock, $this->tokenServiceMock, + $this->routeRepositoryMock, $this->controllerRepositoryMock); } } diff --git a/tests/RouteRepositoryTest.php b/tests/RouteRepositoryTest.php new file mode 100644 index 00000000..39c3ca0f --- /dev/null +++ b/tests/RouteRepositoryTest.php @@ -0,0 +1,40 @@ +assertNotEmpty($routeRepository->getRoutes()); + } + + public function testRouteInjection() + { + $routerMock = $this->mock(Router::class); + $routeMock = $this->mock(AbstractRoute::class); + $routeMock->expects($this->once())->method('getMethods')->willReturn(['POST', 'GET']); + $routeMock->expects($this->atLeast(1))->method('getUrl')->willReturn('/test'); + $routerMock->expects($this->once())->method('post')->with('/test', $this->anything()); + $routerMock->expects($this->once())->method('get')->with('/test', $this->anything()); + $routeRepository = new RouteRepository([$routeMock]); + $routeRepository->injectRoutes($routerMock); + } + + public function testRouteCallbackInjection() + { + $router = new Router(); + $routeMock = $this->mock(AbstractRoute::class); + $routeMock->expects($this->once())->method('getMethods')->willReturn(['POST', 'GET']); + $routeMock->expects($this->atLeast(1))->method('getUrl')->willReturn('/test'); + $routeMock->expects($this->atLeast(1))->method('work'); + $routeRepository = new RouteRepository([$routeMock]); + $routeRepository->injectRoutes($router); + $router->handle('GET', '/test'); + } +}