class AliasManager implements AliasManagerInterface {
protected $connection;
protected $state;
protected $langcode;
protected $lookupMap = array();
protected $noSource = array();
protected $whitelist;
protected $noAliases = array();
protected $firstLookup = TRUE;
protected $preloadedPathLookups = array();
public function __construct(Connection $connection, KeyValueFactory $keyvalue) {
$this->connection = $connection;
$this->state = $keyvalue
->get('state');
$this->langcode = language(LANGUAGE_TYPE_URL)->langcode;
$this->whitelist = $this->state
->get('system.path_alias_whitelist', NULL);
if (!isset($this->whitelist)) {
$this->whitelist = $this
->pathAliasWhitelistRebuild();
}
}
public function getSystemPath($path, $path_language = NULL) {
$path_language = $path_language ?: $this->langcode;
$original_path = $path;
if (!empty($path) && ($source = $this
->lookupPathSource($path, $path_language))) {
$path = $source;
}
return $path;
}
public function getPathAlias($path, $path_language = NULL) {
$path_language = $path_language ?: $this->langcode;
$result = $path;
if (!empty($path) && ($alias = $this
->lookupPathAlias($path, $path_language))) {
$result = $alias;
}
return $result;
}
public function cacheClear($source = NULL) {
$this->lookupMap = array();
$this->noSource = array();
$this->no_aliases = array();
$this->firstCall = TRUE;
$this->preloadedPathLookups = array();
$this->whitelist = $this
->pathAliasWhitelistRebuild($source);
}
public function getPathLookups() {
$current = current($this->lookupMap);
if ($current) {
return array_keys($current);
}
return array();
}
public function preloadPathLookups(array $path_list) {
$this->preloadedPathLookups = $path_list;
}
protected function lookupPathAlias($path, $langcode) {
if (!empty($this->firstLookup)) {
$this->firstLookup = FALSE;
$this->lookupMap[$langcode] = array();
if (!empty($this->preloadedPathLookups)) {
$args = array(
':system' => $this->preloadedPathLookups,
':langcode' => $langcode,
':langcode_undetermined' => LANGUAGE_NOT_SPECIFIED,
);
if ($langcode == LANGUAGE_NOT_SPECIFIED) {
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_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->noAliases[$langcode] = array_flip(array_diff_key($this->preloadedPathLookups, array_keys($this->lookupMap[$langcode])));
}
}
if (isset($this->lookupMap[$langcode][$path])) {
return $this->lookupMap[$langcode][$path];
}
elseif (!isset($this->whitelist[strtok($path, '/')])) {
return FALSE;
}
elseif (!isset($this->noAliases[$langcode][$path])) {
$args = array(
':source' => $path,
':langcode' => $langcode,
':langcode_undetermined' => LANGUAGE_NOT_SPECIFIED,
);
if ($langcode == LANGUAGE_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_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;
}
return FALSE;
}
protected function lookupPathSource($path, $langcode) {
if ($this->whitelist && !isset($this->noSource[$langcode][$path])) {
$source = FALSE;
if (!isset($this->lookupMap[$langcode]) || !($source = array_search($path, $this->lookupMap[$langcode]))) {
$args = array(
':alias' => $path,
':langcode' => $langcode,
':langcode_undetermined' => LANGUAGE_NOT_SPECIFIED,
);
if ($langcode == LANGUAGE_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_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()) {
$this->lookupMap[$langcode][$source] = $path;
}
else {
$this->noSource[$langcode][$path] = TRUE;
}
}
return $source;
}
return FALSE;
}
protected function pathAliasWhitelistRebuild($source = NULL) {
if (!empty($source)) {
$whitelist = $this->state
->get('system.path_alias_whitelist', NULL);
if (isset($whitelist[strtok($source, '/')])) {
return $whitelist;
}
}
$whitelist = array();
$result = $this->connection
->query("SELECT DISTINCT SUBSTRING_INDEX(source, '/', 1) AS path FROM {url_alias}");
foreach ($result as $row) {
$whitelist[$row->path] = TRUE;
}
$this->state
->set('system.path_alias_whitelist', $whitelist);
return $whitelist;
}
}