Skip to content

Instantly share code, notes, and snippets.

@marcvangend
Created July 21, 2016 10:30
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save marcvangend/7fd7a3f503ff8616a0c076ac5fa2dd2e to your computer and use it in GitHub Desktop.
Save marcvangend/7fd7a3f503ff8616a0c076ac5fa2dd2e to your computer and use it in GitHub Desktop.
Drupal 8: Custom path aliases exported to code.
<?php
/**
* @file
* Install, update and uninstall functions for my module.
*/
use Drupal\Core\Database\Database;
use Drupal\Core\Language\LanguageInterface;
/**
* Implements hook_install().
*/
function mymodule_install() {
mymodule_import_aliases();
}
/**
* Add custom path aliases.
*/
function mymodule_update_8001() {
return mymodule_import_aliases();
}
/**
* @return array[]
* An array of arrays with the following structure:
* @code
* array(
* array(
* 'source' => '/calendar', // source path
* 'alias' => '/agenda', // path alias
* 'langcode' => 'nl', // language code for the alias (optional)
* )
* )
* @endcode
*/
function mymodule_get_exported_aliases() {
return [
[
'source' => '/calendar',
'alias' => '/agenda',
'langcode' => 'nl',
],
];
}
/**
* Process the list of exported path aliases and save them to the database,
*/
function mymodule_import_aliases() {
// Get a list of aliases to be imported.
$aliases = mymodule_get_exported_aliases();
// Save aliases.
foreach ($aliases as $alias) {
// Merge in defaults.
$alias += [
'langcode' => LanguageInterface::LANGCODE_NOT_SPECIFIED,
'pid' => NULL,
];
// Check if the path alias already exists.
$query = 'SELECT COUNT(pid) FROM {url_alias} ua WHERE ua.alias = :alias AND ua.langcode = :langcode';
$args = [':alias' => $alias['alias'], ':langcode' => $alias['langcode']];
$count = Database::getConnection()->query($query, $args)->fetchField();
// If the count is 0, we can proceed to insert the alias.
if ((int)$count === 0) {
mymodule_add_path_alias($alias['source'], $alias['alias'], $alias['langcode'], $alias['pid']);
}
// If the alias exists, remember the alias and its language.
else {
$existing[] = $alias['alias'] . ' (' . $alias['langcode'] . ')';
}
}
// Return a message about existing aliases. This is not necessarily a problem,
// so we do not throw an exception.
if (!empty($existing)) {
return t('Aliases %aliases were not imported because they already exist.', ['%aliases' => implode(', ', $existing)]);
}
}
/**
* Helper function to save a path alias to the database. Copied from
* AliasStorage::save() and slightly modified.
*/
function mymodule_add_path_alias($source, $alias, $langcode, $pid) {
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)) {
$try_again = FALSE;
try {
$query = Database::getConnection()->insert('url_alias')
->fields($fields);
$pid = $query->execute();
}
catch (\Exception $e) {
// If there was an exception, try to create the table.
if (!$try_again = $this->ensureTableExists()) {
// If the exception happened for other reason than the missing table,
// propagate the exception.
throw $e;
}
}
// Now that the table has been created, try again if necessary.
if ($try_again) {
$query = Database::getConnection()->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.
try {
$original = Database::getConnection()->query('SELECT source, alias, langcode FROM {url_alias} WHERE pid = :pid', array(':pid' => $pid))
->fetchAssoc();
}
catch (\Exception $e) {
$this->catchException($e);
$original = FALSE;
}
$fields['pid'] = $pid;
$query = Database::getConnection()->update('url_alias')
->fields($fields)
->condition('pid', $pid);
$pid = $query->execute();
$fields['original'] = $original;
$operation = 'update';
}
if ($pid) {
// Do not clear cache or invoke hooks unlike the code in AliasStorage::save().
return $fields;
}
return FALSE;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment