Updates to Router
- Add Router::add method - Refactor Router to contain one RouteTable
This commit is contained in:
parent
b350693aca
commit
5dacb232ec
|
|
@ -15,6 +15,7 @@ use pjdietz\WellRESTed\Interfaces\HandlerInterface;
|
|||
use pjdietz\WellRESTed\Interfaces\RequestInterface;
|
||||
use pjdietz\WellRESTed\Interfaces\ResponseInterface;
|
||||
use pjdietz\WellRESTed\Routes\PrefixRoute;
|
||||
use pjdietz\WellRESTed\Routes\RouteFactory;
|
||||
use pjdietz\WellRESTed\Routes\StaticRoute;
|
||||
|
||||
/**
|
||||
|
|
@ -26,26 +27,64 @@ class Router implements HandlerInterface
|
|||
{
|
||||
/** @var array Hash array of status code => error handler */
|
||||
private $errorHandlers;
|
||||
/** @var array Hash array HTTP verb => RouteTable */
|
||||
private $routeTables;
|
||||
/** @var RouteTable */
|
||||
private $routeTable;
|
||||
|
||||
/** Create a new Router. */
|
||||
public function __construct()
|
||||
{
|
||||
$this->errorHandlers = array();
|
||||
$this->routeTables = array();
|
||||
$this->routeTable = new RouteTable();
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a route or series of routes to the Router.
|
||||
*
|
||||
* When adding a single route, the first argument should be the path, path prefix, URI template, or regex pattern.
|
||||
* The method will attempt to find the best type of route based on this argument and send the remainding arguments
|
||||
* to that routes constructor. @see {RouteFactory::createRoute}
|
||||
*
|
||||
* To add multiple routes, pass arrays to add where each array contains an argument list.
|
||||
*/
|
||||
public function add()
|
||||
{
|
||||
$factory = new RouteFactory();
|
||||
|
||||
$args = func_get_args();
|
||||
if (count($args) > 1 && is_array($args[0])) {
|
||||
foreach ($args as $argumentList) {
|
||||
$route = call_user_func_array(array($factory, "createRoute"), $argumentList);
|
||||
$this->addRoute($route);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
$route = call_user_func_array(array($factory, "createRoute"), $args);
|
||||
$this->addRoute($route);
|
||||
}
|
||||
|
||||
/**
|
||||
* Append a series of routes.
|
||||
*
|
||||
* @param array $routes List array of routes
|
||||
*/
|
||||
public function addRoutes(array $routes)
|
||||
{
|
||||
foreach ($routes as $route) {
|
||||
if ($route instanceof HandlerInterface) {
|
||||
$this->addRoute($route);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Append a new route to the route table.
|
||||
*
|
||||
* @param HandlerInterface $route
|
||||
* @param string $method HTTP Method; * for any
|
||||
*/
|
||||
public function addRoute(HandlerInterface $route, $method = "*")
|
||||
public function addRoute(HandlerInterface $route)
|
||||
{
|
||||
$table = $this->getRouteTable($method);
|
||||
$table->addRoute($route);
|
||||
$this->routeTable->addRoute($route);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -96,7 +135,7 @@ class Router implements HandlerInterface
|
|||
*/
|
||||
public function getResponse(RequestInterface $request, array $args = null)
|
||||
{
|
||||
$response = $this->getResponseFromRouteTables($request, $args);
|
||||
$response = $this->tryResponse($this->routeTable, $request, $args);
|
||||
if ($response) {
|
||||
// Check if the router has an error handler for this status code.
|
||||
$status = $response->getStatusCode();
|
||||
|
|
@ -126,30 +165,6 @@ class Router implements HandlerInterface
|
|||
return $response;
|
||||
}
|
||||
|
||||
private function getRouteTable($method = "*")
|
||||
{
|
||||
if (!isset($this->routeTables[$method])) {
|
||||
$this->routeTables[$method] = new RouteTable();
|
||||
}
|
||||
return $this->routeTables[$method];
|
||||
}
|
||||
|
||||
private function getResponseFromRouteTables(RequestInterface $request, array $args = null)
|
||||
{
|
||||
$method = $request->getMethod();
|
||||
if (isset($this->routeTables[$method])) {
|
||||
$table = $this->routeTables[$method];
|
||||
return $this->tryResponse($table, $request, $args);
|
||||
}
|
||||
|
||||
if (isset($this->routeTables["*"])) {
|
||||
$table = $this->routeTables["*"];
|
||||
return $this->tryResponse($table, $request, $args);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private function getErrorResponse($status, $request, $args = null, $response = null)
|
||||
{
|
||||
if (isset($this->errorHandlers[$status])) {
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@
|
|||
|
||||
namespace pjdietz\WellRESTed\Routes;
|
||||
|
||||
use pjdietz\WellRESTed\Interfaces\HandlerInterface;
|
||||
use ReflectionClass;
|
||||
|
||||
/**
|
||||
|
|
@ -17,6 +18,9 @@ use ReflectionClass;
|
|||
*/
|
||||
class RouteFactory
|
||||
{
|
||||
/**
|
||||
* @return HandlerInterface
|
||||
*/
|
||||
public function createRoute()
|
||||
{
|
||||
$args = func_get_args();
|
||||
|
|
@ -51,6 +55,5 @@ class RouteFactory
|
|||
// Regex
|
||||
$reflector = new ReflectionClass("\\pjdietz\\WellRESTed\\Routes\\RegexRoute");
|
||||
return $reflector->newInstanceArgs($args);
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ namespace pjdietz\WellRESTed\Test;
|
|||
|
||||
use pjdietz\WellRESTed\Exceptions\HttpExceptions\HttpException;
|
||||
use pjdietz\WellRESTed\Router;
|
||||
use pjdietz\WellRESTed\Routes\TemplateRoute;
|
||||
use Prophecy\Argument;
|
||||
|
||||
/**
|
||||
|
|
@ -26,80 +27,63 @@ class RouterTest extends \PHPUnit_Framework_TestCase
|
|||
$this->handler = $this->prophesize("\\pjdietz\\WellRESTed\\Interfaces\\HandlerInterface");
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider httpMethodProvider
|
||||
*/
|
||||
public function testAddsRouteToDefaultRouteTable($method)
|
||||
public function testAddsSingleRoute()
|
||||
{
|
||||
$this->request->getPath()->willReturn("/");
|
||||
$this->request->getMethod()->willReturn($method);
|
||||
$this->route->getResponse(Argument::cetera())->willReturn($this->response->reveal());
|
||||
$this->request->getPath()->willReturn("/cats/");
|
||||
$this->handler->getResponse(Argument::cetera())->willReturn($this->response->reveal());
|
||||
|
||||
$router = new Router();
|
||||
$router->addRoute($this->route->reveal());
|
||||
$router->add("/cats/", $this->handler->reveal());
|
||||
$response = $router->getResponse($this->request->reveal());
|
||||
$this->assertNotNull($response);
|
||||
}
|
||||
|
||||
public function httpMethodProvider()
|
||||
{
|
||||
return [
|
||||
["GET"],
|
||||
["POST"],
|
||||
["PUT"],
|
||||
["DELETE"],
|
||||
["HEAD"],
|
||||
["PATCH"],
|
||||
["OPTIONS"],
|
||||
["CUSTOM"]
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider httpMethodListProvider
|
||||
* @dataProvider pathProvider
|
||||
*/
|
||||
public function testAddsRouteToSpecificRouteTable($registerMethod, $requestMethod, $expectedResponse)
|
||||
public function testAddsMultpleRoutes($path, $exptectedSuccess)
|
||||
{
|
||||
$this->request->getPath()->willReturn("/");
|
||||
$this->request->getMethod()->willReturn($requestMethod);
|
||||
$this->route->getResponse(Argument::cetera())->willReturn($this->response->reveal());
|
||||
|
||||
$router = new Router();
|
||||
$router->addRoute($this->route->reveal(), $registerMethod);
|
||||
$response = $router->getResponse($this->request->reveal());
|
||||
|
||||
$this->assertEquals($expectedResponse, !is_null($response));
|
||||
}
|
||||
|
||||
public function httpMethodListProvider()
|
||||
{
|
||||
return [
|
||||
["GET", "GET", true],
|
||||
["POST", "GET", false]
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider httpMethodProvider
|
||||
*/
|
||||
public function testMatchSpecificTableBeforeDefaultTable($method)
|
||||
{
|
||||
$this->request->getMethod()->willReturn("POST");
|
||||
$this->request->getPath()->willReturn($path);
|
||||
$this->handler->getResponse(Argument::cetera())->willReturn($this->response->reveal());
|
||||
|
||||
$genericRoute = $this->prophesize("\\pjdietz\\WellRESTed\\Interfaces\\HandlerInterface");
|
||||
$genericRoute->getResponse()->willReturn(null);
|
||||
|
||||
$specificRoute = $this->prophesize("\\pjdietz\\WellRESTed\\Interfaces\\HandlerInterface");
|
||||
$specificRoute->getResponse(Argument::cetera())->willReturn(null);
|
||||
|
||||
$router = new Router();
|
||||
$router->addRoute($genericRoute->reveal());
|
||||
$router->addRoute($specificRoute->reveal(), "POST");
|
||||
$router->getResponse($this->request->reveal());
|
||||
$router->add(
|
||||
["/cats/", $this->handler->reveal()],
|
||||
["/cats/*", $this->handler->reveal()],
|
||||
["/dogs/{name}", $this->handler->reveal(), TemplateRoute::RE_ALPHA],
|
||||
["~/hamsters/[a-z]+~", $this->handler->reveal()]
|
||||
);
|
||||
$response = $router->getResponse($this->request->reveal());
|
||||
$this->assertEquals($exptectedSuccess, !is_null($response));
|
||||
}
|
||||
|
||||
$genericRoute->getResponse(Argument::cetera())->shouldNotHaveBeenCalled();
|
||||
$specificRoute->getResponse(Argument::cetera())->shouldHaveBeenCalled();
|
||||
public function pathProvider()
|
||||
{
|
||||
return [
|
||||
["/cats/", true],
|
||||
["/cats/molly", true],
|
||||
["/dogs/bear", true],
|
||||
["/hamsters/fizzgig", true],
|
||||
["/dogs/", false],
|
||||
["/birds/", false],
|
||||
["/hamsters/23", false]
|
||||
];
|
||||
}
|
||||
|
||||
public function testAddsSingleRouteInstance()
|
||||
{
|
||||
$router = new Router();
|
||||
$router->addRoute($this->route->reveal());
|
||||
$router->getResponse($this->request->reveal());
|
||||
$this->route->getResponse(Argument::cetera())->shouldHaveBeenCalled();
|
||||
}
|
||||
|
||||
public function testAddsMultipleRouteInstances()
|
||||
{
|
||||
$router = new Router();
|
||||
$router->addRoutes([$this->route->reveal()]);
|
||||
$router->getResponse($this->request->reveal());
|
||||
$this->route->getResponse(Argument::cetera())->shouldHaveBeenCalled();
|
||||
}
|
||||
|
||||
public function testRespondsWithErrorResponseForHttpException()
|
||||
|
|
|
|||
Loading…
Reference in New Issue