diff --git a/src/Routing/Router.php b/src/Routing/Router.php index b836538..b368d6e 100644 --- a/src/Routing/Router.php +++ b/src/Routing/Router.php @@ -48,8 +48,10 @@ class Router * Attribute name for matched path variables. A null value sets * attributes directly. */ - public function __construct($dispatcher = null, $pathVariablesAttributeName = null) - { + public function __construct( + ?DispatcherInterface $dispatcher = null, + ?string $pathVariablesAttributeName = null + ) { $this->dispatcher = $dispatcher ?: $this->getDefaultDispatcher(); $this->pathVariablesAttributeName = $pathVariablesAttributeName; $this->factory = $this->getRouteFactory($this->dispatcher); @@ -63,8 +65,8 @@ class Router public function __invoke( ServerRequestInterface $request, ResponseInterface $response, - $next - ) { + callable $next + ): ResponseInterface { // Use only the path for routing. $requestTarget = parse_url($request->getRequestTarget(), PHP_URL_PATH); @@ -101,11 +103,11 @@ class Router } private function dispatch( - $route, + callable $route, ServerRequestInterface $request, ResponseInterface $response, - $next - ) { + callable $next + ): ResponseInterface { if (!$this->stack) { return $route($request, $response, $next); } @@ -145,12 +147,12 @@ class Router * - 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 string $target Request target or pattern to match * @param mixed $dispatchable Handler or middleware to dispatch * @return static */ - public function register($method, $target, $dispatchable) + public function register(string $method, string $target, $dispatchable): Router { $route = $this->getRouteForTarget($target); $route->register($method, $dispatchable); @@ -174,7 +176,7 @@ class Router * @param mixed $middleware Middleware to dispatch in sequence * @return static */ - public function add($middleware) + public function add($middleware): Router { $this->stack[] = $middleware; return $this; @@ -186,38 +188,23 @@ class Router * * @return static */ - public function continueOnNotFound() + public function continueOnNotFound(): Router { $this->continueOnNotFound = true; return $this; } - /** - * Return an instance to dispatch middleware. - * - * @return DispatcherInterface - */ - protected function getDefaultDispatcher() + protected function getDefaultDispatcher(): DispatcherInterface { return new Dispatcher(); } - /** - * @param DispatcherInterface $dispatcher - * @return RouteFactoryInterface - */ - protected function getRouteFactory($dispatcher) + protected function getRouteFactory(DispatcherInterface $dispatcher): RouteFactoryInterface { return new RouteFactory($dispatcher); } - /** - * Return the route for a given target. - * - * @param $target - * @return RouteInterface - */ - private function getRouteForTarget($target) + private function getRouteForTarget(string $target): RouteInterface { if (isset($this->routes[$target])) { $route = $this->routes[$target]; @@ -228,7 +215,7 @@ class Router return $route; } - private function registerRouteForTarget($route, $target) + private function registerRouteForTarget(RouteInterface $route, string $target): void { // Store the route to the hash indexed by original target. $this->routes[$target] = $route; @@ -247,7 +234,7 @@ class Router } } - private function getStaticRoute($requestTarget) + private function getStaticRoute(string $requestTarget): ?RouteInterface { if (isset($this->staticRoutes[$requestTarget])) { return $this->staticRoutes[$requestTarget]; @@ -255,7 +242,7 @@ class Router return null; } - private function getPrefixRoute($requestTarget) + private function getPrefixRoute(string $requestTarget): ?RouteInterface { // Find all prefixes that match the start of this path. $prefixes = array_keys($this->prefixRoutes); @@ -273,7 +260,7 @@ class Router // If there are multiple matches, sort them to find the one with the // longest string length. if (count($matches) > 1) { - $compareByLength = function ($a, $b) { + $compareByLength = function (string $a, string $b): int { return strlen($b) - strlen($a); }; usort($matches, $compareByLength); @@ -283,7 +270,7 @@ class Router return $this->prefixRoutes[$bestMatch]; } - private function startsWith($haystack, $needle) + private function startsWith(string $haystack, string $needle): bool { $length = strlen($needle); return (substr($haystack, 0, $length) === $needle); diff --git a/test/tests/unit/Routing/RouterTest.php b/test/tests/unit/Routing/RouterTest.php index 2587c51..3780ff1 100644 --- a/test/tests/unit/Routing/RouterTest.php +++ b/test/tests/unit/Routing/RouterTest.php @@ -5,9 +5,11 @@ namespace WellRESTed\Test\Unit\Routing; use Prophecy\Argument; use Prophecy\PhpUnit\ProphecyTrait; use WellRESTed\Dispatching\Dispatcher; +use WellRESTed\Dispatching\DispatcherInterface; use WellRESTed\Message\Response; use WellRESTed\Message\ServerRequest; use WellRESTed\Routing\Route\RouteFactory; +use WellRESTed\Routing\Route\RouteFactoryInterface; use WellRESTed\Routing\Route\RouteInterface; use WellRESTed\Routing\Router; use WellRESTed\Test\Doubles\NextMock; @@ -30,7 +32,7 @@ class RouterTest extends TestCase $this->route = $this->prophesize(RouteInterface::class); $this->route->__invoke(Argument::cetera())->willReturn(new Response()); - $this->route->register(Argument::cetera())->willReturn(); + $this->route->register(Argument::cetera()); $this->route->getType()->willReturn(RouteInterface::TYPE_STATIC); $this->route->getTarget()->willReturn("/"); $this->route->getPathVariables()->willReturn([]); @@ -134,13 +136,13 @@ class RouterTest extends TestCase public function testDispatchesStaticRouteBeforePrefixRoute() { $staticRoute = $this->prophesize(RouteInterface::class); - $staticRoute->register(Argument::cetera())->willReturn(); + $staticRoute->register(Argument::cetera()); $staticRoute->getTarget()->willReturn("/cats/"); $staticRoute->getType()->willReturn(RouteInterface::TYPE_STATIC); $staticRoute->__invoke(Argument::cetera())->willReturn(new Response()); $prefixRoute = $this->prophesize(RouteInterface::class); - $prefixRoute->register(Argument::cetera())->willReturn(); + $prefixRoute->register(Argument::cetera()); $prefixRoute->getTarget()->willReturn("/cats/*"); $prefixRoute->getType()->willReturn(RouteInterface::TYPE_PREFIX); $prefixRoute->__invoke(Argument::cetera())->willReturn(new Response()); @@ -163,13 +165,13 @@ class RouterTest extends TestCase // Note: The longest route is also good for 2 points in Settlers of Catan. $shortRoute = $this->prophesize(RouteInterface::class); - $shortRoute->register(Argument::cetera())->willReturn(); + $shortRoute->register(Argument::cetera()); $shortRoute->getTarget()->willReturn("/animals/*"); $shortRoute->getType()->willReturn(RouteInterface::TYPE_PREFIX); $shortRoute->__invoke(Argument::cetera())->willReturn(new Response()); $longRoute = $this->prophesize(RouteInterface::class); - $longRoute->register(Argument::cetera())->willReturn(); + $longRoute->register(Argument::cetera()); $longRoute->getTarget()->willReturn("/animals/cats/*"); $longRoute->getType()->willReturn(RouteInterface::TYPE_PREFIX); $longRoute->__invoke(Argument::cetera())->willReturn(new Response()); @@ -191,13 +193,13 @@ class RouterTest extends TestCase public function testDispatchesPrefixRouteBeforePatternRoute() { $prefixRoute = $this->prophesize(RouteInterface::class); - $prefixRoute->register(Argument::cetera())->willReturn(); + $prefixRoute->register(Argument::cetera()); $prefixRoute->getTarget()->willReturn("/cats/*"); $prefixRoute->getType()->willReturn(RouteInterface::TYPE_PREFIX); $prefixRoute->__invoke(Argument::cetera())->willReturn(new Response()); $patternRoute = $this->prophesize(RouteInterface::class); - $patternRoute->register(Argument::cetera())->willReturn(); + $patternRoute->register(Argument::cetera()); $patternRoute->getTarget()->willReturn("/cats/{id}"); $patternRoute->getType()->willReturn(RouteInterface::TYPE_PATTERN); $patternRoute->__invoke(Argument::cetera())->willReturn(new Response()); @@ -218,7 +220,7 @@ class RouterTest extends TestCase public function testDispatchesFirstMatchingPatternRoute() { $patternRoute1 = $this->prophesize(RouteInterface::class); - $patternRoute1->register(Argument::cetera())->willReturn(); + $patternRoute1->register(Argument::cetera()); $patternRoute1->getTarget()->willReturn("/cats/{id}"); $patternRoute1->getType()->willReturn(RouteInterface::TYPE_PATTERN); $patternRoute1->getPathVariables()->willReturn([]); @@ -226,7 +228,7 @@ class RouterTest extends TestCase $patternRoute1->__invoke(Argument::cetera())->willReturn(new Response()); $patternRoute2 = $this->prophesize(RouteInterface::class); - $patternRoute2->register(Argument::cetera())->willReturn(); + $patternRoute2->register(Argument::cetera()); $patternRoute2->getTarget()->willReturn("/cats/{name}"); $patternRoute2->getType()->willReturn(RouteInterface::TYPE_PATTERN); $patternRoute2->getPathVariables()->willReturn([]); @@ -249,7 +251,7 @@ class RouterTest extends TestCase public function testStopsTestingPatternsAfterFirstSuccessfulMatch() { $patternRoute1 = $this->prophesize(RouteInterface::class); - $patternRoute1->register(Argument::cetera())->willReturn(); + $patternRoute1->register(Argument::cetera()); $patternRoute1->getTarget()->willReturn("/cats/{id}"); $patternRoute1->getType()->willReturn(RouteInterface::TYPE_PATTERN); $patternRoute1->getPathVariables()->willReturn([]); @@ -257,7 +259,7 @@ class RouterTest extends TestCase $patternRoute1->__invoke(Argument::cetera())->willReturn(new Response()); $patternRoute2 = $this->prophesize(RouteInterface::class); - $patternRoute2->register(Argument::cetera())->willReturn(); + $patternRoute2->register(Argument::cetera()); $patternRoute2->getTarget()->willReturn("/cats/{name}"); $patternRoute2->getType()->willReturn(RouteInterface::TYPE_PATTERN); $patternRoute2->getPathVariables()->willReturn([]); @@ -447,7 +449,7 @@ class RouterWithFactory extends Router { static $routeFactory; - protected function getRouteFactory($dispatcher) + protected function getRouteFactory(DispatcherInterface $dispatcher): RouteFactoryInterface { return self::$routeFactory; }