Mark Routing\Route classes as @internal

This commit is contained in:
PJ Dietz 2020-08-14 07:00:50 -04:00
parent c75168afae
commit 4eec56b582
11 changed files with 73 additions and 45 deletions

View File

@ -5,8 +5,12 @@ namespace WellRESTed\Routing\Route;
use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface; use Psr\Http\Message\ServerRequestInterface;
use WellRESTed\Dispatching\DispatcherInterface; use WellRESTed\Dispatching\DispatcherInterface;
use WellRESTed\MiddlewareInterface;
class MethodMap /**
* @internal
*/
class MethodMap implements MiddlewareInterface
{ {
/** @var DispatcherInterface */ /** @var DispatcherInterface */
private $dispatcher; private $dispatcher;
@ -21,11 +25,8 @@ class MethodMap
$this->dispatcher = $dispatcher; $this->dispatcher = $dispatcher;
} }
// -------------------------------------------------------------------------
// MethodMapInterface
/** /**
* Register a dispatchable (handler or middleware) with a method. * Register a dispatchable (e.g.m handler or middleware) with a method.
* *
* $method may be: * $method may be:
* - A single verb ("GET"), * - A single verb ("GET"),
@ -41,7 +42,7 @@ class MethodMap
* @param string $method * @param string $method
* @param mixed $dispatchable * @param mixed $dispatchable
*/ */
public function register($method, $dispatchable): void public function register(string $method, $dispatchable): void
{ {
$methods = explode(',', $method); $methods = explode(',', $method);
$methods = array_map('trim', $methods); $methods = array_map('trim', $methods);

View File

@ -2,6 +2,9 @@
namespace WellRESTed\Routing\Route; namespace WellRESTed\Routing\Route;
/**
* @internal
*/
class PrefixRoute extends Route class PrefixRoute extends Route
{ {
public function __construct(string $target, MethodMap $methodMap) public function __construct(string $target, MethodMap $methodMap)

View File

@ -4,6 +4,9 @@ namespace WellRESTed\Routing\Route;
use RuntimeException; use RuntimeException;
/**
* @internal
*/
class RegexRoute extends Route class RegexRoute extends Route
{ {
/** @var array */ /** @var array */

View File

@ -5,6 +5,9 @@ namespace WellRESTed\Routing\Route;
use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface; use Psr\Http\Message\ServerRequestInterface;
/**
* @internal
*/
abstract class Route implements RouteInterface abstract class Route implements RouteInterface
{ {
/** @var string */ /** @var string */
@ -18,6 +21,11 @@ abstract class Route implements RouteInterface
$this->methodMap = $methodMap; $this->methodMap = $methodMap;
} }
/**
* Path, partial path, or pattern to match request paths against.
*
* @return string
*/
public function getTarget(): string public function getTarget(): string
{ {
return $this->target; return $this->target;

View File

@ -5,7 +5,7 @@ namespace WellRESTed\Routing\Route;
use WellRESTed\Dispatching\DispatcherInterface; use WellRESTed\Dispatching\DispatcherInterface;
/** /**
* Class for creating routes * @internal
*/ */
class RouteFactory implements RouteFactoryInterface class RouteFactory implements RouteFactoryInterface
{ {

View File

@ -2,6 +2,9 @@
namespace WellRESTed\Routing\Route; namespace WellRESTed\Routing\Route;
/**
* @internal
*/
interface RouteFactoryInterface interface RouteFactoryInterface
{ {
/** /**

View File

@ -4,19 +4,24 @@ namespace WellRESTed\Routing\Route;
use WellRESTed\MiddlewareInterface; use WellRESTed\MiddlewareInterface;
/**
* @internal
*/
interface RouteInterface extends MiddlewareInterface interface RouteInterface extends MiddlewareInterface
{ {
/** Matches when path is an exact match only */ /** Matches when request path is an exact match to entire target */
const TYPE_STATIC = 0; const TYPE_STATIC = 0;
/** Matches when path has the expected beginning */ /** Matches when request path is an exact match to start of target */
const TYPE_PREFIX = 1; const TYPE_PREFIX = 1;
/** Matches by pattern. Use matchesRequestTarget to test for matches */ /** Matches by request path by pattern and may extract matched varialbes */
const TYPE_PATTERN = 2; const TYPE_PATTERN = 2;
/** /**
* Path, partial path, or pattern to match request paths against.
*
* @return string * @return string
*/ */
public function getTarget(); public function getTarget(): string;
/** /**
* Return the RouteInterface::TYPE_ constants that identifies the type. * Return the RouteInterface::TYPE_ constants that identifies the type.

View File

@ -2,6 +2,9 @@
namespace WellRESTed\Routing\Route; namespace WellRESTed\Routing\Route;
/**
* @internal
*/
class StaticRoute extends Route class StaticRoute extends Route
{ {
public function getType(): int public function getType(): int

View File

@ -2,6 +2,9 @@
namespace WellRESTed\Routing\Route; namespace WellRESTed\Routing\Route;
/**
* @internal
*/
class TemplateRoute extends Route class TemplateRoute extends Route
{ {
/** @var array */ /** @var array */

View File

@ -1,11 +1,10 @@
<?php <?php
namespace WellRESTed\Test\Unit\Routing\Route; namespace WellRESTed\Routing\Route;
use WellRESTed\Dispatching\Dispatcher; use WellRESTed\Dispatching\Dispatcher;
use WellRESTed\Message\Response; use WellRESTed\Message\Response;
use WellRESTed\Message\ServerRequest; use WellRESTed\Message\ServerRequest;
use WellRESTed\Routing\Route\MethodMap;
use WellRESTed\Test\Doubles\MiddlewareMock; use WellRESTed\Test\Doubles\MiddlewareMock;
use WellRESTed\Test\Doubles\NextMock; use WellRESTed\Test\Doubles\NextMock;
use WellRESTed\Test\TestCase; use WellRESTed\Test\TestCase;
@ -27,14 +26,14 @@ class MethodMapTest extends TestCase
$this->dispatcher = new Dispatcher(); $this->dispatcher = new Dispatcher();
} }
private function getMethodMap() private function getMethodMap(): MethodMap
{ {
return new MethodMap($this->dispatcher); return new MethodMap($this->dispatcher);
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
public function testDispatchesMiddlewareWithMatchingMethod() public function testDispatchesMiddlewareWithMatchingMethod(): void
{ {
$this->request = $this->request->withMethod('GET'); $this->request = $this->request->withMethod('GET');
@ -45,7 +44,7 @@ class MethodMapTest extends TestCase
$this->assertTrue($this->middleware->called); $this->assertTrue($this->middleware->called);
} }
public function testTreatsMethodNamesCaseSensitively() public function testTreatsMethodNamesCaseSensitively(): void
{ {
$this->request = $this->request->withMethod('get'); $this->request = $this->request->withMethod('get');
@ -60,7 +59,7 @@ class MethodMapTest extends TestCase
$this->assertTrue($middlewareLower->called); $this->assertTrue($middlewareLower->called);
} }
public function testDispatchesWildcardMiddlewareWithNonMatchingMethod() public function testDispatchesWildcardMiddlewareWithNonMatchingMethod(): void
{ {
$this->request = $this->request->withMethod('GET'); $this->request = $this->request->withMethod('GET');
@ -71,7 +70,7 @@ class MethodMapTest extends TestCase
$this->assertTrue($this->middleware->called); $this->assertTrue($this->middleware->called);
} }
public function testDispatchesGetMiddlewareForHeadByDefault() public function testDispatchesGetMiddlewareForHeadByDefault(): void
{ {
$this->request = $this->request->withMethod('HEAD'); $this->request = $this->request->withMethod('HEAD');
@ -82,7 +81,7 @@ class MethodMapTest extends TestCase
$this->assertTrue($this->middleware->called); $this->assertTrue($this->middleware->called);
} }
public function testRegistersMiddlewareForMultipleMethods() public function testRegistersMiddlewareForMultipleMethods(): void
{ {
$map = $this->getMethodMap(); $map = $this->getMethodMap();
$map->register('GET,POST', $this->middleware); $map->register('GET,POST', $this->middleware);
@ -96,7 +95,7 @@ class MethodMapTest extends TestCase
$this->assertEquals(2, $this->middleware->callCount); $this->assertEquals(2, $this->middleware->callCount);
} }
public function testSettingNullDeregistersMiddleware() public function testSettingNullUnregistersMiddleware(): void
{ {
$this->request = $this->request->withMethod('POST'); $this->request = $this->request->withMethod('POST');
@ -108,7 +107,7 @@ class MethodMapTest extends TestCase
$this->assertEquals(405, $response->getStatusCode()); $this->assertEquals(405, $response->getStatusCode());
} }
public function testSetsStatusTo200ForOptions() public function testSetsStatusTo200ForOptions(): void
{ {
$this->request = $this->request->withMethod('OPTIONS'); $this->request = $this->request->withMethod('OPTIONS');
@ -119,7 +118,7 @@ class MethodMapTest extends TestCase
$this->assertEquals(200, $response->getStatusCode()); $this->assertEquals(200, $response->getStatusCode());
} }
public function testStopsPropagatingAfterOptions() public function testStopsPropagatingAfterOptions(): void
{ {
$this->request = $this->request->withMethod('OPTIONS'); $this->request = $this->request->withMethod('OPTIONS');
@ -130,8 +129,12 @@ class MethodMapTest extends TestCase
$this->assertFalse($this->next->called); $this->assertFalse($this->next->called);
} }
/** @dataProvider allowedMethodProvider */ /**
public function testSetsAllowHeaderForOptions($methodsDeclared, $methodsAllowed) * @dataProvider allowedMethodProvider
* @param string[] $methodsDeclared
* @param string[] $methodsAllowed
*/
public function testSetsAllowHeaderForOptions(array $methodsDeclared, array $methodsAllowed): void
{ {
$this->request = $this->request->withMethod('OPTIONS'); $this->request = $this->request->withMethod('OPTIONS');
@ -144,8 +147,7 @@ class MethodMapTest extends TestCase
$this->assertContainsEach($methodsAllowed, $response->getHeaderLine('Allow')); $this->assertContainsEach($methodsAllowed, $response->getHeaderLine('Allow'));
} }
/** @dataProvider allowedMethodProvider */ public function testSetsStatusTo405ForBadMethod(): void
public function testSetsStatusTo405ForBadMethod()
{ {
$this->request = $this->request->withMethod('POST'); $this->request = $this->request->withMethod('POST');
@ -156,11 +158,7 @@ class MethodMapTest extends TestCase
$this->assertEquals(405, $response->getStatusCode()); $this->assertEquals(405, $response->getStatusCode());
} }
/** public function testStopsPropagatingAfterBadMethod(): void
* @coversNothing
* @dataProvider allowedMethodProvider
*/
public function testStopsPropagatingAfterBadMethod()
{ {
$this->request = $this->request->withMethod('POST'); $this->request = $this->request->withMethod('POST');
@ -170,8 +168,12 @@ class MethodMapTest extends TestCase
$this->assertFalse($this->next->called); $this->assertFalse($this->next->called);
} }
/** @dataProvider allowedMethodProvider */ /**
public function testSetsAllowHeaderForBadMethod($methodsDeclared, $methodsAllowed) * @dataProvider allowedMethodProvider
* @param string[] $methodsDeclared
* @param string[] $methodsAllowed
*/
public function testSetsAllowHeaderForBadMethod(array $methodsDeclared, array $methodsAllowed): void
{ {
$this->request = $this->request->withMethod('BAD'); $this->request = $this->request->withMethod('BAD');
@ -184,7 +186,7 @@ class MethodMapTest extends TestCase
$this->assertContainsEach($methodsAllowed, $response->getHeaderLine('Allow')); $this->assertContainsEach($methodsAllowed, $response->getHeaderLine('Allow'));
} }
public function allowedMethodProvider() public function allowedMethodProvider(): array
{ {
return [ return [
[['GET'], ['GET', 'HEAD', 'OPTIONS']], [['GET'], ['GET', 'HEAD', 'OPTIONS']],
@ -195,7 +197,7 @@ class MethodMapTest extends TestCase
]; ];
} }
private function assertContainsEach($expectedList, $actual) private function assertContainsEach($expectedList, $actual): void
{ {
foreach ($expectedList as $expected) { foreach ($expectedList as $expected) {
if (strpos($actual, $expected) === false) { if (strpos($actual, $expected) === false) {

View File

@ -1,53 +1,50 @@
<?php <?php
namespace WellRESTed\Test\Unit\Routing\Route; namespace WellRESTed\Routing\Route;
use Prophecy\PhpUnit\ProphecyTrait; use Prophecy\PhpUnit\ProphecyTrait;
use WellRESTed\Routing\Route\MethodMap;
use WellRESTed\Routing\Route\PrefixRoute;
use WellRESTed\Routing\Route\RouteInterface;
use WellRESTed\Test\TestCase; use WellRESTed\Test\TestCase;
class PrefixRouteTest extends TestCase class PrefixRouteTest extends TestCase
{ {
use ProphecyTrait; use ProphecyTrait;
public function testTrimsAsteriskFromEndOfTarget() public function testTrimsAsteriskFromEndOfTarget(): void
{ {
$methodMap = $this->prophesize(MethodMap::class); $methodMap = $this->prophesize(MethodMap::class);
$route = new PrefixRoute('/cats/*', $methodMap->reveal()); $route = new PrefixRoute('/cats/*', $methodMap->reveal());
$this->assertEquals('/cats/', $route->getTarget()); $this->assertEquals('/cats/', $route->getTarget());
} }
public function testReturnsPrefixType() public function testReturnsPrefixType(): void
{ {
$methodMap = $this->prophesize(MethodMap::class); $methodMap = $this->prophesize(MethodMap::class);
$route = new PrefixRoute('/*', $methodMap->reveal()); $route = new PrefixRoute('/*', $methodMap->reveal());
$this->assertSame(RouteInterface::TYPE_PREFIX, $route->getType()); $this->assertSame(RouteInterface::TYPE_PREFIX, $route->getType());
} }
public function testReturnsEmptyArrayForPathVariables() public function testReturnsEmptyArrayForPathVariables(): void
{ {
$methodMap = $this->prophesize(MethodMap::class); $methodMap = $this->prophesize(MethodMap::class);
$route = new PrefixRoute('/*', $methodMap->reveal()); $route = new PrefixRoute('/*', $methodMap->reveal());
$this->assertSame([], $route->getPathVariables()); $this->assertSame([], $route->getPathVariables());
} }
public function testMatchesExactRequestTarget() public function testMatchesExactRequestTarget(): void
{ {
$methodMap = $this->prophesize(MethodMap::class); $methodMap = $this->prophesize(MethodMap::class);
$route = new PrefixRoute('/*', $methodMap->reveal()); $route = new PrefixRoute('/*', $methodMap->reveal());
$this->assertTrue($route->matchesRequestTarget('/')); $this->assertTrue($route->matchesRequestTarget('/'));
} }
public function testMatchesRequestTargetWithSamePrefix() public function testMatchesRequestTargetWithSamePrefix(): void
{ {
$methodMap = $this->prophesize(MethodMap::class); $methodMap = $this->prophesize(MethodMap::class);
$route = new PrefixRoute('/*', $methodMap->reveal()); $route = new PrefixRoute('/*', $methodMap->reveal());
$this->assertTrue($route->matchesRequestTarget('/cats/')); $this->assertTrue($route->matchesRequestTarget('/cats/'));
} }
public function testDoesNotMatchNonmatchingRequestTarget() public function testDoesNotMatchNonMatchingRequestTarget(): void
{ {
$methodMap = $this->prophesize(MethodMap::class); $methodMap = $this->prophesize(MethodMap::class);
$route = new PrefixRoute('/animals/cats/', $methodMap->reveal()); $route = new PrefixRoute('/animals/cats/', $methodMap->reveal());