Commit b569d2be authored by Patrick Kenny's avatar Patrick Kenny Committed by Norman Kämper-Leymann
Browse files

Issue #3265249 by ptmkenny, leymannx: Add drush command

parent a67ab883
Loading
Loading
Loading
Loading

drush.services.yml

0 → 100644
+6 −0
Original line number Diff line number Diff line
services:
  resave_all_nodes.commands:
    class: \Drupal\resave_all_nodes\Commands\ResaveAllNodesCommands
    arguments: ['@entity_type.manager']
    tags:
      - { name: drush.command }
+2 −3
Original line number Diff line number Diff line
type: module
name: Resave All Nodes
description: This module provides a form and a Drush command both implementing Batch API to resave all nodes or all nodes of a selected type.
package: Other
core: 8.x
core_version_requirement: ^8 || ^9
package: Development
core_version_requirement: ^8.8 || ^9
configure: resave_all_nodes.form

dependencies:
+7 −6
Original line number Diff line number Diff line
@@ -7,7 +7,8 @@ use Drupal\node\Entity\Node;
/**
 * Resave All Nodes batch.
 *
 *   See https://git.drupalcode.org/project/drupal/blob/8.7.8/core/includes/form.inc#L556-668
 *   See
 * https://git.drupalcode.org/project/drupal/blob/8.7.8/core/includes/form.inc#L556-668
 * for detailed information on batch processing.
 *
 * @package Drupal\resave_all_nodes\Batch
@@ -25,9 +26,9 @@ class ResaveAllNodesBatch {
   * @throws \Drupal\Core\Entity\EntityStorageException
   */
  public static function batchOperation(array $chunk, array &$context) {
    foreach ($chunk as $nid) {
    $nodes = Node::loadMultiple($chunk);
    /** @var \Drupal\node\Entity\Node $node */
      $node = Node::load($nid);
    foreach ($nodes as $node) {
      $node->save();
      // Make sure node is translatable.
      if ($node->isTranslatable()) {
@@ -40,7 +41,7 @@ class ResaveAllNodesBatch {
          }
        }
      }
      $context['results'][] = $nid;
      $context['results'][] = $node->id();
    }
  }

+101 −0
Original line number Diff line number Diff line
<?php

namespace Drupal\resave_all_nodes\Commands;

use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Entity\Query\QueryInterface;
use Drush\Commands\DrushCommands;
use Drush\Utils\StringUtils;

/**
 * Provide Drush commands for the Resave All Nodes module.
 */
class ResaveAllNodesCommands extends DrushCommands {

  /**
   * The entity type manager.
   *
   * @var \Drupal\Core\Entity\EntityTypeManagerInterface
   */
  protected $entityTypeManager;

  /**
   * ResaveAllNodesCommands constructor.
   */
  public function __construct(EntityTypeManagerInterface $entityTypeManager) {
    parent::__construct();
    $this->entityTypeManager = $entityTypeManager;
  }

  /**
   * Resave all nodes command.
   *
   * @param array $options
   *   Array of options as described below.
   *
   * @option bundles
   *   A comma-delimited list of content types to resave.
   * @option chunk-size
   *   Define how many nodes will be resaved in the same step. Default: 250.
   * @usage drush resave-all-nodes
   *   Resave all nodes in chunks of 250.
   * @usage drush resave-all-nodes --bundles=article
   *   Resave all article nodes.
   * @usage drush resave-all-nodes --chunk-size=5
   *   Resave all nodes in chunks of 5.
   *
   * @command resave-all-nodes
   * @aliases ran
   */
  public function resaveAllNodes(array $options = [
    'bundles' => self::REQ,
    'chunk-size' => 250,
  ]) {
    $query = $this->getQuery($options);
    $result = $query->execute();
    if (empty($result)) {
      $this->logger()->success(dt('No matching nodes found.'));
    }
    else {
      $this->io()->progressStart(count($result));
      foreach (array_chunk($result, $options['chunk-size'], TRUE) as $chunk) {
        drush_op('\Drupal\resave_all_nodes\Batch\ResaveAllNodesBatch::batchOperation', $chunk, []);
        $this->io()->progressAdvance(count($chunk));
      }
      $this->io()->progressFinish();
      $this->logger()->success(dt("Saved node IDs: !ids", ['!ids' => implode(', ', array_values($result))]));
    }
  }

  /**
   * The query to get the nodes.
   *
   * @param array $options
   *   The options passed along the command, the get the bundles if any.
   *
   * @return \Drupal\Core\Entity\Query\QueryInterface
   *   The query object that can query the given node types or all nodes.
   *
   * @throws \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException
   * @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException
   */
  protected function getQuery(array $options): QueryInterface {
    $storage = $this->getEntityTypeManager()->getStorage('node');
    $query = $storage->getQuery()->accessCheck(FALSE);
    if ($bundles = StringUtils::csvToArray((string) $options['bundles'])) {
      $query = $query->condition('type', $bundles, 'IN');
    }
    return $query;
  }

  /**
   * Retrieve the entity type manager.
   *
   * @return \Drupal\Core\Entity\EntityTypeManagerInterface
   *   The entity type manager.
   */
  public function getEntityTypeManager(): EntityTypeManagerInterface {
    return $this->entityTypeManager;
  }

}
+2 −2
Original line number Diff line number Diff line
@@ -128,7 +128,7 @@ class ResaveAllNodesForm extends FormBase {
    // An array with lots of node IDs.
    $nids = $this->getNodeIds($node_types);
    // Chop array into sub-arrays (chunks) of specified size.
    $chunks = array_chunk($nids, $chunk_size);
    $chunks = array_chunk($nids, $chunk_size, TRUE);
    $num_chunks = count($chunks);

    // Now resave all nodes chunk by chunk.
@@ -141,7 +141,7 @@ class ResaveAllNodesForm extends FormBase {
    }

    $batch = [
      'title' => $this->t('Resaving nodes'),
      'title' => $this->t('Resaving @count nodes', ['@count' => count($nids)]),
      'progress_message' => $this->t('Completed @current out of @total chunks.'),
      'finished' => '\Drupal\resave_all_nodes\Batch\ResaveAllNodesBatch::batchFinished',
      'operations' => $operations,