Skip to content
Snippets Groups Projects

3419718-drush-command-to: Created drush command to remove circular redirects.

Files

+ 123
0
<?php
namespace Drupal\redirect\Commands;
use Drush\Commands\DrushCommands;
use Drupal\Core\Database\Connection;
use Psr\Log\LoggerInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\StringTranslation\TranslationInterface;
use Drupal\Core\StringTranslation\StringTranslationTrait;
/**
* Drush commands for managing redirects.
*/
class RedirectCommands extends DrushCommands {
use StringTranslationTrait;
/**
* The database connection.
*
* @var \Drupal\Core\Database\Connection
*/
protected $database;
/**
* The entity type manager service.
*
* @var \Drupal\Core\Entity\EntityTypeManagerInterface
*/
protected $entityTypeManager;
/**
* Constructs a RedirectCommands object.
*
* @param \Drupal\Core\Database\Connection $database
* The database connection.
* @param \Psr\Log\LoggerInterface|null $logger
* The logger service.
* @param \Drupal\Core\Entity\EntityTypeManagerInterface $entityTypeManager
* The entity type manager service.
* @param \Drupal\Core\StringTranslation\TranslationInterface $stringTranslation
* The string translation service.
*/
public function __construct(Connection $database, ?LoggerInterface $logger, EntityTypeManagerInterface $entityTypeManager, TranslationInterface $stringTranslation) {
$this->database = $database;
$this->logger = $logger;
$this->entityTypeManager = $entityTypeManager;
$this->stringTranslation = $stringTranslation;
parent::__construct();
}
/**
* Purge circular redirects.
*
* @command redirect:purge-circular-redirects
*/
public function purgeCircularRedirects() {
$redirect_storage = $this->entityTypeManager->getStorage('redirect');
// Loading all redirect entities.
$redirects = $redirect_storage->loadMultiple();
// Creating a map of source and destination paths.
$redirect_map = [];
foreach ($redirects as $redirect) {
$source = $redirect->get('redirect_source')->getValue()[0]['path'];
$destination = $redirect->get('redirect_redirect')->getValue()[0]['uri'];
// Remove 'internal:/' prefix if it exists
if (strpos($destination, 'internal:/') === 0) {
$destination = substr($destination, strlen('internal:/'));
}
$redirect_map[$source] = $destination;
}
// Finding circular redirects.
$circular_rids = [];
foreach ($redirect_map as $source => $destination) {
if (isset($redirect_map[$destination]) && $redirect_map[$destination] === $source) {
$this->logger->notice($this->t('Circular redirect detected: source - @source, destination - @destination', [
'@source' => $source,
'@destination' => $destination,
]));
// Loading the entities to get their RIDs.
$redirect_source = $redirect_storage->loadByProperties(['redirect_source__path' => $source]);
$redirect_destination = $redirect_storage->loadByProperties(['redirect_source__path' => $destination]);
foreach ($redirect_source as $redirect_entity) {
$circular_rids[] = $redirect_entity->id();
}
foreach ($redirect_destination as $redirect_entity) {
$circular_rids[] = $redirect_entity->id();
}
}
}
// Removing duplicates.
$circular_rids = array_unique($circular_rids);
if (!empty($circular_rids)) {
$this->logger->notice($this->t('Found @count circular redirect records to purge: @list', [
'@count' => count($circular_rids),
'@list' => implode(', ', $circular_rids),
]));
// Asking for confirmation before deleting.
if ($this->io()->confirm($this->t('Do you really want to purge these @count circular redirect records?', ['@count' => count($circular_rids)]))) {
// Deleting the circular redirects.
$redirect_storage->delete($redirect_storage->loadMultiple($circular_rids));
$this->logger->notice($this->t('Successfully purged @count circular redirect records.', [
'@count' => count($circular_rids),
]));
} else {
$this->logger->notice($this->t('Purge cancelled.'));
}
} else {
$this->logger->notice($this->t('Circular redirects not found.'));
}
}
}
Loading