diff --git a/core/lib/Drupal/Core/Routing/CompiledRoute.php b/core/lib/Drupal/Core/Routing/CompiledRoute.php index 6f3d84d..054a626 100644 --- a/core/lib/Drupal/Core/Routing/CompiledRoute.php +++ b/core/lib/Drupal/Core/Routing/CompiledRoute.php @@ -36,13 +36,6 @@ class CompiledRoute extends SymfonyCompiledRoute { protected $numParts; /** - * The mapping of numeric path parts to path variable names. - * - * @var array - */ - protected $mappedPathVariables; - - /** * Constructs a new compiled route object. * * This is a ridiculously long set of constructor parameters, but as this @@ -80,7 +73,6 @@ public function __construct($fit, $pattern_outline, $num_parts, $staticPrefix, $ $this->fit = $fit; $this->patternOutline = $pattern_outline; $this->numParts = $num_parts; - $this->mappedPathVariables = $pathVariables; } /** @@ -154,14 +146,22 @@ public function getRequirements() { /** * Returns the path variables. * - * This differs from the parent method in that the numeric array keys - * correspond to a matching path part containing that variable. + * The Drupal implementation differs from from the parent class in that the + * numeric array keys correspond to a matching path part containing that + * variable. For example for a route with path + * @code + * /node/{node}/revisions/{node_revision}/view + * @endcode + * this method will return the array + * @code + * [1 => 'node', 3 => 'node_revision'] + * @endcode * * @return array * The path variable names keyed by numeric path part. */ public function getPathVariables() { - return $this->mappedPathVariables; + return parent::getPathVariables(); } /** @@ -188,7 +188,6 @@ public function unserialize($serialized) { $this->fit = $data['fit']; $this->patternOutline = $data['patternOutline']; $this->numParts = $data['numParts']; - $this->mappedPathVariables = $data['path_vars']; } diff --git a/core/lib/Drupal/Core/Routing/RouteCompiler.php b/core/lib/Drupal/Core/Routing/RouteCompiler.php index 86e7ffb..ece32e2 100644 --- a/core/lib/Drupal/Core/Routing/RouteCompiler.php +++ b/core/lib/Drupal/Core/Routing/RouteCompiler.php @@ -69,6 +69,8 @@ public static function compile(Route $route) { * Drupal only supports path wildcard (variables) that consist of a complete * part of the path separated by slashes. * + * @see \Symfony\Component\Routing\RouteCompiler::compilePattern() + * * @param string $path * The path for which we want the mapping. * @param array $variables diff --git a/core/lib/Drupal/Core/Routing/UrlMatcher.php b/core/lib/Drupal/Core/Routing/UrlMatcher.php index f82cd35..f802d2f 100644 --- a/core/lib/Drupal/Core/Routing/UrlMatcher.php +++ b/core/lib/Drupal/Core/Routing/UrlMatcher.php @@ -51,10 +51,10 @@ public function finalMatch(RouteCollection $collection, Request $request) { * Tries to match a URL with a set of routes. * * This version differs from the Symfony parent version in two respects. - * First, the $pathinfo string is converted to lowercase. In addition, we - * remove the check against any static prefix since we would already have - * matched the static prefix in \Drupal\Core\Routing\RouteProvider before - * arriving here. + * First, the $pathinfo string is converted to lowercase when matching the + * route path regular expression. In addition, we remove the check against any + * static prefix since we would already have matched the static prefix in + * \Drupal\Core\Routing\RouteProvider before arriving here. * * @param string $pathinfo * The path to be parsed. @@ -83,7 +83,8 @@ protected function matchCollection($pathinfo, RouteCollection $routes) { } // Recover the original value for wildcard (named variable) portions // of the path, since they may be case-sensitive data like a base64 - // encoded token. + // encoded token. We create this positional mapping in the route compiler. + // @see \Drupal\Core\Routing\RouteCompiler::getMappedPathVariables() $parts = preg_split('@/+@', $pathinfo, NULL, PREG_SPLIT_NO_EMPTY); foreach ($compiledRoute->getPathVariables() as $position => $variable_name) { if (isset($matches[$variable_name])) { diff --git a/core/modules/system/src/Tests/Routing/RouterTest.php b/core/modules/system/src/Tests/Routing/RouterTest.php index 0b24960..da8a956 100644 --- a/core/modules/system/src/Tests/Routing/RouterTest.php +++ b/core/modules/system/src/Tests/Routing/RouterTest.php @@ -230,15 +230,15 @@ public function testRoutePathMixedCase() { $this->assertIdentical('/router_test/mixedcase2', $route2->getPath()); $this->drupalGet(Url::fromUri('base:router_test/mixEDCASE2')); $this->assertResponse(200); - $this->assertRaw('test2', 'The correct string was returned because the route was successful.'); + $this->assertRaw('test2', 'The expected controller output was found.'); $this->drupalGet(Url::fromUri('base:router_TEST/MIXEDcase2')); $this->assertResponse(200); - $this->assertRaw('test2', 'The correct string was returned because the route was successful.'); + $this->assertRaw('test2', 'The expected controller output was found.'); $this->drupalGet(Url::fromUri('base:router_test/mixedcase2')); $this->assertResponse(200); - $this->assertRaw('test2', 'The correct string was returned because the route was successful.'); + $this->assertRaw('test2', 'The expected controller output was found.'); $route3 = $route_provider->getRouteByName('router_test.mixedcase.3'); // Verify that the variable name in the route path is stored as lowercase @@ -249,15 +249,15 @@ public function testRoutePathMixedCase() { // mixed-case value. Matches route path /router_test/mixedcase3/{value} $this->drupalGet(Url::fromUri('base:router_test/mixedcase3/mixedCASEstring')); $this->assertResponse(200); - $this->assertRaw('mixedCASEstring', 'The correct string was returned because the route was successful.'); + $this->assertRaw('mixedCASEstring', 'The variable string was output with unmodified case.'); $this->drupalGet(Url::fromUri('base:router_test/mixedcase3/mixedcasestring')); $this->assertResponse(200); - $this->assertRaw('mixedcasestring', 'The correct string was returned because the route was successful.'); + $this->assertRaw('mixedcasestring', 'The variable string was output with unmodified case.'); $this->drupalGet(Url::fromUri('base:router_test/mixedcase3/MIXEDCASESTRING')); $this->assertResponse(200); - $this->assertRaw('MIXEDCASESTRING', 'The correct string was returned because the route was successful.'); + $this->assertRaw('MIXEDCASESTRING', 'The variable string was output with unmodified case.'); // Test routes added by \Drupal\router_test\RouteTestSubscriber. // Check that a dynamically added route has path changed to lower-case. $route4 = $route_provider->getRouteByName('router_test.mixedcase.4'); diff --git a/core/modules/views/src/Plugin/views/display/PathPluginBase.php b/core/modules/views/src/Plugin/views/display/PathPluginBase.php index 615f6e7f..175c41b 100644 --- a/core/modules/views/src/Plugin/views/display/PathPluginBase.php +++ b/core/modules/views/src/Plugin/views/display/PathPluginBase.php @@ -245,8 +245,6 @@ public function alterRoutes(RouteCollection $collection) { // Ensure that we don't override a route which is already controlled by // views. if (!$route->hasDefault('view_id') && ('/' . $view_path == $route_path)) { - $parameters = $route->compile()->getPathVariables(); - // @todo Figure out whether we need to merge some settings (like // requirements). @@ -261,9 +259,12 @@ public function alterRoutes(RouteCollection $collection) { $path = $route->getPath(); // Replace the path with the original parameter names and add a mapping. $argument_map = array(); + // The path variables array may have arbitrary keys, so take just the + // values to ensure we have a simple numeric array starting from 0. + $parameters = array_values($route->compile()->getPathVariables()); // We assume that the numeric ids of the parameters match the one from // the view argument handlers. - foreach (array_values($parameters) as $position => $parameter_name) { + foreach ($parameters as $position => $parameter_name) { $path = str_replace('{arg_' . $position . '}', '{' . $parameter_name . '}', $path); $argument_map['arg_' . $position] = $parameter_name; }