Allow Route target to be a callable, string, or instance

This commit is contained in:
PJ Dietz 2015-02-18 20:17:09 -05:00
parent 38639d9ee4
commit 9498542f30
5 changed files with 308 additions and 86 deletions

View File

@ -2,6 +2,7 @@
<profile version="1.0" is_locked="false">
<option name="myName" value="Project Default" />
<option name="myLocal" value="false" />
<inspection_tool class="PhpUndefinedMethodInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="SpellCheckingInspection" enabled="false" level="TYPO" enabled_by_default="false">
<option name="processCode" value="true" />
<option name="processLiterals" value="true" />

View File

@ -16,7 +16,7 @@
},
"require-dev": {
"fzaninotto/faker": "1.5.*@dev",
"phpunit/phpunit": "4.4.*",
"phpunit/phpunit": "~4.5",
"pjdietz/shamserver": "dev-master"
},
"autoload": {

289
composer.lock generated
View File

@ -4,7 +4,7 @@
"Read more about it at http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
"This file is @generated automatically"
],
"hash": "50cc6100ccf35e76d7c82ea498ec8274",
"hash": "6f8afe11003065ccbf5d3a09f4bea340",
"packages": [],
"packages-dev": [
{
@ -67,12 +67,12 @@
"source": {
"type": "git",
"url": "https://github.com/fzaninotto/Faker.git",
"reference": "d82603adc7aa0f7d47c2e767fd33636803f4117a"
"reference": "80c1424e6522a3303d320b611647fa6fbc29a8e4"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/fzaninotto/Faker/zipball/d82603adc7aa0f7d47c2e767fd33636803f4117a",
"reference": "d82603adc7aa0f7d47c2e767fd33636803f4117a",
"url": "https://api.github.com/repos/fzaninotto/Faker/zipball/80c1424e6522a3303d320b611647fa6fbc29a8e4",
"reference": "80c1424e6522a3303d320b611647fa6fbc29a8e4",
"shasum": ""
},
"require": {
@ -82,6 +82,9 @@
"phpunit/phpunit": "~4.0",
"squizlabs/php_codesniffer": "~1.5"
},
"suggest": {
"ext-intl": "*"
},
"type": "library",
"extra": {
"branch-alias": {
@ -108,20 +111,128 @@
"faker",
"fixtures"
],
"time": "2014-12-18 07:45:28"
"time": "2015-02-12 21:08:01"
},
{
"name": "phpunit/php-code-coverage",
"version": "2.0.14",
"name": "phpdocumentor/reflection-docblock",
"version": "2.0.4",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/php-code-coverage.git",
"reference": "ca158276c1200cc27f5409a5e338486bc0b4fc94"
"url": "https://github.com/phpDocumentor/ReflectionDocBlock.git",
"reference": "d68dbdc53dc358a816f00b300704702b2eaff7b8"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/ca158276c1200cc27f5409a5e338486bc0b4fc94",
"reference": "ca158276c1200cc27f5409a5e338486bc0b4fc94",
"url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/d68dbdc53dc358a816f00b300704702b2eaff7b8",
"reference": "d68dbdc53dc358a816f00b300704702b2eaff7b8",
"shasum": ""
},
"require": {
"php": ">=5.3.3"
},
"require-dev": {
"phpunit/phpunit": "~4.0"
},
"suggest": {
"dflydev/markdown": "~1.0",
"erusev/parsedown": "~1.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.0.x-dev"
}
},
"autoload": {
"psr-0": {
"phpDocumentor": [
"src/"
]
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Mike van Riel",
"email": "mike.vanriel@naenius.com"
}
],
"time": "2015-02-03 12:10:50"
},
{
"name": "phpspec/prophecy",
"version": "v1.3.1",
"source": {
"type": "git",
"url": "https://github.com/phpspec/prophecy.git",
"reference": "9ca52329bcdd1500de24427542577ebf3fc2f1c9"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phpspec/prophecy/zipball/9ca52329bcdd1500de24427542577ebf3fc2f1c9",
"reference": "9ca52329bcdd1500de24427542577ebf3fc2f1c9",
"shasum": ""
},
"require": {
"doctrine/instantiator": "~1.0,>=1.0.2",
"phpdocumentor/reflection-docblock": "~2.0"
},
"require-dev": {
"phpspec/phpspec": "~2.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.2.x-dev"
}
},
"autoload": {
"psr-0": {
"Prophecy\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Konstantin Kudryashov",
"email": "ever.zet@gmail.com",
"homepage": "http://everzet.com"
},
{
"name": "Marcello Duarte",
"email": "marcello.duarte@gmail.com"
}
],
"description": "Highly opinionated mocking framework for PHP 5.3+",
"homepage": "http://phpspec.org",
"keywords": [
"Double",
"Dummy",
"fake",
"mock",
"spy",
"stub"
],
"time": "2014-11-17 16:23:49"
},
{
"name": "phpunit/php-code-coverage",
"version": "2.0.15",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/php-code-coverage.git",
"reference": "34cc484af1ca149188d0d9e91412191e398e0b67"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/34cc484af1ca149188d0d9e91412191e398e0b67",
"reference": "34cc484af1ca149188d0d9e91412191e398e0b67",
"shasum": ""
},
"require": {
@ -134,7 +245,7 @@
},
"require-dev": {
"ext-xdebug": ">=2.1.4",
"phpunit/phpunit": "~4.1"
"phpunit/phpunit": "~4"
},
"suggest": {
"ext-dom": "*",
@ -153,9 +264,6 @@
]
},
"notification-url": "https://packagist.org/downloads/",
"include-path": [
""
],
"license": [
"BSD-3-Clause"
],
@ -173,7 +281,7 @@
"testing",
"xunit"
],
"time": "2014-12-26 13:28:33"
"time": "2015-01-24 10:06:35"
},
{
"name": "phpunit/php-file-iterator",
@ -310,16 +418,16 @@
},
{
"name": "phpunit/php-token-stream",
"version": "1.3.0",
"version": "1.4.0",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/php-token-stream.git",
"reference": "f8d5d08c56de5cfd592b3340424a81733259a876"
"reference": "db32c18eba00b121c145575fcbcd4d4d24e6db74"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/f8d5d08c56de5cfd592b3340424a81733259a876",
"reference": "f8d5d08c56de5cfd592b3340424a81733259a876",
"url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/db32c18eba00b121c145575fcbcd4d4d24e6db74",
"reference": "db32c18eba00b121c145575fcbcd4d4d24e6db74",
"shasum": ""
},
"require": {
@ -332,7 +440,7 @@
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.3-dev"
"dev-master": "1.4-dev"
}
},
"autoload": {
@ -355,20 +463,20 @@
"keywords": [
"tokenizer"
],
"time": "2014-08-31 06:12:13"
"time": "2015-01-17 09:51:32"
},
{
"name": "phpunit/phpunit",
"version": "4.4.1",
"version": "4.5.0",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/phpunit.git",
"reference": "6a5e49a86ce5e33b8d0657abe145057fc513543a"
"reference": "5b578d3865a9128b9c209b011fda6539ec06e7a5"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/6a5e49a86ce5e33b8d0657abe145057fc513543a",
"reference": "6a5e49a86ce5e33b8d0657abe145057fc513543a",
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/5b578d3865a9128b9c209b011fda6539ec06e7a5",
"reference": "5b578d3865a9128b9c209b011fda6539ec06e7a5",
"shasum": ""
},
"require": {
@ -378,15 +486,16 @@
"ext-reflection": "*",
"ext-spl": "*",
"php": ">=5.3.3",
"phpspec/prophecy": "~1.3.1",
"phpunit/php-code-coverage": "~2.0",
"phpunit/php-file-iterator": "~1.3.2",
"phpunit/php-text-template": "~1.2",
"phpunit/php-timer": "~1.0.2",
"phpunit/phpunit-mock-objects": "~2.3",
"sebastian/comparator": "~1.0",
"sebastian/comparator": "~1.1",
"sebastian/diff": "~1.1",
"sebastian/environment": "~1.1",
"sebastian/exporter": "~1.0",
"sebastian/environment": "~1.2",
"sebastian/exporter": "~1.2",
"sebastian/global-state": "~1.0",
"sebastian/version": "~1.0",
"symfony/yaml": "~2.0"
@ -400,7 +509,7 @@
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "4.4.x-dev"
"dev-master": "4.5.x-dev"
}
},
"autoload": {
@ -426,7 +535,7 @@
"testing",
"xunit"
],
"time": "2014-12-28 07:57:05"
"time": "2015-02-05 15:51:19"
},
{
"name": "phpunit/phpunit-mock-objects",
@ -489,12 +598,12 @@
"source": {
"type": "git",
"url": "https://github.com/pjdietz/ShamServer.git",
"reference": "5a786f6800d91986b37912049cf6a98b86d7a180"
"reference": "bc4af38991c806bdb3463758ba7f917edf65c5fb"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/pjdietz/ShamServer/zipball/5a786f6800d91986b37912049cf6a98b86d7a180",
"reference": "5a786f6800d91986b37912049cf6a98b86d7a180",
"url": "https://api.github.com/repos/pjdietz/ShamServer/zipball/bc4af38991c806bdb3463758ba7f917edf65c5fb",
"reference": "bc4af38991c806bdb3463758ba7f917edf65c5fb",
"shasum": ""
},
"require": {
@ -527,29 +636,29 @@
"http",
"webserver"
],
"time": "2014-07-26 16:26:07"
"time": "2015-02-10 22:19:39"
},
{
"name": "sebastian/comparator",
"version": "1.1.0",
"version": "1.1.1",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/comparator.git",
"reference": "c484a80f97573ab934e37826dba0135a3301b26a"
"reference": "1dd8869519a225f7f2b9eb663e225298fade819e"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/c484a80f97573ab934e37826dba0135a3301b26a",
"reference": "c484a80f97573ab934e37826dba0135a3301b26a",
"url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/1dd8869519a225f7f2b9eb663e225298fade819e",
"reference": "1dd8869519a225f7f2b9eb663e225298fade819e",
"shasum": ""
},
"require": {
"php": ">=5.3.3",
"sebastian/diff": "~1.1",
"sebastian/exporter": "~1.0"
"sebastian/diff": "~1.2",
"sebastian/exporter": "~1.2"
},
"require-dev": {
"phpunit/phpunit": "~4.1"
"phpunit/phpunit": "~4.4"
},
"type": "library",
"extra": {
@ -591,7 +700,7 @@
"compare",
"equality"
],
"time": "2014-11-16 21:32:38"
"time": "2015-01-29 16:28:08"
},
{
"name": "sebastian/diff",
@ -697,28 +806,29 @@
},
{
"name": "sebastian/exporter",
"version": "1.0.2",
"version": "1.2.0",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/exporter.git",
"reference": "c7d59948d6e82818e1bdff7cadb6c34710eb7dc0"
"reference": "84839970d05254c73cde183a721c7af13aede943"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/c7d59948d6e82818e1bdff7cadb6c34710eb7dc0",
"reference": "c7d59948d6e82818e1bdff7cadb6c34710eb7dc0",
"url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/84839970d05254c73cde183a721c7af13aede943",
"reference": "84839970d05254c73cde183a721c7af13aede943",
"shasum": ""
},
"require": {
"php": ">=5.3.3"
"php": ">=5.3.3",
"sebastian/recursion-context": "~1.0"
},
"require-dev": {
"phpunit/phpunit": "~4.0"
"phpunit/phpunit": "~4.4"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.0.x-dev"
"dev-master": "1.2.x-dev"
}
},
"autoload": {
@ -758,7 +868,7 @@
"export",
"exporter"
],
"time": "2014-09-10 00:51:36"
"time": "2015-01-27 07:23:06"
},
{
"name": "sebastian/global-state",
@ -812,17 +922,70 @@
"time": "2014-10-06 09:23:50"
},
{
"name": "sebastian/version",
"version": "1.0.3",
"name": "sebastian/recursion-context",
"version": "1.0.0",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/version.git",
"reference": "b6e1f0cf6b9e1ec409a0d3e2f2a5fb0998e36b43"
"url": "https://github.com/sebastianbergmann/recursion-context.git",
"reference": "3989662bbb30a29d20d9faa04a846af79b276252"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/version/zipball/b6e1f0cf6b9e1ec409a0d3e2f2a5fb0998e36b43",
"reference": "b6e1f0cf6b9e1ec409a0d3e2f2a5fb0998e36b43",
"url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/3989662bbb30a29d20d9faa04a846af79b276252",
"reference": "3989662bbb30a29d20d9faa04a846af79b276252",
"shasum": ""
},
"require": {
"php": ">=5.3.3"
},
"require-dev": {
"phpunit/phpunit": "~4.4"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.0.x-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Jeff Welch",
"email": "whatthejeff@gmail.com"
},
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de"
},
{
"name": "Adam Harvey",
"email": "aharvey@php.net"
}
],
"description": "Provides functionality to recursively process PHP variables",
"homepage": "http://www.github.com/sebastianbergmann/recursion-context",
"time": "2015-01-24 09:48:32"
},
{
"name": "sebastian/version",
"version": "1.0.4",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/version.git",
"reference": "a77d9123f8e809db3fbdea15038c27a95da4058b"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/version/zipball/a77d9123f8e809db3fbdea15038c27a95da4058b",
"reference": "a77d9123f8e809db3fbdea15038c27a95da4058b",
"shasum": ""
},
"type": "library",
@ -844,21 +1007,21 @@
],
"description": "Library that helps with managing the version number of Git-hosted PHP projects",
"homepage": "https://github.com/sebastianbergmann/version",
"time": "2014-03-07 15:35:33"
"time": "2014-12-15 14:25:24"
},
{
"name": "symfony/yaml",
"version": "v2.6.1",
"version": "v2.6.4",
"target-dir": "Symfony/Component/Yaml",
"source": {
"type": "git",
"url": "https://github.com/symfony/Yaml.git",
"reference": "3346fc090a3eb6b53d408db2903b241af51dcb20"
"reference": "60ed7751671113cf1ee7d7778e691642c2e9acd8"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/Yaml/zipball/3346fc090a3eb6b53d408db2903b241af51dcb20",
"reference": "3346fc090a3eb6b53d408db2903b241af51dcb20",
"url": "https://api.github.com/repos/symfony/Yaml/zipball/60ed7751671113cf1ee7d7778e691642c2e9acd8",
"reference": "60ed7751671113cf1ee7d7778e691642c2e9acd8",
"shasum": ""
},
"require": {
@ -891,7 +1054,7 @@
],
"description": "Symfony Yaml Component",
"homepage": "http://symfony.com",
"time": "2014-12-02 20:19:20"
"time": "2015-01-25 04:39:26"
}
],
"aliases": [],

