Added router

This commit is contained in:
Marcin Kurczewski 2014-08-29 11:20:08 +02:00
parent b7de8ae0bf
commit 1e3e3f94d8
3 changed files with 194 additions and 0 deletions

48
src/Route.php Normal file
View file

@ -0,0 +1,48 @@
<?php
namespace Szurubooru;
final class Route
{
public $query;
public $route;
public function __construct($query, $route)
{
$this->query = $query;
$this->route = $route;
$this->regex = $this->getRegex();
}
public function handle($query)
{
$query = trim($query, '/');
if (!preg_match($this->regex, $query, $matches))
return false;
$routeArguments = $this->getRouteArguments($matches);
call_user_func_array($this->route, $routeArguments);
return true;
}
private function getRegex()
{
$quotedQuery = preg_quote(trim($this->query, '/'), '/');
return '/^' . preg_replace('/\\\?\:([a-zA-Z_-]*)/', '(?P<\1>[^\/]+)', $quotedQuery) . '$/i';
}
private function getRouteArguments($matches)
{
$reflectionFunction = new \ReflectionFunction($this->route);
$arguments = [];
foreach ($reflectionFunction->getParameters() as $reflectionParameter)
{
$key = $reflectionParameter->name;
if (isset($matches[$key]))
$arguments[$key] = $matches[$key];
elseif ($reflectionParameter->isDefaultValueAvailable())
$arguments[$key] = $reflectionParameter->getDefaultValue();
else
$arguments[$key] = null;
}
return $arguments;
}
}

46
src/Router.php Normal file
View file

@ -0,0 +1,46 @@
<?php
namespace Szurubooru;
final class Router
{
private $routes;
public function get($query, $route)
{
$this->route('GET', $query, $route);
}
public function put($query, $route)
{
$this->route('PUT', $query, $route);
}
public function delete($query, $route)
{
$this->route('DELETE', $query, $route);
}
public function post($query, $route)
{
$this->route('POST', $query, $route);
}
private function route($method, $query, $route)
{
$this->routes[$method] []= new Route($query, $route);
}
public function handle($method, $request)
{
if (!isset($this->routes[$method]))
throw new \DomainException('Unhandled request method: ' . $method);
foreach ($this->routes[$method] as $route)
{
if ($route->handle($request))
return;
}
throw new \DomainException('Unhandled request address: ' . $request);
}
}

100
tests/RouterTest.php Normal file
View file

@ -0,0 +1,100 @@
<?php
namespace Szurubooru\Tests;
final class PostDaoTest extends \PHPUnit_Framework_TestCase
{
public function testParameterlessHandling()
{
$router = new \Szurubooru\Router;
$testOk = false;
$router->get('/test', function() use (&$testOk) { $testOk = true; });
$router->handle('GET', '/test');
$this->assertTrue($testOk);
}
public function testTrailingSlashes()
{
$router = new \Szurubooru\Router;
$testOk = false;
$router->get('/test', function() use (&$testOk) { $testOk = true; });
$router->handle('GET', '/test/');
$this->assertTrue($testOk);
}
public function testUnhandledMethod()
{
$router = new \Szurubooru\Router;
$router->get('/test', function() { $this->fail('Route shouldn\'t be executed'); });
$this->setExpectedException('\DomainException');
$router->handle('POST', '/test');
}
public function testUnhandledQuery()
{
$router = new \Szurubooru\Router;
$router->get('/test', function() { $this->fail('Route shouldn\'t be executed'); });
$this->setExpectedException('\DomainException');
$router->handle('GET', '/test2');
}
public function testTwoMethodsHandling()
{
$router = new \Szurubooru\Router;
$testOk = false;
$router->get('/test', function() { $this->fail('Route shouldn\'t be executed'); });
$router->post('/test', function() use (&$testOk) { $testOk = true; });
$router->handle('POST', '/test');
$this->assertTrue($testOk);
}
public function testParameterHandling()
{
$router = new \Szurubooru\Router;
$testOk = false;
$router->get('/tests/:id', function($id) use (&$testOk) {
$this->assertEquals($id, 'test_id');
$testOk = true; });
$router->handle('GET', '/tests/test_id');
$this->assertTrue($testOk);
}
public function testTwoParameterHandling()
{
$router = new \Szurubooru\Router;
$testOk = false;
$router->get('/tests/:id/:page', function($id, $page) use (&$testOk) {
$this->assertEquals($id, 'test_id');
$this->assertEquals($page, 'test_page');
$testOk = true; });
$router->handle('GET', '/tests/test_id/test_page');
$this->assertTrue($testOk);
}
public function testMissingParameterHandling()
{
$router = new \Szurubooru\Router;
$testOk = false;
$router->get('/tests/:id', function($id, $page) use (&$testOk) {
$this->assertEquals($id, 'test_id');
$this->assertNull($page);
$testOk = true; });
$router->handle('GET', '/tests/test_id');
$this->assertTrue($testOk);
}
public function testMissingDefaultParameterHandling()
{
$router = new \Szurubooru\Router;
$testOk = false;
$router->get('/tests/:id', function($id, $page = 1) use (&$testOk) {
$this->assertEquals($id, 'test_id');
$this->assertEquals(1, $page);
$testOk = true; });
$router->handle('GET', '/tests/test_id');
$this->assertTrue($testOk);
}
}