Commit 66b0fda9 authored by pfrenssen's avatar pfrenssen Committed by Berdir
Browse files

Issue #2717721 by pfrenssen, LammensJ, Adita, gaurav.kapoor, Prashant.c: Drush...

Issue #2717721 by pfrenssen, LammensJ, Adita, gaurav.kapoor, Prashant.c: Drush commands for bulk alias updates
parent c934443a
services:
pathauto.commands:
class: \Drupal\pathauto\Commands\PathautoCommands
arguments:
- '@config.factory'
- '@plugin.manager.alias_type'
- '@pathauto.alias_storage_helper'
tags:
- { name: drush.command }
<?php
namespace Drupal\pathauto\Commands;
use Consolidation\AnnotatedCommand\CommandData;
use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\pathauto\AliasStorageHelperInterface;
use Drupal\pathauto\AliasTypeBatchUpdateInterface;
use Drupal\pathauto\AliasTypeManager;
use Drupal\pathauto\Form\PathautoBulkUpdateForm;
use Drupal\pathauto\PathautoGeneratorInterface;
use Drush\Commands\DrushCommands;
use Symfony\Component\Console\Input\Input;
use Symfony\Component\Console\Output\Output;
use Symfony\Component\Console\Question\ChoiceQuestion;
/**
* Drush commands allowing to perform Pathauto tasks from the command line.
*/
class PathautoCommands extends DrushCommands {
/**
* The argument option for generating URL aliases of all possible types.
*/
const TYPE_ALL = 'all';
/**
* The configuration object factory.
*
* @var \Drupal\Core\Config\ConfigFactoryInterface
*/
protected $configFactory;
/**
* The alias type manager.
*
* @var \Drupal\pathauto\AliasTypeManager
*/
protected $aliasTypeManager;
/**
* The alias storage helper.
*
* @var \Drupal\pathauto\AliasStorageHelper
*/
protected $aliasStorageHelper;
/**
* Constructs a new PathautoCommands object.
*
* @param \Drupal\Core\Config\ConfigFactoryInterface $configFactory
* The configuration object factory.
* @param \Drupal\pathauto\AliasTypeManager $aliasTypeManager
* The alias type manager.
* @param \Drupal\pathauto\AliasStorageHelperInterface $aliasStorageHelper
* The alias storage helper.
*/
public function __construct(ConfigFactoryInterface $configFactory, AliasTypeManager $aliasTypeManager, AliasStorageHelperInterface $aliasStorageHelper) {
$this->configFactory = $configFactory;
$this->aliasTypeManager = $aliasTypeManager;
$this->aliasStorageHelper = $aliasStorageHelper;
}
/**
* (Re)generate URL aliases.
*
* @command pathauto:aliases-generate
*
* @param string $action
* The action to take. Possible actions are "create" (generate aliases for
* un-aliased paths only), "update" (update aliases for paths that have an
* existing alias) or "all" (generate aliases for all paths).
* @param array $types
* Comma-separated list of aliase typess to generate. Pass "all" to generate
* aliases for all types.
*
* @throws \Exception
*
* @usage drush pathauto:aliases-generate all all
* Generate all URL aliases.
* @usage drush pathauto:aliases-generate create canonical_entities:node
* Generate URL aliases for un-aliased node paths only.
* @usage drush pathauto:aliases-generate
* When the arguments are omitted they can be chosen from an interactive
* menu.
*
* @aliases pag
*/
public function generateAliases($action = NULL, array $types = NULL) {
$batch = [
'title' => dt('Bulk updating URL aliases'),
'operations' => [
['Drupal\pathauto\Form\PathautoBulkUpdateForm::batchStart', []],
],
'finished' => 'Drupal\pathauto\Form\PathautoBulkUpdateForm::batchFinished',
'progressive' => FALSE,
];
foreach ($types as $type) {
$batch['operations'][] = ['Drupal\pathauto\Form\PathautoBulkUpdateForm::batchProcess', [$type, $action]];
}
batch_set($batch);
drush_backend_batch_process();
}
/**
* Delete URL aliases
*
* @command pathauto:aliases-delete
*
* @param array $types
* Comma-separated list of alias types to delete. Pass "all" to delete
* aliases for all types.
*
* @option purge
* Deletes all URL aliases, including manually created ones.
*
* @throws \Exception
*
* @usage drush pathauto:aliases-delete canonical_entities:node
* Delete all automatically generated URL aliases for node entities,
* preserving manually created aliases.
* @usage drush pathauto:aliases-delete all
* Delete all automatically generated URL aliases, preserving manually
* created ones.
* @usage drush pathauto:aliases-delete all --purge
* Delete all URL aliases, including manually created ones.
* @usage drush pathauto:aliases-delete
* When the alias types are omitted they can be chosen from an interactive
* menu.
*
* @aliases pad
*/
public function deleteAliases(array $types = NULL, $options = ['purge' => FALSE]) {
$delete_all = count($types) === count($this->getAliasTypes());
// Keeping custom aliases forces us to go the slow way to correctly check
// the automatic/manual flag.
if (!$options['purge']) {
$batch = [
'title' => dt('Bulk deleting URL aliases'),
'operations' => [['Drupal\pathauto\Form\PathautoAdminDelete::batchStart', [$delete_all]]],
'finished' => 'Drupal\pathauto\Form\PathautoAdminDelete::batchFinished',
];
foreach ($types as $type) {
$batch['operations'][] = ['Drupal\pathauto\Form\PathautoAdminDelete::batchProcess', [$type]];
}
batch_set($batch);
drush_backend_batch_process();
}
elseif ($delete_all) {
$this->aliasStorageHelper->deleteAll();
$this->logger()->success(dt('All of your path aliases have been deleted.'));
}
else {
foreach ($types as $type) {
/** @var \Drupal\pathauto\AliasTypeInterface $alias_type */
$alias_type = $this->aliasTypeManager->createInstance($type);
$this->aliasStorageHelper->deleteBySourcePrefix($alias_type->getSourcePrefix());
$this->logger()->success(dt('All of your %label path aliases have been deleted.', [
'%label' => $alias_type->getLabel(),
]));
}
}
}
/**
* @hook interact pathauto:aliases-generate
*
* @throws \Drush\Exceptions\UserAbortException
* Thrown when the user cancels the operation during CLI interaction.
*/
public function interactGenerateAliases(Input $input, Output $output) {
if (!$input->getArgument('action')) {
$action = $this->io()->choice(dt('Choose the action to perform.'), $this->getAllowedGenerateActions());
$input->setArgument('action', $action);
}
}
/**
* @hook interact
*/
public function interactAliasTypes(Input $input, Output $output) {
if (!$input->getArgument('types')) {
$available_types = $this->getAliasTypes();
$question = new ChoiceQuestion(dt('Choose the alias type(s). Separate multiple choices with commas, e.g. "1,2,4", or choose "0" for all types.'), array_merge([static::TYPE_ALL], $available_types), NULL);
$question->setMultiselect(TRUE);
$types = $this->io()->askQuestion($question);
$input->setArgument('types', implode(',', $types));
}
}
/**
* @hook validate pathauto:aliases-generate
*
* @throws \InvalidArgumentException
* Thrown when one of the passed arguments is invalid
*/
public function validateGenerateAliases(CommandData $commandData) {
$input = $commandData->input();
$action = $input->getArgument('action');
$valid_actions = array_keys($this->getAllowedGenerateActions());
if (!in_array($action, $valid_actions)) {
$message = dt('Invalid action argument "@invalid_action". Please use one of: @valid_actions', [
'@invalid_action' => $action,
'@valid_actions' => '"' . implode('", "', $valid_actions) . '"',
]);
throw new \InvalidArgumentException($message);
}
}
/**
* @hook validate
*
* @throws \InvalidArgumentException
* Thrown when one of the passed arguments is invalid
* @throws \Drupal\Component\Plugin\Exception\PluginException
* Thrown when an alias type can not be instantiated.
*/
public function validateAliaseTypes(CommandData $commandData) {
$input = $commandData->input();
// Convert the comma-separated list of types to an array with no duplicates.
$types = explode(',', $input->getArgument('types'));
$types = array_map('trim', $types);
sort($types);
$types = array_unique($types);
// Set all available types if the user chooses this option.
if (in_array(static::TYPE_ALL, $types)) {
$types = $this->getAliasTypes();
}
// Check for invalid types.
$available_types = $this->getAliasTypes();
$unsupported_types = array_diff($types, $available_types);
if (!empty($unsupported_types)) {
$message = dt('Invalid type argument "@invalid_types". Please choose from the following: @valid_types', [
'@invalid_types' => '"' . implode('", "', $unsupported_types) . '"',
'@valid_types' => '"' . implode('", "', [static::TYPE_ALL] + $available_types) . '"',
]);
throw new \InvalidArgumentException($message);
}
// Pass the array of types to the command, rather than the comma-separated
// string.
$input->setArgument('types', $types);
}
/**
* Returns the allowed actions according to the site configuration.
*
* @return array
* An associative array of allowed option descriptions, keyed by option
* name.
*/
protected function getAllowedGenerateActions() {
$actions = [
PathautoBulkUpdateForm::ACTION_CREATE => dt('Generate a URL alias for un-aliased paths only.'),
];
// The options that affect existing URL aliases are allowed unless the
// site is configured to preserve existing aliases.
$config = $this->configFactory->get('pathauto.settings');
if ($config->get('update_action') !== PathautoGeneratorInterface::UPDATE_ACTION_NO_NEW) {
$actions[PathautoBulkUpdateForm::ACTION_UPDATE] = dt('Update the URL alias for paths having an old URL alias.');
$actions[PathautoBulkUpdateForm::ACTION_ALL] = dt('Regenerate URL aliases for all paths.');
}
return $actions;
}
/**
* Returns the available alias types for which aliases can be generated.
*
* @return array
* An indexed array of alias types.
*
* @throws \Drupal\Component\Plugin\Exception\PluginException
* Thrown when an alias type can not be instantiated.
*/
public function getAliasTypes() {
$types = [];
foreach ($this->aliasTypeManager->getVisibleDefinitions() as $id => $definition) {
/** @var \Drupal\pathauto\AliasTypeInterface $aliasType */
$aliasType = $this->aliasTypeManager->createInstance($id);
if ($aliasType instanceof AliasTypeBatchUpdateInterface) {
$types[] = $aliasType->getPluginId();
}
}
return $types;
}
}
......@@ -15,6 +15,21 @@ use Symfony\Component\DependencyInjection\ContainerInterface;
*/
class PathautoBulkUpdateForm extends FormBase {
/**
* Generate URL aliases for un-aliased paths only.
*/
const ACTION_CREATE = 'create';
/**
* Update URL aliases for paths that have an existing alias.
*/
const ACTION_UPDATE = 'update';
/**
* Regenerate URL aliases for all paths.
*/
const ACTION_ALL = 'all';
/**
* The alias type manager.
*
......@@ -76,8 +91,8 @@ class PathautoBulkUpdateForm extends FormBase {
$form['action'] = [
'#type' => 'radios',
'#title' => $this->t('Select which URL aliases to generate'),
'#options' => ['create' => $this->t('Generate a URL alias for un-aliased paths only')],
'#default_value' => 'create',
'#options' => [static::ACTION_CREATE => $this->t('Generate a URL alias for un-aliased paths only')],
'#default_value' => static::ACTION_CREATE,
];
$config = $this->config('pathauto.settings');
......@@ -89,8 +104,8 @@ class PathautoBulkUpdateForm extends FormBase {
];
}
else {
$form['action']['#options']['update'] = $this->t('Update the URL alias for paths having an old URL alias');
$form['action']['#options']['all'] = $this->t('Regenerate URL aliases for all paths');
$form['action']['#options'][static::ACTION_UPDATE] = $this->t('Update the URL alias for paths having an old URL alias');
$form['action']['#options'][static::ACTION_ALL] = $this->t('Regenerate URL aliases for all paths');
}
$form['actions']['#type'] = 'actions';
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment