updated contrib modules : pathauto, token, entity_api, search_api, redirect, features

This commit is contained in:
2018-09-12 15:05:44 +02:00
parent b8e8cc8cee
commit a4746432c7
281 changed files with 4839 additions and 2453 deletions
@@ -11,3 +11,10 @@ reduce_ascii : FALSE
case : TRUE
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'
update_action : 2
safe_tokens:
- alias
- path
- join-path
- login-url
- url
- url-brief
@@ -22,14 +22,17 @@ pathauto.settings:
type: boolean
reduce_ascii:
type: boolean
ignore_words:
type: string
case:
type: boolean
ignore_words:
type: string
update_action:
type: integer
safe_tokens:
label: Tokens that are safe to use and do not need to be cleaned.
type: sequence
sequence:
type: string
action.configuration.pathauto_update_alias:
type: action_configuration_default
@@ -93,9 +93,8 @@ function hook_pathauto_is_alias_reserved($alias, $source, $langcode) {
* This hook will only be called if a default pattern is configured (on
* admin/config/search/path/patterns).
*
* @param string $pattern
* The alias pattern for Pathauto to pass to token_replace() to generate the
* URL alias.
* @param \Drupal\pathauto\PathautoPatternInterface $pattern
* The Pathauto pattern to be used.
* @param array $context
* An associative array of additional options, with the following elements:
* - 'module': The module or entity type being aliased.
@@ -103,14 +102,14 @@ function hook_pathauto_is_alias_reserved($alias, $source, $langcode) {
* aliased. Can be either 'insert', 'update', 'return', or 'bulkupdate'.
* - 'source': A string of the source path for the alias (e.g. 'node/1').
* - 'data': An array of keyed objects to pass to token_replace().
* - 'type': The sub-type or bundle of the object being aliased.
* - 'bundle': The sub-type or bundle of the object being aliased.
* - 'language': A string of the language code for the alias (e.g. 'en').
* This can be altered by reference.
*/
function hook_pathauto_pattern_alter(&$pattern, array $context) {
function hook_pathauto_pattern_alter(\Drupal\pathauto\PathautoPatternInterface $pattern, array $context) {
// Switch out any [node:created:*] tokens with [node:updated:*] on update.
if ($context['module'] == 'node' && ($context['op'] == 'update')) {
$pattern = preg_replace('/\[node:created(\:[^]]*)?\]/', '[node:updated$1]', $pattern);
$pattern->setPattern(preg_replace('/\[node:created(\:[^]]*)?\]/', '[node:updated$1]', $pattern->getPattern()));
}
}
@@ -133,7 +132,7 @@ function hook_pathauto_pattern_alter(&$pattern, array $context) {
* - 'pattern': A string of the pattern used for aliasing the object.
*/
function hook_pathauto_alias_alter(&$alias, array &$context) {
// Add a suffix so that all aliases get saved as 'content/my-title.html'
// Add a suffix so that all aliases get saved as 'content/my-title.html'.
$alias .= '.html';
// Force all aliases to be saved as language neutral.
@@ -143,7 +142,7 @@ function hook_pathauto_alias_alter(&$alias, array &$context) {
/**
* Alter the list of punctuation characters for Pathauto control.
*
* @param $punctuation
* @param array $punctuation
* An array of punctuation to be controlled by Pathauto during replacement
* keyed by punctuation name. Each punctuation record should be an array
* with the following key/value pairs:
@@ -6,6 +6,7 @@ type: module
dependencies:
- ctools:ctools
- drupal:path
- drupal:system (>=8.5)
- token:token
configure: entity.pathauto_pattern.collection
@@ -13,8 +14,8 @@ configure: entity.pathauto_pattern.collection
recommends:
- redirect:redirect
# Information added by Drupal.org packaging script on 2018-03-03
version: '8.x-1.1'
# Information added by Drupal.org packaging script on 2018-09-08
version: '8.x-1.3'
core: '8.x'
project: 'pathauto'
datestamp: 1520092688
datestamp: 1536407890
@@ -8,15 +8,13 @@
*/
use Drupal\Core\Entity\Entity\EntityFormDisplay;
use Drupal\Core\Plugin\Context\Context;
use Drupal\Core\Plugin\Context\ContextDefinition;
use Drupal\pathauto\Entity\PathautoPattern;
/**
* Implements hook_install().
*/
function pathauto_install() {
// Set the weight to 1
// Set the weight to 1.
module_set_weight('pathauto', 1);
// Ensure the url_alias table exists.
@@ -170,7 +168,8 @@ function pathauto_update_8100() {
continue;
}
// This is a pattern for a bundle and a language, such as "node_article_es".
// This is a pattern for a bundle and a language, such as
// "node_article_es".
$pattern = PathautoPattern::create([
'id' => $entity_type . '_' . $extracted_bundle . '_' . str_replace('-', '_', $langcode),
'label' => $entity_label . ' ' . $bundle_info[$extracted_bundle]['label'] . ' ' . $language->getName(),
@@ -299,3 +298,23 @@ function pathauto_update_8106() {
$config->set('enabled_entity_types', ['user']);
$config->save();
}
/**
* Initialize the new safe tokens setting.
*/
function pathauto_update_8107() {
$safe_tokens = [
'alias',
'alias',
'path',
'join-path',
'login-url',
'url',
'url-brief',
];
\Drupal::configFactory()->getEditable('pathauto.settings')
->set('safe_tokens', $safe_tokens)
->save();
}
@@ -2,9 +2,9 @@
'use strict';
Drupal.behaviors.pathFieldsetSummaries = {
attach: function (context) {
$('fieldset.path-form', context).drupalSetSummary(function (context) {
var path = $('.form-item-path-alias input', context).val();
var automatic = $('.form-item-path-pathauto input', context).attr('checked');
$(context).find('.path-form').drupalSetSummary(function (context) {
var path = $('.js-form-item-path-0-alias input', context).val();
var automatic = $('.js-form-item-path-0-pathauto input', context).prop('checked');
if (automatic) {
return Drupal.t('Automatic alias');
@@ -3,4 +3,3 @@ entity.pathauto_pattern.add_form:
title: 'Add Pathauto pattern'
appears_on:
- entity.pathauto_pattern.collection
@@ -18,6 +18,8 @@
* @ingroup pathauto
*/
use Drupal\Core\Entity\ContentEntityInterface;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Entity\EntityTypeInterface;
use Drupal\Core\Field\BaseFieldDefinition;
use Drupal\Core\Form\FormStateInterface;
@@ -82,6 +84,30 @@ function pathauto_help($route_name, RouteMatchInterface $route_match) {
}
}
/**
* Implements hook_entity_insert().
*/
function pathauto_entity_insert(EntityInterface $entity) {
\Drupal::service('pathauto.generator')->updateEntityAlias($entity, 'insert');
}
/**
* Implements hook_entity_update().
*/
function pathauto_entity_update(EntityInterface $entity) {
\Drupal::service('pathauto.generator')->updateEntityAlias($entity, 'update');
}
/**
* Implements hook_entity_delete().
*/
function pathauto_entity_delete(EntityInterface $entity) {
if ($entity->hasLinkTemplate('canonical') && $entity instanceof ContentEntityInterface && $entity->hasField('path')) {
\Drupal::service('pathauto.alias_storage_helper')->deleteEntityPathAll($entity);
$entity->get('path')->first()->get('pathauto')->purge();
}
}
/**
* Implements hook_field_info_alter().
*/
@@ -15,7 +15,7 @@ services:
arguments: ['@config.factory', '@pathauto.alias_storage_helper','@module_handler', '@router.route_provider', '@path.alias_manager']
pathauto.verbose_messenger:
class: Drupal\pathauto\VerboseMessenger
arguments: ['@config.factory', '@current_user']
arguments: ['@config.factory', '@current_user', '@messenger']
plugin.manager.alias_type:
class: Drupal\pathauto\AliasTypeManager
parent: default_plugin_manager
@@ -104,7 +104,7 @@ class AliasCleaner implements AliasCleanerInterface {
// Trim duplicate, leading, and trailing separators. Do this before cleaning
// backslashes since a pattern like "[token1]/[token2]-[token3]/[token4]"
// could end up like "value1/-/value2" and if backslashes were cleaned first
// this would result in a duplicate blackslash.
// this would result in a duplicate backslash.
$output = $this->getCleanSeparators($output);
// Trim duplicate, leading, and trailing backslashes.
@@ -247,7 +247,7 @@ class AliasCleaner implements AliasCleanerInterface {
// Get rid of words that are on the ignore list.
if ($this->cleanStringCache['ignore_words_regex']) {
$words_removed = $this->cleanStringCache['ignore_words_callback']($this->cleanStringCache['ignore_words_regex'], '', $output);
if (Unicode::strlen(trim($words_removed)) > 0) {
if (mb_strlen(trim($words_removed)) > 0) {
$output = $words_removed;
}
}
@@ -260,7 +260,7 @@ class AliasCleaner implements AliasCleanerInterface {
// Optionally convert to lower case.
if ($this->cleanStringCache['lowercase']) {
$output = Unicode::strtolower($output);
$output = mb_strtolower($output);
}
// Shorten to a logical place based on word boundaries.
@@ -335,7 +335,9 @@ class AliasCleaner implements AliasCleanerInterface {
public function cleanTokenValues(&$replacements, $data = array(), $options = array()) {
foreach ($replacements as $token => $value) {
// Only clean non-path tokens.
if (!preg_match('/(path|alias|url|url-brief)\]$/', $token)) {
$config = $this->configFactory->get('pathauto.settings');
$safe_tokens = implode('|', (array) $config->get('safe_tokens'));
if (!preg_match('/:(' . $safe_tokens . ')(:|\]$)/', $token)) {
$replacements[$token] = $this->cleanString($value, $options);
}
}
@@ -72,8 +72,8 @@ interface AliasCleanerInterface {
/**
* Return an array of arrays for punctuation values.
*
* Returns an array of arrays for punctuation values keyed by a name, including
* the value and a textual description.
* Returns an array of arrays for punctuation values keyed by a name,
* including the value and a textual description.
* Can and should be expanded to include "all" non text punctuation values.
*
* @return array
@@ -1,6 +1,7 @@
<?php
namespace Drupal\pathauto;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Language\LanguageInterface;
@@ -94,7 +95,6 @@ interface AliasStorageHelperInterface {
*/
public function loadBySourcePrefix($source);
/**
* Returns the count of url aliases for the source.
*
@@ -13,7 +13,8 @@ interface AliasTypeBatchUpdateInterface extends AliasTypeInterface {
* @param string $action
* One of:
* - 'create' to generate a URL alias for paths having none.
* - 'update' to recreate the URL alias for paths already having one, useful if the pattern changed.
* - 'update' to recreate the URL alias for paths already having one, useful
* if the pattern changed.
* - 'all' to do both actions above at the same time.
* @param array $context
* Batch context.
@@ -38,7 +38,7 @@ class AliasUniquifier implements AliasUniquifierInterface {
/**
* The route provider service.
*
* @var \Drupal\Core\Routing\RouteProviderInterface.
* @var \Drupal\Core\Routing\RouteProviderInterface
*/
protected $routeProvider;
@@ -60,6 +60,8 @@ class AliasUniquifier implements AliasUniquifierInterface {
* The module handler.
* @param \Drupal\Core\Routing\RouteProviderInterface $route_provider
* The route provider service.
* @param \Drupal\Core\Path\AliasManagerInterface $alias_manager
* The alias manager.
*/
public function __construct(ConfigFactoryInterface $config_factory, AliasStorageHelperInterface $alias_storage_helper, ModuleHandlerInterface $module_handler, RouteProviderInterface $route_provider, AliasManagerInterface $alias_manager) {
$this->configFactory = $config_factory;
@@ -1,6 +1,7 @@
<?php
namespace Drupal\pathauto;
use Drupal\Core\Language\LanguageInterface;
/**
@@ -21,9 +21,9 @@ class AliasType extends Plugin {
/**
* The human-readable name of the action plugin.
*
* @ingroup plugin_translatable
*
* @var \Drupal\Core\Annotation\Translation
*
* @ingroup plugin_translatable
*/
public $label;
@@ -13,11 +13,25 @@ use Drupal\pathauto\AliasTypeManager;
*/
class PathautoSettingsCacheTag implements EventSubscriberInterface {
/**
* @var \Drupal\Core\Entity\EntityFieldManagerInterface
*/
protected $entityFieldManager;
/**
* The alias type manager.
*
* @var \Drupal\pathauto\AliasTypeManager
*/
protected $aliasTypeManager;
/**
* Constructs a PathautoSettingsCacheTag object.
*
* @param \Drupal\Core\Entity\EntityFieldManagerInterface $entity_field_manager
* The entity field manager.
* @param \Drupal\pathauto\AliasTypeManager $alias_type_manager
* The alias type manager.
*/
public function __construct(EntityFieldManagerInterface $entity_field_manager, AliasTypeManager $alias_type_manager) {
$this->entityFieldManager = $entity_field_manager;
@@ -133,14 +133,14 @@ class PathautoAdminDelete extends FormBase {
}
else if ($delete_all) {
\Drupal::service('pathauto.alias_storage_helper')->deleteAll();
drupal_set_message($this->t('All of your path aliases have been deleted.'));
$this->messenger()->addMessage($this->t('All of your path aliases have been deleted.'));
}
else {
$storage_helper = \Drupal::service('pathauto.alias_storage_helper');
foreach (array_keys(array_filter($form_state->getValue(['delete', 'plugins']))) as $id) {
$alias_type = $this->aliasTypeManager->createInstance($id);
$storage_helper->deleteBySourcePrefix((string) $alias_type->getSourcePrefix());
drupal_set_message($this->t('All of your %label path aliases have been deleted.', ['%label' => $alias_type->getLabel()]));
$this->messenger()->addMessage($this->t('All of your %label path aliases have been deleted.', ['%label' => $alias_type->getLabel()]));
}
}
}
@@ -168,17 +168,25 @@ class PathautoAdminDelete extends FormBase {
public static function batchFinished($success, $results, $operations) {
if ($success) {
if ($results['delete_all']) {
drupal_set_message(t('All of your automatically generated path aliases have been deleted.'));
\Drupal::service('messenger')
->addMessage(t('All of your automatically generated path aliases have been deleted.'));
}
else if (isset($results['deletions'])) {
foreach (array_values($results['deletions']) as $label) {
drupal_set_message(t('All of your automatically generated %label path aliases have been deleted.', ['%label' => $label]));
\Drupal::service('messenger')
->addMessage(t('All of your automatically generated %label path aliases have been deleted.', [
'%label' => $label,
]));
}
}
}
else {
$error_operation = reset($operations);
drupal_set_message(t('An error occurred while processing @operation with arguments : @args', array('@operation' => $error_operation[0], '@args' => print_r($error_operation[0], TRUE))));
\Drupal::service('messenger')
->addMessage(t('An error occurred while processing @operation with arguments : @args', [
'@operation' => $error_operation[0],
'@args' => print_r($error_operation[0]),
]));
}
}
@@ -149,15 +149,21 @@ class PathautoBulkUpdateForm extends FormBase {
public static function batchFinished($success, $results, $operations) {
if ($success) {
if ($results['updates']) {
drupal_set_message(\Drupal::translation()->formatPlural($results['updates'], 'Generated 1 URL alias.', 'Generated @count URL aliases.'));
\Drupal::service('messenger')->addMessage(\Drupal::translation()
->formatPlural($results['updates'], 'Generated 1 URL alias.', 'Generated @count URL aliases.'));
}
else {
drupal_set_message(t('No new URL aliases to generate.'));
\Drupal::service('messenger')
->addMessage(t('No new URL aliases to generate.'));
}
}
else {
$error_operation = reset($operations);
drupal_set_message(t('An error occurred while processing @operation with arguments : @args', array('@operation' => $error_operation[0], '@args' => print_r($error_operation[0], TRUE))));
\Drupal::service('messenger')
->addMessage(t('An error occurred while processing @operation with arguments : @args'), [
'@operation' => $error_operation[0],
'@args' => print_r($error_operation[0]),
]);
}
}
@@ -35,7 +35,7 @@ class PathautoSettingsForm extends ConfigFormBase {
protected $aliasTypeManager;
/**
* {@inheritDoc}
* {@inheritdoc}
*/
public function __construct(ConfigFactoryInterface $config_factory, EntityTypeManagerInterface $entity_type_manager, EntityFieldManagerInterface $entity_field_manager, AliasTypeManager $alias_type_manager) {
parent::__construct($config_factory);
@@ -45,7 +45,7 @@ class PathautoSettingsForm extends ConfigFormBase {
}
/**
* {@inheritDoc}
* {@inheritdoc}
*/
public static function create(ContainerInterface $container) {
return new static(
@@ -195,7 +195,13 @@ class PathautoSettingsForm extends ConfigFormBase {
'#title' => $this->t('Strings to Remove'),
'#default_value' => $config->get('ignore_words'),
'#description' => $this->t('Words to strip out of the URL alias, separated by commas. Do not use this to remove punctuation.'),
'#wysiwyg' => FALSE,
);
$form['safe_tokens'] = array(
'#type' => 'textarea',
'#title' => $this->t('Safe tokens'),
'#default_value' => implode(', ', $config->get('safe_tokens')),
'#description' => $this->t('List of tokens that are safe to use in alias patterns and do not need to be cleaned. For example urls, aliases, machine names. Separated with a comma.'),
);
$form['punctuation'] = array(
@@ -254,6 +260,9 @@ class PathautoSettingsForm extends ConfigFormBase {
}
$value = $enabled_entity_types;
}
elseif ($key == 'safe_tokens') {
$value = array_filter(array_map('trim', explode(',', $value)));
}
$config->set($key, $value);
}
$config->save();
@@ -44,7 +44,9 @@ class PatternDisableForm extends EntityConfirmFormBase {
*/
public function submitForm(array &$form, FormStateInterface $form_state) {
$this->entity->disable()->save();
drupal_set_message($this->t('Disabled pattern %label.', array('%label' => $this->entity->label())));
$this->messenger()->addMessage($this->t('Disabled pattern %label.', [
'%label' => $this->entity->label(),
]));
$form_state->setRedirectUrl($this->getCancelUrl());
}
@@ -16,6 +16,8 @@ use Symfony\Component\DependencyInjection\ContainerInterface;
class PatternEditForm extends EntityForm {
/**
* The alias type manager.
*
* @var \Drupal\pathauto\AliasTypeManager
*/
protected $manager;
@@ -33,11 +35,15 @@ class PatternEditForm extends EntityForm {
protected $entityTypeBundleInfo;
/**
* The entity manager service.
*
* @var \Drupal\Core\Entity\EntityTypeManagerInterface
*/
protected $entityTypeManager;
/**
* The language manager service.
*
* @var \Drupal\Core\Language\LanguageManagerInterface
*/
protected $languageManager;
@@ -58,9 +64,13 @@ class PatternEditForm extends EntityForm {
* PatternEditForm constructor.
*
* @param \Drupal\pathauto\AliasTypeManager $manager
* The alias type manager.
* @param \Drupal\Core\Entity\EntityTypeBundleInfoInterface $entity_type_bundle_info
* The entity type bundle info service.
* @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
* The entity manager service.
* @param \Drupal\Core\Language\LanguageManagerInterface $language_manager
* The language manager service.
*/
function __construct(AliasTypeManager $manager, EntityTypeBundleInfoInterface $entity_type_bundle_info, EntityTypeManagerInterface $entity_type_manager, LanguageManagerInterface $language_manager) {
$this->manager = $manager;
@@ -70,7 +80,7 @@ class PatternEditForm extends EntityForm {
}
/**
* {@inheritDoc}
* {@inheritdoc}
*/
public function buildForm(array $form, FormStateInterface $form_state) {
@@ -199,7 +209,7 @@ class PatternEditForm extends EntityForm {
}
/**
* {@inheritDoc}
* {@inheritdoc}
*/
public function buildEntity(array $form, FormStateInterface $form_state) {
/** @var \Drupal\pathauto\PathautoPatternInterface $entity */
@@ -259,11 +269,13 @@ class PatternEditForm extends EntityForm {
}
/**
* {@inheritDoc}
* {@inheritdoc}
*/
public function save(array $form, FormStateInterface $form_state) {
parent::save($form, $form_state);
drupal_set_message($this->t('Pattern @label saved.', ['@label' => $this->entity->label()]));
$this->messenger()->addMessage($this->t('Pattern %label saved.', [
'%label' => $this->entity->label(),
]));
$form_state->setRedirectUrl($this->entity->toUrl('collection'));
}
@@ -44,7 +44,9 @@ class PatternEnableForm extends EntityConfirmFormBase {
*/
public function submitForm(array &$form, FormStateInterface $form_state) {
$this->entity->enable()->save();
drupal_set_message($this->t('Enabled pattern %label.', array('%label' => $this->entity->label())));
$this->messenger()->addMessage($this->t('Enabled pattern %label.', [
'%label' => $this->entity->label(),
]));
$form_state->setRedirectUrl($this->getCancelUrl());
}
@@ -7,7 +7,7 @@ use Drupal\path\Plugin\Field\FieldType\PathFieldItemList;
class PathautoFieldItemList extends PathFieldItemList {
/**
* @inheritDoc
* @{inheritdoc}
*/
protected function delegateMethod($method) {
// @todo Workaround until this is fixed, see
@@ -27,7 +27,7 @@ class PathautoFieldItemList extends PathFieldItemList {
}
/**
* @inheritDoc
* @{inheritdoc}
*/
protected function computeValue() {
parent::computeValue();
@@ -38,12 +38,4 @@ class PathautoFieldItemList extends PathFieldItemList {
}
}
/**
* @inheritDoc
*/
public function delete() {
\Drupal::service('pathauto.alias_storage_helper')->deleteEntityPathAll($this->getEntity());
$this->first()->get('pathauto')->purge();
}
}
@@ -2,7 +2,6 @@
namespace Drupal\pathauto;
use Drupal\Component\Utility\Unicode;
use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\Entity\ContentEntityInterface;
use Drupal\Core\Entity\EntityInterface;
@@ -87,12 +86,16 @@ class PathautoGenerator implements PathautoGeneratorInterface {
protected $messenger;
/**
* The token entity mapper.
*
* @var \Drupal\token\TokenEntityMapperInterface
*/
protected $tokenEntityMapper;
/**
* @var Drupal\Core\Entity\EntityTypeManagerInterface
* The entity type manager.
*
* @var \Drupal\Core\Entity\EntityTypeManagerInterface
*/
protected $entityTypeManager;
@@ -115,10 +118,12 @@ class PathautoGenerator implements PathautoGeneratorInterface {
* The messenger service.
* @param \Drupal\Core\StringTranslation\TranslationInterface $string_translation
* The string translation service.
* @param Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
* The entity type manager
* @param \Drupal\token\TokenEntityMapperInterface $token_entity_mapper
* The token entity mapper.
* @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
* The entity type manager.
*/
public function __construct(ConfigFactoryInterface $config_factory, ModuleHandlerInterface $module_handler, Token $token, AliasCleanerInterface $alias_cleaner, AliasStorageHelperInterface $alias_storage_helper, AliasUniquifierInterface $alias_uniquifier, MessengerInterface $messenger, TranslationInterface $string_translation, TokenEntityMapperInterface $token_entity_mappper, EntityTypeManagerInterface $entity_type_manager) {
public function __construct(ConfigFactoryInterface $config_factory, ModuleHandlerInterface $module_handler, Token $token, AliasCleanerInterface $alias_cleaner, AliasStorageHelperInterface $alias_storage_helper, AliasUniquifierInterface $alias_uniquifier, MessengerInterface $messenger, TranslationInterface $string_translation, TokenEntityMapperInterface $token_entity_mapper, EntityTypeManagerInterface $entity_type_manager) {
$this->configFactory = $config_factory;
$this->moduleHandler = $module_handler;
$this->token = $token;
@@ -127,7 +132,7 @@ class PathautoGenerator implements PathautoGeneratorInterface {
$this->aliasUniquifier = $alias_uniquifier;
$this->messenger = $messenger;
$this->stringTranslation = $string_translation;
$this->tokenEntityMapper = $token_entity_mappper;
$this->tokenEntityMapper = $token_entity_mapper;
$this->entityTypeManager = $entity_type_manager;
}
@@ -165,8 +170,9 @@ class PathautoGenerator implements PathautoGeneratorInterface {
'bundle' => $entity->bundle(),
'language' => &$langcode,
);
// @todo Is still hook still useful?
$pattern_original = $pattern->getPattern();
$this->moduleHandler->alter('pathauto_pattern', $pattern, $context);
$pattern_altered = $pattern->getPattern();
// Special handling when updating an item which is already aliased.
$existing_alias = NULL;
@@ -209,7 +215,7 @@ class PathautoGenerator implements PathautoGeneratorInterface {
$this->moduleHandler->alter('pathauto_alias', $alias, $context);
// If we have arrived at an empty string, discontinue.
if (!Unicode::strlen($alias)) {
if (!mb_strlen($alias)) {
return NULL;
}
@@ -236,11 +242,19 @@ class PathautoGenerator implements PathautoGeneratorInterface {
'language' => $langcode,
);
return $this->aliasStorageHelper->save($path, $existing_alias, $op);
$return = $this->aliasStorageHelper->save($path, $existing_alias, $op);
// Because there is no way to set an altered pattern to not be cached,
// change it back to the original value.
if ($pattern_altered !== $pattern_original) {
$pattern->setPattern($pattern_original);
}
return $return;
}
/**
* Loads pathauto patterns for a given entity type ID
* Loads pathauto patterns for a given entity type ID.
*
* @param string $entity_type_id
* An entity type ID.
@@ -335,7 +349,7 @@ class PathautoGenerator implements PathautoGeneratorInterface {
$result = $this->createEntityAlias($entity, $op);
}
catch (\InvalidArgumentException $e) {
drupal_set_message($e->getMessage(), 'error');
$this->messenger->addError($e->getMessage());
return NULL;
}
@@ -49,6 +49,7 @@ interface PathautoGeneratorInterface {
*
* @param \Drupal\Core\Entity\EntityInterface $entity
* An entity.
*
* @return \Drupal\pathauto\PathautoPatternInterface|null
*/
public function getPatternByEntity(EntityInterface $entity);
@@ -33,9 +33,6 @@ class PathautoItem extends PathItem {
if ($this->pathauto == PathautoState::SKIP) {
parent::postSave($update);
}
else {
\Drupal::service('pathauto.generator')->updateEntityAlias($this->getEntity(), $update ? 'update' : 'insert');
}
$this->get('pathauto')->persist();
}
@@ -88,6 +88,7 @@ class PathautoState extends TypedData {
/**
* Returns the key value collection that should be used for the given entity.
*
* @return string
*/
protected function getCollection() {
@@ -26,6 +26,8 @@ class EntityAliasTypeDeriver extends DeriverBase implements ContainerDeriverInte
protected $entityTypeManager;
/**
* The entity field manager.
*
* @var \Drupal\Core\Entity\EntityFieldManagerInterface
*/
protected $entityFieldManager;
@@ -44,7 +46,7 @@ class EntityAliasTypeDeriver extends DeriverBase implements ContainerDeriverInte
* The entity field manager.
* @param \Drupal\Core\StringTranslation\TranslationInterface $string_translation
* The string translation service.
* @apram \Drupal\Token\TokenEntityMapperInterface $token_entity_mapper
* @param \Drupal\Token\TokenEntityMapperInterface $token_entity_mapper
* The token entity mapper.
*/
public function __construct(EntityTypeManagerInterface $entity_type_manager, EntityFieldManagerInterface $entity_field_manager, TranslationInterface $string_translation, TokenEntityMapperInterface $token_entity_mapper) {
@@ -11,6 +11,7 @@ use Drupal\Core\Language\LanguageManagerInterface;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Drupal\Core\Plugin\Context\Context;
use Drupal\Core\Plugin\ContextAwarePluginBase;
use Drupal\Core\Messenger\MessengerTrait;
use Drupal\pathauto\AliasTypeBatchUpdateInterface;
use Drupal\pathauto\AliasTypeInterface;
use Drupal\pathauto\PathautoState;
@@ -26,6 +27,8 @@ use Symfony\Component\DependencyInjection\ContainerInterface;
*/
class EntityAliasTypeBase extends ContextAwarePluginBase implements AliasTypeInterface, AliasTypeBatchUpdateInterface, ContainerFactoryPluginInterface {
use MessengerTrait;
/**
* The module handler service.
*
@@ -151,12 +154,15 @@ class EntityAliasTypeBase extends ContextAwarePluginBase implements AliasTypeInt
case 'create':
$query->isNull('ua.source');
break;
case 'update':
$query->isNotNull('ua.source');
break;
case 'all':
// Nothing to do. We want all paths.
break;
default:
// Unknown action. Abort!
return;
@@ -182,7 +188,7 @@ class EntityAliasTypeBase extends ContextAwarePluginBase implements AliasTypeInt
$updates = $this->bulkUpdate($ids);
$context['sandbox']['count'] += count($ids);
$context['sandbox']['current'] = max($ids);
$context['sandbox']['current'] = !empty($ids) ? max($ids) : 0;
$context['results']['updates'] += $updates;
$context['message'] = $this->t('Updated alias for %label @id.', array('%label' => $entity_type->getLabel(), '@id' => end($ids)));
@@ -255,7 +261,7 @@ class EntityAliasTypeBase extends ContextAwarePluginBase implements AliasTypeInt
* An optional array of additional options.
*
* @return int
* The number of updated URL aliases.
* The number of updated URL aliases.
*/
protected function bulkUpdate(array $ids, array $options = array()) {
$options += array('message' => FALSE);
@@ -274,7 +280,10 @@ class EntityAliasTypeBase extends ContextAwarePluginBase implements AliasTypeInt
}
if (!empty($options['message'])) {
drupal_set_message(\Drupal::translation()->formatPlural(count($ids), 'Updated 1 %label URL alias.', 'Updated @count %label URL aliases.'), array('%label' => $this->getLabel()));
$this->messenger->addMessage($this->translationManager
->formatPlural(count($ids), 'Updated 1 %label URL alias.', 'Updated @count %label URL aliases.'), [
'%label' => $this->getLabel(),
]);
}
return $updates;
@@ -330,5 +339,4 @@ class EntityAliasTypeBase extends ContextAwarePluginBase implements AliasTypeInt
return $this;
}
}
@@ -44,7 +44,7 @@ class PathautoBulkUpdateTest extends WebTestBase {
protected $patterns;
/**
* {inheritdoc}
* {@inheritdoc}
*/
function setUp() {
parent::setUp();
@@ -103,7 +103,7 @@ class PathautoBulkUpdateTest extends WebTestBase {
$this->assertText('No new URL aliases to generate.');
$this->assertNoEntityAliasExists($new_node);
// Make sure existing aliases can be overriden.
// Make sure existing aliases can be overridden.
$this->drupalPostForm('admin/config/search/path/settings', ['update_action' => PathautoGeneratorInterface::UPDATE_ACTION_DELETE], t('Save configuration'));
// Patterns did not change, so no aliases should be regenerated.
@@ -111,16 +111,17 @@ class PathautoBulkUpdateTest extends WebTestBase {
$this->drupalPostForm('admin/config/search/path/update_bulk', $edit, t('Update'));
$this->assertText('No new URL aliases to generate.');
// Update the node pattern, and leave other patterns alone. Existing nodes should get a new alias,
// except the node above whose alias is manually set. Other aliases must be left alone.
// Update the node pattern, and leave other patterns alone. Existing nodes
// should get a new alias, except the node above whose alias is manually
// set. Other aliases must be left alone.
$this->patterns['node']->delete();
$this->patterns['node'] = $this->createPattern('node', '/archive/node-[node:nid]');
$this->drupalPostForm('admin/config/search/path/update_bulk', $edit, t('Update'));
$this->assertText('Generated 5 URL aliases.');
// Prevent existing aliases to be overriden. The bulk generate page should only offer
// to create an alias for paths which have none.
// Prevent existing aliases to be overridden. The bulk generate page should
// only offer to create an alias for paths which have none.
$this->drupalPostForm('admin/config/search/path/settings', ['update_action' => PathautoGeneratorInterface::UPDATE_ACTION_NO_NEW], t('Save configuration'));
$this->drupalGet('admin/config/search/path/update_bulk');
@@ -13,6 +13,7 @@ use Drupal\comment\Tests\CommentTestTrait;
class PathautoEnablingEntityTypesTest extends WebTestBase {
use PathautoTestHelperTrait;
use CommentTestTrait;
/**
@@ -30,7 +31,7 @@ class PathautoEnablingEntityTypesTest extends WebTestBase {
protected $adminUser;
/**
* {inheritdoc}
* {@inheritdoc}
*/
function setUp() {
parent::setUp();
@@ -49,9 +49,8 @@ class PathautoMassDeleteTest extends WebTestBase {
*/
protected $terms;
/**
* {inheritdoc}
* {@inheritdoc}
*/
function setUp() {
parent::setUp();
@@ -136,14 +135,16 @@ class PathautoMassDeleteTest extends WebTestBase {
* Helper function to generate aliases.
*/
function generateAliases() {
// Delete all aliases to avoid duplicated aliases. They will be recreated below.
// Delete all aliases to avoid duplicated aliases. They will be recreated
// below.
$this->deleteAllAliases();
// We generate a bunch of aliases for nodes, users and taxonomy terms. If
// the entities are already created we just update them, otherwise we create
// them.
if (empty($this->nodes)) {
// Create a large number of nodes (100+) to make sure that the batch code works.
// Create a large number of nodes (100+) to make sure that the batch code
// works.
for ($i = 1; $i <= 105; $i++) {
// Set the alias of two nodes manually.
$settings = ($i > 103) ? ['path' => ['alias' => "/custom_alias_$i", 'pathauto' => PathautoState::SKIP]] : [];
@@ -1,6 +1,7 @@
<?php
namespace Drupal\pathauto\Tests;
use Drupal\pathauto\Entity\PathautoPattern;
use Drupal\node\Entity\Node;
use Drupal\pathauto\PathautoState;
@@ -30,7 +31,7 @@ class PathautoNodeWebTest extends WebTestBase {
protected $adminUser;
/**
* {inheritdoc}
* {@inheritdoc}
*/
function setUp() {
parent::setUp();
@@ -56,7 +57,8 @@ class PathautoNodeWebTest extends WebTestBase {
* Tests editing nodes with different settings.
*/
function testNodeEditing() {
// Ensure that the Pathauto checkbox is checked by default on the node add form.
// Ensure that the Pathauto checkbox is checked by default on the node add
// form.
$this->drupalGet('node/add/page');
$this->assertFieldChecked('edit-path-0-pathauto');
@@ -85,7 +85,7 @@ class PathautoSettingsFormWebTest extends WebTestBase {
);
/**
* {inheritdoc}
* {@inheritdoc}
*/
function setUp() {
parent::setUp();
@@ -27,7 +27,7 @@ class PathautoTaxonomyWebTest extends WebTestBase {
protected $adminUser;
/**
* {inheritdoc}
* {@inheritdoc}
*/
function setUp() {
parent::setUp();
@@ -45,7 +45,6 @@ class PathautoTaxonomyWebTest extends WebTestBase {
$this->createPattern('taxonomy_term', '/[term:vocabulary]/[term:name]');
}
/**
* Basic functional testing of Pathauto with taxonomy terms.
*/
@@ -2,7 +2,6 @@
namespace Drupal\pathauto\Tests;
use Drupal\Component\Utility\Unicode;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Language\Language;
use Drupal\Core\Render\BubbleableMetadata;
@@ -34,7 +33,7 @@ trait PathautoTestHelperTrait {
$type = ($entity_type_id == 'forum') ? 'forum' : 'canonical_entities:' . $entity_type_id;
$pattern = PathautoPattern::create([
'id' => Unicode::strtolower($this->randomMachineName()),
'id' => mb_strtolower($this->randomMachineName()),
'type' => $type,
'pattern' => $pattern,
'weight' => $weight,
@@ -51,7 +50,7 @@ trait PathautoTestHelperTrait {
* @param string $entity_type
* The entity type ID.
* @param string $bundle
* The bundle
* The bundle.
*/
protected function addBundleCondition(PathautoPatternInterface $pattern, $entity_type, $bundle) {
$plugin_id = $entity_type == 'node' ? 'node_type' : 'entity_bundle:' . $entity_type;
@@ -142,10 +141,11 @@ trait PathautoTestHelperTrait {
/**
* @param array $values
*
* @return \Drupal\taxonomy\VocabularyInterface
*/
public function addVocabulary(array $values = array()) {
$name = Unicode::strtolower($this->randomMachineName(5));
$name = mb_strtolower($this->randomMachineName(5));
$values += array(
'name' => $name,
'vid' => $name,
@@ -158,7 +158,7 @@ trait PathautoTestHelperTrait {
public function addTerm(VocabularyInterface $vocabulary, array $values = array()) {
$values += array(
'name' => Unicode::strtolower($this->randomMachineName(5)),
'name' => mb_strtolower($this->randomMachineName(5)),
'vid' => $vocabulary->id(),
);
@@ -30,7 +30,7 @@ class PathautoUiTest extends WebTestBase {
protected $adminUser;
/**
* {inheritdoc}
* {@inheritdoc}
*/
function setUp() {
parent::setUp();
@@ -1,7 +1,7 @@
<?php
namespace Drupal\pathauto\Tests;
use Drupal\Component\Utility\Unicode;
use Drupal\simpletest\WebTestBase;
use Drupal\views\Views;
@@ -29,7 +29,7 @@ class PathautoUserWebTest extends WebTestBase {
protected $adminUser;
/**
* {inheritdoc}
* {@inheritdoc}
*/
function setUp() {
parent::setUp();
@@ -47,7 +47,6 @@ class PathautoUserWebTest extends WebTestBase {
$this->createPattern('user', '/users/[user:name]');
}
/**
* Basic functional testing of Pathauto with users.
*/
@@ -71,7 +70,6 @@ class PathautoUserWebTest extends WebTestBase {
$view->initDisplay();
$view->preview('page_1');
foreach ($view->result as $key => $row) {
if ($view->field['name']->getValue($row) == $account->getUsername()) {
break;
@@ -85,7 +83,7 @@ class PathautoUserWebTest extends WebTestBase {
$this->drupalPostForm('admin/people', $edit, t('Apply to selected items'));
$this->assertText('Update URL alias was applied to 1 item.');
$this->assertEntityAlias($account, '/users/' . Unicode::strtolower($account->getUsername()));
$this->assertEntityAlias($account, '/users/' . mb_strtolower($account->getUsername()));
$this->assertEntityAlias($this->adminUser, '/user/' . $this->adminUser->id());
}
@@ -3,6 +3,7 @@
namespace Drupal\pathauto;
use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\Messenger\MessengerInterface as CoreMessengerInterface;
use Drupal\Core\Session\AccountInterface;
/**
@@ -32,11 +33,26 @@ class VerboseMessenger implements MessengerInterface {
protected $account;
/**
* Creates a verbose messenger.
* The messenger service.
*
* @var \Drupal\Core\Messenger\MessengerInterface
*/
public function __construct(ConfigFactoryInterface $config_factory, AccountInterface $account) {
protected $messenger;
/**
* Creates a verbose messenger.
*
* @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
* The config factory.
* @param \Drupal\Core\Session\AccountInterface $account
* The current user account.
* @param \Drupal\Core\Messenger\MessengerInterface $messenger
* The messenger service.
*/
public function __construct(ConfigFactoryInterface $config_factory, AccountInterface $account, CoreMessengerInterface $messenger) {
$this->configFactory = $config_factory;
$this->account = $account;
$this->messenger = $messenger;
}
/**
@@ -54,7 +70,7 @@ class VerboseMessenger implements MessengerInterface {
}
if ($message) {
drupal_set_message($message);
$this->messenger->addMessage($message);
}
return TRUE;
@@ -6,8 +6,8 @@ package: Testing
dependencies:
- token
# Information added by Drupal.org packaging script on 2018-03-03
version: '8.x-1.1'
# Information added by Drupal.org packaging script on 2018-09-08
version: '8.x-1.3'
core: '8.x'
project: 'pathauto'
datestamp: 1520092688
datestamp: 1536407890
@@ -7,8 +7,8 @@ package: Testing
dependencies:
- views
# Information added by Drupal.org packaging script on 2018-03-03
version: '8.x-1.1'
# Information added by Drupal.org packaging script on 2018-09-08
version: '8.x-1.3'
core: '8.x'
project: 'pathauto'
datestamp: 1520092688
datestamp: 1536407890
@@ -61,7 +61,7 @@ class PathautoEntityWithStringIdTest extends KernelTestBase {
protected function setUp() {
parent::setUp();
$this->installSchema('system', ['key_value']);
$this->installConfig(['system']);
$this->installConfig(['system', 'pathauto']);
$this->installEntitySchema('pathauto_string_id_test');
$this->createPattern('pathauto_string_id_test', '/[pathauto_string_id_test:name]');
/** @var \Drupal\pathauto\AliasTypeManager $alias_type_manager */
@@ -87,7 +87,7 @@ class PathautoEntityWithStringIdTest extends KernelTestBase {
$entity->save();
// Check that the path was generated.
$this->assertEntityAlias($entity, "/$name");
$this->assertEntityAlias($entity, mb_strtolower("/$name"));
// Check that the path auto state was saved with the expected key.
$value = \Drupal::keyValue('pathauto_state.pathauto_string_id_test')->get($expected_key);
$this->assertEquals(PathautoState::CREATE, $value);
@@ -3,7 +3,6 @@
namespace Drupal\Tests\pathauto\Kernel;
use Drupal\Component\Utility\Html;
use Drupal\Component\Utility\Unicode;
use Drupal\Core\Language\Language;
use Drupal\Core\Language\LanguageInterface;
use Drupal\language\Entity\ConfigurableLanguage;
@@ -285,7 +284,7 @@ class PathautoKernelTest extends KernelTestBase {
$this->assertEntityAlias($node, '/content/second-title');
$this->assertNoAliasExists(array('alias' => '/content/first-title'));
// Test PATHAUTO_UPDATE_ACTION_LEAVE
// Test PATHAUTO_UPDATE_ACTION_LEAVE.
$config->set('update_action', PathautoGeneratorInterface::UPDATE_ACTION_LEAVE);
$config->save();
$node->setTitle('Third title');
@@ -323,8 +322,8 @@ class PathautoKernelTest extends KernelTestBase {
}
/**
* Test that \Drupal::service('pathauto.generator')->createEntityAlias() will not create an alias for a pattern
* that does not get any tokens replaced.
* Test that \Drupal::service('pathauto.generator')->createEntityAlias() will
* not create an alias for a pattern that does not get any tokens replaced.
*/
public function testNoTokensNoAlias() {
$this->installConfig(['filter']);
@@ -365,12 +364,11 @@ class PathautoKernelTest extends KernelTestBase {
function testParentChildPathTokens() {
// First create a field which will be used to create the path. It must
// begin with a letter.
$this->installEntitySchema('taxonomy_term');
Vocabulary::create(['vid' => 'tags'])->save();
$fieldname = 'a' . Unicode::strtolower($this->randomMachineName());
$fieldname = 'a' . mb_strtolower($this->randomMachineName());
$field_storage = FieldStorageConfig::create(['entity_type' => 'taxonomy_term', 'field_name' => $fieldname, 'type' => 'string']);
$field_storage->save();
$field = FieldConfig::create(['field_storage' => $field_storage, 'bundle' => 'tags']);
@@ -391,11 +389,11 @@ class PathautoKernelTest extends KernelTestBase {
// Create the child term.
$child = Term::create(['vid' => 'tags', $fieldname => $this->randomMachineName(), 'parent' => $parent, 'name' => $this->randomMachineName()]);
$child->save();
$this->assertEntityAlias($child, '/' . Unicode::strtolower($parent->getName() . '/' . $child->$fieldname->value));
$this->assertEntityAlias($child, '/' . mb_strtolower($parent->getName() . '/' . $child->$fieldname->value));
// Re-saving the parent term should not modify the child term's alias.
$parent->save();
$this->assertEntityAlias($child, '/' . Unicode::strtolower($parent->getName() . '/' . $child->$fieldname->value));
$this->assertEntityAlias($child, '/' . mb_strtolower($parent->getName() . '/' . $child->$fieldname->value));
}
/**
@@ -506,7 +504,7 @@ class PathautoKernelTest extends KernelTestBase {
}
/**
* Tests that enabled entity types genrates the necessary fields and plugins.
* Tests that enabled entity types generates the necessary fields and plugins.
*/
public function testSettingChangeInvalidatesCache() {
@@ -39,6 +39,42 @@ class PathautoTokenTest extends KernelTestBase {
$alias_cleaner = \Drupal::service('pathauto.alias_cleaner');
$alias_cleaner->cleanTokenValues($replacements, $data, array());
$this->assertEqual($replacements['[array:join-path]'], 'test-first-arg/array-value');
// Test additional token cleaning and its configuration.
$safe_tokens = $this->config('pathauto.settings')->get('safe_tokens');
$safe_tokens[] = 'safe';
$this->config('pathauto.settings')
->set('safe_tokens', $safe_tokens)
->save();
$safe_tokens = [
'[example:path]',
'[example:url]',
'[example:url-brief]',
'[example:login-url]',
'[example:login-url:relative]',
'[example:url:relative]',
'[example:safe]',
];
$unsafe_tokens = [
'[example:path_part]',
'[example:something_url]',
'[example:unsafe]',
];
foreach ($safe_tokens as $token) {
$replacements = [
$token => 'this/is/a/path',
];
$alias_cleaner->cleanTokenValues($replacements);
$this->assertEquals('this/is/a/path', $replacements[$token], "Token $token cleaned.");
}
foreach ($unsafe_tokens as $token) {
$replacements = [
$token => 'This is not a / path',
];
$alias_cleaner->cleanTokenValues($replacements);
$this->assertEquals('not-path', $replacements[$token], "Token $token not cleaned.");
}
}
/**
@@ -1,59 +1,54 @@
<?php
namespace Drupal\Tests\pathauto\Unit {
namespace Drupal\Tests\pathauto\Unit;
use Drupal\pathauto\VerboseMessenger;
use Drupal\Tests\UnitTestCase;
use Drupal\Core\Messenger\MessengerInterface;
use Drupal\Core\Session\AccountInterface;
use Drupal\pathauto\VerboseMessenger;
use Drupal\Tests\UnitTestCase;
/**
* @coversDefaultClass \Drupal\pathauto\VerboseMessenger
* @group pathauto
*/
class VerboseMessengerTest extends UnitTestCase {
/**
* @coversDefaultClass \Drupal\pathauto\VerboseMessenger
* @group pathauto
* The messenger under test.
*
* @var \Drupal\pathauto\VerboseMessenger
*/
class VerboseMessengerTest extends UnitTestCase {
protected $messenger;
/**
* The messenger under test.
*
* @var \Drupal\pathauto\VerboseMessenger
*/
protected $messenger;
/**
* {@inheritdoc}
*/
protected function setUp() {
$config_factory = $this->getConfigFactoryStub(['pathauto.settings' => ['verbose' => TRUE]]);
$account = $this->createMock(AccountInterface::class);
$account->expects($this->once())
->method('hasPermission')
->withAnyParameters()
->willReturn(TRUE);
$messenger = $this->createMock(MessengerInterface::class);
/**
* {@inheritdoc}
*/
protected function setUp() {
$config_factory = $this->getConfigFactoryStub(array('pathauto.settings' => array('verbose' => TRUE)));
$account = $this->getMock('\Drupal\Core\Session\AccountInterface');
$account->expects($this->once())
->method('hasPermission')
->withAnyParameters()
->willReturn(TRUE);
$this->messenger = new VerboseMessenger($config_factory, $account);
}
/**
* Tests add messages.
* @covers ::addMessage
*/
public function testAddMessage() {
$this->assertTrue($this->messenger->addMessage("Test message"), "The message was added");
}
/**
* @covers ::addMessage
*/
public function testDoNotAddMessageWhileBulkupdate() {
$this->assertFalse($this->messenger->addMessage("Test message", "bulkupdate"), "The message was NOT added");
}
}
}
namespace {
// @todo Delete after https://drupal.org/node/1858196 is in.
if (!function_exists('drupal_set_message')) {
function drupal_set_message() {
}
$this->messenger = new VerboseMessenger($config_factory, $account, $messenger);
}
/**
* Tests add messages.
*
* @covers ::addMessage
*/
public function testAddMessage() {
$this->assertTrue($this->messenger->addMessage("Test message"), "The message was added");
}
/**
* @covers ::addMessage
*/
public function testDoNotAddMessageWhileBulkupdate() {
$this->assertFalse($this->messenger->addMessage("Test message", "bulkupdate"), "The message was NOT added");
}
}