Added Route layer proof of concept

This commit is contained in:
Marcin Kurczewski 2014-11-19 22:00:50 +01:00
parent 9e894bc41c
commit 2a7ca79b2d
7 changed files with 107 additions and 7 deletions

View file

@ -24,6 +24,7 @@ final class Dispatcher
HttpHelper $httpHelper, HttpHelper $httpHelper,
AuthService $authService, AuthService $authService,
TokenService $tokenService, TokenService $tokenService,
RouteRepository $routeRepository,
ControllerRepository $controllerRepository) ControllerRepository $controllerRepository)
{ {
$this->router = $router; $this->router = $router;
@ -38,6 +39,8 @@ final class Dispatcher
foreach ($controllerRepository->getControllers() as $controller) foreach ($controllerRepository->getControllers() as $controller)
$controller->registerRoutes($router); $controller->registerRoutes($router);
$routeRepository->injectRoutes($router);
} }
public function run($requestMethod, $requestUri) public function run($requestMethod, $requestUri)

29
src/RouteRepository.php Normal file
View file

@ -0,0 +1,29 @@
<?php
namespace Szurubooru;
class RouteRepository
{
private $routes = [];
public function __construct(array $routes)
{
$this->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']);
}
}
}
}

View file

@ -0,0 +1,11 @@
<?php
namespace Szurubooru\Routes;
abstract class AbstractRoute
{
public abstract function getMethods();
public abstract function getUrl();
public abstract function work();
}

View file

