Refactor DispatcherInterface to HandlerInterface

Update file doc blocks
Code inspection
This commit is contained in:
PJ Dietz 2014-06-29 10:43:39 -04:00
parent 3718e03c78
commit aa06181e40
16 changed files with 125 additions and 107 deletions

View File

@ -4,7 +4,7 @@
* pjdietz\WellRESTed\Exceptions\CurlException * pjdietz\WellRESTed\Exceptions\CurlException
* *
* @author PJ Dietz <pj@pjdietz.com> * @author PJ Dietz <pj@pjdietz.com>
* @copyright Copyright 2013 by PJ Dietz * @copyright Copyright 2014 by PJ Dietz
* @license MIT * @license MIT
*/ */

View File

@ -0,0 +1,18 @@
<?php
/**
* pjdietz\WellRESTed\Exceptions\ParseException
*
* @author PJ Dietz <pj@pjdietz.com>
* @copyright Copyright 2014 by PJ Dietz
* @license MIT
*/
namespace pjdietz\WellRESTed\Exceptions;
/**
* Exception related to a parsing data.
*/
class ParseException extends WellRESTedException
{
}

View File

@ -4,36 +4,41 @@
* pjdietz\WellRESTed\Handler * pjdietz\WellRESTed\Handler
* *
* @author PJ Dietz <pj@pjdietz.com> * @author PJ Dietz <pj@pjdietz.com>
* @copyright Copyright 2013 by PJ Dietz * @copyright Copyright 2014 by PJ Dietz
* @license MIT * @license MIT
*/ */
namespace pjdietz\WellRESTed; namespace pjdietz\WellRESTed;
use pjdietz\WellRESTed\Interfaces\DispatcherInterface; use pjdietz\WellRESTed\Interfaces\HandlerInterface;
use pjdietz\WellRESTed\Interfaces\ResponseInterface; use pjdietz\WellRESTed\Interfaces\ResponseInterface;
use pjdietz\WellRESTed\Interfaces\RoutableInterface; use pjdietz\WellRESTed\Interfaces\RequestInterface;
/** /**
* A Handler issues a response for a given resource. * Responds to a request based on the HTTP method.
* *
* @property-read ResponseInterface response The Response to the request * To use Handler, create a subclass and implement the methods for any HTTP
* verbs you would like to support. (get() for GET, post() for POST, etc).
*
* - Access the request via the protected member $this->request
* - Access a map of arguments via $this->args (e.g., URI path variables)
* - Modify $this->response to provide the response the instance will return
*/ */
abstract class Handler implements DispatcherInterface abstract class Handler implements HandlerInterface
{ {
/** @var array Matches array from the preg_match() call used to find this Handler */ /** @var array Map of variables to suppliement the request, usually path variables. */
protected $args; protected $args;
/** @var RoutableInterface The HTTP request to respond to. */ /** @var RequestInterface The HTTP request to respond to. */
protected $request; protected $request;
/** @var ResponseInterface The HTTP response to send based on the request. */ /** @var ResponseInterface The HTTP response to send based on the request. */
protected $response; protected $response;
/** /**
* @param RoutableInterface $request * @param RequestInterface $request
* @param array|null $args * @param array|null $args
* @return ResponseInterface * @return ResponseInterface
*/ */
public function getResponse(RoutableInterface $request = null, $args = null) public function getResponse(RequestInterface $request, array $args = null)
{ {
$this->request = $request; $this->request = $request;
$this->args = $args; $this->args = $args;
@ -95,9 +100,7 @@ abstract class Handler implements DispatcherInterface
{ {
// The default function calls the instance's get() method, then sets // The default function calls the instance's get() method, then sets
// the resonse's body member to an empty string. // the resonse's body member to an empty string.
$this->get(); $this->get();
if ($this->response->getStatusCode() == 200) { if ($this->response->getStatusCode() == 200) {
$this->response->setBody('', false); $this->response->setBody('', false);
} }

View File

@ -1,18 +0,0 @@
<?php
namespace pjdietz\WellRESTed\Interfaces;
/**
* Provides a mechanism for obtaining a response given a request.
* @package pjdietz\WellRESTed\Interfaces
*/
interface DispatcherInterface {
/**
* @param RoutableInterface $request The request to build a responce for.
* @param array|null $args Optional associate array of arguments.
* @return ResponseInterface|null
*/
public function getResponse(RoutableInterface $request, $args = null);
}

View File

@ -0,0 +1,26 @@
<?php
/**
* pjdietz\WellRESTed\Interfaces\HandlerInterface
*
* @author PJ Dietz <pj@pjdietz.com>
* @copyright Copyright 2014 by PJ Dietz
* @license MIT
*/
namespace pjdietz\WellRESTed\Interfaces;
/**
* Provides a mechanism for obtaining a response given a request.
* @package pjdietz\WellRESTed
*/
interface HandlerInterface {
/**
* @param RequestInterface $request The request to build a responce for.
* @param array|null $args Optional associate array of arguments.
* @return ResponseInterface|null
*/
public function getResponse(RequestInterface $request, array $args = null);
}

View File

@ -4,7 +4,7 @@
* pjdietz\WellRESTed\Interfaces\RequestInterface * pjdietz\WellRESTed\Interfaces\RequestInterface
* *
* @author PJ Dietz <pj@pjdietz.com> * @author PJ Dietz <pj@pjdietz.com>
* @copyright Copyright 2013 by PJ Dietz * @copyright Copyright 2014 by PJ Dietz
* @license MIT * @license MIT
*/ */

View File

@ -4,7 +4,7 @@
* pjdietz\WellRESTed\Interfaces\ResponseInterface * pjdietz\WellRESTed\Interfaces\ResponseInterface
* *
* @author PJ Dietz <pj@pjdietz.com> * @author PJ Dietz <pj@pjdietz.com>
* @copyright Copyright 2013 by PJ Dietz * @copyright Copyright 2014 by PJ Dietz
* @license MIT * @license MIT
*/ */

View File

@ -1,12 +0,0 @@
<?php
namespace pjdietz\WellRESTed\Interfaces;
interface RoutableInterface extends RequestInterface
{
/** @return int The number of times a router has dispatched this Routable */
public function getRouteDepth();
/** Increase the instance's internal count of its depth in nested route tables */
public function incrementRouteDepth();
}

View File

@ -4,7 +4,7 @@
* pjdietz\WellRESTed\Message * pjdietz\WellRESTed\Message
* *
* @author PJ Dietz <pj@pjdietz.com> * @author PJ Dietz <pj@pjdietz.com>
* @copyright Copyright 2013 by PJ Dietz * @copyright Copyright 2014 by PJ Dietz
* @license MIT * @license MIT
*/ */
@ -12,12 +12,6 @@ namespace pjdietz\WellRESTed;
/** /**
* Common base class for the Request and Response classes. * Common base class for the Request and Response classes.
*
* @property string body Entity body of the message
* @property-read array headers Associative array of HTTP headers
* @property-read array headerLines Numeric array of HTTP headers
* @property string protocol The protocol, e.g. HTTP
* @property string protocolVersion The version of the protocol
*/ */
abstract class Message abstract class Message
{ {

View File

@ -4,14 +4,14 @@
* pjdietz\WellRESTed\Request * pjdietz\WellRESTed\Request
* *
* @author PJ Dietz <pj@pjdietz.com> * @author PJ Dietz <pj@pjdietz.com>
* @copyright Copyright 2013 by PJ Dietz * @copyright Copyright 2014 by PJ Dietz
* @license MIT * @license MIT
*/ */
namespace pjdietz\WellRESTed; namespace pjdietz\WellRESTed;
use pjdietz\WellRESTed\Exceptions\CurlException; use pjdietz\WellRESTed\Exceptions\CurlException;
use pjdietz\WellRESTed\Interfaces\RoutableInterface; use pjdietz\WellRESTed\Interfaces\RequestInterface;
/** /**
* A Request instance represents an HTTP request. This class has two main uses: * A Request instance represents an HTTP request. This class has two main uses:
@ -22,15 +22,8 @@ use pjdietz\WellRESTed\Interfaces\RoutableInterface;
* *
* Second, you can create a custom Request and use it to obtain a Response * Second, you can create a custom Request and use it to obtain a Response
* from a server through cURL. * from a server through cURL.
*
* @property string hostname Hostname part of the URI
* @property string method HTTP method (GET, POST, PUT, DELETE, etc.)
* @property string path Path component of the URI for the request
* @property-read string pathParts Fragments of the path, delimited by slashes
* @property array query Associative array of query parameters
* @property array uri Full URI (protocol, hostname, path, etc.)
*/ */
class Request extends Message implements RoutableInterface class Request extends Message implements RequestInterface
{ {
/** /**
* Singleton instance derived from reading info from Apache. * Singleton instance derived from reading info from Apache.
@ -65,11 +58,9 @@ class Request extends Message implements RoutableInterface
public function __construct($uri = null, $method = 'GET') public function __construct($uri = null, $method = 'GET')
{ {
parent::__construct(); parent::__construct();
if (!is_null($uri)) { if (!is_null($uri)) {
$this->setUri($uri); $this->setUri($uri);
} }
$this->method = $method; $this->method = $method;
} }
@ -89,7 +80,6 @@ class Request extends Message implements RoutableInterface
$request->readHttpRequest(); $request->readHttpRequest();
self::$theRequest = $request; self::$theRequest = $request;
} }
return self::$theRequest; return self::$theRequest;
} }
@ -398,7 +388,7 @@ class Request extends Message implements RoutableInterface
// Make a reponse to populate and return with data obtained via cURL. // Make a reponse to populate and return with data obtained via cURL.
$resp = new Response(); $resp = new Response();
$resp->statusCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); $resp->setStatusCode(curl_getinfo($ch, CURLINFO_HTTP_CODE));
// Split the result into headers and body. // Split the result into headers and body.
$headerSize = curl_getinfo($ch, CURLINFO_HEADER_SIZE); $headerSize = curl_getinfo($ch, CURLINFO_HEADER_SIZE);

View File

@ -4,7 +4,7 @@
* pjdietz\WellRESTed\Response * pjdietz\WellRESTed\Response
* *
* @author PJ Dietz <pj@pjdietz.com> * @author PJ Dietz <pj@pjdietz.com>
* @copyright Copyright 2013 by PJ Dietz * @copyright Copyright 2014 by PJ Dietz
* @license MIT * @license MIT
*/ */
@ -16,11 +16,6 @@ use pjdietz\WellRESTed\Interfaces\ResponseInterface;
/** /**
* A Response instance allows you to build an HTTP response and send it when * A Response instance allows you to build an HTTP response and send it when
* finished. * finished.
*
* @property string reasonPhrase Text explanation of status code.
* @property int statusCode HTTP status code
* @property-read string statusLine HTTP status line, e.g. "HTTP/1.1 200 OK"
* @property-read bool success True if the status code is 2xx
*/ */
class Response extends Message implements ResponseInterface class Response extends Message implements ResponseInterface
{ {

View File

@ -1,21 +1,39 @@
<?php <?php
/**
* pjdietz\WellRESTed\RouteBuilder
*
* @author PJ Dietz <pj@pjdietz.com>
* @copyright Copyright 2014 by PJ Dietz
* @license MIT
*/
namespace pjdietz\WellRESTed; namespace pjdietz\WellRESTed;
use pjdietz\WellRESTed\Interfaces\DispatcherInterface; use pjdietz\WellRESTed\Exceptions\ParseException;
use pjdietz\WellRESTed\Interfaces\HandlerInterface;
use pjdietz\WellRESTed\Routes\RegexRoute; use pjdietz\WellRESTed\Routes\RegexRoute;
use pjdietz\WellRESTed\Routes\StaticRoute; use pjdietz\WellRESTed\Routes\StaticRoute;
use pjdietz\WellRESTed\Routes\TemplateRoute; use pjdietz\WellRESTed\Routes\TemplateRoute;
use stdClass; use stdClass;
use UnexpectedValueException;
/**
* Class for facilitating constructing Routers.
*/
class RouteBuilder class RouteBuilder
{ {
private $handlerNamespace; private $handlerNamespace;
private $templateVariablePatterns; private $templateVariablePatterns;
private $defaultVariablePattern; private $defaultVariablePattern;
public function getRoutes($data) /**
* Contruct and return an array of routes.
*
* @param $data
* @return array
* @throws Exceptions\ParseException
*/
public function buildRoutes($data)
{ {
// Locate the list of routes. This should be one of these: // Locate the list of routes. This should be one of these:
// - If $data is an object, $data->routes // - If $data is an object, $data->routes
@ -26,7 +44,7 @@ class RouteBuilder
$dataRoutes = $data->routes; $dataRoutes = $data->routes;
$this->readConfiguration($data); $this->readConfiguration($data);
} else { } else {
throw new UnexpectedValueException("Unable to parse. Missing array of routes."); throw new ParseException("Unable to parse. Missing array of routes.");
} }
// Build a route instance and append it to the list. // Build a route instance and append it to the list.
@ -37,10 +55,14 @@ class RouteBuilder
return $routes; return $routes;
} }
public function buildRoutesFromJson($json) {
return $this->buildRoutes(json_decode($json));
}
/** /**
* @param stdClass|array $item * @param stdClass|array $item
* @return DispatcherInterface * @return HandlerInterface
* @throws \UnexpectedValueException Parse error * @throws Exceptions\ParseException
*/ */
protected function buildRoute($item) protected function buildRoute($item)
{ {
@ -51,7 +73,7 @@ class RouteBuilder
$handler = $this->getHandlerNamespace() . "\\" . $handler; $handler = $this->getHandlerNamespace() . "\\" . $handler;
} }
} else { } else {
throw new UnexpectedValueException("Unable to parse. Route is missing a handler."); throw new ParseException("Unable to parse. Route is missing a handler.");
} }
// Static Route // Static Route

View File

@ -4,22 +4,22 @@
* pjdietz\WellRESTed\Router * pjdietz\WellRESTed\Router
* *
* @author PJ Dietz <pj@pjdietz.com> * @author PJ Dietz <pj@pjdietz.com>
* @copyright Copyright 2013 by PJ Dietz * @copyright Copyright 2014 by PJ Dietz
* @license MIT * @license MIT
*/ */
namespace pjdietz\WellRESTed; namespace pjdietz\WellRESTed;
use pjdietz\WellRESTed\Interfaces\DispatcherInterface; use pjdietz\WellRESTed\Interfaces\HandlerInterface;
use pjdietz\WellRESTed\Interfaces\ResponseInterface; use pjdietz\WellRESTed\Interfaces\ResponseInterface;
use pjdietz\WellRESTed\Interfaces\RoutableInterface; use pjdietz\WellRESTed\Interfaces\RequestInterface;
/** /**
* Router * Router
* *
* A Router uses a table of Routes to find the appropriate Handler for a request. * A Router uses a table of Routes to find the appropriate Handler for a request.
*/ */
class Router implements DispatcherInterface class Router implements HandlerInterface
{ {
/** @var array Array of Route objects */ /** @var array Array of Route objects */
private $routes; private $routes;
@ -33,11 +33,11 @@ class Router implements DispatcherInterface
/** /**
* Return the response built by the handler based on the request * Return the response built by the handler based on the request
* *
* @param RoutableInterface $request * @param RequestInterface $request
* @param null $args * @param array|null $args
* @return ResponseInterface * @return ResponseInterface
*/ */
public function getResponse(RoutableInterface $request, $args = null) public function getResponse(RequestInterface $request, array $args = null)
{ {
// Use the singleton if the caller did not pass a request. // Use the singleton if the caller did not pass a request.
if (is_null($request)) { if (is_null($request)) {
@ -45,7 +45,7 @@ class Router implements DispatcherInterface
} }
foreach ($this->routes as $route) { foreach ($this->routes as $route) {
/** @var DispatcherInterface $route */ /** @var HandlerInterface $route */
$responce = $route->getResponse($request, $args); $responce = $route->getResponse($request, $args);
if ($responce) { if ($responce) {
return $responce; return $responce;
@ -58,9 +58,9 @@ class Router implements DispatcherInterface
/** /**
* Append a new route to the route route table. * Append a new route to the route route table.
* *
* @param DispatcherInterface $route * @param HandlerInterface $route
*/ */
public function addRoute(DispatcherInterface $route) public function addRoute(HandlerInterface $route)
{ {
$this->routes[] = $route; $this->routes[] = $route;
} }
@ -68,12 +68,12 @@ class Router implements DispatcherInterface
/** /**
* Append a series of routes. * Append a series of routes.
* *
* @param array $routes List array of DispatcherInterface instances * @param array $routes List array of HandlerInterface instances
*/ */
public function addRoutes(array $routes) public function addRoutes(array $routes)
{ {
foreach ($routes as $route) { foreach ($routes as $route) {
if ($route instanceof DispatcherInterface) { if ($route instanceof HandlerInterface) {
$this->addRoute($route); $this->addRoute($route);
} }
} }
@ -87,10 +87,10 @@ class Router implements DispatcherInterface
/** /**
* Prepare a resonse indicating a 404 Not Found error * Prepare a resonse indicating a 404 Not Found error
* *
* @param RoutableInterface $request * @param RequestInterface $request
* @return ResponseInterface * @return ResponseInterface
*/ */
protected function getNoRouteResponse(RoutableInterface $request) protected function getNoRouteResponse(RequestInterface $request)
{ {
$response = new Response(404); $response = new Response(404);
$response->setBody('No resource at ' . $request->getPath()); $response->setBody('No resource at ' . $request->getPath());
@ -100,11 +100,11 @@ class Router implements DispatcherInterface
/** /**
* Prepare a response indicating a 500 Internal Server Error * Prepare a response indicating a 500 Internal Server Error
* *
* @param RoutableInterface $request * @param RequestInterface $request
* @param string $message Optional additional message. * @param string $message Optional additional message.
* @return ResponseInterface * @return ResponseInterface
*/ */
protected function getInternalServerErrorResponse(RoutableInterface $request, $message = '') protected function getInternalServerErrorResponse(RequestInterface $request, $message = '')
{ {
$response = new Response(500); $response = new Response(500);
$response->setBody('Server error at ' . $request->getPath() . "\n" . $message); $response->setBody('Server error at ' . $request->getPath() . "\n" . $message);

View File

@ -2,16 +2,16 @@
namespace pjdietz\WellRESTed\Routes; namespace pjdietz\WellRESTed\Routes;
use pjdietz\WellRESTed\Interfaces\DispatcherInterface; use pjdietz\WellRESTed\Interfaces\HandlerInterface;
/** /**
* Base class for Routes. * Base class for Routes.
* @package pjdietz\WellRESTed\Routes * @package pjdietz\WellRESTed\Routes
*/ */
abstract class BaseRoute implements DispatcherInterface abstract class BaseRoute implements HandlerInterface
{ {
/** @var string Fully qualified name for the interface for handlers */ /** @var string Fully qualified name for the interface for handlers */
const DISPATCHER_INTERFACE = '\\pjdietz\\WellRESTed\\Interfaces\\DispatcherInterface'; const DISPATCHER_INTERFACE = '\\pjdietz\\WellRESTed\\Interfaces\\HandlerInterface';
/** @var string */ /** @var string */
private $targetClassName; private $targetClassName;
@ -25,17 +25,17 @@ abstract class BaseRoute implements DispatcherInterface
} }
/** /**
* @return DispatcherInterface * @return HandlerInterface
* @throws \UnexpectedValueException * @throws \UnexpectedValueException
*/ */
protected function getTarget() protected function getTarget()
{ {
if (is_subclass_of($this->targetClassName, self::DISPATCHER_INTERFACE)) { if (is_subclass_of($this->targetClassName, self::DISPATCHER_INTERFACE)) {
/** @var DispatcherInterface $target */ /** @var HandlerInterface $target */
$target = new $this->targetClassName(); $target = new $this->targetClassName();
return $target; return $target;
} else { } else {
throw new \UnexpectedValueException("Target class must implement DispatcherInterface"); throw new \UnexpectedValueException("Target class must implement HandlerInterface");
} }
} }

View File

@ -2,7 +2,7 @@
namespace pjdietz\WellRESTed\Routes; namespace pjdietz\WellRESTed\Routes;
use pjdietz\WellRESTed\Interfaces\RoutableInterface; use pjdietz\WellRESTed\Interfaces\RequestInterface;
class RegexRoute extends BaseRoute class RegexRoute extends BaseRoute
{ {
@ -19,9 +19,9 @@ class RegexRoute extends BaseRoute
} }
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
/* DispatcherInterface */ /* HandlerInterface */
public function getResponse(RoutableInterface $request, $args = null) public function getResponse(RequestInterface $request, array $args = null)
{ {
if (preg_match($this->getPattern(), $request->getPath(), $matches)) { if (preg_match($this->getPattern(), $request->getPath(), $matches)) {
$target = $this->getTarget(); $target = $this->getTarget();

View File

@ -3,7 +3,7 @@
namespace pjdietz\WellRESTed\Routes; namespace pjdietz\WellRESTed\Routes;
use InvalidArgumentException; use InvalidArgumentException;
use pjdietz\WellRESTed\Interfaces\RoutableInterface; use pjdietz\WellRESTed\Interfaces\RequestInterface;
/** /**
* Class StaticRoute * Class StaticRoute
@ -31,9 +31,9 @@ class StaticRoute extends BaseRoute
} }
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
/* DispatcherInterface */ /* HandlerInterface */
public function getResponse(RoutableInterface $request, $args = null) public function getResponse(RequestInterface $request, array $args = null)
{ {
$requestPath = $request->getPath(); $requestPath = $request->getPath();
foreach ($this->paths as $path) { foreach ($this->paths as $path) {