Update Composer, update everything
This commit is contained in:
parent
ea3e94409f
commit
dda5c284b6
19527 changed files with 1135420 additions and 351004 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 2017-04-29
|
||||
version: '8.x-1.0'
|
||||
# Information added by Drupal.org packaging script on 2018-09-08
|
||||
version: '8.x-1.3'
|
||||
core: '8.x'
|
||||
project: 'pathauto'
|
||||
datestamp: 1493468049
|
||||
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
|
||||
|
||||
|
|
|
@ -25,7 +25,8 @@ use Drupal\Core\Field\BaseFieldDefinition;
|
|||
use Drupal\Core\Form\FormStateInterface;
|
||||
use Drupal\Core\Routing\RouteMatchInterface;
|
||||
use Drupal\Core\Url;
|
||||
use Drupal\pathauto\PathautoState;
|
||||
use Drupal\pathauto\PathautoFieldItemList;
|
||||
use Drupal\pathauto\PathautoItem;
|
||||
|
||||
/**
|
||||
* The default ignore word list.
|
||||
|
@ -98,12 +99,12 @@ function pathauto_entity_update(EntityInterface $entity) {
|
|||
}
|
||||
|
||||
/**
|
||||
* Implements hook_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->path->first()->get('pathauto')->purge();
|
||||
$entity->get('path')->first()->get('pathauto')->purge();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -111,7 +112,8 @@ function pathauto_entity_delete(EntityInterface $entity) {
|
|||
* Implements hook_field_info_alter().
|
||||
*/
|
||||
function pathauto_field_info_alter(&$info) {
|
||||
$info['path']['class'] = '\Drupal\pathauto\PathautoItem';
|
||||
$info['path']['class'] = PathautoItem::class;
|
||||
$info['path']['list_class'] = PathautoFieldItemList::class;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -146,17 +148,6 @@ function pathauto_entity_base_field_info(EntityTypeInterface $entity_type) {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_entity_base_field_info_alter().
|
||||
*/
|
||||
function pathauto_entity_base_field_info_alter(&$fields, EntityTypeInterface $entity_type) {
|
||||
if (isset($fields['path'])) {
|
||||
// Path fields need to be computed so that the pathauto state can be
|
||||
// accessed even if there is no alias being set.
|
||||
$fields['path']->setComputed(TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate the pattern field, to ensure it doesn't contain any characters that
|
||||
* are invalid in URLs.
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@ use Drupal\Component\Plugin\Exception\ContextException;
|
|||
use Drupal\Core\Condition\ConditionPluginCollection;
|
||||
use Drupal\Core\Config\Entity\ConfigEntityBase;
|
||||
use Drupal\Core\Entity\EntityStorageInterface;
|
||||
use Drupal\Core\Plugin\Context\Context;
|
||||
use Drupal\Core\Plugin\ContextAwarePluginInterface;
|
||||
use Drupal\Core\Plugin\DefaultSingleLazyPluginCollection;
|
||||
use Drupal\pathauto\PathautoPatternInterface;
|
||||
|
@ -345,6 +346,17 @@ class PathautoPattern extends ConfigEntityBase implements PathautoPatternInterfa
|
|||
$context_handler = \Drupal::service('context.handler');
|
||||
$conditions = $this->getSelectionConditions();
|
||||
foreach ($conditions as $condition) {
|
||||
|
||||
// As the context object is kept and only the value is switched out,
|
||||
// it can over time grow to a huge number of cache contexts. Reset it
|
||||
// if there are 100 cache tags to prevent cache tag merging getting too
|
||||
// slow.
|
||||
foreach ($condition->getContextDefinitions() as $name => $context_definition) {
|
||||
if (count($condition->getContext($name)->getCacheTags()) > 100) {
|
||||
$condition->setContext($name, new Context($context_definition));
|
||||
}
|
||||
}
|
||||
|
||||
if ($condition instanceof ContextAwarePluginInterface) {
|
||||
try {
|
||||
$context_handler->applyContextMapping($condition, $contexts);
|
||||
|
|
|
@ -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,14 +195,19 @@ 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(
|
||||
'#type' => 'fieldset',
|
||||
'#type' => 'details',
|
||||
'#title' => $this->t('Punctuation'),
|
||||
'#collapsible' => TRUE,
|
||||
'#collapsed' => TRUE,
|
||||
'#open' => FALSE,
|
||||
'#tree' => TRUE,
|
||||
);
|
||||
|
||||
|
@ -241,7 +246,6 @@ class PathautoSettingsForm extends ConfigFormBase {
|
|||
|
||||
$form_state->cleanValues();
|
||||
|
||||
$original_entity_types = $config->get('enabled_entity_types');
|
||||
foreach ($form_state->getValues() as $key => $value) {
|
||||
if ($key == 'enabled_entity_types') {
|
||||
$enabled_entity_types = [];
|
||||
|
@ -256,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());
|
||||
}
|
||||
|
|
41
web/modules/contrib/pathauto/src/PathautoFieldItemList.php
Normal file
41
web/modules/contrib/pathauto/src/PathautoFieldItemList.php
Normal file
|
@ -0,0 +1,41 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\pathauto;
|
||||
|
||||
use Drupal\path\Plugin\Field\FieldType\PathFieldItemList;
|
||||
|
||||
class PathautoFieldItemList extends PathFieldItemList {
|
||||
|
||||
/**
|
||||
* @{inheritdoc}
|
||||
*/
|
||||
protected function delegateMethod($method) {
|
||||
// @todo Workaround until this is fixed, see
|
||||
// https://www.drupal.org/project/drupal/issues/2946289.
|
||||
$this->ensureComputedValue();
|
||||
|
||||
// Duplicate the logic instead of calling the parent due to the dynamic
|
||||
// arguments.
|
||||
$result = [];
|
||||
$args = array_slice(func_get_args(), 1);
|
||||
foreach ($this->list as $delta => $item) {
|
||||
// call_user_func_array() is way slower than a direct call so we avoid
|
||||
// using it if have no parameters.
|
||||
$result[$delta] = $args ? call_user_func_array([$item, $method], $args) : $item->{$method}();
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @{inheritdoc}
|
||||
*/
|
||||
protected function computeValue() {
|
||||
parent::computeValue();
|
||||
|
||||
// For a new entity, default to creating a new alias.
|
||||
if ($this->getEntity()->isNew()) {
|
||||
$this->list[0]->set('pathauto', PathautoState::CREATE);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -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);
|
||||
|
|
|
@ -45,14 +45,4 @@ class PathautoItem extends PathItem {
|
|||
return !$this->alias && !$this->get('pathauto')->hasValue();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function applyDefaultValue($notify = TRUE) {
|
||||
parent::applyDefaultValue($notify);
|
||||
// Created fields default creating a new alias.
|
||||
$this->setValue(array('pathauto' => PathautoState::CREATE), $notify);
|
||||
return $this;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\pathauto;
|
||||
|
||||
use Drupal\Component\Utility\Crypt;
|
||||
use Drupal\Core\TypedData\TypedData;
|
||||
|
||||
/**
|
||||
|
@ -38,7 +40,7 @@ class PathautoState extends TypedData {
|
|||
// If no value has been set or loaded yet, try to load a value if this
|
||||
// entity has already been saved.
|
||||
$this->value = \Drupal::keyValue($this->getCollection())
|
||||
->get($this->parent->getEntity()->id());
|
||||
->get(static::getPathautoStateKey($this->parent->getEntity()->id()));
|
||||
// If it was not yet saved or no value was found, then set the flag to
|
||||
// create the alias if there is a matching pattern.
|
||||
if ($this->value === NULL) {
|
||||
|
@ -72,10 +74,8 @@ class PathautoState extends TypedData {
|
|||
* Persists the state.
|
||||
*/
|
||||
public function persist() {
|
||||
\Drupal::keyValue($this->getCollection())->set(
|
||||
$this->parent->getEntity()
|
||||
->id(), $this->value
|
||||
);
|
||||
\Drupal::keyValue($this->getCollection())
|
||||
->set(static::getPathautoStateKey($this->parent->getEntity()->id()), $this->getValue());
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -83,15 +83,77 @@ class PathautoState extends TypedData {
|
|||
*/
|
||||
public function purge() {
|
||||
\Drupal::keyValue($this->getCollection())
|
||||
->delete($this->parent->getEntity()->id());
|
||||
->delete(static::getPathautoStateKey($this->parent->getEntity()->id()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the key value collection that should be used for the given entity.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function getCollection() {
|
||||
return 'pathauto_state.' . $this->parent->getEntity()->getEntityTypeId();
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes the URL aliases for multiple entities of the same type.
|
||||
*
|
||||
* @param string $entity_type_id
|
||||
* The entity type ID of entities being deleted.
|
||||
* @param int[] $pids_by_id
|
||||
* A list of path IDs keyed by entity ID.
|
||||
*/
|
||||
public static function bulkDelete($entity_type_id, array $pids_by_id) {
|
||||
foreach ($pids_by_id as $id => $pid) {
|
||||
// Some key-values store entries have computed keys.
|
||||
$key = static::getPathautoStateKey($id);
|
||||
if ($key !== $id) {
|
||||
$pids_by_id[$key] = $pid;
|
||||
unset($pids_by_id[$id]);
|
||||
}
|
||||
}
|
||||
$states = \Drupal::keyValue("pathauto_state.$entity_type_id")
|
||||
->getMultiple(array_keys($pids_by_id));
|
||||
|
||||
$pids = [];
|
||||
foreach ($pids_by_id as $id => $pid) {
|
||||
// Only delete aliases that were created by this module.
|
||||
if (isset($states[$id]) && $states[$id] == PathautoState::CREATE) {
|
||||
$pids[] = $pid;
|
||||
}
|
||||
}
|
||||
\Drupal::service('pathauto.alias_storage_helper')->deleteMultiple($pids);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the key-value store entry key for 'pathauto_state.*' collections.
|
||||
*
|
||||
* Normally we want to use the entity ID as key for 'pathauto_state.*'
|
||||
* collection entries. But some entity types may use string IDs. When such IDs
|
||||
* are exceeding 128 characters, which is the limit for the 'name' column in
|
||||
* the {key_value} table, the insertion of the ID in {key_value} will fail.
|
||||
* Thus we test if we can use the plain ID or we need to store a hashed
|
||||
* version of the entity ID. Also, it is not possible to rely on the UUID as
|
||||
* entity types might not have one or might use a non-standard format.
|
||||
*
|
||||
* The code is inspired by
|
||||
* \Drupal\Core\Cache\DatabaseBackend::normalizeCid().
|
||||
*
|
||||
* @param int|string $entity_id
|
||||
* The entity id for which to compute the key.
|
||||
*
|
||||
* @return int|string
|
||||
* The key used to store the value in the key-value store.
|
||||
*
|
||||
* @see \Drupal\Core\Cache\DatabaseBackend::normalizeCid()
|
||||
*/
|
||||
public static function getPathautoStateKey($entity_id) {
|
||||
$entity_id_is_ascii = mb_check_encoding($entity_id, 'ASCII');
|
||||
if ($entity_id_is_ascii && strlen($entity_id) <= 128) {
|
||||
// The original entity ID, if it's an ASCII of 128 characters or less.
|
||||
return $entity_id;
|
||||
}
|
||||
return Crypt::hashBase64($entity_id);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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)));
|
||||
|
||||
|
@ -226,7 +232,7 @@ class EntityAliasTypeBase extends ContextAwarePluginBase implements AliasTypeInt
|
|||
$query->range(0, 100);
|
||||
$pids_by_id = $query->execute()->fetchAllKeyed();
|
||||
|
||||
$this->bulkDelete($pids_by_id);
|
||||
PathautoState::bulkDelete($this->getEntityTypeId(), $pids_by_id);
|
||||
$context['sandbox']['count'] += count($pids_by_id);
|
||||
$context['sandbox']['current'] = max($pids_by_id);
|
||||
$context['results']['deletions'][] = $this->getLabel();
|
||||
|
@ -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;
|
||||
|
@ -285,19 +294,11 @@ class EntityAliasTypeBase extends ContextAwarePluginBase implements AliasTypeInt
|
|||
*
|
||||
* @param int[] $pids_by_id
|
||||
* A list of path IDs keyed by entity ID.
|
||||
*
|
||||
* @deprecated Use \Drupal\pathauto\PathautoState::bulkDelete() instead.
|
||||
*/
|
||||
protected function bulkDelete(array $pids_by_id) {
|
||||
$collection = 'pathauto_state.' . $this->getEntityTypeId();
|
||||
$states = $this->keyValue->get($collection)->getMultiple(array_keys($pids_by_id));
|
||||
|
||||
$pids = [];
|
||||
foreach ($pids_by_id as $id => $pid) {
|
||||
// Only delete aliases that were created by this module.
|
||||
if (isset($states[$id]) && $states[$id] == PathautoState::CREATE) {
|
||||
$pids[] = $pid;
|
||||
}
|
||||
}
|
||||
\Drupal::service('pathauto.alias_storage_helper')->deleteMultiple($pids);
|
||||
PathautoState::bulkDelete($this->getEntityTypeId(), $pids_by_id);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -338,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();
|
||||
|
|
|
@ -87,7 +87,21 @@ class PathautoLocaleTest extends WebTestBase {
|
|||
* Test that patterns work on multilingual content.
|
||||
*/
|
||||
function testLanguagePatterns() {
|
||||
$this->drupalLogin($this->rootUser);
|
||||
|
||||
// Allow other modules to add additional permissions for the admin user.
|
||||
$permissions = array(
|
||||
'administer pathauto',
|
||||
'administer url aliases',
|
||||
'create url aliases',
|
||||
'bypass node access',
|
||||
'access content overview',
|
||||
'administer languages',
|
||||
'translate any entity',
|
||||
'administer content translation'
|
||||
|
||||
);
|
||||
$admin_user = $this->drupalCreateUser($permissions);
|
||||
$this->drupalLogin($admin_user);
|
||||
|
||||
// Add French language.
|
||||
$edit = array(
|
||||
|
@ -134,8 +148,9 @@ class PathautoLocaleTest extends WebTestBase {
|
|||
'title[0][value]' => 'English node',
|
||||
'langcode[0][value]' => 'en',
|
||||
);
|
||||
$this->drupalPostForm('node/add/article', $edit, t('Save and publish'));
|
||||
$this->drupalPostForm('node/add/article', $edit, t('Save'));
|
||||
$english_node = $this->drupalGetNodeByTitle('English node');
|
||||
return;
|
||||
$this->assertAlias('/node/' . $english_node->id(), '/the-articles/english-node', 'en');
|
||||
|
||||
$this->drupalGet('node/' . $english_node->id() . '/translations');
|
||||
|
@ -143,7 +158,7 @@ class PathautoLocaleTest extends WebTestBase {
|
|||
$edit = array(
|
||||
'title[0][value]' => 'French node',
|
||||
);
|
||||
$this->drupalPostForm(NULL, $edit, t('Save and keep published (this translation)'));
|
||||
$this->drupalPostForm(NULL, $edit, t('Save (this translation)'));
|
||||
$this->rebuildContainer();
|
||||
$english_node = $this->drupalGetNodeByTitle('English node');
|
||||
$french_node = $english_node->getTranslation('fr');
|
||||
|
|
|
@ -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();
|
||||
|
@ -43,7 +44,6 @@ class PathautoNodeWebTest extends WebTestBase {
|
|||
'administer pathauto',
|
||||
'administer url aliases',
|
||||
'create url aliases',
|
||||
'administer nodes',
|
||||
'bypass node access',
|
||||
'access content overview',
|
||||
);
|
||||
|
@ -57,14 +57,15 @@ 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');
|
||||
|
||||
// Create a node by saving the node form.
|
||||
$title = ' Testing: node title [';
|
||||
$automatic_alias = '/content/testing-node-title';
|
||||
$this->drupalPostForm(NULL, array('title[0][value]' => $title), t('Save and publish'));
|
||||
$this->drupalPostForm(NULL, array('title[0][value]' => $title), t('Save'));
|
||||
$node = $this->drupalGetNodeByTitle($title);
|
||||
|
||||
// Look for alias generated in the form.
|
||||
|
@ -82,7 +83,7 @@ class PathautoNodeWebTest extends WebTestBase {
|
|||
'path[0][pathauto]' => FALSE,
|
||||
'path[0][alias]' => $manual_alias,
|
||||
);
|
||||
$this->drupalPostForm($node->toUrl('edit-form'), $edit, t('Save and keep published'));
|
||||
$this->drupalPostForm($node->toUrl('edit-form'), $edit, t('Save'));
|
||||
$this->assertText(t('@type @title has been updated.', array('@type' => 'page', '@title' => $title)));
|
||||
|
||||
// Check that the automatic alias checkbox is now unchecked by default.
|
||||
|
@ -91,7 +92,7 @@ class PathautoNodeWebTest extends WebTestBase {
|
|||
$this->assertFieldByName('path[0][alias]', $manual_alias);
|
||||
|
||||
// Submit the node form with the default values.
|
||||
$this->drupalPostForm(NULL, array('path[0][pathauto]' => FALSE), t('Save and keep published'));
|
||||
$this->drupalPostForm(NULL, array('path[0][pathauto]' => FALSE), t('Save'));
|
||||
$this->assertText(t('@type @title has been updated.', array('@type' => 'page', '@title' => $title)));
|
||||
|
||||
// Test that the old (automatic) alias has been deleted and only accessible
|
||||
|
@ -109,7 +110,7 @@ class PathautoNodeWebTest extends WebTestBase {
|
|||
'path[0][pathauto]' => TRUE,
|
||||
'path[0][alias]' => '/should-not-get-created',
|
||||
);
|
||||
$this->drupalPostForm('node/add/page', $edit, t('Save and publish'));
|
||||
$this->drupalPostForm('node/add/page', $edit, t('Save'));
|
||||
$this->assertNoAliasExists(array('alias' => 'should-not-get-created'));
|
||||
$node = $this->drupalGetNodeByTitle($title);
|
||||
$this->assertEntityAlias($node, '/content/automatic-title');
|
||||
|
@ -130,7 +131,7 @@ class PathautoNodeWebTest extends WebTestBase {
|
|||
$edit = array();
|
||||
$edit['title'] = 'My test article';
|
||||
$this->drupalCreateNode($edit);
|
||||
//$this->drupalPostForm(NULL, $edit, t('Save and keep published'));
|
||||
//$this->drupalPostForm(NULL, $edit, t('Save'));
|
||||
$node = $this->drupalGetNodeByTitle($edit['title']);
|
||||
|
||||
// Pathauto checkbox should still not exist.
|
||||
|
@ -271,7 +272,7 @@ class PathautoNodeWebTest extends WebTestBase {
|
|||
'title[0][value]' => 'Sample article',
|
||||
'path[0][alias]' => '/sample-article',
|
||||
];
|
||||
$this->drupalPostForm('node/add/article', $edit, t('Save and publish'));
|
||||
$this->drupalPostForm('node/add/article', $edit, t('Save'));
|
||||
$this->assertText(t('article Sample article has been created.'));
|
||||
|
||||
// Test the alias.
|
||||
|
|
|
@ -85,7 +85,7 @@ class PathautoSettingsFormWebTest extends WebTestBase {
|
|||
);
|
||||
|
||||
/**
|
||||
* {inheritdoc}
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
function setUp() {
|
||||
parent::setUp();
|
||||
|
@ -97,7 +97,6 @@ class PathautoSettingsFormWebTest extends WebTestBase {
|
|||
'notify of path changes',
|
||||
'administer url aliases',
|
||||
'create url aliases',
|
||||
'administer nodes',
|
||||
'bypass node access',
|
||||
);
|
||||
$this->adminUser = $this->drupalCreateUser($permissions);
|
||||
|
@ -133,11 +132,11 @@ class PathautoSettingsFormWebTest extends WebTestBase {
|
|||
$title = 'Verbose settings test';
|
||||
$this->drupalGet('/node/add/article');
|
||||
$this->assertFieldChecked('edit-path-0-pathauto');
|
||||
$this->drupalPostForm(NULL, array('title[0][value]' => $title), t('Save and publish'));
|
||||
$this->drupalPostForm(NULL, array('title[0][value]' => $title), t('Save'));
|
||||
$this->assertText('Created new alias /content/verbose-settings-test for');
|
||||
|
||||
$node = $this->drupalGetNodeByTitle($title);
|
||||
$this->drupalPostForm('/node/' . $node->id() . '/edit', array('title[0][value]' => 'Updated title'), t('Save and keep published'));
|
||||
$this->drupalPostForm('/node/' . $node->id() . '/edit', array('title[0][value]' => 'Updated title'), t('Save'));
|
||||
$this->assertText('Created new alias /content/updated-title for');
|
||||
$this->assertText('replacing /content/verbose-settings-test.');
|
||||
}
|
||||
|
|
|
@ -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(),
|
||||
);
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
namespace Drupal\pathauto\Tests;
|
||||
|
||||
use Drupal\Core\Url;
|
||||
use Drupal\simpletest\WebTestBase;
|
||||
use Drupal\pathauto\Entity\PathautoPattern;
|
||||
|
||||
|
@ -29,7 +30,7 @@ class PathautoUiTest extends WebTestBase {
|
|||
protected $adminUser;
|
||||
|
||||
/**
|
||||
* {inheritdoc}
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
function setUp() {
|
||||
parent::setUp();
|
||||
|
@ -132,7 +133,8 @@ class PathautoUiTest extends WebTestBase {
|
|||
// Edit workflow, set a new label and weight for the pattern.
|
||||
$this->drupalPostForm('/admin/config/search/path/patterns', ['entities[page_pattern][weight]' => '4'], t('Save'));
|
||||
$this->clickLink(t('Edit'));
|
||||
$this->assertUrl('/admin/config/search/path/patterns/page_pattern');
|
||||
$destination_query = ['query' => ['destination' => Url::fromRoute('entity.pathauto_pattern.collection')->toString()]];
|
||||
$this->assertUrl('/admin/config/search/path/patterns/page_pattern', $destination_query);
|
||||
$this->assertFieldByName('pattern', '[node:title]');
|
||||
$this->assertFieldByName('label', 'Page pattern');
|
||||
$this->assertFieldChecked('edit-status');
|
||||
|
@ -148,7 +150,7 @@ class PathautoUiTest extends WebTestBase {
|
|||
$this->drupalGet('/admin/config/search/path/patterns');
|
||||
$this->assertNoLink(t('Enable'));
|
||||
$this->clickLink(t('Disable'));
|
||||
$this->assertUrl('/admin/config/search/path/patterns/page_pattern/disable');
|
||||
$this->assertUrl('/admin/config/search/path/patterns/page_pattern/disable', $destination_query);
|
||||
$this->drupalPostForm(NULL, [], t('Disable'));
|
||||
$this->assertText('Disabled pattern Test.');
|
||||
|
||||
|
@ -167,7 +169,7 @@ class PathautoUiTest extends WebTestBase {
|
|||
$this->drupalGet('/admin/config/search/path/patterns');
|
||||
$this->assertNoLink(t('Disable'));
|
||||
$this->clickLink(t('Enable'));
|
||||
$this->assertUrl('/admin/config/search/path/patterns/page_pattern/enable');
|
||||
$this->assertUrl('/admin/config/search/path/patterns/page_pattern/enable', $destination_query);
|
||||
$this->drupalPostForm(NULL, [], t('Enable'));
|
||||
$this->assertText('Enabled pattern Test.');
|
||||
|
||||
|
@ -178,7 +180,7 @@ class PathautoUiTest extends WebTestBase {
|
|||
// Delete workflow.
|
||||
$this->drupalGet('/admin/config/search/path/patterns');
|
||||
$this->clickLink(t('Delete'));
|
||||
$this->assertUrl('/admin/config/search/path/patterns/page_pattern/delete');
|
||||
$this->assertUrl('/admin/config/search/path/patterns/page_pattern/delete', $destination_query);
|
||||
$this->assertText(t('This action cannot be undone.'));
|
||||
$this->drupalPostForm(NULL, [], t('Delete'));
|
||||
$this->assertText('The pathauto pattern Test has been deleted.');
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
name: 'Pathauto testing module'
|
||||
type: module
|
||||
# core: '8.x'
|
||||
description: 'Pathauto for Entity with string ID.'
|
||||
package: Testing
|
||||
dependencies:
|
||||
- token
|
||||
|
||||
# Information added by Drupal.org packaging script on 2018-09-08
|
||||
version: '8.x-1.3'
|
||||
core: '8.x'
|
||||
project: 'pathauto'
|
||||
datestamp: 1536407890
|
|
@ -0,0 +1,50 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\pathauto_string_id_test\Entity;
|
||||
|
||||
use Drupal\Core\Entity\ContentEntityBase;
|
||||
use Drupal\Core\Entity\EntityTypeInterface;
|
||||
use Drupal\Core\Field\BaseFieldDefinition;
|
||||
|
||||
/**
|
||||
* Defines a test entity with a string ID.
|
||||
*
|
||||
* @ContentEntityType(
|
||||
* id = "pathauto_string_id_test",
|
||||
* label = @Translation("Test entity with string ID"),
|
||||
* handlers = {
|
||||
* "route_provider" = {
|
||||
* "html" = "Drupal\Core\Entity\Routing\DefaultHtmlRouteProvider",
|
||||
* },
|
||||
* },
|
||||
* base_table = "pathauto_string_id_test",
|
||||
* entity_keys = {
|
||||
* "id" = "id",
|
||||
* "label" = "name",
|
||||
* },
|
||||
* links = {
|
||||
* "canonical" = "/pathauto_string_id_test/{pathauto_string_id_test}",
|
||||
* },
|
||||
* )
|
||||
*/
|
||||
class PathautoStringIdTest extends ContentEntityBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function baseFieldDefinitions(EntityTypeInterface $entity_type) {
|
||||
$fields['id'] = BaseFieldDefinition::create('string')
|
||||
->setLabel('ID')
|
||||
->setReadOnly(TRUE)
|
||||
// A bigger value will not be allowed to build the index.
|
||||
->setSetting('max_length', 191);
|
||||
$fields['name'] = BaseFieldDefinition::create('string')
|
||||
->setLabel('Name');
|
||||
$fields['path'] = BaseFieldDefinition::create('path')
|
||||
->setLabel('Path')
|
||||
->setComputed(TRUE);
|
||||
|
||||
return $fields;
|
||||
}
|
||||
|
||||
}
|
|
@ -7,8 +7,8 @@ package: Testing
|
|||
dependencies:
|
||||
- views
|
||||
|
||||
# Information added by Drupal.org packaging script on 2017-04-29
|
||||
version: '8.x-1.0'
|
||||
# Information added by Drupal.org packaging script on 2018-09-08
|
||||
version: '8.x-1.3'
|
||||
core: '8.x'
|
||||
project: 'pathauto'
|
||||
datestamp: 1493468049
|
||||
datestamp: 1536407890
|
||||
|
|
|
@ -0,0 +1,130 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\pathauto\Kernel;
|
||||
|
||||
use Drupal\Component\Serialization\PhpSerialize;
|
||||
use Drupal\Component\Utility\Crypt;
|
||||
use Drupal\Core\DependencyInjection\ContainerBuilder;
|
||||
use Drupal\Core\KeyValueStore\KeyValueDatabaseFactory;
|
||||
use Drupal\pathauto\PathautoState;
|
||||
use Drupal\pathauto\Tests\PathautoTestHelperTrait;
|
||||
use Drupal\KernelTests\KernelTestBase;
|
||||
use Drupal\pathauto_string_id_test\Entity\PathautoStringIdTest;
|
||||
|
||||
/**
|
||||
* Tests auto-aliasing of entities that use string IDs.
|
||||
*
|
||||
* @group pathauto
|
||||
*/
|
||||
class PathautoEntityWithStringIdTest extends KernelTestBase {
|
||||
|
||||
use PathautoTestHelperTrait;
|
||||
|
||||
/**
|
||||
* The alias type plugin instance.
|
||||
*
|
||||
* @var \Drupal\pathauto\AliasTypeBatchUpdateInterface
|
||||
*/
|
||||
protected $aliasType;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $modules = [
|
||||
'system',
|
||||
'user',
|
||||
'field',
|
||||
'token',
|
||||
'path',
|
||||
'pathauto',
|
||||
'pathauto_string_id_test',
|
||||
];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function register(ContainerBuilder $container) {
|
||||
parent::register($container);
|
||||
// Kernel tests are using the 'keyvalue.memory' store but we want to test
|
||||
// against the 'keyvalue.database'.
|
||||
$container
|
||||
->register('keyvalue.database', KeyValueDatabaseFactory::class)
|
||||
->addArgument(new PhpSerialize())
|
||||
->addArgument($container->get('database'))
|
||||
->addTag('persist');
|
||||
$container->setAlias('keyvalue', 'keyvalue.database');
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
$this->installSchema('system', ['key_value']);
|
||||
$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 */
|
||||
$alias_type_manager = $this->container->get('plugin.manager.alias_type');
|
||||
$this->aliasType = $alias_type_manager->createInstance('canonical_entities:pathauto_string_id_test');
|
||||
}
|
||||
|
||||
/**
|
||||
* Test aliasing entities with long string ID.
|
||||
*
|
||||
* @dataProvider entityWithStringIdProvider
|
||||
*
|
||||
* @param string|int $id
|
||||
* The entity ID
|
||||
* @param string $expected_key
|
||||
* The expected key for 'pathauto_state.*' collections.
|
||||
*/
|
||||
public function testEntityWithStringId($id, $expected_key) {
|
||||
$entity = PathautoStringIdTest::create([
|
||||
'id' => $id,
|
||||
'name' => $name = $this->randomMachineName(),
|
||||
]);
|
||||
$entity->save();
|
||||
|
||||
// Check that the path was generated.
|
||||
$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);
|
||||
|
||||
$context = [];
|
||||
// Batch delete uses the key-value store collection 'pathauto_state.*. We
|
||||
// test that after a bulk delete all aliases are removed. Running only once
|
||||
// the batch delete process is enough as the batch size is 100.
|
||||
$this->aliasType->batchDelete($context);
|
||||
|
||||
// Check that the paths were removed on batch delete.
|
||||
$this->assertNoEntityAliasExists($entity, "/$name");
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides test cases for ::testEntityWithStringId().
|
||||
*
|
||||
* @see \Drupal\Tests\pathauto\Kernel\PathautoEntityWithStringIdTest::testEntityWithStringId()
|
||||
*/
|
||||
public function entityWithStringIdProvider() {
|
||||
return [
|
||||
'ascii with less or equal 128 chars' => [
|
||||
str_repeat('a', 128), str_repeat('a', 128)
|
||||
],
|
||||
'ascii with over 128 chars' => [
|
||||
str_repeat('a', 191), Crypt::hashBase64(str_repeat('a', 191))
|
||||
],
|
||||
'non-ascii with less or equal 128 chars' => [
|
||||
str_repeat('社', 128), Crypt::hashBase64(str_repeat('社', 128))
|
||||
],
|
||||
'non-ascii with over 128 chars' => [
|
||||
str_repeat('社', 191), Crypt::hashBase64(str_repeat('社', 191))
|
||||
],
|
||||
'simulating an integer id' => [
|
||||
123, '123'
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
}
|
|
@ -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() {
|
||||
|
||||
|
@ -547,6 +545,22 @@ class PathautoKernelTest extends KernelTestBase {
|
|||
$this->assertEntityAlias($node1, '/content/default-revision');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that the pathauto state property gets set to CREATED for new nodes.
|
||||
*
|
||||
* In some cases, this can trigger $node->path to be set up with no default
|
||||
* value for the pathauto property.
|
||||
*/
|
||||
public function testCreateNodeWhileAccessingPath() {
|
||||
$node = Node::create([
|
||||
'type' => 'article',
|
||||
'title' => 'TestAlias',
|
||||
]);
|
||||
$node->path->langcode;
|
||||
$node->save();
|
||||
$this->assertEntityAlias($node, '/content/testalias');
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a node programmatically.
|
||||
*
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Reference in a new issue