class AliasStorage in Zircon Profile 8
Same name and namespace in other branches
- 8.0 core/lib/Drupal/Core/Path/AliasStorage.php \Drupal\Core\Path\AliasStorage
Provides a class for CRUD operations on path aliases.
All queries perform case-insensitive matching on the 'source' and 'alias' fields, so the aliases '/test-alias' and '/test-Alias' are considered to be the same, and will both refer to the same internal system path.
Hierarchy
- class \Drupal\Core\Path\AliasStorage implements AliasStorageInterface
Expanded class hierarchy of AliasStorage
2 files declare their use of AliasStorage
- AliasTest.php in core/
modules/ system/ src/ Tests/ Path/ AliasTest.php - Contains \Drupal\system\Tests\Path\AliasTest.
- UrlAlias.php in core/
modules/ path/ src/ Plugin/ migrate/ destination/ UrlAlias.php - Contains \Drupal\path\Plugin\migrate\destination\UrlAlias.
1 string reference to 'AliasStorage'
- core.services.yml in core/
core.services.yml - core/core.services.yml
1 service uses AliasStorage
File
- core/
lib/ Drupal/ Core/ Path/ AliasStorage.php, line 23 - Contains \Drupal\Core\Path\AliasStorage.
Namespace
Drupal\Core\PathView source
class AliasStorage implements AliasStorageInterface {
/**
* The database connection.
*
* @var \Drupal\Core\Database\Connection
*/
protected $connection;
/**
* The module handler.
*
* @var \Drupal\Core\Extension\ModuleHandlerInterface
*/
protected $moduleHandler;
/**
* Constructs a Path CRUD object.
*
* @param \Drupal\Core\Database\Connection $connection
* A database connection for reading and writing path aliases.
*
* @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
* The module handler.
*/
public function __construct(Connection $connection, ModuleHandlerInterface $module_handler) {
$this->connection = $connection;
$this->moduleHandler = $module_handler;
}
/**
* {@inheritdoc}
*/
public function save($source, $alias, $langcode = LanguageInterface::LANGCODE_NOT_SPECIFIED, $pid = NULL) {
if ($source[0] !== '/') {
throw new \InvalidArgumentException(sprintf('Source path %s has to start with a slash.', $source));
}
if ($alias[0] !== '/') {
throw new \InvalidArgumentException(sprintf('Alias path %s has to start with a slash.', $alias));
}
$fields = array(
'source' => $source,
'alias' => $alias,
'langcode' => $langcode,
);
// Insert or update the alias.
if (empty($pid)) {
$query = $this->connection
->insert('url_alias')
->fields($fields);
$pid = $query
->execute();
$fields['pid'] = $pid;
$operation = 'insert';
}
else {
// Fetch the current values so that an update hook can identify what
// exactly changed.
$original = $this->connection
->query('SELECT source, alias, langcode FROM {url_alias} WHERE pid = :pid', array(
':pid' => $pid,
))
->fetchAssoc();
$fields['pid'] = $pid;
$query = $this->connection
->update('url_alias')
->fields($fields)
->condition('pid', $pid);
$pid = $query
->execute();
$fields['original'] = $original;
$operation = 'update';
}
if ($pid) {
// @todo Switch to using an event for this instead of a hook.
$this->moduleHandler
->invokeAll('path_' . $operation, array(
$fields,
));
Cache::invalidateTags([
'route_match',
]);
return $fields;
}
return FALSE;
}
/**
* {@inheritdoc}
*/
public function load($conditions) {
$select = $this->connection
->select('url_alias');
foreach ($conditions as $field => $value) {
if ($field == 'source' || $field == 'alias') {
// Use LIKE for case-insensitive matching.
$select
->condition($field, $this->connection
->escapeLike($value), 'LIKE');
}
else {
$select
->condition($field, $value);
}
}
return $select
->fields('url_alias')
->orderBy('pid', 'DESC')
->range(0, 1)
->execute()
->fetchAssoc();
}
/**
* {@inheritdoc}
*/
public function delete($conditions) {
$path = $this
->load($conditions);
$query = $this->connection
->delete('url_alias');
foreach ($conditions as $field => $value) {
if ($field == 'source' || $field == 'alias') {
// Use LIKE for case-insensitive matching.
$query
->condition($field, $this->connection
->escapeLike($value), 'LIKE');
}
else {
$query
->condition($field, $value);
}
}
$deleted = $query
->execute();
// @todo Switch to using an event for this instead of a hook.
$this->moduleHandler
->invokeAll('path_delete', array(
$path,
));
Cache::invalidateTags([
'route_match',
]);
return $deleted;
}
/**
* {@inheritdoc}
*/
public function preloadPathAlias($preloaded, $langcode) {
$langcode_list = [
$langcode,
LanguageInterface::LANGCODE_NOT_SPECIFIED,
];
$select = $this->connection
->select('url_alias')
->fields('url_alias', [
'source',
'alias',
]);
if (!empty($preloaded)) {
$conditions = new Condition('OR');
foreach ($preloaded as $preloaded_item) {
$conditions
->condition('source', $this->connection
->escapeLike($preloaded_item), 'LIKE');
}
$select
->condition($conditions);
}
// 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.
if ($langcode == LanguageInterface::LANGCODE_NOT_SPECIFIED) {
array_pop($langcode_list);
}
elseif ($langcode < LanguageInterface::LANGCODE_NOT_SPECIFIED) {
$select
->orderBy('langcode', 'ASC');
}
else {
$select
->orderBy('langcode', 'DESC');
}
$select
->orderBy('pid', 'ASC');
$select
->condition('langcode', $langcode_list, 'IN');
return $select
->execute()
->fetchAllKeyed();
}
/**
* {@inheritdoc}
*/
public function lookupPathAlias($path, $langcode) {
$source = $this->connection
->escapeLike($path);
$langcode_list = [
$langcode,
LanguageInterface::LANGCODE_NOT_SPECIFIED,
];
// See the queries above. Use LIKE for case-insensitive matching.
$select = $this->connection
->select('url_alias')
->fields('url_alias', [
'alias',
])
->condition('source', $source, 'LIKE');
if ($langcode == LanguageInterface::LANGCODE_NOT_SPECIFIED) {
array_pop($langcode_list);
}
elseif ($langcode > LanguageInterface::LANGCODE_NOT_SPECIFIED) {
$select
->orderBy('langcode', 'DESC');
}
else {
$select
->orderBy('langcode', 'ASC');
}
$select
->orderBy('pid', 'DESC');
$select
->condition('langcode', $langcode_list, 'IN');
return $select
->execute()
->fetchField();
}
/**
* {@inheritdoc}
*/
public function lookupPathSource($path, $langcode) {
$alias = $this->connection
->escapeLike($path);
$langcode_list = [
$langcode,
LanguageInterface::LANGCODE_NOT_SPECIFIED,
];
// See the queries above. Use LIKE for case-insensitive matching.
$select = $this->connection
->select('url_alias')
->fields('url_alias', [
'source',
])
->condition('alias', $alias, 'LIKE');
if ($langcode == LanguageInterface::LANGCODE_NOT_SPECIFIED) {
array_pop($langcode_list);
}
elseif ($langcode > LanguageInterface::LANGCODE_NOT_SPECIFIED) {
$select
->orderBy('langcode', 'DESC');
}
else {
$select
->orderBy('langcode', 'ASC');
}
$select
->orderBy('pid', 'DESC');
$select
->condition('langcode', $langcode_list, 'IN');
return $select
->execute()
->fetchField();
}
/**
* {@inheritdoc}
*/
public function aliasExists($alias, $langcode, $source = NULL) {
// Use LIKE and NOT LIKE for case-insensitive matching.
$query = $this->connection
->select('url_alias')
->condition('alias', $this->connection
->escapeLike($alias), 'LIKE')
->condition('langcode', $langcode);
if (!empty($source)) {
$query
->condition('source', $this->connection
->escapeLike($source), 'NOT LIKE');
}
$query
->addExpression('1');
$query
->range(0, 1);
return (bool) $query
->execute()
->fetchField();
}
/**
* {@inheritdoc}
*/
public function languageAliasExists() {
return (bool) $this->connection
->queryRange('SELECT 1 FROM {url_alias} WHERE langcode <> :langcode', 0, 1, array(
':langcode' => LanguageInterface::LANGCODE_NOT_SPECIFIED,
))
->fetchField();
}
/**
* {@inheritdoc}
*/
public function getAliasesForAdminListing($header, $keys = NULL) {
$query = $this->connection
->select('url_alias')
->extend('Drupal\\Core\\Database\\Query\\PagerSelectExtender')
->extend('Drupal\\Core\\Database\\Query\\TableSortExtender');
if ($keys) {
// Replace wildcards with PDO wildcards.
$query
->condition('alias', '%' . preg_replace('!\\*+!', '%', $keys) . '%', 'LIKE');
}
return $query
->fields('url_alias')
->orderByHeader($header)
->limit(50)
->execute()
->fetchAll();
}
/**
* {@inheritdoc}
*/
public function pathHasMatchingAlias($initial_substring) {
$query = $this->connection
->select('url_alias', 'u');
$query
->addExpression(1);
return (bool) $query
->condition('u.source', $this->connection
->escapeLike($initial_substring) . '%', 'LIKE')
->range(0, 1)
->execute()
->fetchField();
}
}
Members
Name | Modifiers | Type | Description | Overrides |
---|---|---|---|---|
AliasStorage:: |
protected | property | The database connection. | |
AliasStorage:: |
protected | property | The module handler. | |
AliasStorage:: |
public | function |
Checks if alias already exists. Overrides AliasStorageInterface:: |
|
AliasStorage:: |
public | function |
Deletes a URL alias. Overrides AliasStorageInterface:: |
|
AliasStorage:: |
public | function |
Loads aliases for admin listing. Overrides AliasStorageInterface:: |
|
AliasStorage:: |
public | function |
Checks if there are any aliases with language defined. Overrides AliasStorageInterface:: |
|
AliasStorage:: |
public | function |
Fetches a specific URL alias from the database. Overrides AliasStorageInterface:: |
|
AliasStorage:: |
public | function |
Returns an alias of Drupal system URL. Overrides AliasStorageInterface:: |
|
AliasStorage:: |
public | function |
Returns Drupal system URL of an alias. Overrides AliasStorageInterface:: |
|
AliasStorage:: |
public | function |
Check if any alias exists starting with $initial_substring. Overrides AliasStorageInterface:: |
|
AliasStorage:: |
public | function |
Pre-loads path alias information for a given list of source paths. Overrides AliasStorageInterface:: |
|
AliasStorage:: |
public | function |
Saves a path alias to the database. Overrides AliasStorageInterface:: |
|
AliasStorage:: |
public | function | Constructs a Path CRUD object. |