Rework Router
This commit is contained in:
parent
9083f2a444
commit
ec7dceac98
|
|
@ -0,0 +1,46 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace WellRESTed\Routing;
|
||||||
|
|
||||||
|
use Psr\Http\Message\ResponseInterface;
|
||||||
|
use Psr\Http\Message\ServerRequestInterface;
|
||||||
|
|
||||||
|
class RouteMap implements RouteMapInterface
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Register middleware with the router for a given path and method.
|
||||||
|
*
|
||||||
|
* $method may be:
|
||||||
|
* - A single verb ("GET"),
|
||||||
|
* - A comma-separated list of verbs ("GET,PUT,DELETE")
|
||||||
|
* - "*" to indicate any method.
|
||||||
|
* @see MethodMapInterface::addMethod
|
||||||
|
*
|
||||||
|
* $target may be:
|
||||||
|
* - An exact path (e.g., "/path/")
|
||||||
|
* - An prefix path ending with "*"" ("/path/*"")
|
||||||
|
* - A URI template with variables enclosed in "{}" ("/path/{id}")
|
||||||
|
* - A regular expression ("~/cat/([0-9]+)~")
|
||||||
|
*
|
||||||
|
* $middleware may be:
|
||||||
|
* - An instance implementing MiddlewareInterface
|
||||||
|
* - A string containing the fully qualified class name of a class
|
||||||
|
* implementing MiddlewareInterface
|
||||||
|
* - A callable that returns an instance implementing MiddleInterface
|
||||||
|
* - A callable maching the signature of MiddlewareInteraface::dispatch
|
||||||
|
* @see DispatchedInterface::dispatch
|
||||||
|
*
|
||||||
|
* @param string $target Request target or pattern to match
|
||||||
|
* @param string $method HTTP method(s) to match
|
||||||
|
* @param mixed $middleware Middleware to dispatch
|
||||||
|
*/
|
||||||
|
public function add($method, $target, $middleware)
|
||||||
|
{
|
||||||
|
// TODO: Implement addRoute() method.
|
||||||
|
}
|
||||||
|
|
||||||
|
public function dispatch(ServerRequestInterface $request, ResponseInterface &$response)
|
||||||
|
{
|
||||||
|
// TODO: Implement dispatch() method.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,35 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace WellRESTed\Routing;
|
||||||
|
|
||||||
|
interface RouteMapInterface extends MiddlewareInterface
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Register middleware with the router for a given path and method.
|
||||||
|
*
|
||||||
|
* $method may be:
|
||||||
|
* - A single verb ("GET"),
|
||||||
|
* - A comma-separated list of verbs ("GET,PUT,DELETE")
|
||||||
|
* - "*" to indicate any method.
|
||||||
|
* @see MethodMapInterface::addMethod
|
||||||
|
*
|
||||||
|
* $target may be:
|
||||||
|
* - An exact path (e.g., "/path/")
|
||||||
|
* - An prefix path ending with "*"" ("/path/*"")
|
||||||
|
* - A URI template with variables enclosed in "{}" ("/path/{id}")
|
||||||
|
* - A regular expression ("~/cat/([0-9]+)~")
|
||||||
|
*
|
||||||
|
* $middleware may be:
|
||||||
|
* - An instance implementing MiddlewareInterface
|
||||||
|
* - A string containing the fully qualified class name of a class
|
||||||
|
* implementing MiddlewareInterface
|
||||||
|
* - A callable that returns an instance implementing MiddleInterface
|
||||||
|
* - A callable maching the signature of MiddlewareInteraface::dispatch
|
||||||
|
* @see DispatchedInterface::dispatch
|
||||||
|
*
|
||||||
|
* @param string $target Request target or pattern to match
|
||||||
|
* @param string $method HTTP method(s) to match
|
||||||
|
* @param mixed $middleware Middleware to dispatch
|
||||||
|
*/
|
||||||
|
public function add($method, $target, $middleware);
|
||||||
|
}
|
||||||
|
|
@ -8,117 +8,93 @@ use WellRESTed\HttpExceptions\HttpException;
|
||||||
use WellRESTed\Message\Response;
|
use WellRESTed\Message\Response;
|
||||||
use WellRESTed\Message\ServerRequest;
|
use WellRESTed\Message\ServerRequest;
|
||||||
use WellRESTed\Message\Stream;
|
use WellRESTed\Message\Stream;
|
||||||
use WellRESTed\Routing\ResponsePrep\ContentLengthPrep;
|
|
||||||
use WellRESTed\Routing\ResponsePrep\HeadPrep;
|
|
||||||
use WellRESTed\Routing\Route\RouteFactory;
|
|
||||||
use WellRESTed\Routing\Route\RouteFactoryInterface;
|
|
||||||
|
|
||||||
class Router implements MiddlewareInterface
|
class Router implements MiddlewareInterface, RouteMapInterface
|
||||||
{
|
{
|
||||||
/** @var DispatcherInterface */
|
/** @var DispatcherInterface */
|
||||||
protected $dispatcher;
|
private $dispatcher;
|
||||||
|
|
||||||
/** @var MiddlewareInterface[] List of middleware to dispatch immediatly before outputting the response */
|
/** @var mixed[] List of middleware to dispatch immediately before concluding the request-response cycle. */
|
||||||
protected $responsePreparationHooks;
|
private $finalizationHooks;
|
||||||
|
|
||||||
/** @var MiddlewareInterface[] List of middleware to dispatch before the router evaluates the route. */
|
/** @var mixed[] List of middleware to dispatch after the router dispatches the matched route. */
|
||||||
private $preRouteHooks;
|
|
||||||
|
|
||||||
/** @var MiddlewareInterface[] List of middleware to dispatch after the router dispatches all other middleware */
|
|
||||||
private $postRouteHooks;
|
private $postRouteHooks;
|
||||||
|
|
||||||
|
/** @var mixed[] List of middleware to dispatch before the router dispatches the matched route. */
|
||||||
|
private $preRouteHooks;
|
||||||
|
|
||||||
/** @var array Hash array of status code => middleware */
|
/** @var array Hash array of status code => middleware */
|
||||||
private $statusHandlers;
|
private $statusHooks;
|
||||||
|
|
||||||
/** @var RouteTable Collection of routes */
|
/** @var RouteMapInterface */
|
||||||
private $routeTable;
|
private $routeMap;
|
||||||
|
|
||||||
/** @var RouteFactoryInterface */
|
|
||||||
private $routeFactory;
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
|
|
||||||
public function __construct()
|
public function __construct()
|
||||||
{
|
{
|
||||||
$this->responsePreparationHooks = $this->getResponsePreparationHooks();
|
$this->dispatcher = $this->getDispatcher();
|
||||||
$this->routeFactory = $this->getRouteFactory();
|
$this->finalizationHooks = $this->getFinalizationHooks();
|
||||||
$this->routeTable = $this->getRouteTable();
|
$this->postRouteHooks = $this->getPostRouteHooks();
|
||||||
$this->statusHandlers = [];
|
$this->preRouteHooks = $this->getPreRouteHooks();
|
||||||
|
$this->statusHooks = $this->getStatusHooks();
|
||||||
|
$this->routeMap = $this->getRouteMap();
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
|
// MiddlewareInterface
|
||||||
/**
|
|
||||||
* Create and return a route given a string path, a handler, and optional
|
|
||||||
* extra arguments.
|
|
||||||
*
|
|
||||||
* The method will determine the most appropriate route subclass to use
|
|
||||||
* and will forward the arguments on to the subclass's constructor.
|
|
||||||
*
|
|
||||||
* - Paths with no special characters will generate StaticRoutes
|
|
||||||
* - Paths ending with * will generate PrefixRoutes
|
|
||||||
* - Paths containing URI variables (e.g., {id}) will generate TemplateRoutes
|
|
||||||
* - Regular exressions will generate RegexRoutes
|
|
||||||
*
|
|
||||||
* @param string $target Path, prefix, or pattern to match
|
|
||||||
* @param mixed $middleware Middleware to dispatch
|
|
||||||
* @param mixed $extra
|
|
||||||
*/
|
|
||||||
public function add($target, $middleware, $extra = null)
|
|
||||||
{
|
|
||||||
if (is_array($middleware)) {
|
|
||||||
$map = $this->getMethodMap();
|
|
||||||
$map->addMap($middleware);
|
|
||||||
$middleware = $map;
|
|
||||||
}
|
|
||||||
$this->routeFactory->registerRoute($this->routeTable, $target, $middleware, $extra);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function addPreRouteHook($middleware)
|
|
||||||
{
|
|
||||||
if (!isset($this->preRouteHooks)) {
|
|
||||||
$this->preRouteHooks = [];
|
|
||||||
}
|
|
||||||
$this->preRouteHooks[] = $middleware;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function addPostRouteHook($middleware)
|
|
||||||
{
|
|
||||||
if (!isset($this->postRouteHooks)) {
|
|
||||||
$this->postRouteHooks = [];
|
|
||||||
}
|
|
||||||
$this->postRouteHooks[] = $middleware;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function addResponsePreparationHook($middleware)
|
|
||||||
{
|
|
||||||
$this->responsePreparationHooks[] = $middleware;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function setStatusHandler($statusCode, $middleware)
|
|
||||||
{
|
|
||||||
$this->statusHandlers[$statusCode] = $middleware;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function dispatch(ServerRequestInterface $request, ResponseInterface &$response)
|
public function dispatch(ServerRequestInterface $request, ResponseInterface &$response)
|
||||||
{
|
{
|
||||||
$this->disptachPreRouteHooks($request, $response);
|
$this->dispatchPreRouteHooks($request, $response);
|
||||||
try {
|
try {
|
||||||
$this->routeTable->dispatch($request, $response);
|
$this->routeMap->dispatch($request, $response);
|
||||||
} catch (HttpException $e) {
|
} catch (HttpException $e) {
|
||||||
$response = $response->withStatus($e->getCode());
|
$response = $response->withStatus($e->getCode());
|
||||||
$response = $response->withBody(new Stream($e->getMessage()));
|
$response = $response->withBody(new Stream($e->getMessage()));
|
||||||
}
|
}
|
||||||
$statusCode = $response->getStatusCode();
|
$this->dispatchStatusHooks($request, $response);
|
||||||
if (isset($this->statusHandlers[$statusCode])) {
|
$this->dispatchPostRouteHooks($request, $response);
|
||||||
$middleware = $this->statusHandlers[$statusCode];
|
$this->dispatchFinalizationHooks($request, $response);
|
||||||
$dispatcher = $this->getDispatcher();
|
|
||||||
$dispatcher->dispatch($middleware, $request, $response);
|
|
||||||
}
|
|
||||||
$this->disptachPostRouteHooks($request, $response);
|
|
||||||
$this->dispatchResponsePreparationHooks($request, $response);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
// RouteMapInterface
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register middleware with the router for a given path and method.
|
||||||
|
*
|
||||||
|
* $method may be:
|
||||||
|
* - A single verb ("GET"),
|
||||||
|
* - A comma-separated list of verbs ("GET,PUT,DELETE")
|
||||||
|
* - "*" to indicate any method.
|
||||||
|
* @see MethodMapInterface::addMethod
|
||||||
|
*
|
||||||
|
* $target may be:
|
||||||
|
* - An exact path (e.g., "/path/")
|
||||||
|
* - An prefix path ending with "*"" ("/path/*"")
|
||||||
|
* - A URI template with variables enclosed in "{}" ("/path/{id}")
|
||||||
|
* - A regular expression ("~/cat/([0-9]+)~")
|
||||||
|
*
|
||||||
|
* $middleware may be:
|
||||||
|
* - An instance implementing MiddlewareInterface
|
||||||
|
* - A string containing the fully qualified class name of a class
|
||||||
|
* implementing MiddlewareInterface
|
||||||
|
* - A callable that returns an instance implementing MiddleInterface
|
||||||
|
* - A callable maching the signature of MiddlewareInteraface::dispatch
|
||||||
|
* @see DispatchedInterface::dispatch
|
||||||
|
*
|
||||||
|
* @param string $target Request target or pattern to match
|
||||||
|
* @param string $method HTTP method(s) to match
|
||||||
|
* @param mixed $middleware Middleware to dispatch
|
||||||
|
*/
|
||||||
|
public function add($method, $target, $middleware)
|
||||||
|
{
|
||||||
|
$this->routeMap->add($method, $target, $middleware);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
|
||||||
public function respond()
|
public function respond()
|
||||||
{
|
{
|
||||||
$request = $this->getRequest();
|
$request = $this->getRequest();
|
||||||
|
|
@ -128,34 +104,91 @@ class Router implements MiddlewareInterface
|
||||||
$responder->respond($response);
|
$responder->respond($response);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
// Hooks
|
||||||
|
|
||||||
|
public function addPreRouteHook($middleware)
|
||||||
|
{
|
||||||
|
$this->preRouteHooks[] = $middleware;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function addPostRouteHook($middleware)
|
||||||
|
{
|
||||||
|
$this->postRouteHooks[] = $middleware;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function addFinalizationHook($middleware)
|
||||||
|
{
|
||||||
|
$this->finalizationHooks[] = $middleware;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setStatusHook($statusCode, $middleware)
|
||||||
|
{
|
||||||
|
$this->statusHooks[$statusCode] = $middleware;
|
||||||
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
// The following methods provide instaces the router will use. Override
|
// The following methods provide instaces the router will use. Override
|
||||||
// to provide custom classes or configured instances.
|
// to provide custom classes or configured instances.
|
||||||
|
|
||||||
// @codeCoverageIgnoreStart
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return an instance that can dispatch middleware.
|
* Return an instance that can dispatch middleware.
|
||||||
|
*
|
||||||
* Override to provide a custom class.
|
* Override to provide a custom class.
|
||||||
*
|
*
|
||||||
* @return DispatcherInterface
|
* @return DispatcherInterface
|
||||||
*/
|
*/
|
||||||
protected function getDispatcher()
|
protected function getDispatcher()
|
||||||
{
|
{
|
||||||
if (!isset($this->dispatcher)) {
|
return new Dispatcher();
|
||||||
$this->dispatcher = new Dispatcher();
|
|
||||||
}
|
|
||||||
return $this->dispatcher;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return MethodMapInterface
|
* Return an instance that maps routes to middleware.
|
||||||
|
*
|
||||||
|
* Override to provide a custom class.
|
||||||
|
*
|
||||||
|
* @return RouteMapInterface
|
||||||
*/
|
*/
|
||||||
protected function getMethodMap()
|
protected function getRouteMap()
|
||||||
{
|
{
|
||||||
return new MethodMap();
|
return new RouteMap();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
protected function getPreRouteHooks()
|
||||||
|
{
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
protected function getPostRouteHooks()
|
||||||
|
{
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
protected function getStatusHooks()
|
||||||
|
{
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
protected function getFinalizationHooks()
|
||||||
|
{
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
// @codeCoverageIgnoreStart
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return ServerRequestInterface
|
* @return ServerRequestInterface
|
||||||
*/
|
*/
|
||||||
|
|
@ -180,62 +213,38 @@ class Router implements MiddlewareInterface
|
||||||
return new Response();
|
return new Response();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @return MiddlewareInterface[]
|
|
||||||
*/
|
|
||||||
protected function getResponsePreparationHooks()
|
|
||||||
{
|
|
||||||
return [
|
|
||||||
new ContentLengthPrep(),
|
|
||||||
new HeadPrep()
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return RouteFactoryInterface
|
|
||||||
*/
|
|
||||||
protected function getRouteFactory()
|
|
||||||
{
|
|
||||||
return new RouteFactory();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return RouteTableInterface
|
|
||||||
*/
|
|
||||||
protected function getRouteTable()
|
|
||||||
{
|
|
||||||
return new RouteTable();
|
|
||||||
}
|
|
||||||
|
|
||||||
// @codeCoverageIgnoreEnd
|
// @codeCoverageIgnoreEnd
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
|
|
||||||
private function disptachPreRouteHooks(ServerRequestInterface $request, ResponseInterface &$response)
|
private function dispatchPreRouteHooks(ServerRequestInterface $request, ResponseInterface &$response)
|
||||||
{
|
{
|
||||||
if ($this->preRouteHooks) {
|
foreach ($this->preRouteHooks as $hook) {
|
||||||
$dispatcher = $this->getDispatcher();
|
$this->dispatcher->dispatch($hook, $request, $response);
|
||||||
foreach ($this->preRouteHooks as $hook) {
|
|
||||||
$dispatcher->dispatch($hook, $request, $response);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private function disptachPostRouteHooks(ServerRequestInterface $request, ResponseInterface &$response)
|
private function dispatchPostRouteHooks(ServerRequestInterface $request, ResponseInterface &$response)
|
||||||
{
|
{
|
||||||
if ($this->postRouteHooks) {
|
foreach ($this->postRouteHooks as $hook) {
|
||||||
$dispatcher = $this->getDispatcher();
|
$this->dispatcher->dispatch($hook, $request, $response);
|
||||||
foreach ($this->postRouteHooks as $hook) {
|
|
||||||
$dispatcher->dispatch($hook, $request, $response);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private function dispatchResponsePreparationHooks(ServerRequestInterface $request, ResponseInterface &$response)
|
private function dispatchFinalizationHooks(ServerRequestInterface $request, ResponseInterface &$response)
|
||||||
{
|
{
|
||||||
$dispatcher = $this->getDispatcher();
|
foreach ($this->finalizationHooks as $hook) {
|
||||||
foreach ($this->responsePreparationHooks as $hook) {
|
$this->dispatcher->dispatch($hook, $request, $response);
|
||||||
$dispatcher->dispatch($hook, $request, $response);
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private function dispatchStatusHooks(ServerRequestInterface $request, ResponseInterface &$response)
|
||||||
|
{
|
||||||
|
$statusCode = $response->getStatusCode();
|
||||||
|
if (isset($this->statusHooks[$statusCode])) {
|
||||||
|
$middleware = $this->statusHooks[$statusCode];
|
||||||
|
$dispatcher = $this->getDispatcher();
|
||||||
|
$dispatcher->dispatch($middleware, $request, $response);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,46 +6,26 @@ use Prophecy\Argument;
|
||||||
use WellRESTed\HttpExceptions\NotFoundException;
|
use WellRESTed\HttpExceptions\NotFoundException;
|
||||||
use WellRESTed\Routing\Router;
|
use WellRESTed\Routing\Router;
|
||||||
|
|
||||||
|
// TODO Tests that ensure hooks are called at correct times
|
||||||
|
// TODO Test default finalization hooks
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @coversDefaultClass WellRESTed\Routing\Router
|
* @coversDefaultClass WellRESTed\Routing\Router
|
||||||
* @uses WellRESTed\Routing\Router
|
* @uses WellRESTed\Routing\Router
|
||||||
* @uses WellRESTed\Message\Stream
|
* @uses WellRESTed\Message\Stream
|
||||||
* @uses WellRESTed\Routing\Dispatcher
|
* @uses WellRESTed\Routing\Dispatcher
|
||||||
* @uses WellRESTed\Routing\MethodMap
|
* @uses WellRESTed\Routing\RouteMap
|
||||||
* @uses WellRESTed\Routing\ResponsePrep\ContentLengthPrep
|
|
||||||
* @uses WellRESTed\Routing\ResponsePrep\HeadPrep
|
|
||||||
* @uses WellRESTed\Routing\Route\PrefixRoute
|
|
||||||
* @uses WellRESTed\Routing\Route\RegexRoute
|
|
||||||
* @uses WellRESTed\Routing\Route\Route
|
|
||||||
* @uses WellRESTed\Routing\Route\RouteFactory
|
|
||||||
* @uses WellRESTed\Routing\Route\StaticRoute
|
|
||||||
* @uses WellRESTed\Routing\Route\TemplateRoute
|
|
||||||
* @uses WellRESTed\Routing\RouteTable
|
|
||||||
*/
|
*/
|
||||||
class RouterTest extends \PHPUnit_Framework_TestCase
|
class RouterTest extends \PHPUnit_Framework_TestCase
|
||||||
{
|
{
|
||||||
private $dispatcher;
|
|
||||||
private $middleware;
|
|
||||||
private $request;
|
private $request;
|
||||||
private $responder;
|
|
||||||
private $response;
|
private $response;
|
||||||
|
|
||||||
public function setUp()
|
public function setUp()
|
||||||
{
|
{
|
||||||
$this->dispatcher = $this->prophesize('WellRESTed\Routing\DispatcherInterface');
|
parent::setUp();
|
||||||
$this->dispatcher->dispatch(Argument::any())->willReturn();
|
|
||||||
$this->middleware = $this->prophesize('WellRESTed\Routing\MiddlewareInterface');
|
|
||||||
$this->middleware->dispatch(Argument::cetera())->willReturn();
|
|
||||||
$this->request = $this->prophesize('Psr\Http\Message\ServerRequestInterface');
|
$this->request = $this->prophesize('Psr\Http\Message\ServerRequestInterface');
|
||||||
$this->request->getRequestTarget()->willReturn("/");
|
|
||||||
$this->request->getMethod()->willReturn("GET");
|
|
||||||
$this->responder = $this->prophesize('WellRESTed\Routing\ResponderInterface');
|
|
||||||
$this->responder->respond(Argument::any())->willReturn();
|
|
||||||
$this->response = $this->prophesize('Psr\Http\Message\ResponseInterface');
|
$this->response = $this->prophesize('Psr\Http\Message\ResponseInterface');
|
||||||
$this->response->withStatus(Argument::any())->willReturn($this->response->reveal());
|
|
||||||
$this->response->withBody(Argument::any())->willReturn($this->response->reveal());
|
|
||||||
$this->response->hasHeader("Content-length")->willReturn(true);
|
|
||||||
$this->response->getStatusCode()->willReturn(200);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
|
|
@ -53,6 +33,12 @@ class RouterTest extends \PHPUnit_Framework_TestCase
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @covers ::__construct
|
* @covers ::__construct
|
||||||
|
* @covers ::getDispatcher
|
||||||
|
* @covers ::getRouteMap
|
||||||
|
* @covers ::getPreRouteHooks
|
||||||
|
* @covers ::getPostRouteHooks
|
||||||
|
* @covers ::getFinalizationHooks
|
||||||
|
* @covers ::getStatusHooks
|
||||||
*/
|
*/
|
||||||
public function testCreatesInstance()
|
public function testCreatesInstance()
|
||||||
{
|
{
|
||||||
|
|
@ -66,85 +52,26 @@ class RouterTest extends \PHPUnit_Framework_TestCase
|
||||||
/**
|
/**
|
||||||
* @covers ::add
|
* @covers ::add
|
||||||
*/
|
*/
|
||||||
public function testAddWithSimpleRouteRegistersRoute()
|
public function testAddRegistersRouteWithRouteMap()
|
||||||
{
|
{
|
||||||
$factory = $this->prophesize('WellRESTed\Routing\Route\RouteFactoryInterface');
|
$routeMap = $this->prophesize('WellRESTed\Routing\RouteMapInterface');
|
||||||
$factory->registerRoute(Argument::cetera())->willReturn();
|
$routeMap->add(Argument::cetera())->willReturn();
|
||||||
|
|
||||||
$router = $this->getMockBuilder('WellRESTed\Routing\Router')
|
$router = $this->getMockBuilder('WellRESTed\Routing\Router')
|
||||||
->setMethods(["getRouteFactory"])
|
->setMethods(["getRouteMap"])
|
||||||
->disableOriginalConstructor()
|
->disableOriginalConstructor()
|
||||||
->getMock();
|
->getMock();
|
||||||
$router->expects($this->any())
|
$router->expects($this->any())
|
||||||
->method("getRouteFactory")
|
->method("getRouteMap")
|
||||||
->will($this->returnValue($factory->reveal()));
|
->will($this->returnValue($routeMap->reveal()));
|
||||||
$router->__construct();
|
$router->__construct();
|
||||||
|
|
||||||
$target = "/cats/";
|
$method = "GET";
|
||||||
$middleware = $this->middleware->reveal();
|
$target = "/path/{id}";
|
||||||
$router->add($target, $middleware);
|
$middleware = "Middleware";
|
||||||
|
|
||||||
$factory->registerRoute(Argument::any(), $target, $middleware, Argument::any())->shouldHaveBeenCalled();
|
$router->add($method, $target, $middleware);
|
||||||
}
|
$routeMap->add($method, $target, $middleware)->shouldHaveBeenCalled();
|
||||||
|
|
||||||
/**
|
|
||||||
* @covers ::add
|
|
||||||
*/
|
|
||||||
public function testAddWithMapAddsMiddlewareToMethodMap()
|
|
||||||
{
|
|
||||||
$map = $this->prophesize('WellRESTed\Routing\MethodMapInterface');
|
|
||||||
$map->addMap(Argument::any())->willReturn();
|
|
||||||
|
|
||||||
$factory = $this->prophesize('WellRESTed\Routing\Route\RouteFactoryInterface');
|
|
||||||
$factory->registerRoute(Argument::cetera())->willReturn();
|
|
||||||
|
|
||||||
$router = $this->getMockBuilder('WellRESTed\Routing\Router')
|
|
||||||
->setMethods(["getRouteFactory", "getMethodMap"])
|
|
||||||
->disableOriginalConstructor()
|
|
||||||
->getMock();
|
|
||||||
$router->expects($this->any())
|
|
||||||
->method("getMethodMap")
|
|
||||||
->will($this->returnValue($map->reveal()));
|
|
||||||
$router->expects($this->any())
|
|
||||||
->method("getRouteFactory")
|
|
||||||
->will($this->returnValue($factory->reveal()));
|
|
||||||
$router->__construct();
|
|
||||||
|
|
||||||
$target = "/cats/";
|
|
||||||
$middleware = ["GET" => $this->middleware->reveal()];
|
|
||||||
$router->add($target, $middleware);
|
|
||||||
|
|
||||||
$map->addMap($middleware)->shouldHaveBeenCalled();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @covers ::add
|
|
||||||
*/
|
|
||||||
public function testAddWithMapRegistersMethodMap()
|
|
||||||
{
|
|
||||||
$map = $this->prophesize('WellRESTed\Routing\MethodMapInterface');
|
|
||||||
$map->addMap(Argument::any())->willReturn();
|
|
||||||
|
|
||||||
$factory = $this->prophesize('WellRESTed\Routing\Route\RouteFactoryInterface');
|
|
||||||
$factory->registerRoute(Argument::cetera())->willReturn();
|
|
||||||
|
|
||||||
$router = $this->getMockBuilder('WellRESTed\Routing\Router')
|
|
||||||
->setMethods(["getRouteFactory", "getMethodMap"])
|
|
||||||
->disableOriginalConstructor()
|
|
||||||
->getMock();
|
|
||||||
$router->expects($this->any())
|
|
||||||
->method("getMethodMap")
|
|
||||||
->will($this->returnValue($map->reveal()));
|
|
||||||
$router->expects($this->any())
|
|
||||||
->method("getRouteFactory")
|
|
||||||
->will($this->returnValue($factory->reveal()));
|
|
||||||
$router->__construct();
|
|
||||||
|
|
||||||
$target = "/cats/";
|
|
||||||
$middleware = ["GET" => $this->middleware->reveal()];
|
|
||||||
$router->add($target, $middleware);
|
|
||||||
|
|
||||||
$factory->registerRoute(Argument::any(), $target, $map, Argument::any())->shouldHaveBeenCalled();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
|
|
@ -153,18 +80,25 @@ class RouterTest extends \PHPUnit_Framework_TestCase
|
||||||
/**
|
/**
|
||||||
* @covers ::dispatch
|
* @covers ::dispatch
|
||||||
*/
|
*/
|
||||||
public function testDispatchesMatchedRoute()
|
public function testDispatchesRouteMap()
|
||||||
{
|
{
|
||||||
$this->request->getRequestTarget()->willReturn("/cats/");
|
$routeMap = $this->prophesize('WellRESTed\Routing\RouteMapInterface');
|
||||||
|
$routeMap->dispatch(Argument::cetera())->willReturn();
|
||||||
|
|
||||||
$router = new Router();
|
$router = $this->getMockBuilder('WellRESTed\Routing\Router')
|
||||||
$router->add("/cats/", $this->middleware->reveal());
|
->setMethods(["getRouteMap"])
|
||||||
|
->disableOriginalConstructor()
|
||||||
|
->getMock();
|
||||||
|
$router->expects($this->any())
|
||||||
|
->method("getRouteMap")
|
||||||
|
->will($this->returnValue($routeMap->reveal()));
|
||||||
|
$router->__construct();
|
||||||
|
|
||||||
$request = $this->request->reveal();
|
$request = $this->request->reveal();
|
||||||
$response = $this->response->reveal();
|
$resonse = $this->response->reveal();
|
||||||
$router->dispatch($request, $response);
|
$router->dispatch($request, $resonse);
|
||||||
|
|
||||||
$this->middleware->dispatch(Argument::cetera())->shouldHaveBeenCalled();
|
$routeMap->dispatch($request, Argument::any())->shouldHaveBeenCalled();
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
|
|
@ -172,9 +106,9 @@ class RouterTest extends \PHPUnit_Framework_TestCase
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @covers ::addPreRouteHook
|
* @covers ::addPreRouteHook
|
||||||
* @covers ::disptachPreRouteHooks
|
* @covers ::dispatchPreRouteHooks
|
||||||
*/
|
*/
|
||||||
public function testDispatchesPreRouteHooks()
|
public function testDispatchesPreRouteHook()
|
||||||
{
|
{
|
||||||
$hook = $this->prophesize('\WellRESTed\Routing\MiddlewareInterface');
|
$hook = $this->prophesize('\WellRESTed\Routing\MiddlewareInterface');
|
||||||
$hook->dispatch(Argument::cetera())->willReturn();
|
$hook->dispatch(Argument::cetera())->willReturn();
|
||||||
|
|
@ -183,7 +117,6 @@ class RouterTest extends \PHPUnit_Framework_TestCase
|
||||||
|
|
||||||
$router = new Router();
|
$router = new Router();
|
||||||
$router->addPreRouteHook($hook->reveal());
|
$router->addPreRouteHook($hook->reveal());
|
||||||
$router->add("/cats/", $this->middleware->reveal());
|
|
||||||
|
|
||||||
$request = $this->request->reveal();
|
$request = $this->request->reveal();
|
||||||
$response = $this->response->reveal();
|
$response = $this->response->reveal();
|
||||||
|
|
@ -194,9 +127,9 @@ class RouterTest extends \PHPUnit_Framework_TestCase
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @covers ::addPostRouteHook
|
* @covers ::addPostRouteHook
|
||||||
* @covers ::disptachPostRouteHooks
|
* @covers ::dispatchPostRouteHooks
|
||||||
*/
|
*/
|
||||||
public function testDispatchesPostRouteHooks()
|
public function testDispatchesPostRouteHook()
|
||||||
{
|
{
|
||||||
$hook = $this->prophesize('\WellRESTed\Routing\MiddlewareInterface');
|
$hook = $this->prophesize('\WellRESTed\Routing\MiddlewareInterface');
|
||||||
$hook->dispatch(Argument::cetera())->willReturn();
|
$hook->dispatch(Argument::cetera())->willReturn();
|
||||||
|
|
@ -205,7 +138,6 @@ class RouterTest extends \PHPUnit_Framework_TestCase
|
||||||
|
|
||||||
$router = new Router();
|
$router = new Router();
|
||||||
$router->addPostRouteHook($hook->reveal());
|
$router->addPostRouteHook($hook->reveal());
|
||||||
$router->add("/cats/", $this->middleware->reveal());
|
|
||||||
|
|
||||||
$request = $this->request->reveal();
|
$request = $this->request->reveal();
|
||||||
$response = $this->response->reveal();
|
$response = $this->response->reveal();
|
||||||
|
|
@ -215,10 +147,10 @@ class RouterTest extends \PHPUnit_Framework_TestCase
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @covers ::addResponsePreparationHook
|
* @covers ::addFinalizationHook
|
||||||
* @covers ::dispatchResponsePreparationHooks
|
* @covers ::dispatchFinalizationHooks
|
||||||
*/
|
*/
|
||||||
public function testDispatchesResponsePreparationHooks()
|
public function testDispatchesFinalHooks()
|
||||||
{
|
{
|
||||||
$hook = $this->prophesize('\WellRESTed\Routing\MiddlewareInterface');
|
$hook = $this->prophesize('\WellRESTed\Routing\MiddlewareInterface');
|
||||||
$hook->dispatch(Argument::cetera())->willReturn();
|
$hook->dispatch(Argument::cetera())->willReturn();
|
||||||
|
|
@ -226,8 +158,7 @@ class RouterTest extends \PHPUnit_Framework_TestCase
|
||||||
$this->request->getRequestTarget()->willReturn("/cats/");
|
$this->request->getRequestTarget()->willReturn("/cats/");
|
||||||
|
|
||||||
$router = new Router();
|
$router = new Router();
|
||||||
$router->addResponsePreparationHook($hook->reveal());
|
$router->addFinalizationHook($hook->reveal());
|
||||||
$router->add("/cats/", $this->middleware->reveal());
|
|
||||||
|
|
||||||
$request = $this->request->reveal();
|
$request = $this->request->reveal();
|
||||||
$response = $this->response->reveal();
|
$response = $this->response->reveal();
|
||||||
|
|
@ -241,9 +172,10 @@ class RouterTest extends \PHPUnit_Framework_TestCase
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @covers ::dispatch
|
* @covers ::dispatch
|
||||||
* @covers ::setStatusHandler
|
* @covers ::dispatchStatusHooks
|
||||||
|
* @covers ::setStatusHook
|
||||||
*/
|
*/
|
||||||
public function testDispatchesHandlerForStatusCode()
|
public function testDispatchesHookForStatusCode()
|
||||||
{
|
{
|
||||||
$this->response->getStatusCode()->willReturn(403);
|
$this->response->getStatusCode()->willReturn(403);
|
||||||
|
|
||||||
|
|
@ -251,8 +183,7 @@ class RouterTest extends \PHPUnit_Framework_TestCase
|
||||||
$statusMiddleware->dispatch(Argument::cetera())->willReturn();
|
$statusMiddleware->dispatch(Argument::cetera())->willReturn();
|
||||||
|
|
||||||
$router = new Router();
|
$router = new Router();
|
||||||
$router->add("/cats/", $this->middleware->reveal());
|
$router->setStatusHook(403, $statusMiddleware->reveal());
|
||||||
$router->setStatusHandler(403, $statusMiddleware->reveal());
|
|
||||||
|
|
||||||
$request = $this->request->reveal();
|
$request = $this->request->reveal();
|
||||||
$response = $this->response->reveal();
|
$response = $this->response->reveal();
|
||||||
|
|
@ -263,15 +194,33 @@ class RouterTest extends \PHPUnit_Framework_TestCase
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @covers ::dispatch
|
* @covers ::dispatch
|
||||||
* @covers ::setStatusHandler
|
* @covers ::dispatchStatusHooks
|
||||||
|
* @covers ::setStatusHook
|
||||||
*/
|
*/
|
||||||
public function testDispatchesHandlerForStatusCodeForHttpException()
|
public function testDispatchesStatusHookForHttpException()
|
||||||
{
|
{
|
||||||
$this->request->getRequestTarget()->willReturn("/cats/");
|
$statusMiddleware = $this->prophesize('\WellRESTed\Routing\MiddlewareInterface');
|
||||||
$this->middleware->dispatch(Argument::cetera())->willThrow(new NotFoundException());
|
$statusMiddleware->dispatch(Argument::cetera())->willReturn();
|
||||||
|
|
||||||
$router = new Router();
|
$routeMap = $this->prophesize('WellRESTed\Routing\RouteMapInterface');
|
||||||
$router->add("/cats/", $this->middleware->reveal());
|
$routeMap->dispatch(Argument::cetera())->willThrow(new NotFoundException());
|
||||||
|
|
||||||
|
$this->response->withStatus(Argument::any())->will(
|
||||||
|
function ($args) {
|
||||||
|
$this->getStatusCode()->willReturn($args[0]);
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
$this->response->withBody(Argument::any())->willReturn($this->response->reveal());
|
||||||
|
|
||||||
|
$router = $this->getMockBuilder('WellRESTed\Routing\Router')
|
||||||
|
->setMethods(["getRouteMap"])
|
||||||
|
->disableOriginalConstructor()
|
||||||
|
->getMock();
|
||||||
|
$router->expects($this->any())
|
||||||
|
->method("getRouteMap")
|
||||||
|
->will($this->returnValue($routeMap->reveal()));
|
||||||
|
$router->__construct();
|
||||||
|
|
||||||
$request = $this->request->reveal();
|
$request = $this->request->reveal();
|
||||||
$response = $this->response->reveal();
|
$response = $this->response->reveal();
|
||||||
|
|
@ -285,16 +234,27 @@ class RouterTest extends \PHPUnit_Framework_TestCase
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @covers ::respond
|
* @covers ::respond
|
||||||
|
* @covers ::getRequest
|
||||||
|
* @covers ::getResponse
|
||||||
|
* @covers ::getResponder
|
||||||
*/
|
*/
|
||||||
public function testRespondDispatchesRequest()
|
public function testRespondDispatchesRequest()
|
||||||
{
|
{
|
||||||
$target = "/cats/";
|
$middleware = $this->prophesize('\WellRESTed\Routing\MiddlewareInterface');
|
||||||
|
$middleware->dispatch(Argument::cetera())->willReturn();
|
||||||
|
|
||||||
$this->request->getRequestTarget()->willReturn($target);
|
$responder = $this->prophesize('WellRESTed\Routing\ResponderInterface');
|
||||||
$this->responder->respond(Argument::any())->willReturn();
|
$responder->respond(Argument::any())->willReturn();
|
||||||
|
|
||||||
|
$routeMap = $this->prophesize('WellRESTed\Routing\RouteMapInterface');
|
||||||
|
$routeMap->dispatch(Argument::cetera())->will(
|
||||||
|
function ($args) use ($middleware) {
|
||||||
|
$middleware->reveal()->dispatch($args[0], $args[1]);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
$router = $this->getMockBuilder('WellRESTed\Routing\Router')
|
$router = $this->getMockBuilder('WellRESTed\Routing\Router')
|
||||||
->setMethods(["getRequest", "getResponse", "getResponder"])
|
->setMethods(["getRequest", "getResponse", "getResponder", "getRouteMap"])
|
||||||
->disableOriginalConstructor()
|
->disableOriginalConstructor()
|
||||||
->getMock();
|
->getMock();
|
||||||
$router->expects($this->any())
|
$router->expects($this->any())
|
||||||
|
|
@ -305,25 +265,39 @@ class RouterTest extends \PHPUnit_Framework_TestCase
|
||||||
->will($this->returnValue($this->response->reveal()));
|
->will($this->returnValue($this->response->reveal()));
|
||||||
$router->expects($this->any())
|
$router->expects($this->any())
|
||||||
->method("getResponder")
|
->method("getResponder")
|
||||||
->will($this->returnValue($this->responder->reveal()));
|
->will($this->returnValue($responder->reveal()));
|
||||||
|
$router->expects($this->any())
|
||||||
|
->method("getRouteMap")
|
||||||
|
->will($this->returnValue($routeMap->reveal()));
|
||||||
$router->__construct();
|
$router->__construct();
|
||||||
$router->add($target, $this->middleware->reveal());
|
|
||||||
$router->respond();
|
$router->respond();
|
||||||
|
|
||||||
$this->middleware->dispatch(Argument::cetera())->shouldHaveBeenCalled();
|
$middleware->dispatch(Argument::cetera())->shouldHaveBeenCalled();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @covers ::respond
|
* @covers ::respond
|
||||||
|
* @covers ::getRequest
|
||||||
|
* @covers ::getResponse
|
||||||
|
* @covers ::getResponder
|
||||||
*/
|
*/
|
||||||
public function testSendsResponseToResponder()
|
public function testSendsResponseToResponder()
|
||||||
{
|
{
|
||||||
$target = "/cats/";
|
$middleware = $this->prophesize('\WellRESTed\Routing\MiddlewareInterface');
|
||||||
|
$middleware->dispatch(Argument::cetera())->willReturn();
|
||||||
|
|
||||||
$this->request->getRequestTarget()->willReturn($target);
|
$responder = $this->prophesize('WellRESTed\Routing\ResponderInterface');
|
||||||
|
$responder->respond(Argument::any())->willReturn();
|
||||||
|
|
||||||
|
$routeMap = $this->prophesize('WellRESTed\Routing\RouteMapInterface');
|
||||||
|
$routeMap->dispatch(Argument::cetera())->will(
|
||||||
|
function ($args) use ($middleware) {
|
||||||
|
$middleware->reveal()->dispatch($args[0], $args[1]);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
$router = $this->getMockBuilder('WellRESTed\Routing\Router')
|
$router = $this->getMockBuilder('WellRESTed\Routing\Router')
|
||||||
->setMethods(["getRequest", "getResponse", "getResponder"])
|
->setMethods(["getRequest", "getResponse", "getResponder", "getRouteMap"])
|
||||||
->disableOriginalConstructor()
|
->disableOriginalConstructor()
|
||||||
->getMock();
|
->getMock();
|
||||||
$router->expects($this->any())
|
$router->expects($this->any())
|
||||||
|
|
@ -334,11 +308,13 @@ class RouterTest extends \PHPUnit_Framework_TestCase
|
||||||
->will($this->returnValue($this->response->reveal()));
|
->will($this->returnValue($this->response->reveal()));
|
||||||
$router->expects($this->any())
|
$router->expects($this->any())
|
||||||
->method("getResponder")
|
->method("getResponder")
|
||||||
->will($this->returnValue($this->responder->reveal()));
|
->will($this->returnValue($responder->reveal()));
|
||||||
|
$router->expects($this->any())
|
||||||
|
->method("getRouteMap")
|
||||||
|
->will($this->returnValue($routeMap->reveal()));
|
||||||
$router->__construct();
|
$router->__construct();
|
||||||
$router->add($target, $this->middleware->reveal());
|
|
||||||
$router->respond();
|
$router->respond();
|
||||||
|
|
||||||
$this->responder->respond($this->response->reveal())->shouldHaveBeenCalled();
|
$responder->respond($this->response->reveal())->shouldHaveBeenCalled();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue