summaryrefslogtreecommitdiffstats
path: root/core/lib/Drupal/Core/Routing
diff options
context:
space:
mode:
authorAlex Pott2017-02-20 16:02:05 (GMT)
committerAlex Pott2017-02-20 16:02:05 (GMT)
commit77a2431e2e5bd4c95266b0cd7da8a4f192da714a (patch)
tree92fce263dbc3ea24ea4670453d7021ab0396e5d5 /core/lib/Drupal/Core/Routing
parent182edb2171779d277ce01fdc7d005d8eddaf40e7 (diff)
Issue #2075889 by pwolanin, kgoel, catch, mpdonadio, YesCT, dawehner, alexpott, johnshortess, Crell, Wim Leers, jhodgdon, mradcliffe, xjm, attiks, tstoeckler, webchick: Make Drupal handle incoming paths in a case-insensitive fashion for routing
Diffstat (limited to 'core/lib/Drupal/Core/Routing')
-rw-r--r--core/lib/Drupal/Core/Routing/RouteCompiler.php21
-rw-r--r--core/lib/Drupal/Core/Routing/RouteProvider.php20
-rw-r--r--core/lib/Drupal/Core/Routing/RouteProviderInterface.php4
3 files changed, 32 insertions, 13 deletions
diff --git a/core/lib/Drupal/Core/Routing/RouteCompiler.php b/core/lib/Drupal/Core/Routing/RouteCompiler.php
index 937bf48..52d0041 100644
--- a/core/lib/Drupal/Core/Routing/RouteCompiler.php
+++ b/core/lib/Drupal/Core/Routing/RouteCompiler.php
@@ -2,6 +2,7 @@
namespace Drupal\Core\Routing;
+use Drupal\Component\Utility\Unicode;
use Symfony\Component\Routing\RouteCompilerInterface;
use Symfony\Component\Routing\Route;
use Symfony\Component\Routing\RouteCompiler as SymfonyRouteCompiler;
@@ -37,7 +38,8 @@ class RouteCompiler extends SymfonyRouteCompiler implements RouteCompilerInterfa
// The Drupal-specific compiled information.
$stripped_path = static::getPathWithoutDefaults($route);
$fit = static::getFit($stripped_path);
- $pattern_outline = static::getPatternOutline($stripped_path);
+ // Store a lower-case pattern outline to enable case-insensitive matching.
+ $pattern_outline = Unicode::strtolower(static::getPatternOutline($stripped_path));
// We count the number of parts including any optional trailing parts. This
// allows the RouteProvider to filter candidate routes more efficiently.
$num_parts = count(explode('/', trim($route->getPath(), '/')));
@@ -46,23 +48,30 @@ class RouteCompiler extends SymfonyRouteCompiler implements RouteCompilerInterfa
$fit,
$pattern_outline,
$num_parts,
- // These are the Symfony compiled parts.
- $symfony_compiled->getStaticPrefix(),
- $symfony_compiled->getRegex(),
+
+ // The following parameters are what Symfony uses in
+ // \Symfony\Component\Routing\Matcher\UrlMatcher::matchCollection().
+
+ // Set the static prefix to an empty string since it is redundant to
+ // the matching in \Drupal\Core\Routing\RouteProvider::getRoutesByPath()
+ // and by skipping it we more easily make the routing case insensitive.
+ '',
+ // Set the regex to use UTF-8 and be case-insensitive.
+ $symfony_compiled->getRegex() . 'ui',
$symfony_compiled->getTokens(),
$symfony_compiled->getPathVariables(),
$symfony_compiled->getHostRegex(),
$symfony_compiled->getHostTokens(),
$symfony_compiled->getHostVariables(),
$symfony_compiled->getVariables()
- );
+ );
}
/**
* Returns the pattern outline.
*
* The pattern outline is the path pattern but normalized so that all
- * placeholders are equal strings and default values are removed.
+ * placeholders are the string '%'.
*
* @param string $path
* The path for which we want the normalized outline.
diff --git a/core/lib/Drupal/Core/Routing/RouteProvider.php b/core/lib/Drupal/Core/Routing/RouteProvider.php
index 53ed626..4586652 100644
--- a/core/lib/Drupal/Core/Routing/RouteProvider.php
+++ b/core/lib/Drupal/Core/Routing/RouteProvider.php
@@ -5,6 +5,7 @@ namespace Drupal\Core\Routing;
use Drupal\Core\Cache\Cache;
use Drupal\Core\Cache\CacheBackendInterface;
use Drupal\Core\Cache\CacheTagsInvalidatorInterface;
+use Drupal\Component\Utility\Unicode;
use Drupal\Core\Path\CurrentPathStack;
use Drupal\Core\PathProcessor\InboundPathProcessorInterface;
use Drupal\Core\State\StateInterface;
@@ -139,7 +140,9 @@ class RouteProvider implements PreloadableRouteProviderInterface, PagedRouteProv
*
* @return \Symfony\Component\Routing\RouteCollection with all urls that
* could potentially match $request. Empty collection if nothing can
- * match.
+ * match. The collection will be sorted from highest to lowest fit (match
+ * of path parts) and then in ascending order by route name for routes
+ * with the same fit.
*/
public function getRouteCollectionForRequest(Request $request) {
// Cache both the system path as well as route parameters and matching
@@ -317,15 +320,19 @@ class RouteProvider implements PreloadableRouteProviderInterface, PagedRouteProv
* Get all routes which match a certain pattern.
*
* @param string $path
- * The route pattern to search for (contains % as placeholders).
+ * The route pattern to search for.
*
* @return \Symfony\Component\Routing\RouteCollection
- * Returns a route collection of matching routes.
+ * Returns a route collection of matching routes. The collection may be
+ * empty and will be sorted from highest to lowest fit (match of path parts)
+ * and then in ascending order by route name for routes with the same fit.
*/
protected function getRoutesByPath($path) {
// Split the path up on the slashes, ignoring multiple slashes in a row
- // or leading or trailing slashes.
- $parts = preg_split('@/+@', $path, NULL, PREG_SPLIT_NO_EMPTY);
+ // or leading or trailing slashes. Convert to lower case here so we can
+ // have a case insensitive match from the incoming path to the lower case
+ // pattern outlines from \Drupal\Core\Routing\RouteCompiler::compile().
+ $parts = preg_split('@/+@', Unicode::strtolower($path), NULL, PREG_SPLIT_NO_EMPTY);
$collection = new RouteCollection();
@@ -347,7 +354,8 @@ class RouteProvider implements PreloadableRouteProviderInterface, PagedRouteProv
$routes = [];
}
- // We sort by fit and name in PHP to avoid a SQL filesort.
+ // We sort by fit and name in PHP to avoid a SQL filesort and avoid any
+ // difference in the sorting behavior of SQL back-ends.
usort($routes, array($this, 'routeProviderRouteCompare'));
foreach ($routes as $row) {
diff --git a/core/lib/Drupal/Core/Routing/RouteProviderInterface.php b/core/lib/Drupal/Core/Routing/RouteProviderInterface.php
index ce07a6d..f53593a 100644
--- a/core/lib/Drupal/Core/Routing/RouteProviderInterface.php
+++ b/core/lib/Drupal/Core/Routing/RouteProviderInterface.php
@@ -18,7 +18,9 @@ interface RouteProviderInterface extends RouteProviderBaseInterface {
* The route pattern to search for (contains {} as placeholders).
*
* @return \Symfony\Component\Routing\RouteCollection
- * Returns a route collection of matching routes.
+ * Returns a route collection of matching routes. The collection may be
+ * empty and will be sorted from highest to lowest fit (match of path parts)
+ * and then in ascending order by route name for routes with the same fit.
*/
public function getRoutesByPattern($pattern);