Use of drush validate and post hook

In this post we are going to learn how to create module and drush commands using Drush, along with a demonstration of the validate and post hook commands.

First, we will create a module using the drush command. Let's run the following drush command and follow the instructions shown in the below picture.

drush generate module-standard
drush-input

Here we have created a module named content_processor. Now let's create a drush command in the same module which will process node content based on the provided node type.

Run the following drush command to generate command boilerplate code, which we'll further modify as per our needs.

drush generate drush-command-file
drush cmd file

As we have created a drush command boilerplate code along with a module, the structure should look like below:

drush cmd structure

Now, let's update the ContentProcessorCommands.php class code by adding the below functions:

namespace Drupal\content_processor\Commands;

use Drush\Commands\DrushCommands;

/**
 * A Drush command file.
 *
 * In addition to this file, you need a drush.services.yml
 * in root of your module, and a composer.json file that provides the name
 * of the services file to use.
 *
 * See these files for an example of injecting Drupal services:
 *   - http://cgit.drupalcode.org/devel/tree/src/Commands/DevelCommands.php
 *   - http://cgit.drupalcode.org/devel/tree/drush.services.yml
 */
class ContentProcessorCommands extends DrushCommands {
  /**
   * A command to process node content based on provided type.
   *
   * @param $node_type
   *   Node types whose content has to process.
   * @param array $options
   *   An associative array of options whose values come from cli, aliases, config, etc.
   * @option batch
   *   Number of item which should be process in one go.
   * @usage content-processor:process-content page --batch=50
   *   Usage description
   *
   * @command content-processor:process-content
   * @aliases cppc
   */
  public function processContentCommand($node_type, $options = ['batch' => '10']) {
    // Add your logic to process the content
    // or may be create a service which will the work
    // and just call that service from here
    $this->logger()->success(dt('Processing node...'));
  }

  /**
   * A validate hook for content-processor:process-content command.
   *
   * @hook validate content-processor:process-content
   *
   * @param \Consolidation\AnnotatedCommand\CommandData $commandData
   *   The command data.
   *
   * @return \Consolidation\AnnotatedCommand\CommandError|null
   *   The command data or null.
   */
  public function validateProcessContentCommand(CommandData $commandData) {
    // This is the best place to validate all your command input
    // either its interactive or non-interactive, ex node_type,
    // let assume we want to check the provide node type should be valid one.
    $node_type = $commandData->input()->getArgument('node_type');
    $allowed_node_types = ['article','page'];
    $message = [];
    if (!in_array($node_type, $allowed_node_types)) {
      $message[] = 'Invalid node type';
    }
    if ($message) {
      return new CommandError(implode(' ', $message));
    }
  }

  /**
   * This hook will be trigger just after the command.
   * @hook post-command content-processor:process-content
   */
  public function processContentPostCommand($result, CommandData $commandData) {
    // Do something after content-processor:process-content
    $this->logger()->success(dt('performing some cleanup...'));
  }
}

Run the below command to validate that it's working as expected.

drush content-processor:process-content article
0/5