3 namespace Drupal\pathauto;
5 use Drupal\Core\Config\ConfigFactoryInterface;
6 use Drupal\Core\Database\Connection;
7 use Drupal\Core\Entity\EntityInterface;
8 use Drupal\Core\Language\LanguageInterface;
9 use Drupal\Core\Path\AliasStorageInterface;
10 use Drupal\Core\StringTranslation\StringTranslationTrait;
11 use Drupal\Core\StringTranslation\TranslationInterface;
14 * Provides helper methods for accessing alias storage.
16 class AliasStorageHelper implements AliasStorageHelperInterface {
18 use StringTranslationTrait;
21 * Alias schema max length.
25 protected $aliasSchemaMaxLength = 255;
30 * @var \Drupal\Core\Config\ConfigFactoryInterface
32 protected $configFactory;
37 * @var \Drupal\Core\Path\AliasStorageInterface
39 protected $aliasStorage;
42 * The database connection.
44 * @var \Drupal\Core\Database\Connection
51 * @var \Drupal\pathauto\MessengerInterface
58 * @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
60 * @param \Drupal\Core\Path\AliasStorageInterface $alias_storage
62 * @param \Drupal\Core\Database\Connection $database
63 * The database connection.
64 * @param MessengerInterface $messenger
66 * @param \Drupal\Core\StringTranslation\TranslationInterface $string_translation
67 * The string translation service.
69 public function __construct(ConfigFactoryInterface $config_factory, AliasStorageInterface $alias_storage, Connection $database, MessengerInterface $messenger, TranslationInterface $string_translation) {
70 $this->configFactory = $config_factory;
71 $this->aliasStorage = $alias_storage;
72 $this->database = $database;
73 $this->messenger = $messenger;
74 $this->stringTranslation = $string_translation;
80 public function getAliasSchemaMaxLength() {
81 return $this->aliasSchemaMaxLength;
87 public function save(array $path, $existing_alias = NULL, $op = NULL) {
88 $config = $this->configFactory->get('pathauto.settings');
90 // Alert users if they are trying to create an alias that is the same as the
92 if ($path['source'] == $path['alias']) {
93 $this->messenger->addMessage($this->t('Ignoring alias %alias because it is the same as the internal path.', array('%alias' => $path['alias'])));
97 // Skip replacing the current alias with an identical alias.
98 if (empty($existing_alias) || $existing_alias['alias'] != $path['alias']) {
101 'original' => $existing_alias,
105 // If there is already an alias, respect some update actions.
106 if (!empty($existing_alias)) {
107 switch ($config->get('update_action')) {
108 case PathautoGeneratorInterface::UPDATE_ACTION_NO_NEW:
109 // Do not create the alias.
112 case PathautoGeneratorInterface::UPDATE_ACTION_LEAVE:
113 // Create a new alias instead of overwriting the existing by leaving
114 // $path['pid'] empty.
117 case PathautoGeneratorInterface::UPDATE_ACTION_DELETE:
118 // The delete actions should overwrite the existing alias.
119 $path['pid'] = $existing_alias['pid'];
124 // Save the path array.
125 $this->aliasStorage->save($path['source'], $path['alias'], $path['language'], $path['pid']);
127 if (!empty($existing_alias['pid'])) {
128 $this->messenger->addMessage($this->t(
129 'Created new alias %alias for %source, replacing %old_alias.',
131 '%alias' => $path['alias'],
132 '%source' => $path['source'],
133 '%old_alias' => $existing_alias['alias'],
139 $this->messenger->addMessage($this->t('Created new alias %alias for %source.', array(
140 '%alias' => $path['alias'],
141 '%source' => $path['source'],
152 public function loadBySource($source, $language = LanguageInterface::LANGCODE_NOT_SPECIFIED) {
153 $alias = $this->aliasStorage->load([
155 'langcode' => $language,
157 // If no alias was fetched and if a language was specified, fallbacks to
158 // undefined language.
159 if (!$alias && ($language !== LanguageInterface::LANGCODE_NOT_SPECIFIED)) {
160 $alias = $this->aliasStorage->load([
162 'langcode' => LanguageInterface::LANGCODE_NOT_SPECIFIED,
171 public function deleteBySourcePrefix($source) {
172 $pids = $this->loadBySourcePrefix($source);
174 $this->deleteMultiple($pids);
181 public function deleteAll() {
182 $this->database->truncate('url_alias')->execute();
188 public function deleteEntityPathAll(EntityInterface $entity, $default_uri = NULL) {
189 $this->deleteBySourcePrefix('/' . $entity->toUrl('canonical')->getInternalPath());
190 if (isset($default_uri) && $entity->toUrl('canonical')->toString() != $default_uri) {
191 $this->deleteBySourcePrefix($default_uri);
198 public function loadBySourcePrefix($source) {
199 $select = $this->database->select('url_alias', 'u')
200 ->fields('u', array('pid'));
202 $or_group = $select->orConditionGroup()
203 ->condition('source', $source)
204 ->condition('source', rtrim($source, '/') . '/%', 'LIKE');
207 ->condition($or_group)
215 public function countBySourcePrefix($source) {
216 $select = $this->database->select('url_alias', 'u')
217 ->fields('u', array('pid'));
219 $or_group = $select->orConditionGroup()
220 ->condition('source', $source)
221 ->condition('source', rtrim($source, '/') . '/%', 'LIKE');
224 ->condition($or_group)
233 public function countAll() {
234 return $this->database->select('url_alias')
241 * Delete multiple URL aliases.
243 * Intent of this is to abstract a potential path_delete_multiple() function
247 * An array of path IDs to delete.
249 public function deleteMultiple($pids) {
250 foreach ($pids as $pid) {
251 $this->aliasStorage->delete(array('pid' => $pid));