From cf5da01d8c68f4ac3391c44cfa5b3fe5037465a8 Mon Sep 17 00:00:00 2001 From: Giuseppe Mazzapica Date: Thu, 18 Feb 2016 16:39:57 +0100 Subject: [PATCH] Fix bug in paged routes auto-building --- src/Cortex/Route/PriorityRouteCollection.php | 37 ++++++++++++-------- src/Cortex/Route/RouteInterface.php | 1 + src/Cortex/Router/ResultHandler.php | 2 +- tests/src/Functional/CortexTest.php | 29 ++++++++++++++- 4 files changed, 52 insertions(+), 17 deletions(-) diff --git a/src/Cortex/Route/PriorityRouteCollection.php b/src/Cortex/Route/PriorityRouteCollection.php index 4892832..2b29758 100644 --- a/src/Cortex/Route/PriorityRouteCollection.php +++ b/src/Cortex/Route/PriorityRouteCollection.php @@ -17,6 +17,8 @@ */ final class PriorityRouteCollection implements RouteCollectionInterface { + private static $pagedFlags = [RouteInterface::PAGED_ARCHIVE, RouteInterface::PAGED_SINGLE]; + /** * @var \SplPriorityQueue */ @@ -48,7 +50,18 @@ public function addRoute(RouteInterface $route) $route->offsetSet('priority', $next); } - $priority = $this->maybeAddPaged($route, (int) $route->offsetGet('priority')); + $priority = $route->offsetGet('priority'); + + $paged = $this->maybeBuildPaged($route, (int) $route->offsetGet('priority')); + if ( + $paged instanceof RouteInterface + && ! in_array($paged['paged'], self::$pagedFlags, true) // ensure avoid infinite loops + ) { + $paged->offsetSet('priority', $priority); + $priority++; + $this->addRoute($paged); + } + in_array($priority, $this->priorities, true) or $this->priorities[] = $priority; $this->queue->insert($route, ((-1) * $priority)); @@ -105,31 +118,25 @@ public function count() /** * @param \Brain\Cortex\Route\RouteInterface $route - * @param int $priority * @return int */ - private function maybeAddPaged(RouteInterface $route, $priority) + private function maybeBuildPaged(RouteInterface $route) { - $pagedOpts = [RouteInterface::PAGED_ARCHIVE, RouteInterface::PAGED_SINGLE]; $pagedArg = $route->offsetExists('paged') ? $route->offsetGet('paged') : ''; $path = $route->offsetExists('path') ? $route->offsetGet('path') : ''; - if (in_array($pagedArg, $pagedOpts, true) && $path && is_string($path)) { + if (in_array($pagedArg, self::$pagedFlags, true) && $path && is_string($path)) { $base = 'page'; /** @var \WP_Rewrite $wp_rewrite */ global $wp_rewrite; $wp_rewrite instanceof \WP_Rewrite and $base = $wp_rewrite->pagination_base; - $paged = clone $route; - $newPath = $pagedArg === RouteInterface::PAGED_ARCHIVE + $array = $route->toArray(); + $array['id'] = $route->id().'_paged'; + $array['paged'] = RouteInterface::PAGED_UNPAGED; + $array['path'] = $pagedArg === RouteInterface::PAGED_ARCHIVE ? $path.'/'.$base.'/{paged:\d+}' : $path.'/{page:\d+}'; - $paged->offsetSet('path', $newPath); - $paged->offsetSet('id', $route->offsetGet('id').'_paged'); - $paged->offsetSet('paged', ''); - $paged->offsetSet('priority', $priority); - $this->addRoute($paged); - $priority++; - } - return $priority; + return apply_filters('cortex.paged-route', new Route($array), $route); + } } } diff --git a/src/Cortex/Route/RouteInterface.php b/src/Cortex/Route/RouteInterface.php index 932373f..5556e02 100644 --- a/src/Cortex/Route/RouteInterface.php +++ b/src/Cortex/Route/RouteInterface.php @@ -19,6 +19,7 @@ interface RouteInterface extends \ArrayAccess { const PAGED_SINGLE = 'paged_single'; const PAGED_ARCHIVE = 'paged_archive'; + const PAGED_UNPAGED = ''; const PAGED_SEARCH = 'paged_archive'; const PAGED_FRONT_PAGE = 'paged_archive'; const NOT_PAGED = 'not_paged'; diff --git a/src/Cortex/Router/ResultHandler.php b/src/Cortex/Router/ResultHandler.php index 8cdecf2..62f032f 100644 --- a/src/Cortex/Router/ResultHandler.php +++ b/src/Cortex/Router/ResultHandler.php @@ -36,7 +36,7 @@ public function handle(MatchingResult $result, \WP $wp, $doParseRequest) is_callable($before) and $before($vars, $wp); is_callable($handler) and $doParseRequest = $handler($vars, $wp); is_callable($after) and $after($vars, $wp); - is_string($template) and $this->setTemplate($template); + (is_string($template) && $template) and $this->setTemplate($template); do_action('cortex.matched-after', $result, $wp, $doParseRequest); diff --git a/tests/src/Functional/CortexTest.php b/tests/src/Functional/CortexTest.php index e5b2618..2a57cd4 100644 --- a/tests/src/Functional/CortexTest.php +++ b/tests/src/Functional/CortexTest.php @@ -109,7 +109,6 @@ public function testRouterReturnRouteResultsWhenGiven() assertTrue($do); assertFalse(isset($wp->query_vars)); - } public function testCortexMatchStaticRoute() @@ -138,6 +137,34 @@ public function testCortexMatchStaticRoute() assertFalse($do); } + public function testCortexMatchPagedRoute() + { + Functions::when('home_url')->justReturn('http://example.com/'); + Functions::when('remove_all_filters')->justReturn(); + + Actions::expectFired('cortex.routes') + ->once() + ->whenHappen(function (RouteCollectionInterface $routes) { + $routes->addRoute(new QueryRoute('/bar', function ($vars) { + isset($vars['paged']) and $vars['paged'] = (int) $vars['paged']; + + return $vars; + }, ['paged' => QueryRoute::PAGED_ARCHIVE])); + }); + + Actions::expectFired('cortex.matched')->once(); + + $request = self::buildPsrRequest('http://example.com/bar/page/3'); + + $cortex = new Proxy(new Cortex()); + $wp = \Mockery::mock('WP'); + + $do = $cortex->doBoot($wp, true, $request); + + assertSame(['paged' => 3], $wp->query_vars); + assertFalse($do); + } + public function testCortexNotMatchIfDifferentMethod() { Functions::when('home_url')->justReturn('http://example.com/foo/');