Commit a60a5b87 authored by catch's avatar catch

Issue #2136503 by slashrsm: Make \Drupal\Core\Path\AliasManager storage independent.

parent 28f6c023
......@@ -151,7 +151,7 @@ services:
arguments: [path_alias_whitelist, '@cache.cache', '@lock', '@state', '@database']
path.alias_manager:
class: Drupal\Core\Path\AliasManager
arguments: ['@database', '@path.alias_whitelist', '@language_manager']
arguments: ['@path.crud', '@path.alias_whitelist', '@language_manager']
http_client_simpletest_subscriber:
class: Drupal\Core\Http\Plugin\SimpletestHttpRequestSubscriber
http_default_client:
......
......@@ -7,18 +7,17 @@
namespace Drupal\Core\Path;
use Drupal\Core\Database\Connection;
use Drupal\Core\Language\Language;
use Drupal\Core\Language\LanguageManager;
class AliasManager implements AliasManagerInterface {
/**
* The database connection to use for path lookups.
* The Path CRUD service.
*
* @var \Drupal\Core\Database\Connection
* @var \Drupal\Core\Path\Path
*/
protected $connection;
protected $path;
/**
* Language manager for retrieving the default langcode when none is specified.
......@@ -75,15 +74,15 @@ class AliasManager implements AliasManagerInterface {
/**
* Constructs an AliasManager.
*
* @param \Drupal\Core\Database\Connection $connection
* The database connection to use.
* @param \Drupal\Core\Path\Path $path
* The Path CRUD service.
* @param \Drupal\Core\Path\AliasWhitelistInterface $whitelist
* The whitelist implementation to use.
* @param \Drupal\Core\Language\LanguageManager $language_manager
* The language manager.
*/
public function __construct(Connection $connection, AliasWhitelistInterface $whitelist, LanguageManager $language_manager) {
$this->connection = $connection;
public function __construct(Path $path, AliasWhitelistInterface $whitelist, LanguageManager $language_manager) {
$this->path = $path;
$this->languageManager = $language_manager;
$this->whitelist = $whitelist;
}
......@@ -181,30 +180,7 @@ protected function lookupPathAlias($path, $langcode) {
// Load system paths from cache.
if (!empty($this->preloadedPathLookups)) {
// Now fetch the aliases corresponding to these system paths.
$args = array(
':system' => $this->preloadedPathLookups,
':langcode' => $langcode,
':langcode_undetermined' => Language::LANGCODE_NOT_SPECIFIED,
);
// Always get the language-specific alias before the language-neutral
// one. For example 'de' is less than 'und' so the order needs to be
// ASC, while 'xx-lolspeak' is more than 'und' so the order needs to
// be DESC. We also order by pid ASC so that fetchAllKeyed() returns
// the most recently created alias for each source. Subsequent queries
// using fetchField() must use pid DESC to have the same effect.
// For performance reasons, the query builder is not used here.
if ($langcode == Language::LANGCODE_NOT_SPECIFIED) {
// Prevent PDO from complaining about a token the query doesn't use.
unset($args[':langcode']);
$result = $this->connection->query('SELECT source, alias FROM {url_alias} WHERE source IN (:system) AND langcode = :langcode_undetermined ORDER BY pid ASC', $args);
}
elseif ($langcode < Language::LANGCODE_NOT_SPECIFIED) {
$result = $this->connection->query('SELECT source, alias FROM {url_alias} WHERE source IN (:system) AND langcode IN (:langcode, :langcode_undetermined) ORDER BY langcode ASC, pid ASC', $args);
}
else {
$result = $this->connection->query('SELECT source, alias FROM {url_alias} WHERE source IN (:system) AND langcode IN (:langcode, :langcode_undetermined) ORDER BY langcode DESC, pid ASC', $args);
}
$this->lookupMap[$langcode] = $result->fetchAllKeyed();
$this->lookupMap[$langcode] = $this->path->preloadPathAlias($this->preloadedPathLookups, $langcode);
// Keep a record of paths with no alias to avoid querying twice.
$this->noAliases[$langcode] = array_flip(array_diff_key($this->preloadedPathLookups, array_keys($this->lookupMap[$langcode])));
}
......@@ -221,24 +197,8 @@ protected function lookupPathAlias($path, $langcode) {
}
// For system paths which were not cached, query aliases individually.
elseif (!isset($this->noAliases[$langcode][$path])) {
$args = array(
':source' => $path,
':langcode' => $langcode,
':langcode_undetermined' => Language::LANGCODE_NOT_SPECIFIED,
);
// See the queries above.
if ($langcode == Language::LANGCODE_NOT_SPECIFIED) {
unset($args[':langcode']);
$alias = $this->connection->query("SELECT alias FROM {url_alias} WHERE source = :source AND langcode = :langcode_undetermined ORDER BY pid DESC", $args)->fetchField();
}
elseif ($langcode > Language::LANGCODE_NOT_SPECIFIED) {
$alias = $this->connection->query("SELECT alias FROM {url_alias} WHERE source = :source AND langcode IN (:langcode, :langcode_undetermined) ORDER BY langcode DESC, pid DESC", $args)->fetchField();
}
else {
$alias = $this->connection->query("SELECT alias FROM {url_alias} WHERE source = :source AND langcode IN (:langcode, :langcode_undetermined) ORDER BY langcode ASC, pid DESC", $args)->fetchField();
}
$this->lookupMap[$langcode][$path] = $alias;
return $alias;
$this->lookupMap[$langcode][$path] = $this->path->lookupPathAlias($path, $langcode);
return $this->lookupMap[$langcode][$path];
}
return FALSE;
}
......@@ -262,23 +222,7 @@ protected function lookupPathSource($path, $langcode) {
// Look for the value $path within the cached $map
$source = isset($this->lookupMap[$langcode]) ? array_search($path, $this->lookupMap[$langcode]) : FALSE;
if (!$source) {
$args = array(
':alias' => $path,
':langcode' => $langcode,
':langcode_undetermined' => Language::LANGCODE_NOT_SPECIFIED,
);
// See the queries above.
if ($langcode == Language::LANGCODE_NOT_SPECIFIED) {
unset($args[':langcode']);
$result = $this->connection->query("SELECT source FROM {url_alias} WHERE alias = :alias AND langcode = :langcode_undetermined ORDER BY pid DESC", $args);
}
elseif ($langcode > Language::LANGCODE_NOT_SPECIFIED) {
$result = $this->connection->query("SELECT source FROM {url_alias} WHERE alias = :alias AND langcode IN (:langcode, :langcode_undetermined) ORDER BY langcode DESC, pid DESC", $args);
}
else {
$result = $this->connection->query("SELECT source FROM {url_alias} WHERE alias = :alias AND langcode IN (:langcode, :langcode_undetermined) ORDER BY langcode ASC, pid DESC", $args);
}
if ($source = $result->fetchField()) {
if ($source = $this->path->lookupPathSource($path, $langcode)) {
$this->lookupMap[$langcode][$source] = $path;
}
else {
......
......@@ -141,4 +141,109 @@ public function delete($conditions) {
$this->moduleHandler->invokeAll('path_delete', array($path));
return $deleted;
}
/**
* Preloads path alias information for a given list of source paths.
*
* @param $path
* The path to investigate for corresponding aliases.
* @param $langcode
* Language code to search the path with. If there's no path defined for
* that language it will search paths without language.
* @return array
* Source (keys) to alias (values) mapping.
*/
public function preloadPathAlias($preloaded, $langcode) {
$args = array(
':system' => $preloaded,
':langcode' => $langcode,
':langcode_undetermined' => Language::LANGCODE_NOT_SPECIFIED,
);
// Always get the language-specific alias before the language-neutral one.
// For example 'de' is less than 'und' so the order needs to be ASC, while
// 'xx-lolspeak' is more than 'und' so the order needs to be DESC. We also
// order by pid ASC so that fetchAllKeyed() returns the most recently
// created alias for each source. Subsequent queries using fetchField() must
// use pid DESC to have the same effect. For performance reasons, the query
// builder is not used here.
if ($langcode == Language::LANGCODE_NOT_SPECIFIED) {
// Prevent PDO from complaining about a token the query doesn't use.
unset($args[':langcode']);
$result = $this->connection->query('SELECT source, alias FROM {url_alias} WHERE source IN (:system) AND langcode = :langcode_undetermined ORDER BY pid ASC', $args);
}
elseif ($langcode < Language::LANGCODE_NOT_SPECIFIED) {
$result = $this->connection->query('SELECT source, alias FROM {url_alias} WHERE source IN (:system) AND langcode IN (:langcode, :langcode_undetermined) ORDER BY langcode ASC, pid ASC', $args);
}
else {
$result = $this->connection->query('SELECT source, alias FROM {url_alias} WHERE source IN (:system) AND langcode IN (:langcode, :langcode_undetermined) ORDER BY langcode DESC, pid ASC', $args);
}
return $result->fetchAllKeyed();
}
/**
* Returns an alias of Drupal system URL.
*
* @param string $path
* The path to investigate for corresponding path aliases.
* @param string $langcode
* Language code to search the path with. If there's no path defined for
* that language it will search paths without language.
*
* @return string|bool
* A path alias, or FALSE if no path was found.
*/
public function lookupPathAlias($path, $langcode) {
$args = array(
':source' => $path,
':langcode' => $langcode,
':langcode_undetermined' => Language::LANGCODE_NOT_SPECIFIED,
);
// See the queries above.
if ($langcode == Language::LANGCODE_NOT_SPECIFIED) {
unset($args[':langcode']);
$alias = $this->connection->query("SELECT alias FROM {url_alias} WHERE source = :source AND langcode = :langcode_undetermined ORDER BY pid DESC", $args)->fetchField();
}
elseif ($langcode > Language::LANGCODE_NOT_SPECIFIED) {
$alias = $this->connection->query("SELECT alias FROM {url_alias} WHERE source = :source AND langcode IN (:langcode, :langcode_undetermined) ORDER BY langcode DESC, pid DESC", $args)->fetchField();
}
else {
$alias = $this->connection->query("SELECT alias FROM {url_alias} WHERE source = :source AND langcode IN (:langcode, :langcode_undetermined) ORDER BY langcode ASC, pid DESC", $args)->fetchField();
}
return $alias;
}
/**
* Returns Drupal system URL of an alias.
*
* @param string $path
* The path to investigate for corresponding system URLs.
* @param string $langcode
* Language code to search the path with. If there's no path defined for
* that language it will search paths without language.
*
* @return string|bool
* A Drupal system path, or FALSE if no path was found.
*/
public function lookupPathSource($path, $langcode) {
$args = array(
':alias' => $path,
':langcode' => $langcode,
':langcode_undetermined' => Language::LANGCODE_NOT_SPECIFIED,
);
// See the queries above.
if ($langcode == Language::LANGCODE_NOT_SPECIFIED) {
unset($args[':langcode']);
$result = $this->connection->query("SELECT source FROM {url_alias} WHERE alias = :alias AND langcode = :langcode_undetermined ORDER BY pid DESC", $args);
}
elseif ($langcode > Language::LANGCODE_NOT_SPECIFIED) {
$result = $this->connection->query("SELECT source FROM {url_alias} WHERE alias = :alias AND langcode IN (:langcode, :langcode_undetermined) ORDER BY langcode DESC, pid DESC", $args);
}
else {
$result = $this->connection->query("SELECT source FROM {url_alias} WHERE alias = :alias AND langcode IN (:langcode, :langcode_undetermined) ORDER BY langcode ASC, pid DESC", $args);
}
return $result->fetchField();
}
}
......@@ -169,8 +169,8 @@ function testWhitelist() {
// Create AliasManager and Path object.
$whitelist = new AliasWhitelist('path_alias_whitelist', $memoryCounterBackend, $this->container->get('lock'), $this->container->get('state'), $connection);
$aliasManager = new AliasManager($connection, $whitelist, $this->container->get('language_manager'));
$path = new Path($connection, $this->container->get('module_handler'));
$aliasManager = new AliasManager($path, $whitelist, $this->container->get('language_manager'));
// No alias for user and admin yet, so should be NULL.
$this->assertNull($whitelist->get('user'));
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment