Commit 607a59f6 authored by Berdir's avatar Berdir Committed by Berdir
Browse files

Issue #3042582 by zeuty, andreyjan, katherined, Berdir, pranit84, thalles,...

Issue #3042582 by zeuty, andreyjan, katherined, Berdir, pranit84, thalles, malaynayak, fm_, robpowell, Sergiu Stici, robertoperuzzo: Drupal 9 Deprecated Code Report for Pathauto
parent 6aa4b7c6
name : 'Pathauto'
description : 'Provides a mechanism for modules to automatically generate aliases for the content they manage.'
core_version_requirement: ^8.7.7 || ^9
core_version_requirement: ^8.8 || ^9
type: module
dependencies:
......
......@@ -12,7 +12,7 @@ services:
- { name: backend_overridable }
pathauto.alias_uniquifier:
class: Drupal\pathauto\AliasUniquifier
arguments: ['@config.factory', '@pathauto.alias_storage_helper','@module_handler', '@router.route_provider', '@path.alias_manager']
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', '@messenger']
......
......@@ -7,9 +7,9 @@ use Drupal\Core\Database\Connection;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Language\LanguageInterface;
use Drupal\Core\Path\AliasRepositoryInterface;
use Drupal\Core\StringTranslation\StringTranslationTrait;
use Drupal\Core\StringTranslation\TranslationInterface;
use Drupal\path_alias\AliasRepositoryInterface;
/**
* Provides helper methods for accessing alias storage.
......@@ -35,7 +35,7 @@ class AliasStorageHelper implements AliasStorageHelperInterface {
/**
* The alias repository.
*
* @var \Drupal\Core\Path\AliasRepositoryInterface
* @var \Drupal\path_alias\AliasRepositoryInterface
*/
protected $aliasRepository;
......@@ -65,7 +65,7 @@ class AliasStorageHelper implements AliasStorageHelperInterface {
*
* @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
* The config factory.
* @param \Drupal\Core\Path\AliasRepositoryInterface $alias_repository
* @param \Drupal\path_alias\AliasRepositoryInterface $alias_repository
* The alias repository.
* @param \Drupal\Core\Database\Connection $database
* The database connection.
......
......@@ -6,8 +6,8 @@ use Drupal\Component\Utility\Unicode;
use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\Extension\ModuleHandlerInterface;
use Drupal\Core\Language\LanguageInterface;
use Drupal\Core\Path\AliasManagerInterface;
use Drupal\Core\Routing\RouteProviderInterface;
use Drupal\path_alias\AliasManagerInterface;
/**
* Provides a utility for creating a unique path alias.
......@@ -45,7 +45,7 @@ class AliasUniquifier implements AliasUniquifierInterface {
/**
* The alias manager.
*
* @var \Drupal\Core\Path\AliasManagerInterface
* @var \Drupal\path_alias\AliasManagerInterface
*/
protected $aliasManager;
......@@ -60,7 +60,7 @@ 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
* @param \Drupal\path_alias\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) {
......
<?php
namespace Drupal\pathauto;
use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\Database\Connection;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Language\LanguageInterface;
use Drupal\Core\Path\AliasStorageInterface;
use Drupal\Core\StringTranslation\StringTranslationTrait;
use Drupal\Core\StringTranslation\TranslationInterface;
/**
* Provides helper methods for accessing alias storage.
*/
class LegacyAliasStorageHelper implements AliasStorageHelperInterface {
use StringTranslationTrait;
/**
* Alias schema max length.
*
* @var int
*/
protected $aliasSchemaMaxLength = 255;
/**
* Config factory.
*
* @var \Drupal\Core\Config\ConfigFactoryInterface
*/
protected $configFactory;
/**
* The alias storage.
*
* @var \Drupal\Core\Path\AliasStorageInterface
*/
protected $aliasStorage;
/**
* The database connection.
*
* @var \Drupal\Core\Database\Connection
*/
protected $database;
/**
* The messenger.
*
* @var \Drupal\pathauto\MessengerInterface
*/
protected $messenger;
/**
* The config factory.
*
* @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
* The config factory.
* @param \Drupal\Core\Path\AliasStorageInterface $alias_storage
* The alias storage.
* @param \Drupal\Core\Database\Connection $database
* The database connection.
* @param MessengerInterface $messenger
* The messenger.
* @param \Drupal\Core\StringTranslation\TranslationInterface $string_translation
* The string translation service.
*/
public function __construct(ConfigFactoryInterface $config_factory, AliasStorageInterface $alias_storage, Connection $database, MessengerInterface $messenger, TranslationInterface $string_translation) {
$this->configFactory = $config_factory;
$this->aliasStorage = $alias_storage;
$this->database = $database;
$this->messenger = $messenger;
$this->stringTranslation = $string_translation;
}
/**
* {@inheritdoc}
*/
public function getAliasSchemaMaxLength() {
return $this->aliasSchemaMaxLength;
}
/**
* {@inheritdoc}
*/
public function save(array $path, $existing_alias = NULL, $op = NULL) {
$config = $this->configFactory->get('pathauto.settings');
// Alert users if they are trying to create an alias that is the same as the
// internal path.
if ($path['source'] == $path['alias']) {
$this->messenger->addMessage($this->t('Ignoring alias %alias because it is the same as the internal path.', ['%alias' => $path['alias']]));
return NULL;
}
// Skip replacing the current alias with an identical alias.
if (empty($existing_alias) || $existing_alias['alias'] != $path['alias']) {
$path += [
'pathauto' => TRUE,
'original' => $existing_alias,
'pid' => NULL,
];
// If there is already an alias, respect some update actions.
if (!empty($existing_alias)) {
switch ($config->get('update_action')) {
case PathautoGeneratorInterface::UPDATE_ACTION_NO_NEW:
// Do not create the alias.
return NULL;
case PathautoGeneratorInterface::UPDATE_ACTION_LEAVE:
// Create a new alias instead of overwriting the existing by leaving
// $path['pid'] empty.
break;
case PathautoGeneratorInterface::UPDATE_ACTION_DELETE:
// The delete actions should overwrite the existing alias.
$path['pid'] = $existing_alias['pid'];
break;
}
}
// Save the path array.
$this->aliasStorage->save($path['source'], $path['alias'], $path['language'], $path['pid']);
if (!empty($existing_alias['pid'])) {
$this->messenger->addMessage($this->t(
'Created new alias %alias for %source, replacing %old_alias.',
[
'%alias' => $path['alias'],
'%source' => $path['source'],
'%old_alias' => $existing_alias['alias'],
]
)
);
}
else {
$this->messenger->addMessage($this->t('Created new alias %alias for %source.', [
'%alias' => $path['alias'],
'%source' => $path['source'],
]));
}
return $path;
}
}
/**
* {@inheritdoc}
*/
public function loadBySource($source, $language = LanguageInterface::LANGCODE_NOT_SPECIFIED) {
$alias = $this->aliasStorage->load([
'source' => $source,
'langcode' => $language,
]);
// If no alias was fetched and if a language was specified, fallbacks to
// undefined language.
if (!$alias && ($language !== LanguageInterface::LANGCODE_NOT_SPECIFIED)) {
$alias = $this->aliasStorage->load([
'source' => $source,
'langcode' => LanguageInterface::LANGCODE_NOT_SPECIFIED,
]);
}
return $alias;
}
/**
* {@inheritdoc}
*/
public function deleteBySourcePrefix($source) {
$pids = $this->loadBySourcePrefix($source);
if ($pids) {
$this->deleteMultiple($pids);
}
}
/**
* {@inheritdoc}
*/
public function deleteAll() {
$this->database->truncate('url_alias')->execute();
}
/**
* {@inheritdoc}
*/
public function deleteEntityPathAll(EntityInterface $entity, $default_uri = NULL) {
$this->deleteBySourcePrefix('/' . $entity->toUrl('canonical')->getInternalPath());
if (isset($default_uri) && $entity->toUrl('canonical')->toString() != $default_uri) {
$this->deleteBySourcePrefix($default_uri);
}
}
/**
* {@inheritdoc}
*/
public function loadBySourcePrefix($source) {
$select = $this->database->select('url_alias', 'u')
->fields('u', ['pid']);
$or_group = $select->orConditionGroup()
->condition('source', $source)
->condition('source', rtrim($source, '/') . '/%', 'LIKE');
return $select
->condition($or_group)
->execute()
->fetchCol();
}
/**
* {@inheritdoc}
*/
public function countBySourcePrefix($source) {
$select = $this->database->select('url_alias', 'u')
->fields('u', ['pid']);
$or_group = $select->orConditionGroup()
->condition('source', $source)
->condition('source', rtrim($source, '/') . '/%', 'LIKE');
return $select
->condition($or_group)
->countQuery()
->execute()
->fetchField();
}
/**
* {@inheritdoc}
*/
public function countAll() {
return $this->database->select('url_alias')
->countQuery()
->execute()
->fetchField();
}
/**
* {@inheritdoc}
*/
public function deleteMultiple($pids) {
foreach ($pids as $pid) {
$this->aliasStorage->delete(['pid' => $pid]);
}
}
}
<?php
namespace Drupal\pathauto;
use Drupal\Core\DependencyInjection\ContainerBuilder;
use Drupal\Core\DependencyInjection\ServiceProviderBase;
use Symfony\Component\DependencyInjection\Reference;
/**
* Overrides the pathauto.alias_storage_helper service if needed.
*/
class PathautoServiceProvider extends ServiceProviderBase {
/**
* {@inheritdoc}
*/
public function alter(ContainerBuilder $container) {
if (version_compare(\Drupal::VERSION, '8.8', '<')) {
$definition = $container->getDefinition('pathauto.alias_storage_helper');
$definition->setClass(LegacyAliasStorageHelper::class);
$definition->setArgument(1, new Reference('path.alias_storage'));
}
}
}
......@@ -2,8 +2,8 @@
namespace Drupal\pathauto\Plugin\migrate\source;
use Drupal\Core\Entity\EntityManagerInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Entity\EntityTypeBundleInfo;
use Drupal\Core\State\StateInterface;
use Drupal\migrate\Plugin\MigrationInterface;
use Drupal\migrate\Row;
......@@ -21,18 +21,18 @@ use Symfony\Component\DependencyInjection\ContainerInterface;
class PathautoPattern extends DrupalSqlBase {
/**
* The entity type manager.
* The entity type bundle info.
*
* @var \Drupal\Core\Entity\EntityTypeManagerInterface
* @var \Drupal\Core\Entity\EntityTypeBundleInfo
*/
protected $entityTypeManager;
protected $entityTypeBundleInfo;
/**
* {@inheritdoc}
*/
public function __construct(array $configuration, $plugin_id, $plugin_definition, MigrationInterface $migration, StateInterface $state, EntityManagerInterface $entity_manager, EntityTypeManagerInterface $entity_type_manager) {
parent::__construct($configuration, $plugin_id, $plugin_definition, $migration, $state, $entity_manager);
$this->entityTypeManager = $entity_type_manager;
public function __construct(array $configuration, $plugin_id, $plugin_definition, MigrationInterface $migration, StateInterface $state, EntityTypeManagerInterface $entity_type_manager, EntityTypeBundleInfo $entity_bundle_info) {
parent::__construct($configuration, $plugin_id, $plugin_definition, $migration, $state, $entity_type_manager);
$this->entityTypeBundleInfo = $entity_bundle_info;
}
/**
......@@ -45,8 +45,8 @@ class PathautoPattern extends DrupalSqlBase {
$plugin_definition,
$migration,
$container->get('state'),
$container->get('entity.manager'),
$container->get('entity_type.manager')
$container->get('entity_type.manager'),
$container->get('entity_type.bundle.info')
);
}
......@@ -104,7 +104,7 @@ class PathautoPattern extends DrupalSqlBase {
$bundle = $matches[1];
// Check that the bundle exists.
$bundles = $this->entityManager->getBundleInfo($entity_type);
$bundles = $this->entityTypeBundleInfo->getBundleInfo($entity_type);
if (!in_array($bundle, array_keys($bundles))) {
// No matching bundle found in destination.
return FALSE;
......
name: 'Pathauto testing module'
type: module
core_version_requirement: ^8.7.7 || ^9
core_version_requirement: ^8.8 || ^9
description: 'Pathauto for Entity with string ID.'
package: Testing
dependencies:
......
......@@ -2,6 +2,6 @@ name: 'Views Test Config'
type: module
description: 'Provides default views for tests.'
package: Testing
core_version_requirement: ^8.7.7 || ^9
core_version_requirement: ^8.8 || ^9
dependencies:
- drupal:views
......@@ -98,7 +98,7 @@ class PathautoBulkUpdateTest extends BrowserTestBase {
}
$this->assertEntityAliasExists($this->adminUser);
// This is the default "General discussion" forum.
$this->assertAliasExists(['source' => '/taxonomy/term/1']);
$this->assertAliasExists(['path' => '/taxonomy/term/1']);
// Add a new node.
$new_node = $this->drupalCreateNode(['path' => ['alias' => '', 'pathauto' => PathautoState::SKIP]]);
......
......@@ -10,12 +10,15 @@ use Drupal\pathauto\PathautoPatternInterface;
use Drupal\taxonomy\VocabularyInterface;
use Drupal\taxonomy\Entity\Vocabulary;
use Drupal\taxonomy\Entity\Term;
use Drupal\Tests\Traits\Core\PathAliasTestTrait;
/**
* Helper test class with some added functions for testing.
*/
trait PathautoTestHelperTrait {
use PathAliasTestTrait;
/**
* Creates a pathauto pattern.
*
......@@ -76,17 +79,12 @@ trait PathautoTestHelperTrait {
$this->assertSame($tokens[$token], $expected, t("Token value for [@type:@token] was '@actual', expected value '@expected'.", ['@type' => $type, '@token' => $token, '@actual' => $tokens[$token], '@expected' => $expected]));
}
public function saveAlias($source, $alias, $langcode = Language::LANGCODE_NOT_SPECIFIED) {
\Drupal::service('path.alias_storage')->delete(['source' => $source, 'langcode' => $langcode]);
return \Drupal::service('path.alias_storage')->save($source, $alias, $langcode);
}
public function saveEntityAlias(EntityInterface $entity, $alias, $langcode = NULL) {
// By default, use the entity language.
if (!$langcode) {
$langcode = $entity->language()->getId();
}
return $this->saveAlias('/' . $entity->toUrl()->getInternalPath(), $alias, $langcode);
return $this->createPathAlias('/' . $entity->toUrl()->getInternalPath(), $alias, $langcode);
}
public function assertEntityAlias(EntityInterface $entity, $expected_alias, $langcode = NULL) {
......@@ -98,7 +96,7 @@ trait PathautoTestHelperTrait {
}
public function assertEntityAliasExists(EntityInterface $entity) {
return $this->assertAliasExists(['source' => '/' . $entity->toUrl()->getInternalPath()]);
return $this->assertAliasExists(['path' => '/' . $entity->toUrl()->getInternalPath()]);
}
public function assertNoEntityAlias(EntityInterface $entity, $langcode = NULL) {
......@@ -110,7 +108,7 @@ trait PathautoTestHelperTrait {
}
public function assertNoEntityAliasExists(EntityInterface $entity, $alias = NULL) {
$path = ['source' => '/' . $entity->toUrl()->getInternalPath()];
$path = ['path' => '/' . $entity->toUrl()->getInternalPath()];
if (!empty($alias)) {
$path['alias'] = $alias;
}
......@@ -118,29 +116,29 @@ trait PathautoTestHelperTrait {
}
public function assertAlias($source, $expected_alias, $langcode = Language::LANGCODE_NOT_SPECIFIED) {
\Drupal::service('path.alias_manager')->cacheClear($source);
\Drupal::service('path_alias.manager')->cacheClear($source);
$entity_type_manager = \Drupal::entityTypeManager();
if ($entity_type_manager->hasDefinition('path_alias')) {
$entity_type_manager->getStorage('path_alias')->resetCache();
}
$this->assertEquals($expected_alias, \Drupal::service('path.alias_manager')->getAliasByPath($source, $langcode), t("Alias for %source with language '@language' is correct.",
$this->assertEquals($expected_alias, \Drupal::service('path_alias.manager')->getAliasByPath($source, $langcode), t("Alias for %source with language '@language' is correct.",
['%source' => $source, '@language' => $langcode]));
}
public function assertAliasExists($conditions) {
$path = \Drupal::service('path.alias_storage')->load($conditions);
$path = $this->loadPathAliasByConditions($conditions);
$this->assertNotEmpty($path, t('Alias with conditions @conditions found.', ['@conditions' => var_export($conditions, TRUE)]));
return $path;
}
public function assertNoAliasExists($conditions) {
$alias = \Drupal::service('path.alias_storage')->load($conditions);
$this->assertFalse($alias, t('Alias with conditions @conditions not found.', ['@conditions' => var_export($conditions, TRUE)]));
$alias = $this->loadPathAliasByConditions($conditions);
$this->assertEmpty($alias, t('Alias with conditions @conditions not found.', ['@conditions' => var_export($conditions, TRUE)]));
}
public function deleteAllAliases() {
\Drupal::service('pathauto.alias_storage_helper')->deleteAll();
\Drupal::service('path.alias_manager')->cacheClear();
\Drupal::service('path_alias.manager')->cacheClear();
}
/**
......
......@@ -60,8 +60,8 @@ class PathautoLocaleTest extends WebDriverTestBase {
]],
];
$node = $this->drupalCreateNode($node);
$english_alias = \Drupal::service('path.alias_storage')->load(['alias' => '/english-node', 'langcode' => 'en']);
$this->assertTrue($english_alias, 'Alias created with proper language.');
$english_alias = $this->loadPathAliasByConditions(['alias' => '/english-node', 'langcode' => 'en']);
$this->assertNotEmpty($english_alias, 'Alias created with proper language.');
// Also save a French alias that should not be left alone, even though
// it is the newer alias.
......@@ -69,7 +69,7 @@ class PathautoLocaleTest extends WebDriverTestBase {
// Add an alias with the soon-to-be generated alias, causing the upcoming
// alias update to generate a unique alias with the '-0' suffix.
$this->saveAlias('/node/invalid', '/content/english-node', Language::LANGCODE_NOT_SPECIFIED);
$this->createPathAlias('/node/invalid', '/content/english-node', Language::LANGCODE_NOT_SPECIFIED);
// Update the node, triggering a change in the English alias.
$node->path->pathauto = PathautoState::CREATE;
......@@ -78,7 +78,7 @@ class PathautoLocaleTest extends WebDriverTestBase {
// Check that the new English alias replaced the old one.
$this->assertEntityAlias($node, '/content/english-node-0', 'en');
$this->assertEntityAlias($node, '/french-node', 'fr');
$this->assertAliasExists(['pid' => $english_alias['pid'], 'alias' => '/content/english-node-0']);
$this->assertAliasExists(['id' => $english_alias->id(), 'alias' => '/content/english-node-0']);
// Create a new node with the same title as before but without
// specifying a language.
......
......@@ -199,7 +199,7 @@ class PathautoUiTest extends WebDriverTestBase {
$this->drupalPostForm(NULL, [], t('Delete'));
$this->assertSession()->pageTextContains('The pathauto pattern Test has been deleted.');
$this->assertFalse(PathautoPattern::load('page_pattern'));
$this->assertEmpty(PathautoPattern::load('page_pattern'));
}
}
......@@ -36,6 +36,7 @@ class PathautoEntityWithStringIdTest extends KernelTestBase {
'field',
'token',
'path',
'path_alias',
'pathauto',
'pathauto_string_id_test',
];
......
......@@ -27,7 +27,7 @@ class PathautoKernelTest extends KernelTestBase {
use PathautoTestHelperTrait;
public static $modules = ['system', 'field', 'text', 'user', 'node', 'path', 'pathauto', 'taxonomy', 'token', 'filter', 'ctools', 'language'];
public static $modules = ['system', 'field', 'text', 'user', 'node', 'path', 'path_alias', 'pathauto', 'taxonomy', 'token', 'filter', 'ctools', 'language'];
protected $currentUser;
......@@ -44,7 +44,6 @@ class PathautoKernelTest extends KernelTestBase {
public function setUp() {
parent::setup();
$this->installEntitySchema('user');
$this->installEntitySchema('node');
$this->installEntitySchema('taxonomy_term');
......@@ -251,18 +250,18 @@ class PathautoKernelTest extends KernelTestBase {
* Test pathauto_path_delete_multiple().
*/
public function testPathDeleteMultiple() {
$this->saveAlias('/node/1', '/node-1-alias');
$this->saveAlias('/node/1/view', '/node-1-alias/view');
$this->saveAlias('/node/1', '/node-1-alias-en', 'en');
$this->saveAlias('/node/1', '/node-1-alias-fr', 'fr');
$this->saveAlias('/node/2', '/node-2-alias');
$this->saveAlias('/node/10', '/node-10-alias');
$this->createPathAlias('/node/1', '/node-1-alias');
$this->createPathAlias('/node/1/view', '/node-1-alias/view');
$this->createPathAlias('/node/1', '/node-1-alias-en', 'en');
$this->createPathAlias('/node/1', '/node-1-alias-fr', 'fr');
$this->createPathAlias('/node/2', '/node-2-alias');
$this->createPathAlias('/node/10', '/node-10-alias');
\Drupal::service('pathauto.alias_storage_helper')->deleteBySourcePrefix('/node/1');
$this->assertNoAliasExists(['source' => "/node/1"]);
$this->assertNoAliasExists(['source' => "/node/1/view"]);
$this->assertAliasExists(['source' => "/node/2"]);