Remove MethodMapInterface

This commit is contained in:
PJ Dietz 2018-06-22 15:10:50 -04:00
parent 73b6e4ab83
commit ac8bdce037
10 changed files with 121 additions and 160 deletions

View File

@ -6,7 +6,7 @@ use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use WellRESTed\Dispatching\DispatcherInterface;
class MethodMap implements MethodMapInterface
class MethodMap
{
private $dispatcher;
private $map;

View File

@ -1,39 +0,0 @@
<?php
namespace WellRESTed\Routing;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use WellRESTed\MiddlewareInterface;
/**
* Maps HTTP methods to handlers and middleware
*/
interface MethodMapInterface extends MiddlewareInterface
{
/**
* Evaluate $request's method and dispatches matching dispatchable.
*
* @param ServerRequestInterface $request
* @param ResponseInterface $response
* @param callable $next
* @return ResponseInterface
*/
public function __invoke(ServerRequestInterface $request, ResponseInterface $response, $next);
/**
* Register a dispatchable (handler or middleware) with a method.
*
* $method may be:
* - A single verb ("GET"),
* - A comma-separated list of verbs ("GET,PUT,DELETE")
* - "*" to indicate any method.
*
* $dispatchable may be anything a Dispatcher can dispatch.
* @see DispatcherInterface::dispatch
*
* @param string $method
* @param mixed $dispatchable
*/
public function register($method, $dispatchable);
}

View File

@ -4,13 +4,13 @@ namespace WellRESTed\Routing\Route;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use WellRESTed\Routing\MethodMapInterface;
use WellRESTed\Routing\MethodMap;
abstract class Route implements RouteInterface
{
/** @var string */
protected $target;
/** @var MethodMapInterface */
/** @var MethodMap */
protected $methodMap;
public function __construct($target, $methodMap)
@ -19,16 +19,6 @@ abstract class Route implements RouteInterface
$this->methodMap = $methodMap;
}
/**
* Return the instance mapping methods to middleware for this route.
*
* @return MethodMapInterface
*/
public function getMethodMap()
{
return $this->methodMap;
}
/**
* @return string
*/

View File

@ -3,7 +3,6 @@
namespace WellRESTed\Routing\Route;
use WellRESTed\MiddlewareInterface;
use WellRESTed\Routing\MethodMapInterface;
interface RouteInterface extends MiddlewareInterface
{
@ -48,13 +47,6 @@ interface RouteInterface extends MiddlewareInterface
*/
public function getPathVariables();
/**
* Return the instance mapping methods to middleware for this route.
*
* @return MethodMapInterface
*/
public function getMethodMap();
/**
* Examines a request target to see if it is a match for the route.
*

View File

@ -111,37 +111,44 @@ class Router implements RouterInterface
}
/**
* Register middleware with the router for a given path and method.
* Register handlers and 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::register
*
* $target may be:
* - An exact path (e.g., "/path/")
* - An prefix path ending with "*"" ("/path/*"")
* - A 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
* $dispatchable may be:
* - An instance implementing one of these interfaces:
* - Psr\Http\Server\RequestHandlerInterface
* - Psr\Http\Server\MiddlewareInterface
* - WellRESTed\MiddlewareInterface
* - Psr\Http\Message\ResponseInterface
* - A string containing the fully qualified class name of a class
* implementing MiddlewareInterface
* - A callable that returns an instance implementing MiddleInterface
* - A callable matching the signature of MiddlewareInterface::dispatch
* implementing one of the interfaces listed above.
* - A callable that returns an instance implementing one of the
* interfaces listed above.
* - A callable with a signature matching the signature of
* WellRESTed\MiddlewareInterface::__invoke
* - An array containing any of the items in this list.
* @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
* @return self
* @param mixed $dispatchable Handler or middleware to dispatch
* @return static
*/
public function register($method, $target, $middleware)
public function register($method, $target, $dispatchable)
{
$route = $this->getRouteForTarget($target);
$route->register($method, $middleware);
$route->register($method, $dispatchable);
return $this;
}

View File

@ -25,34 +25,41 @@ interface RouterInterface extends MiddlewareInterface
public function __invoke(ServerRequestInterface $request, ResponseInterface $response, $next);
/**
* Register middleware with the router for a given path and method.
* Register handlers and middleware with the router for a given path and
* method.
*
* $method may be:
* - A single verb ("GET")
* - A single verb ("GET"),
* - A comma-separated list of verbs ("GET,PUT,DELETE")
* - "*" to indicate any method
* @see MethodMapInterface::register
* - "*" to indicate any method.
*
* $target may be:
* - An exact path (e.g., "/path/")
* - A prefix path ending with "*"" ("/path/*"")
* - A URI template with one or more variables ("/path/{id}")
* - A URI template with variables enclosed in "{}" ("/path/{id}")
* - A regular expression ("~/cat/([0-9]+)~")
*
* $middleware may be:
* - An instance implementing MiddlewareInterface
* $dispatchable may be:
* - An instance implementing one of these interfaces:
* - Psr\Http\Server\RequestHandlerInterface
* - Psr\Http\Server\MiddlewareInterface
* - WellRESTed\MiddlewareInterface
* - Psr\Http\Message\ResponseInterface
* - A string containing the fully qualified class name of a class
* implementing MiddlewareInterface
* - A callable that returns an instance implementing MiddleInterface
* - A callable matching the signature of MiddlewareInterface::dispatch
* implementing one of the interfaces listed above.
* - A callable that returns an instance implementing one of the
* interfaces listed above.
* - A callable with a signature matching the signature of
* WellRESTed\MiddlewareInterface::__invoke
* - An array containing any of the items in this list.
* @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
* @param mixed $dispatchable Middleware to dispatch
* @return static
*/
public function register($method, $target, $middleware);
public function register($method, $target, $dispatchable);
/**
* Push a new middleware onto the stack. Middleware for a router runs only

View File

@ -2,6 +2,7 @@
namespace WellRESTed\Test\Unit\Routing\Route;
use WellRESTed\Routing\MethodMap;
use WellRESTed\Routing\Route\PrefixRoute;
use WellRESTed\Routing\Route\RouteInterface;
use WellRESTed\Test\TestCase;
@ -10,43 +11,43 @@ class PrefixRouteTest extends TestCase
{
public function testTrimsAsteriskFromEndOfTarget()
{
$methodMap = $this->prophesize('WellRESTed\Routing\MethodMapInterface');
$route = new PrefixRoute("/cats/*", $methodMap->reveal());
$this->assertEquals("/cats/", $route->getTarget());
$methodMap = $this->prophesize(MethodMap::class);
$route = new PrefixRoute('/cats/*', $methodMap->reveal());
$this->assertEquals('/cats/', $route->getTarget());
}
public function testReturnsPrefixType()
{
$methodMap = $this->prophesize('WellRESTed\Routing\MethodMapInterface');
$route = new PrefixRoute("/*", $methodMap->reveal());
$methodMap = $this->prophesize(MethodMap::class);
$route = new PrefixRoute('/*', $methodMap->reveal());
$this->assertSame(RouteInterface::TYPE_PREFIX, $route->getType());
}
public function testReturnsEmptyArrayForPathVariables()
{
$methodMap = $this->prophesize('WellRESTed\Routing\MethodMapInterface');
$route = new PrefixRoute("/*", $methodMap->reveal());
$methodMap = $this->prophesize(MethodMap::class);
$route = new PrefixRoute('/*', $methodMap->reveal());
$this->assertSame([], $route->getPathVariables());
}
public function testMatchesExactRequestTarget()
{
$methodMap = $this->prophesize('WellRESTed\Routing\MethodMapInterface');
$route = new PrefixRoute("/*", $methodMap->reveal());
$this->assertTrue($route->matchesRequestTarget("/"));
$methodMap = $this->prophesize(MethodMap::class);
$route = new PrefixRoute('/*', $methodMap->reveal());
$this->assertTrue($route->matchesRequestTarget('/'));
}
public function testMatchesRequestTargetWithSamePrefix()
{
$methodMap = $this->prophesize('WellRESTed\Routing\MethodMapInterface');
$route = new PrefixRoute("/*", $methodMap->reveal());
$this->assertTrue($route->matchesRequestTarget("/cats/"));
$methodMap = $this->prophesize(MethodMap::class);
$route = new PrefixRoute('/*', $methodMap->reveal());
$this->assertTrue($route->matchesRequestTarget('/cats/'));
}
public function testDoesNotMatchNonmatchingRequestTarget()
{
$methodMap = $this->prophesize('WellRESTed\Routing\MethodMapInterface');
$route = new PrefixRoute("/animals/cats/", $methodMap->reveal());
$this->assertFalse($route->matchesRequestTarget("/animals/dogs/"));
$methodMap = $this->prophesize(MethodMap::class);
$route = new PrefixRoute('/animals/cats/', $methodMap->reveal());
$this->assertFalse($route->matchesRequestTarget('/animals/dogs/'));
}
}

View File

@ -4,6 +4,7 @@ namespace WellRESTed\Test\Unit\Routing\Route;
use PHPUnit\Framework\Error\Notice;
use PHPUnit\Framework\Error\Warning;
use WellRESTed\Routing\MethodMap;
use WellRESTed\Routing\Route\RegexRoute;
use WellRESTed\Routing\Route\RouteInterface;
use WellRESTed\Test\TestCase;
@ -14,12 +15,12 @@ class RegexRouteTest extends TestCase
public function setUp()
{
$this->methodMap = $this->prophesize('WellRESTed\Routing\MethodMapInterface');
$this->methodMap = $this->prophesize(MethodMap::class);
}
public function testReturnsPatternType()
{
$route = new RegexRoute("/", $this->methodMap->reveal());
$route = new RegexRoute('/', $this->methodMap->reveal());
$this->assertSame(RouteInterface::TYPE_PATTERN, $route->getType());
}
@ -48,16 +49,16 @@ class RegexRouteTest extends TestCase
public function matchingRouteProvider()
{
return [
["~/cat/[0-9]+~", "/cat/2", [0 => "/cat/2"]],
["#/dog/.*#", "/dog/his-name-is-bear", [0 => "/dog/his-name-is-bear"]],
["~/cat/([0-9]+)~", "/cat/2", [
0 => "/cat/2",
1 => "2"
['~/cat/[0-9]+~', '/cat/2', [0 => '/cat/2']],
['#/dog/.*#', '/dog/his-name-is-bear', [0 => '/dog/his-name-is-bear']],
['~/cat/([0-9]+)~', '/cat/2', [
0 => '/cat/2',
1 => '2'
]],
["~/dog/(?<id>[0-9+])~", "/dog/2", [
0 => "/dog/2",
1 => "2",
"id" => "2"
['~/dog/(?<id>[0-9+])~', '/dog/2', [
0 => '/dog/2',
1 => '2',
'id' => '2'
]]
];
}
@ -72,9 +73,9 @@ class RegexRouteTest extends TestCase
public function mismatchingRouteProvider()
{
return [
["~/cat/[0-9]+~", "/cat/molly"],
["~/cat/[0-9]+~", "/dog/bear"],
["#/dog/.*#", "/dog"]
['~/cat/[0-9]+~', '/cat/molly'],
['~/cat/[0-9]+~', '/dog/bear'],
['#/dog/.*#', '/dog']
];
}
@ -89,7 +90,7 @@ class RegexRouteTest extends TestCase
Notice::$enabled = false;
$level = error_reporting();
error_reporting($level & ~E_WARNING);
$route->matchesRequestTarget("/");
$route->matchesRequestTarget('/');
error_reporting($level);
Warning::$enabled = true;
Notice::$enabled = true;
@ -98,8 +99,8 @@ class RegexRouteTest extends TestCase
public function invalidRouteProvider()
{
return [
["~/unterminated"],
["/nope"]
['~/unterminated'],
['/nope']
];
}
}

View File

@ -2,6 +2,7 @@
namespace WellRESTed\Test\Unit\Routing\Route;
use WellRESTed\Routing\MethodMap;
use WellRESTed\Routing\Route\RouteInterface;
use WellRESTed\Routing\Route\StaticRoute;
use WellRESTed\Test\TestCase;
@ -10,29 +11,29 @@ class StaticRouteTest extends TestCase
{
public function testReturnsStaticType()
{
$methodMap = $this->prophesize('WellRESTed\Routing\MethodMapInterface');
$route = new StaticRoute("/", $methodMap->reveal());
$methodMap = $this->prophesize(MethodMap::class);
$route = new StaticRoute('/', $methodMap->reveal());
$this->assertSame(RouteInterface::TYPE_STATIC, $route->getType());
}
public function testMatchesExactRequestTarget()
{
$methodMap = $this->prophesize('WellRESTed\Routing\MethodMapInterface');
$route = new StaticRoute("/", $methodMap->reveal());
$this->assertTrue($route->matchesRequestTarget("/"));
$methodMap = $this->prophesize(MethodMap::class);
$route = new StaticRoute('/', $methodMap->reveal());
$this->assertTrue($route->matchesRequestTarget('/'));
}
public function testReturnsEmptyArrayForPathVariables()
{
$methodMap = $this->prophesize('WellRESTed\Routing\MethodMapInterface');
$route = new StaticRoute("/", $methodMap->reveal());
$methodMap = $this->prophesize(MethodMap::class);
$route = new StaticRoute('/', $methodMap->reveal());
$this->assertSame([], $route->getPathVariables());
}
public function testDoesNotMatchNonmatchingRequestTarget()
{
$methodMap = $this->prophesize('WellRESTed\Routing\MethodMapInterface');
$route = new StaticRoute("/", $methodMap->reveal());
$this->assertFalse($route->matchesRequestTarget("/cats/"));
$methodMap = $this->prophesize(MethodMap::class);
$route = new StaticRoute('/', $methodMap->reveal());
$this->assertFalse($route->matchesRequestTarget('/cats/'));
}
}

View File

@ -2,6 +2,7 @@
namespace WellRESTed\Test\Unit\Routing\Route;
use WellRESTed\Routing\MethodMap;
use WellRESTed\Routing\Route\RouteInterface;
use WellRESTed\Routing\Route\TemplateRoute;
use WellRESTed\Test\TestCase;
@ -12,22 +13,22 @@ class TemplateRouteTest extends TestCase
public function setUp()
{
$this->methodMap = $this->prophesize('WellRESTed\Routing\MethodMapInterface');
$this->methodMap = $this->prophesize(MethodMap::class);
}
private function getExpectedValues($keys)
{
$expectedValues = [
"var" => "value",
"hello" => "Hello World!",
"x" => "1024",
"y" => "768",
"path" => "/foo/bar",
"who" => "fred",
"half" => "50%",
"empty" => "",
"count" => ["one", "two", "three"],
"list" => ["red", "green", "blue"]
'var' => 'value',
'hello' => 'Hello World!',
'x' => '1024',
'y' => '768',
'path' => '/foo/bar',
'who' => 'fred',
'half' => '50%',
'empty' => '',
'count' => ['one', 'two', 'three'],
'list' => ['red', 'green', 'blue']
];
return array_intersect_key($expectedValues, array_flip($keys));
}
@ -43,7 +44,7 @@ class TemplateRouteTest extends TestCase
public function testReturnsPatternType()
{
$route = new TemplateRoute("/", $this->methodMap->reveal());
$route = new TemplateRoute('/', $this->methodMap->reveal());
$this->assertSame(RouteInterface::TYPE_PATTERN, $route->getType());
}
@ -60,10 +61,10 @@ class TemplateRouteTest extends TestCase
public function nonMatchingTargetProvider()
{
return [
["/foo/{var}", "/bar/12", "Mismatch before first template expression"],
["/foo/{foo}/bar/{bar}", "/foo/12/13", "Mismatch after first template expression"],
["/hello/{hello}", "/hello/Hello%20World!", "Requires + operator to match reserved characters"],
["{/var}", "/bar/12", "Path contains more segments than template"],
['/foo/{var}', '/bar/12', 'Mismatch before first template expression'],
['/foo/{foo}/bar/{bar}', '/foo/12/13', 'Mismatch after first template expression'],
['/hello/{hello}', '/hello/Hello%20World!', 'Requires + operator to match reserved characters'],
['{/var}', '/bar/12', 'Path contains more segments than template'],
];
}
@ -88,11 +89,11 @@ class TemplateRouteTest extends TestCase
public function simpleStringProvider()
{
return [
["/foo", "/foo", []],
["/{var}", "/value", ["var"]],
["/{hello}", "/Hello%20World%21", ["hello"]],
["/{x,hello,y}", "/1024,Hello%20World%21,768", ["x", "hello", "y"]],
["/{x,hello,y}", "/1024,Hello%20World%21,768", ["x", "hello", "y"]],
['/foo', '/foo', []],
['/{var}', '/value', ['var']],
['/{hello}', '/Hello%20World%21', ['hello']],
['/{x,hello,y}', '/1024,Hello%20World%21,768', ['x', 'hello', 'y']],
['/{x,hello,y}', '/1024,Hello%20World%21,768', ['x', 'hello', 'y']],
];
}
@ -117,9 +118,9 @@ class TemplateRouteTest extends TestCase
public function reservedStringProvider()
{
return [
["/{+var}", "/value", ["var"]],
["/{+hello}", "/Hello%20World!", ["hello"]],
["{+path}/here", "/foo/bar/here", ["path"]],
['/{+var}', '/value', ['var']],
['/{+hello}', '/Hello%20World!', ['hello']],
['{+path}/here', '/foo/bar/here', ['path']],
];
}
@ -144,9 +145,9 @@ class TemplateRouteTest extends TestCase
public function labelWithDotPrefixProvider()
{
return [
["/{.who}", "/.fred", ["who"]],
["/{.half,who}", "/.50%25.fred", ["half", "who"]],
["/X{.empty}", "/X.", ["empty"]]
['/{.who}', '/.fred', ['who']],
['/{.half,who}', '/.50%25.fred', ['half', 'who']],
['/X{.empty}', '/X.', ['empty']]
];
}
@ -171,9 +172,9 @@ class TemplateRouteTest extends TestCase
public function pathSegmentProvider()
{
return [
["{/who}", "/fred", ["who"]],
["{/half,who}", "/50%25/fred", ["half", "who"]],
["{/var,empty}", "/value/", ["var", "empty"]]
['{/who}', '/fred', ['who']],
['{/half,who}', '/50%25/fred', ['half', 'who']],
['{/var,empty}', '/value/', ['var', 'empty']]
];
}
@ -198,9 +199,9 @@ class TemplateRouteTest extends TestCase
public function pathExplosionProvider()
{
return [
["/{count*}", "/one,two,three", ["count"]],
["{/count*}", "/one/two/three", ["count"]],
["X{.list*}", "X.red.green.blue", ["list"]]
['/{count*}', '/one,two,three', ['count']],
['{/count*}', '/one/two/three', ['count']],
['X{.list*}', 'X.red.green.blue', ['list']]
];
}
}