View File

@ -4,7 +4,7 @@
* pjdietz\WellRESTed\BaseRoute
*
* @author PJ Dietz <pj@pjdietz.com>
* @copyright Copyright 2014 by PJ Dietz
* @copyright Copyright 2015 by PJ Dietz
* @license MIT
*/
@ -17,20 +17,22 @@ use pjdietz\WellRESTed\Interfaces\HandlerInterface;
*/
abstract class BaseRoute implements HandlerInterface
{
/** @var string Fully qualified name for the interface for handlers */
const HANDLER_INTERFACE = '\\pjdietz\\WellRESTed\\Interfaces\\HandlerInterface';
/** @var string Fully qualified classname of the HandlerInterface to dispatch */
private $targetClassName;
/** @var callable|string|HandlerInterface HandlerInterface to dispatch */
private $target;
/**
* Create a new route that will dispatch an instance of the given handelr class.
*
* @param string $targetClassName Fully qualified name to a handler class.
* $target may be:
* - A callable expecting no arguments that returns a HandlerInterface
* - A string containing the fully qualified class of a HandlerInterface
* - A HandlerInterface
*
* @param callable|string|HandlerInterface $target HandlerInterface to dispatch
*/
public function __construct($targetClassName)
public function __construct($target)
{
$this->targetClassName = $targetClassName;
$this->target = $target;
}
/**
@ -41,13 +43,19 @@ abstract class BaseRoute implements HandlerInterface
*/
protected function getTarget()
{
if (is_subclass_of($this->targetClassName, self::HANDLER_INTERFACE)) {
/** @var HandlerInterface $target */
$target = new $this->targetClassName();
if (is_callable($this->target)) {
$callable = $this->target;
$target = $callable();
} elseif (is_string($this->target)) {
$className = $this->target;
$target = new $className();
} else {
$target = $this->target;
}
if ($target instanceof HandlerInterface) {
return $target;
} else {
throw new \UnexpectedValueException("Target class must implement HandlerInterface");
}
}
}

View File

@ -2,25 +2,75 @@
namespace pjdietz\WellRESTed\Test;
use pjdietz\WellRESTed\Interfaces\HandlerInterface;
use pjdietz\WellRESTed\Interfaces\RequestInterface;
use pjdietz\WellRESTed\Routes\StaticRoute;
class BaseRouteTest extends \PHPUnit_Framework_TestCase
{
private $path = "/";
private $request;
/**
* Create a route that will match, but has an incorrect handler assigned.
* @covers pjdietz\WellRESTed\Routes\BaseRoute
*/
public function testDispatchesHandlerFromCallable()
{
$target = function () {
$handler = $this->prophesize("\\pjdietz\\WellRESTed\\Interfaces\\HandlerInterface");
return $handler->reveal();
};
$route = new StaticRoute($this->path, $target);
$route->getResponse($this->request->reveal());
}
/**
* @covers pjdietz\WellRESTed\Routes\BaseRoute
*/
public function testDispatchesHandlerFromString()
{
$target = __NAMESPACE__ . "\\ValidHandler";
$route = new StaticRoute($this->path, $target);
$route->getResponse($this->request->reveal());
}
/**
* @covers pjdietz\WellRESTed\Routes\BaseRoute
*/
public function testDispatchesHandlerInstance()
{
$target = new ValidHandler();
$route = new StaticRoute($this->path, $target);
$route->getResponse($this->request->reveal());
}
/**
* @covers pjdietz\WellRESTed\Routes\BaseRoute
* @expectedException \UnexpectedValueException
*/
public function testFailOnHandlerDoesNotImplementInterface()
public function testFailWhenHandlerDoesNotImplementInterface()
{
$path = "/";
$target = "\\stdClass";
$mockRequest = $this->getMock('\pjdietz\WellRESTed\Interfaces\RequestInterface');
$mockRequest->expects($this->any())
->method('getPath')
->will($this->returnValue($path));
$route = new StaticRoute($this->path, $target);
$route->getResponse($this->request->reveal());
}
$route = new StaticRoute($path, __NAMESPACE__ . '\NotAHandler');
$route->getResponse($mockRequest);
public function setUp()
{
$this->request = $this->prophesize("\\pjdietz\\WellRESTed\\Interfaces\\RequestInterface");
$this->request->getPath()->willReturn($this->path);
}
}
class ValidHandler implements HandlerInterface
{
public function getResponse(RequestInterface $request, array $args = null)
{
return null;
}
}