@ -1,5 +1,5 @@
<?php <?php
namespace Szurubooru\Controllers; namespace Szurubooru\Routes;
use Szurubooru\Controllers\ViewProxies\TokenViewProxy; use Szurubooru\Controllers\ViewProxies\TokenViewProxy;
use Szurubooru\Controllers\ViewProxies\UserViewProxy; use Szurubooru\Controllers\ViewProxies\UserViewProxy;
use Szurubooru\FormData\LoginFormData; use Szurubooru\FormData\LoginFormData;
@ -10,7 +10,7 @@ use Szurubooru\Services\PrivilegeService;
use Szurubooru\Services\TokenService; use Szurubooru\Services\TokenService;
use Szurubooru\Services\UserService; use Szurubooru\Services\UserService;
final class AuthController extends AbstractController class Login extends AbstractRoute
{ {
private $authService; private $authService;
private $userService; private $userService;
@ -38,13 +38,17 @@ final class AuthController extends AbstractController
$this->tokenViewProxy = $tokenViewProxy; $this->tokenViewProxy = $tokenViewProxy;
} }
public function registerRoutes(Router $router) public function getMethods()
{ {
$router->post('/api/login', [$this, 'login']); return ['POST', 'PUT'];
$router->put('/api/login', [$this, 'login']);
} }
public function login() public function getUrl()
{
return '/api/login';
}
public function work()
{ {
if (isset($this->inputReader->userNameOrEmail) && isset($this->inputReader->password)) if (isset($this->inputReader->userNameOrEmail) && isset($this->inputReader->password))
{ {

View file

@ -11,6 +11,7 @@ $publicDataDirectory = __DIR__
return [ return [
\Szurubooru\Config::class => DI\object()->constructor($dataDirectory, $publicDataDirectory), \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\ControllerRepository::class => DI\object()->constructor(DI\link('controllers')),
\Szurubooru\Upgrades\UpgradeRepository::class => DI\object()->constructor(DI\link('upgrades')), \Szurubooru\Upgrades\UpgradeRepository::class => DI\object()->constructor(DI\link('upgrades')),
@ -56,7 +57,6 @@ return [
'controllers' => DI\factory(function (DI\container $container) { 'controllers' => DI\factory(function (DI\container $container) {
return [ return [
$container->get(\Szurubooru\Controllers\AuthController::class),
$container->get(\Szurubooru\Controllers\UserController::class), $container->get(\Szurubooru\Controllers\UserController::class),
$container->get(\Szurubooru\Controllers\UserAvatarController::class), $container->get(\Szurubooru\Controllers\UserAvatarController::class),
$container->get(\Szurubooru\Controllers\PostController::class), $container->get(\Szurubooru\Controllers\PostController::class),
@ -70,4 +70,10 @@ return [
$container->get(\Szurubooru\Controllers\TagController::class), $container->get(\Szurubooru\Controllers\TagController::class),
]; ];
}), }),
'routes' => DI\factory(function (DI\container $container) {
return [
$container->get(\Szurubooru\Routes\Login::class),
];
}),
]; ];

View file

@ -3,6 +3,7 @@ namespace Szurubooru\Tests;
use Szurubooru\ControllerRepository; use Szurubooru\ControllerRepository;
use Szurubooru\Dispatcher; use Szurubooru\Dispatcher;
use Szurubooru\Helpers\HttpHelper; use Szurubooru\Helpers\HttpHelper;
use Szurubooru\RouteRepository;
use Szurubooru\Router; use Szurubooru\Router;
use Szurubooru\Services\AuthService; use Szurubooru\Services\AuthService;
use Szurubooru\Services\TokenService; use Szurubooru\Services\TokenService;
@ -16,6 +17,7 @@ final class DispatcherTest extends AbstractDatabaseTestCase
private $authServiceMock; private $authServiceMock;
private $tokenServiceMock; private $tokenServiceMock;
private $controllerRepositoryMock; private $controllerRepositoryMock;
private $routeRepositoryMock;
public function setUp() public function setUp()
{ {
@ -26,6 +28,7 @@ final class DispatcherTest extends AbstractDatabaseTestCase
$this->authServiceMock = $this->mock(AuthService::class); $this->authServiceMock = $this->mock(AuthService::class);
$this->tokenServiceMock = $this->mock(TokenService::class); $this->tokenServiceMock = $this->mock(TokenService::class);
$this->controllerRepositoryMock = $this->mock(ControllerRepository::class); $this->controllerRepositoryMock = $this->mock(ControllerRepository::class);
$this->routeRepositoryMock = $this->mock(RouteRepository::class);
$this->configMock->set('misc/dumpSqlIntoQueries', 0); $this->configMock->set('misc/dumpSqlIntoQueries', 0);
} }
@ -39,6 +42,7 @@ final class DispatcherTest extends AbstractDatabaseTestCase
->withConsecutive([$this->equalTo(500)], [$this->equalTo(200)]); ->withConsecutive([$this->equalTo(500)], [$this->equalTo(200)]);
$this->routerMock->expects($this->once())->method('handle')->willReturn($expected); $this->routerMock->expects($this->once())->method('handle')->willReturn($expected);
$this->controllerRepositoryMock->method('getControllers')->willReturn([]); $this->controllerRepositoryMock->method('getControllers')->willReturn([]);
$this->routeRepositoryMock->expects($this->once())->method('injectRoutes');
$dispatcher = $this->getDispatcher(); $dispatcher = $this->getDispatcher();
$actual = $dispatcher->run('GET', '/'); $actual = $dispatcher->run('GET', '/');
@ -55,6 +59,7 @@ final class DispatcherTest extends AbstractDatabaseTestCase
$this->routerMock->expects($this->once())->method('handle')->willReturn($classData); $this->routerMock->expects($this->once())->method('handle')->willReturn($classData);
$this->controllerRepositoryMock->method('getControllers')->willReturn([]); $this->controllerRepositoryMock->method('getControllers')->willReturn([]);
$this->routeRepositoryMock->expects($this->once())->method('injectRoutes');
$dispatcher = $this->getDispatcher(); $dispatcher = $this->getDispatcher();
$actual = $dispatcher->run('GET', '/'); $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->httpHelperMock->expects($this->once())->method('getRequestHeader')->with($this->equalTo('X-Authorization-Token'))->willReturn('test');
$this->tokenServiceMock->expects($this->once())->method('getByName'); $this->tokenServiceMock->expects($this->once())->method('getByName');
$this->controllerRepositoryMock->method('getControllers')->willReturn([]); $this->controllerRepositoryMock->method('getControllers')->willReturn([]);
$this->routeRepositoryMock->expects($this->once())->method('injectRoutes');
$dispatcher = $this->getDispatcher(); $dispatcher = $this->getDispatcher();
$dispatcher->run('GET', '/'); $dispatcher->run('GET', '/');
@ -82,6 +88,7 @@ final class DispatcherTest extends AbstractDatabaseTestCase
$this->httpHelperMock, $this->httpHelperMock,
$this->authServiceMock, $this->authServiceMock,
$this->tokenServiceMock, $this->tokenServiceMock,
$this->routeRepositoryMock,
$this->controllerRepositoryMock); $this->controllerRepositoryMock);
} }
} }

View file

@ -0,0 +1,40 @@
<?php
namespace Szurubooru\Tests;
use Szurubooru\Injector;
use Szurubooru\RouteRepository;
use Szurubooru\Router;
use Szurubooru\Routes\AbstractRoute;
use Szurubooru\Tests\AbstractTestCase;
final class RouteRepositoryTest extends AbstractTestCase
{
public function testFactory()
{
$routeRepository = Injector::get(RouteRepository::class);
$this->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');
}
}