Skip to content
Snippets Groups Projects
Commit 55a2b407 authored by Francesco Placella's avatar Francesco Placella
Browse files

Issue #3011807 by amateescu, Berdir: Convert the path alias admin overview to a list builder

parent c6c18413
No related branches found
No related tags found
6 merge requests!7452Issue #1797438. HTML5 validation is preventing form submit and not fully...,!1012Issue #3226887: Hreflang on non-canonical content pages,!789Issue #3210310: Adjust Database API to remove deprecated Drupal 9 code in Drupal 10,!596Issue #3046532: deleting an entity reference field, used in a contextual view, makes the whole site unrecoverable,!496Issue #2463967: Use .user.ini file for PHP settings,!144Issue #2666286: Clean up menu_ui to conform to Drupal coding standards
......@@ -16,13 +16,13 @@
*
* @ContentEntityType(
* id = "path_alias",
* label = @Translation("Path alias"),
* label_collection = @Translation("Path aliases"),
* label_singular = @Translation("path alias"),
* label_plural = @Translation("path aliases"),
* label = @Translation("URL alias"),
* label_collection = @Translation("URL aliases"),
* label_singular = @Translation("URL alias"),
* label_plural = @Translation("URL aliases"),
* label_count = @PluralTranslation(
* singular = "@count path alias",
* plural = "@count path aliases"
* singular = "@count URL alias",
* plural = "@count URL aliases"
* ),
* handlers = {
* "storage" = "Drupal\Core\Path\PathAliasStorage",
......@@ -68,7 +68,7 @@ public static function baseFieldDefinitions(EntityTypeInterface $entity_type) {
->addPropertyConstraints('value', ['ValidPath' => []]);
$fields['alias'] = BaseFieldDefinition::create('string')
->setLabel(new TranslatableMarkup('Path alias'))
->setLabel(new TranslatableMarkup('URL alias'))
->setDescription(new TranslatableMarkup('An alias used with this path.'))
->setRequired(TRUE)
->setRevisionable(TRUE)
......
......@@ -15,6 +15,7 @@
use Drupal\Core\Language\LanguageInterface;
use Drupal\Core\Routing\RouteMatchInterface;
use Drupal\path\PathAliasForm;
use Drupal\path\PathAliasListBuilder;
/**
* Implements hook_help().
......@@ -50,6 +51,7 @@ function path_entity_type_alter(array &$entity_types) {
$entity_types['path_alias']->setFormClass('default', PathAliasForm::class);
$entity_types['path_alias']->setFormClass('delete', ContentEntityDeleteForm::class);
$entity_types['path_alias']->setHandlerClass('route_provider', ['html' => AdminHtmlRouteProvider::class]);
$entity_types['path_alias']->setListBuilderClass(PathAliasListBuilder::class);
$entity_types['path_alias']->setLinkTemplate('collection', '/admin/config/search/path');
$entity_types['path_alias']->setLinkTemplate('add-form', '/admin/config/search/path/add');
$entity_types['path_alias']->setLinkTemplate('edit-form', '/admin/config/search/path/edit/{path_alias}');
......
entity.path_alias.collection:
path: '/admin/config/search/path'
defaults:
_title: 'URL aliases'
_controller: '\Drupal\path\Controller\PathController::adminOverview'
keys: NULL
requirements:
_permission: 'administer url aliases'
path.admin_overview_filter:
path: '/admin/config/search/path/filter'
defaults:
_title: 'URL aliases'
_controller: '\Drupal\path\Controller\PathController::adminOverview'
requirements:
_permission: 'administer url aliases'
<?php
namespace Drupal\path\Controller;
use Drupal\Component\Utility\Unicode;
use Drupal\Core\Controller\ControllerBase;
use Drupal\Core\Link;
use Drupal\Core\Path\AliasStorageInterface;
use Drupal\Core\Path\AliasManagerInterface;
use Drupal\Core\Url;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpFoundation\Request;
/**
* Controller routines for path routes.
*/
class PathController extends ControllerBase {
/**
* The path alias storage.
*
* @var \Drupal\Core\Path\AliasStorageInterface
*/
protected $aliasStorage;
/**
* The path alias manager.
*
* @var \Drupal\Core\Path\AliasManagerInterface
*/
protected $aliasManager;
/**
* Constructs a new PathController.
*
* @param \Drupal\Core\Path\AliasStorageInterface $alias_storage
* The path alias storage.
* @param \Drupal\Core\Path\AliasManagerInterface $alias_manager
* The path alias manager.
*/
public function __construct(AliasStorageInterface $alias_storage, AliasManagerInterface $alias_manager) {
$this->aliasStorage = $alias_storage;
$this->aliasManager = $alias_manager;
}
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container) {
return new static(
$container->get('path.alias_storage'),
$container->get('path.alias_manager')
);
}
/**
* Displays the path administration overview page.
*
* @param \Symfony\Component\HttpFoundation\Request $request
* The request object.
*
* @return array
* A render array as expected by
* \Drupal\Core\Render\RendererInterface::render().
*/
public function adminOverview(Request $request) {
$keys = $request->query->get('search');
// Add the filter form above the overview table.
$build['path_admin_filter_form'] = $this->formBuilder()->getForm('Drupal\path\Form\PathFilterForm', $keys);
// Enable language column if language.module is enabled or if we have any
// alias with a language.
$multilanguage = ($this->moduleHandler()->moduleExists('language') || $this->aliasStorage->languageAliasExists());
$header = [];
$header[] = ['data' => $this->t('Alias'), 'field' => 'alias', 'sort' => 'asc'];
$header[] = ['data' => $this->t('System'), 'field' => 'source'];
if ($multilanguage) {
$header[] = ['data' => $this->t('Language'), 'field' => 'langcode'];
}
$header[] = $this->t('Operations');
$rows = [];
$destination = $this->getDestinationArray();
foreach ($this->aliasStorage->getAliasesForAdminListing($header, $keys) as $data) {
$row = [];
// @todo Should Path module store leading slashes? See
// https://www.drupal.org/node/2430593.
$row['data']['alias'] = Link::fromTextAndUrl(Unicode::truncate($data->alias, 50, FALSE, TRUE), Url::fromUserInput($data->source, [
'attributes' => ['title' => $data->alias],
]))->toString();
$row['data']['source'] = Link::fromTextAndUrl(Unicode::truncate($data->source, 50, FALSE, TRUE), Url::fromUserInput($data->source, [
'alias' => TRUE,
'attributes' => ['title' => $data->source],
]))->toString();
if ($multilanguage) {
$row['data']['language_name'] = $this->languageManager()->getLanguageName($data->langcode);
}
$operations = [];
$operations['edit'] = [
'title' => $this->t('Edit'),
'url' => Url::fromRoute('entity.path_alias.edit_form', ['path_alias' => $data->pid], ['query' => $destination]),
];
$operations['delete'] = [
'title' => $this->t('Delete'),
'url' => Url::fromRoute('entity.path_alias.delete_form', ['path_alias' => $data->pid], ['query' => $destination]),
];
$row['data']['operations'] = [
'data' => [
'#type' => 'operations',
'#links' => $operations,
],
];
// If the system path maps to a different URL alias, highlight this table
// row to let the user know of old aliases.
if ($data->alias != $this->aliasManager->getAliasByPath($data->source, $data->langcode)) {
$row['class'] = ['warning'];
}
$rows[] = $row;
}
$build['path_table'] = [
'#type' => 'table',
'#header' => $header,
'#rows' => $rows,
'#empty' => $this->t('No URL aliases available. <a href=":link">Add URL alias</a>.', [':link' => Url::fromRoute('entity.path_alias.add_form')->toString()]),
];
$build['path_pager'] = ['#type' => 'pager'];
return $build;
}
}
......@@ -56,7 +56,7 @@ public function buildForm(array $form, FormStateInterface $form_state, $keys = N
* {@inheritdoc}
*/
public function submitForm(array &$form, FormStateInterface $form_state) {
$form_state->setRedirect('path.admin_overview_filter', [], [
$form_state->setRedirect('entity.path_alias.collection', [], [
'query' => ['search' => trim($form_state->getValue('filter'))],
]);
}
......
<?php
namespace Drupal\path;
use Drupal\Component\Utility\Unicode;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Entity\EntityListBuilder;
use Drupal\Core\Entity\EntityStorageInterface;
use Drupal\Core\Entity\EntityTypeInterface;
use Drupal\Core\Form\FormBuilderInterface;
use Drupal\Core\Language\LanguageManagerInterface;
use Drupal\Core\Path\AliasManagerInterface;
use Drupal\Core\Url;
use Drupal\path\Form\PathFilterForm;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpFoundation\Request;
/**
* Defines a class to build a listing of path_alias entities.
*
* @see \Drupal\Core\Path\Entity\PathAlias
*/
class PathAliasListBuilder extends EntityListBuilder {
/**
* The current request.
*
* @var \Symfony\Component\HttpFoundation\Request
*/
protected $currentRequest;
/**
* The form builder.
*
* @var \Drupal\Core\Form\FormBuilderInterface
*/
protected $formBuilder;
/**
* The language manager.
*
* @var \Drupal\Core\Language\LanguageManagerInterface
*/
protected $languageManager;
/**
* The path alias manager.
*
* @var \Drupal\Core\Path\AliasManagerInterface
*/
protected $aliasManager;
/**
* Constructs a new PathAliasListBuilder object.
*
* @param \Drupal\Core\Entity\EntityTypeInterface $entity_type
* The entity type definition.
* @param \Drupal\Core\Entity\EntityStorageInterface $storage
* The entity storage class.
* @param \Symfony\Component\HttpFoundation\Request $current_request
* The current request.
* @param \Drupal\Core\Form\FormBuilderInterface $form_builder
* The form builder.
* @param \Drupal\Core\Language\LanguageManagerInterface $language_manager
* The language manager.
* @param \Drupal\Core\Path\AliasManagerInterface $alias_manager
* The path alias manager.
*/
public function __construct(EntityTypeInterface $entity_type, EntityStorageInterface $storage, Request $current_request, FormBuilderInterface $form_builder, LanguageManagerInterface $language_manager, AliasManagerInterface $alias_manager) {
parent::__construct($entity_type, $storage);
$this->currentRequest = $current_request;
$this->formBuilder = $form_builder;
$this->languageManager = $language_manager;
$this->aliasManager = $alias_manager;
}
/**
* {@inheritdoc}
*/
public static function createInstance(ContainerInterface $container, EntityTypeInterface $entity_type) {
return new static(
$entity_type,
$container->get('entity_type.manager')->getStorage($entity_type->id()),
$container->get('request_stack')->getCurrentRequest(),
$container->get('form_builder'),
$container->get('language_manager'),
$container->get('path.alias_manager')
);
}
/**
* {@inheritdoc}
*/
protected function getEntityIds() {
$query = $this->getStorage()->getQuery();
$search = $this->currentRequest->query->get('search');
if ($search) {
$query->condition('alias', $search, 'CONTAINS');
}
// Only add the pager if a limit is specified.
if ($this->limit) {
$query->pager($this->limit);
}
// Allow the entity query to sort using the table header.
$header = $this->buildHeader();
$query->tableSort($header);
return $query->execute();
}
/**
* {@inheritdoc}
*/
public function render() {
$keys = $this->currentRequest->query->get('search');
$build['path_admin_filter_form'] = $this->formBuilder->getForm(PathFilterForm::class, $keys);
$build += parent::render();
$build['table']['#empty'] = $this->t('No path aliases available. <a href=":link">Add URL alias</a>.', [':link' => Url::fromRoute('entity.path_alias.add_form')->toString()]);
return $build;
}
/**
* {@inheritdoc}
*/
public function buildHeader() {
$header = [
'alias' => [
'data' => $this->t('Alias'),
'field' => 'alias',
'specifier' => 'alias',
'sort' => 'asc',
],
'path' => [
'data' => $this->t('System path'),
'field' => 'path',
'specifier' => 'path',
],
];
// Enable language column and filter if multiple languages are added.
if ($this->languageManager->isMultilingual()) {
$header['language_name'] = [
'data' => $this->t('Language'),
'field' => 'langcode',
'specifier' => 'langcode',
'class' => [RESPONSIVE_PRIORITY_MEDIUM],
];
}
return $header + parent::buildHeader();
}
/**
* {@inheritdoc}
*/
public function buildRow(EntityInterface $entity) {
/** @var \Drupal\Core\Path\Entity\PathAlias $entity */
$langcode = $entity->language()->getId();
$alias = $entity->getAlias();
$path = $entity->getPath();
$url = Url::fromUserInput($path);
$row['data']['alias']['data'] = [
'#type' => 'link',
'#title' => Unicode::truncate($alias, 50, FALSE, TRUE),
'#url' => $url->setOption('attributes', ['title' => $alias]),
];
$row['data']['path']['data'] = [
'#type' => 'link',
'#title' => Unicode::truncate($path, 50, FALSE, TRUE),
'#url' => $url->setOption('attributes', ['title' => $path]),
];
if ($this->languageManager->isMultilingual()) {
$row['data']['language_name'] = $this->languageManager->getLanguageName($langcode);
}
$row['data']['operations']['data'] = $this->buildOperations($entity);
// If the system path maps to a different URL alias, highlight this table
// row to let the user know of old aliases.
if ($alias != $this->aliasManager->getAliasByPath($path, $langcode)) {
$row['class'] = ['warning'];
}
return $row;
}
}
......@@ -38,6 +38,7 @@ public function processOutbound($route_name, Route $route, array &$parameters, B
'path.admin_edit' => 'entity.path_alias.edit_form',
'path.delete' => 'entity.path_alias.delete_form',
'path.admin_overview' => 'entity.path_alias.collection',
'path.admin_overview_filter' => 'entity.path_alias.collection',
];
if (in_array($route_name, array_keys($redirected_route_names), TRUE)) {
......
......@@ -25,6 +25,7 @@ public function onDynamicRouteEvent(RouteBuildEvent $event) {
$route_collection->add('path.admin_edit', new BcRoute());
$route_collection->add('path.delete', new BcRoute());
$route_collection->add('path.admin_overview', new BcRoute());
$route_collection->add('path.admin_overview_filter', new BcRoute());
}
/**
......
......@@ -143,7 +143,7 @@ public function testAdminAlias() {
// Delete alias.
$this->drupalGet('admin/config/search/path/edit/' . $pid);
$this->clickLink(t('Delete'));
$this->assertRaw(t('Are you sure you want to delete the path alias %name?', ['%name' => $edit['alias[0][value]']]));
$this->assertRaw(t('Are you sure you want to delete the URL alias %name?', ['%name' => $edit['alias[0][value]']]));
$this->drupalPostForm(NULL, [], t('Delete'));
// Confirm that the alias no longer works.
......
......@@ -46,4 +46,11 @@ public function testLegacyCollectionRoute() {
$this->assertNotEmpty(Url::fromRoute('path.admin_overview')->toString());
}
/**
* @expectedDeprecation The 'path.admin_overview_filter' route is deprecated in drupal:8.8.0 and is removed from drupal:9.0.0. Use the 'entity.path_alias.collection' route instead. See https://www.drupal.org/node/3013865
*/
public function testLegacyCollectionFilterRoute() {
$this->assertNotEmpty(Url::fromRoute('path.admin_overview_filter')->toString());
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment