Browse Source

Add support for routing placeholders to scoped middleware.

This allows scopes that contain routing placeholders to have middleware
attached and function. I've chosen to use the most liberal placeholder
replacement as scope variables don't allow patterns to be set.
Mark Story 9 years ago
parent
commit
2db4a5e913
2 changed files with 15 additions and 6 deletions
  1. 6 2
      src/Routing/RouteCollection.php
  2. 9 4
      tests/TestCase/Routing/RouteCollectionTest.php

+ 6 - 2
src/Routing/RouteCollection.php

@@ -425,6 +425,10 @@ class RouteCollection
                 throw new RuntimeException($message);
             }
         }
+        // Matches route element pattern in Cake\Routing\Route
+        $path = '#^' . preg_quote($path, '#') . '#';
+        $path = preg_replace('/\\\\:([a-z0-9-_]+(?<![-_]))/i', '[^/]+', $path);
+
         if (!isset($this->_middlewarePaths[$path])) {
             $this->_middlewarePaths[$path] = [];
         }
@@ -447,8 +451,8 @@ class RouteCollection
     public function getMatchingMiddleware($needle)
     {
         $matching = [];
-        foreach ($this->_middlewarePaths as $path => $middleware) {
-            if (strpos($needle, $path) === 0) {
+        foreach ($this->_middlewarePaths as $pattern => $middleware) {
+            if (preg_match($pattern, $needle)) {
                 $matching = array_merge($matching, $middleware);
             }
         }

+ 9 - 4
tests/TestCase/Routing/RouteCollectionTest.php

@@ -747,13 +747,18 @@ class RouteCollectionTest extends TestCase
             ->getMock();
         $this->collection->registerMiddleware('callable', $mock);
 
-        $this->collection->enableMiddleware('/articles/:article_id/comments', ['callable']);
-        $this->markTestIncomplete();
+        $this->collection->enableMiddleware('/api-:version/articles/:article_id/comments', ['callable']);
 
-        $middleware = $this->collection->getMatchingMiddleware('/articles/123/comments');
+        $middleware = $this->collection->getMatchingMiddleware('/api-1/articles/comments');
+        $this->assertEmpty($middleware);
+
+        $middleware = $this->collection->getMatchingMiddleware('/api-1/articles/yay/comments');
+        $this->assertEquals([$mock], $middleware);
+
+        $middleware = $this->collection->getMatchingMiddleware('/api-1/articles/123/comments');
         $this->assertEquals([$mock], $middleware);
 
-        $middleware = $this->collection->getMatchingMiddleware('/articles/abc-123/comments/99');
+        $middleware = $this->collection->getMatchingMiddleware('/api-abc123/articles/abc-123/comments/99');
         $this->assertEquals([$mock], $middleware);
     }