pathauto.module 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. <?php
  2. /**
  3. * @file
  4. * @defgroup pathauto Pathauto: Automatically generates aliases for content
  5. *
  6. * The Pathauto module automatically generates path aliases for various kinds of
  7. * content (nodes, categories, users) without requiring the user to manually
  8. * specify the path alias. This allows you to get aliases like
  9. * /category/my-node-title.html instead of /node/123. The aliases are based upon
  10. * a "pattern" system which the administrator can control.
  11. */
  12. /**
  13. * @file
  14. * Main file for the Pathauto module, which automatically generates aliases for content.
  15. *
  16. * @ingroup pathauto
  17. */
  18. use Drupal\Core\Entity\ContentEntityInterface;
  19. use Drupal\Core\Entity\EntityInterface;
  20. use Drupal\Core\Entity\EntityTypeInterface;
  21. use Drupal\Core\Field\BaseFieldDefinition;
  22. use Drupal\Core\Form\FormStateInterface;
  23. use Drupal\Core\Routing\RouteMatchInterface;
  24. use Drupal\Core\Url;
  25. use Drupal\pathauto\PathautoFieldItemList;
  26. use Drupal\pathauto\PathautoItem;
  27. /**
  28. * The default ignore word list.
  29. */
  30. define('PATHAUTO_IGNORE_WORDS', 'a, an, as, at, before, but, by, for, from, is, in, into, like, of, off, on, onto, per, since, than, the, this, that, to, up, via, with');
  31. /**
  32. * Implements hook_hook_info().
  33. */
  34. function pathauto_hook_info() {
  35. $hooks = array(
  36. 'pathauto_pattern_alter',
  37. 'pathauto_alias_alter',
  38. 'pathauto_is_alias_reserved',
  39. );
  40. return array_fill_keys($hooks, array('group' => 'pathauto'));
  41. }
  42. /**
  43. * Implements hook_help().
  44. */
  45. function pathauto_help($route_name, RouteMatchInterface $route_match) {
  46. switch ($route_name) {
  47. case 'help.page.pathauto':
  48. $output = '<h3>' . t('About') . '</h3>';
  49. $output .= '<p>' . t('The Pathauto module provides a mechanism to automate the creation of <a href="path">path</a> aliases. This makes URLs more readable and helps search engines index content more effectively. For more information, see the <a href=":online">online documentation for Pathauto</a>.', [':online' => 'https://www.drupal.org/documentation/modules/pathauto']) . '</p>';
  50. $output .= '<dl>';
  51. $output .= '<h3>' . t('Uses') . '</h3>';
  52. $output .= '<dd>' . t('Pathauto is accessed from the tabs it adds to the list of <a href=":aliases">URL aliases</a>.', [':aliases' => Url::fromRoute('path.admin_overview')->toString()]) . '</dd>';
  53. $output .= '<dt>' . t('Creating Pathauto Patterns') . '</dt>';
  54. $output .= '<dd>' . t('The <a href=":pathauto_pattern">"Patterns"</a> page is used to configure automatic path aliasing. New patterns are created here using the <a href=":add_form">Add Pathauto pattern</a> button which presents a form to simplify pattern creation thru the use of <a href="token">available tokens</a>. The patterns page provides a list of all patterns on the site and allows you to edit and reorder them. An alias is generated for the first pattern that applies.', [':pathauto_pattern' => Url::fromRoute('entity.pathauto_pattern.collection')->toString(), ':add_form' => Url::fromRoute('entity.pathauto_pattern.add_form')->toString()]) . '</dd>';
  55. $output .= '<dt>' . t('Pathauto Settings') . '</dt>';
  56. $output .= '<dd>' . t('The <a href=":settings">"Settings"</a> page is used to customize global Pathauto settings for automated pattern creation.', [':settings' => Url::fromRoute('pathauto.settings.form')->toString()]) . '</dd>';
  57. $output .= '<dd>' . t('The <strong>maximum alias length</strong> and <strong>maximum component length</strong> values default to 100 and have a limit of @max from Pathauto. You should enter a value that is the length of the "alias" column of the url_alias database table minus the length of any strings that might get added to the end of the URL. The recommended and default value is 100.', array('@max' => \Drupal::service('pathauto.alias_storage_helper')->getAliasSchemaMaxlength())) . '</dd>';
  58. $output .= '<dt>' . t('Bulk Generation') . '</dt>';
  59. $output .= '<dd>' . t('The <a href=":pathauto_bulk">"Bulk Generate"</a> page allows you to create URL aliases for items that currently have no aliases. This is typically used when installing Pathauto on a site that has existing un-aliased content that needs to be aliased in bulk.', [':pathauto_bulk' => Url::fromRoute('pathauto.bulk.update.form')->toString()]) . '</dd>';
  60. $output .= '<dt>' . t('Delete Aliases') . '</dt>';
  61. $output .= '<dd>' . t('The <a href=":pathauto_delete">"Delete Aliases"</a> page allows you to remove URL aliases from items that have previously been assigned aliases using pathauto.', [':pathauto_delete' => Url::fromRoute('pathauto.admin.delete')->toString()]) . '</dd>';
  62. $output .= '</dl>';
  63. return $output;
  64. case 'entity.pathauto_pattern.collection':
  65. $output = '<p>' . t('This page provides a list of all patterns on the site and allows you to edit and reorder them.') . '</p>';
  66. return $output;
  67. case 'entity.pathauto_pattern.add_form':
  68. $output = '<p>' . t('You need to select a pattern type, then a pattern and filter, and a label. Additional types can be enabled on the <a href=":settings">Settings</a> page.', [':settings' => Url::fromRoute('pathauto.settings.form')->toString()]) . '</p>';
  69. return $output;
  70. case 'pathauto.bulk.update.form':
  71. $output = '<p>' . t('Bulk generation can be used to generate URL aliases for items that currently have no aliases. This is typically used when installing Pathauto on a site that has existing un-aliased content that needs to be aliased in bulk.') . '<br>';
  72. $output .= t('It can also be used to regenerate URL aliases for items that have an old alias and for which the Pathauto pattern has been changed.') . '</p>';
  73. $output .= '<p>' . t('Note that this will only affect items which are configured to have their URL alias automatically set. Items whose URL alias is manually set are not affected.') . '</p>';
  74. return $output;
  75. }
  76. }
  77. /**
  78. * Implements hook_entity_insert().
  79. */
  80. function pathauto_entity_insert(EntityInterface $entity) {
  81. \Drupal::service('pathauto.generator')->updateEntityAlias($entity, 'insert');
  82. }
  83. /**
  84. * Implements hook_entity_update().
  85. */
  86. function pathauto_entity_update(EntityInterface $entity) {
  87. \Drupal::service('pathauto.generator')->updateEntityAlias($entity, 'update');
  88. }
  89. /**
  90. * Implements hook_entity_delete().
  91. */
  92. function pathauto_entity_delete(EntityInterface $entity) {
  93. if ($entity->hasLinkTemplate('canonical') && $entity instanceof ContentEntityInterface && $entity->hasField('path')) {
  94. \Drupal::service('pathauto.alias_storage_helper')->deleteEntityPathAll($entity);
  95. $entity->get('path')->first()->get('pathauto')->purge();
  96. }
  97. }
  98. /**
  99. * Implements hook_field_info_alter().
  100. */
  101. function pathauto_field_info_alter(&$info) {
  102. $info['path']['class'] = PathautoItem::class;
  103. $info['path']['list_class'] = PathautoFieldItemList::class;
  104. }
  105. /**
  106. * Implements hook_field_widget_info_alter().
  107. */
  108. function pathauto_field_widget_info_alter(&$widgets) {
  109. $widgets['path']['class'] = 'Drupal\pathauto\PathautoWidget';
  110. }
  111. /**
  112. * Implements hook_entity_base_field_info().
  113. */
  114. function pathauto_entity_base_field_info(EntityTypeInterface $entity_type) {
  115. $config = \Drupal::config('pathauto.settings');
  116. // Verify that the configuration data isn't null (as is the case before the
  117. // module's initialization, in tests), so that in_array() won't fail.
  118. if ($enabled_entity_types = $config->get('enabled_entity_types')) {
  119. if (in_array($entity_type->id(), $enabled_entity_types)) {
  120. $fields['path'] = BaseFieldDefinition::create('path')
  121. ->setCustomStorage(TRUE)
  122. ->setLabel(t('URL alias'))
  123. ->setTranslatable(TRUE)
  124. ->setComputed(TRUE)
  125. ->setDisplayOptions('form', array(
  126. 'type' => 'path',
  127. 'weight' => 30,
  128. ))
  129. ->setDisplayConfigurable('form', TRUE);
  130. return $fields;
  131. }
  132. }
  133. }
  134. /**
  135. * Validate the pattern field, to ensure it doesn't contain any characters that
  136. * are invalid in URLs.
  137. */
  138. function pathauto_pattern_validate($element, FormStateInterface $form_state) {
  139. if (isset($element['#value'])) {
  140. $title = empty($element['#title']) ? $element['#parents'][0] : $element['#title'];
  141. $invalid_characters = ['#', '?', '&'];
  142. $invalid_characters_used = [];
  143. foreach ($invalid_characters as $invalid_character) {
  144. if (strpos($element['#value'], $invalid_character) !== FALSE) {
  145. $invalid_characters_used[] = $invalid_character;
  146. }
  147. }
  148. if (!empty($invalid_characters_used)) {
  149. $form_state->setError($element, t('The %element-title is using the following invalid characters: @invalid-characters.', array('%element-title' => $title, '@invalid-characters' => implode(', ', $invalid_characters_used))));
  150. }
  151. if (preg_match('/(\s$)+/', $element['#value'])) {
  152. $form_state->setError($element, t('The %element-title doesn\'t allow the patterns ending with whitespace.', array('%element-title' => $title)));
  153. }
  154. }
  155. return $element;
  156. }