Browse Source

First pass at making it possible to add host conditions.

By passing the request we can make it possible to add route conditions
for more than just the URL. I've had to add new methods onto Router and
RouteCollection to make this possible, but I feel that passing the
object around is better long term anyways.
Mark Story 9 years ago
parent
commit
29c9e13206

+ 12 - 0
src/Routing/Route/Route.php

@@ -360,6 +360,18 @@ class Route
     }
 
     /**
+     * Check to see if the host matches the route requirements
+     */
+    public function hostMatches($host)
+    {
+        if (!isset($this->options['_host'])) {
+            return true;
+        }
+        // TODO implement
+        return true;
+    }
+
+    /**
      * Removes the extension from $url if it contains a registered extension.
      * If no registered extension is found, no extension is returned and the URL is returned unmodified.
      *

+ 40 - 0
src/Routing/RouteCollection.php

@@ -17,6 +17,7 @@ namespace Cake\Routing;
 use Cake\Routing\Exception\DuplicateNamedRouteException;
 use Cake\Routing\Exception\MissingRouteException;
 use Cake\Routing\Route\Route;
+use Psr\Http\Message\ServerRequestInterface;
 
 /**
  * Contains a collection of routes.
@@ -148,6 +149,45 @@ class RouteCollection
     }
 
     /**
+     * Takes the ServerRequestInterface, iterates the routes until one is able to parse the route.
+     *
+     * @param \Psr\Http\Messages\ServerRequestInterface $request The request to parse route data from.
+     * @return array An array of request parameters parsed from the URL.
+     * @throws \Cake\Routing\Exception\MissingRouteException When a URL has no matching route.
+     */
+    public function parseRequest(ServerRequestInterface $request)
+    {
+        $method = $request->getMethod();
+        $uri = $request->getUri();
+        $urlPath = $uri->getPath();
+        foreach (array_keys($this->_paths) as $path) {
+            if (strpos($urlPath, $path) !== 0) {
+                continue;
+            }
+
+            $host = $uri->getHost();
+            /* @var \Cake\Routing\Route\Route $route */
+            foreach ($this->_paths[$path] as $route) {
+                if (!$route->hostMatches($host)) {
+                    continue;
+                }
+
+                $r = $route->parse($urlPath, $method);
+                if ($r === false) {
+                    continue;
+                }
+                if ($uri->getQuery()) {
+                    parse_str($uri->getQuery(), $queryParameters);
+                    $r['?'] = $queryParameters;
+                }
+
+                return $r;
+            }
+        }
+        throw new MissingRouteException(['url' => $url]);
+    }
+
+    /**
      * Get the set of names from the $url.  Accepts both older style array urls,
      * and newer style urls containing '_name'
      *

+ 17 - 0
src/Routing/Router.php

@@ -338,6 +338,7 @@ class Router
      * @param string $method The HTTP method being used.
      * @return array Parsed elements from URL.
      * @throws \Cake\Routing\Exception\MissingRouteException When a route cannot be handled
+     * @deprecated 3.4.0 Use Router::parseRequest() instead.
      */
     public static function parse($url, $method = '')
     {
@@ -352,6 +353,22 @@ class Router
     }
 
     /**
+     * Get the routing parameters for the request is possible.
+     *
+     * @param \Psr\Http\Message\ServerRequestInterface $request The request to parse request data from.
+     * @return array Parsed elements from URL.
+     * @throws \Cake\Routing\Exception\MissingRouteException When a route cannot be handled
+     */
+    public static function parseRequest(ServerRequestInterface $request)
+    {
+        if (!static::$initialized) {
+            static::_loadRoutes();
+        }
+
+        return static::$_collection->parseRequest($request);
+    }
+
+    /**
      * Takes parameter and path information back from the Dispatcher, sets these
      * parameters as the current request parameters that are merged with URL arrays
      * created later in the request.

+ 20 - 0
tests/TestCase/Routing/RouterTest.php

@@ -1596,6 +1596,26 @@ class RouterTest extends TestCase
     }
 
     /**
+     * test parseRequest
+     *
+     * @return void
+     */
+    public function testParseRequest()
+    {
+        Router::connect('/articles/:action/*', ['controller' => 'Articles']);
+        $request = new Request(['url' => '/articles/view/1']);
+        $result = Router::parseRequest($request);
+        $expected = [
+            'pass' => ['1'],
+            'plugin' => null,
+            'controller' => 'Articles',
+            'action' => 'view',
+            '_matchedRoute' => '/articles/:action/*',
+        ];
+        $this->assertEquals($expected, $result);
+    }
+
+    /**
      * testUuidRoutes method
      *
      * @return void