diff --git a/src/pjdietz/WellRESTed/Handler.php b/src/pjdietz/WellRESTed/Handler.php
index a1a81af..408c400 100644
--- a/src/pjdietz/WellRESTed/Handler.php
+++ b/src/pjdietz/WellRESTed/Handler.php
@@ -10,7 +10,6 @@
namespace pjdietz\WellRESTed;
-use pjdietz\WellRESTed\Exceptions\HttpExceptions\HttpException;
use pjdietz\WellRESTed\Interfaces\HandlerInterface;
use pjdietz\WellRESTed\Interfaces\RequestInterface;
use pjdietz\WellRESTed\Interfaces\ResponseInterface;
@@ -46,12 +45,7 @@ abstract class Handler implements HandlerInterface
$this->request = $request;
$this->args = $args;
$this->response = new Response();
- try {
- $this->buildResponse();
- } catch (HttpException $e) {
- $this->response->setStatusCode($e->getCode());
- $this->response->setBody($e->getMessage());
- }
+ $this->buildResponse();
return $this->response;
}
diff --git a/src/pjdietz/WellRESTed/RouteBuilder.php b/src/pjdietz/WellRESTed/RouteBuilder.php
index 09b2e66..f449811 100644
--- a/src/pjdietz/WellRESTed/RouteBuilder.php
+++ b/src/pjdietz/WellRESTed/RouteBuilder.php
@@ -83,6 +83,8 @@ class RouteBuilder
* ->variablePattern is passed to setDefaultVariablePattern()
*
* ->vars is passed to setTemplateVars()
+ *
+ * @param object
*/
public function readConfiguration($data)
{
diff --git a/src/pjdietz/WellRESTed/Router.php b/src/pjdietz/WellRESTed/Router.php
index a3d5fc2..6cf9f54 100644
--- a/src/pjdietz/WellRESTed/Router.php
+++ b/src/pjdietz/WellRESTed/Router.php
@@ -10,6 +10,7 @@
namespace pjdietz\WellRESTed;
+use pjdietz\WellRESTed\Exceptions\HttpExceptions\HttpException;
use pjdietz\WellRESTed\Interfaces\HandlerInterface;
use pjdietz\WellRESTed\Interfaces\RequestInterface;
use pjdietz\WellRESTed\Interfaces\ResponseInterface;
@@ -23,7 +24,7 @@ class Router implements HandlerInterface
{
/** @var array Array of Route objects */
private $routes;
- /** @var array Array of Route objects for error handling. */
+ /** @var array Hash array of status code => qualified HandlerInterface names for error handling. */
private $errorHandlers;
/** Create a new Router. */
@@ -44,9 +45,27 @@ class Router implements HandlerInterface
{
foreach ($this->routes as $route) {
/** @var HandlerInterface $route */
- $responce = $route->getResponse($request, $args);
- if ($responce) {
- return $responce;
+ try {
+ $response = $route->getResponse($request, $args);
+ } catch (HttpException $e) {
+ $response = new Response();
+ $response->setStatusCode($e->getCode());
+ $response->setBody($e->getMessage());
+ }
+ if ($response) {
+ // Check if the router has an error handler for this status code.
+ $status = $response->getStatusCode();
+ if (array_key_exists($status, $this->errorHandlers)) {
+ /** @var HandlerInterface $errorHandler */
+ $errorHandler = new $this->errorHandlers[$status]();
+ // Pass the response triggering this along to the error handler.
+ $errorArgs = array("response" => $response);
+ if ($args) {
+ $errorArgs = array_merge($args, $errorArgs);
+ }
+ return $errorHandler->getResponse($request, $errorArgs);
+ }
+ return $response;
}
}
return null;
@@ -79,23 +98,23 @@ class Router implements HandlerInterface
/**
* Add a custom error handler.
*
- * @param integer $error The error code.
- * @param HandlerInterface $errorHandler The handler for the error.
+ * @param integer $statusCode The error status code.
+ * @param string $errorHandler Fully qualified name to an autoloadable handler class.
*/
- public function addErrorHandler($error, $errorHandler)
+ public function setErrorHandler($statusCode, $errorHandler)
{
- $this->errorHandlers[$error] = $errorHandler;
+ $this->errorHandlers[$statusCode] = $errorHandler;
}
/**
* Add custom error handlers.
*
- * @param array $errorHandlers An array mapping an integer error code to something implementing an HandlerInterface.
+ * @param array $errorHandlers Array mapping integer error codes to qualified handler names.
*/
- public function addErrorHandlers(array $errorHandlers)
+ public function setErrorHandlers(array $errorHandlers)
{
- foreach ($errorHandlers as $error => $errorHandler) {
- $this->addErrorHandler($error, $errorHandler);
+ foreach ($errorHandlers as $statusCode => $errorHandler) {
+ $this->setErrorHandler($statusCode, $errorHandler);
}
}
@@ -103,6 +122,7 @@ class Router implements HandlerInterface
* Dispatch the singleton Request through the router and output the response.
*
* Respond with a 404 Not Found if no route provides a response.
+ * @param array|null $args
*/
public function respond($args = null)
{
@@ -111,16 +131,11 @@ class Router implements HandlerInterface
if (!$response) {
$response = $this->getNoRouteResponse($request);
}
- $status = $response->getStatusCode();
- if (array_key_exists($status, $this->errorHandlers)) {
- $errorHandler = new $this->errorHandlers[$status]();
- $response = $errorHandler->getResponse($request, $args);
- }
$response->respond();
}
/**
- * Prepare a resonse indicating a 404 Not Found error
+ * Prepare a response indicating a 404 Not Found error
*
* @param RequestInterface $request
* @return ResponseInterface
diff --git a/test/HandlerTest.php b/test/HandlerTest.php
index ca0f732..5c55ba6 100644
--- a/test/HandlerTest.php
+++ b/test/HandlerTest.php
@@ -2,7 +2,6 @@
namespace pjdietz\WellRESTed\Test;
-use pjdietz\WellRESTed\Exceptions\HttpExceptions\NotFoundException;
use pjdietz\WellRESTed\Handler;
class HandlerTest extends \PHPUnit_Framework_TestCase
@@ -44,18 +43,6 @@ class HandlerTest extends \PHPUnit_Framework_TestCase
];
}
- public function testTranslateHttpExceptionToResponse()
- {
- $mockRequest = $this->getMock('\pjdietz\WellRESTed\Interfaces\RequestInterface');
- $mockRequest->expects($this->any())
- ->method('getMethod')
- ->will($this->returnValue("GET"));
-
- $handler = new ExceptionHandler();
- $resp = $handler->getResponse($mockRequest);
- $this->assertEquals(404, $resp->getStatusCode());
- }
-
public function testReadAllowedMethods()
{
$mockRequest = $this->getMock('\pjdietz\WellRESTed\Interfaces\RequestInterface');
@@ -71,14 +58,6 @@ class HandlerTest extends \PHPUnit_Framework_TestCase
}
-class ExceptionHandler extends Handler
-{
- protected function get()
- {
- throw new NotFoundException();
- }
-}
-
class OptionsHandler extends Handler
{
protected function getAllowedMethods()
diff --git a/test/RouterTest.php b/test/RouterTest.php
index 5278136..afd9c0a 100644
--- a/test/RouterTest.php
+++ b/test/RouterTest.php
@@ -2,8 +2,10 @@
namespace pjdietz\WellRESTed\Test;
+use pjdietz\WellRESTed\Exceptions\HttpExceptions\ForbiddenException;
use pjdietz\WellRESTed\Interfaces\HandlerInterface;
use pjdietz\WellRESTed\Interfaces\RequestInterface;
+use pjdietz\WellRESTed\Interfaces\ResponseInterface;
use pjdietz\WellRESTed\Response;
use pjdietz\WellRESTed\Router;
use pjdietz\WellRESTed\Routes\StaticRoute;
@@ -46,6 +48,75 @@ class RouterTest extends \PHPUnit_Framework_TestCase
$this->assertEquals(200, $resp->getStatusCode());
}
+ public function testRespondWithDefaultErrorForException()
+ {
+ $mockRequest = $this->getMock('\pjdietz\WellRESTed\Interfaces\RequestInterface');
+ $mockRequest->expects($this->any())
+ ->method('getPath')
+ ->will($this->returnValue("/"));
+
+ $router = new Router();
+ $router->addRoute(new StaticRoute("/", __NAMESPACE__ . '\\ForbiddenExceptionHandler'));
+ $resp = $router->getResponse($mockRequest);
+ $this->assertEquals(403, $resp->getStatusCode());
+ }
+
+ public function testRespondWithErrorHandlerForException()
+ {
+ $mockRequest = $this->getMock('\pjdietz\WellRESTed\Interfaces\RequestInterface');
+ $mockRequest->expects($this->any())
+ ->method('getPath')
+ ->will($this->returnValue("/"));
+
+ $router = new Router();
+ $router->addRoute(new StaticRoute("/", __NAMESPACE__ . '\\ForbiddenExceptionHandler'));
+ $router->setErrorHandler(403, __NAMESPACE__ . '\\ForbiddenErrorHandler');
+ $resp = $router->getResponse($mockRequest);
+ $this->assertEquals("YOU SHALL NOT PASS!", $resp->getBody());
+ }
+
+ public function testRespondWithErrorHandlerForStatusCode()
+ {
+ $mockRequest = $this->getMock('\pjdietz\WellRESTed\Interfaces\RequestInterface');
+ $mockRequest->expects($this->any())
+ ->method('getPath')
+ ->will($this->returnValue("/"));
+
+ $router = new Router();
+ $router->addRoute(new StaticRoute("/", __NAMESPACE__ . '\\ForbiddenHandler'));
+ $router->setErrorHandler(403, __NAMESPACE__ . '\\ForbiddenErrorHandler');
+ $resp = $router->getResponse($mockRequest);
+ $this->assertEquals("YOU SHALL NOT PASS!", $resp->getBody());
+ }
+
+ public function testRespondWithErrorHandlerUsingOriginalResponse()
+ {
+ $mockRequest = $this->getMock('\pjdietz\WellRESTed\Interfaces\RequestInterface');
+ $mockRequest->expects($this->any())
+ ->method('getPath')
+ ->will($this->returnValue("/"));
+
+ $router = new Router();
+ $router->addRoute(new StaticRoute("/", __NAMESPACE__ . '\\MessageHandler'));
+ $router->setErrorHandlers([404 => __NAMESPACE__ . '\\MessageErrorHandler']);
+ $resp = $router->getResponse($mockRequest);
+ $this->assertEquals("