summaryrefslogtreecommitdiffstats
path: root/core/lib/Drupal
diff options
context:
space:
mode:
authorNathaniel Catchpole2018-02-08 10:59:32 (GMT)
committerNathaniel Catchpole2018-02-08 10:59:32 (GMT)
commitc13d37fdaee27fa3c42c1c1e7b65798706d668a0 (patch)
tree8b86c8929f2feec210edf18f684a0b43e96b7faf /core/lib/Drupal
parentf51c227edd4889cafd7e7826c8fbe10c33c8a3a7 (diff)
Issue #2802403 by _Archy_, Berdir, rjay, catch, Tachion, jacktonkin, oriol_e9g, willwh, tameeshb, dawehner, dhansen, bmcclure, DeFr, david.gil, gagarine, plach: Combination of language negotiation and path aliasing can cause a corrupted route cache, 404s
Diffstat (limited to 'core/lib/Drupal')
-rw-r--r--core/lib/Drupal/Core/Routing/RouteProvider.php47
1 files changed, 45 insertions, 2 deletions
diff --git a/core/lib/Drupal/Core/Routing/RouteProvider.php b/core/lib/Drupal/Core/Routing/RouteProvider.php
index 6c20b1e..95cbd67 100644
--- a/core/lib/Drupal/Core/Routing/RouteProvider.php
+++ b/core/lib/Drupal/Core/Routing/RouteProvider.php
@@ -6,6 +6,8 @@ use Drupal\Component\Utility\Unicode;
use Drupal\Core\Cache\Cache;
use Drupal\Core\Cache\CacheBackendInterface;
use Drupal\Core\Cache\CacheTagsInvalidatorInterface;
+use Drupal\Core\Language\LanguageInterface;
+use Drupal\Core\Language\LanguageManagerInterface;
use Drupal\Core\Path\CurrentPathStack;
use Drupal\Core\PathProcessor\InboundPathProcessorInterface;
use Drupal\Core\State\StateInterface;
@@ -86,6 +88,13 @@ class RouteProvider implements PreloadableRouteProviderInterface, PagedRouteProv
protected $pathProcessor;
/**
+ * The language manager.
+ *
+ * @var \Drupal\Core\Language\LanguageManagerInterface
+ */
+ protected $languageManager;
+
+ /**
* Cache ID prefix used to load routes.
*/
const ROUTE_LOAD_CID_PREFIX = 'route_provider.route_load:';
@@ -107,8 +116,10 @@ class RouteProvider implements PreloadableRouteProviderInterface, PagedRouteProv
* The cache tag invalidator.
* @param string $table
* (Optional) The table in the database to use for matching. Defaults to 'router'
+ * @param \Drupal\Core\Language\LanguageManagerInterface $language_manager
+ * (Optional) The language manager.
*/
- public function __construct(Connection $connection, StateInterface $state, CurrentPathStack $current_path, CacheBackendInterface $cache_backend, InboundPathProcessorInterface $path_processor, CacheTagsInvalidatorInterface $cache_tag_invalidator, $table = 'router') {
+ public function __construct(Connection $connection, StateInterface $state, CurrentPathStack $current_path, CacheBackendInterface $cache_backend, InboundPathProcessorInterface $path_processor, CacheTagsInvalidatorInterface $cache_tag_invalidator, $table = 'router', LanguageManagerInterface $language_manager = NULL) {
$this->connection = $connection;
$this->state = $state;
$this->currentPath = $current_path;
@@ -116,6 +127,7 @@ class RouteProvider implements PreloadableRouteProviderInterface, PagedRouteProv
$this->cacheTagInvalidator = $cache_tag_invalidator;
$this->pathProcessor = $path_processor;
$this->tableName = $table;
+ $this->languageManager = $language_manager ?: \Drupal::languageManager();
}
/**
@@ -147,7 +159,7 @@ class RouteProvider implements PreloadableRouteProviderInterface, PagedRouteProv
public function getRouteCollectionForRequest(Request $request) {
// Cache both the system path as well as route parameters and matching
// routes.
- $cid = 'route:' . $request->getPathInfo() . ':' . $request->getQueryString();
+ $cid = $this->getRouteCollectionCacheId($request);
if ($cached = $this->cache->get($cid)) {
$this->currentPath->setPath($cached->data['path'], $request);
$request->query->replace($cached->data['query']);
@@ -431,4 +443,35 @@ class RouteProvider implements PreloadableRouteProviderInterface, PagedRouteProv
return $this->connection->query("SELECT COUNT(*) FROM {" . $this->connection->escapeTable($this->tableName) . "}")->fetchField();
}
+ /**
+ * Returns the cache ID for the route collection cache.
+ *
+ * @param \Symfony\Component\HttpFoundation\Request $request
+ * The request object.
+ *
+ * @return string
+ * The cache ID.
+ */
+ protected function getRouteCollectionCacheId(Request $request) {
+ // Include the current language code in the cache identifier as
+ // the language information can be elsewhere than in the path, for example
+ // based on the domain.
+ $language_part = $this->getCurrentLanguageCacheIdPart();
+ return 'route:' . $language_part . ':' . $request->getPathInfo() . ':' . $request->getQueryString();
+ }
+
+ /**
+ * Returns the language identifier for the route collection cache.
+ *
+ * @return string
+ * The language identifier.
+ */
+ protected function getCurrentLanguageCacheIdPart() {
+ // This must be in sync with the language logic in
+ // \Drupal\Core\PathProcessor\PathProcessorAlias::processInbound() and
+ // \Drupal\Core\Path\AliasManager::getPathByAlias().
+ // @todo Update this if necessary in https://www.drupal.org/node/1125428.
+ return $this->languageManager->getCurrentLanguage(LanguageInterface::TYPE_URL)->getId();
+ }
+
}