Create A Custom Drush Command In Drupal

Drush Command in Drupal

Drush is a command line tool built to assist you in working with Drupal from the terminal. It comes by default with a bunch of useful commands, such as downloading, enabling or even updating modules.

With drupal, drush can be extended. It is really simple and everyone can write their own drush commands. As an example, I am going to show you how you to trigger a node save.

First, we will need a drush command file. The drush command file must end with .drush.inc.

It can be placed in a number of locations.

1. Drush folder in your home directory: ~/.drush. If you put the drush command file in that directory, your commands will be available for all your projects.

2. Inside a module: Add your command file to the module folder. This is more preferable if the command functionality is specific for a project.

In this file, we are going to implement the hook_drush_command() hook. This hook defines the drush command.

File: mymodule.drush.inc

Hook function: mymodule_drush_command()

<?php
function MYMODULE_drush_command() {
  $items  = array();
  $items['nodecreate'] = array(
    'callback'    => 'custom_drush_create_node',
    'description' => dt('Triggers a node-save'),
    'aliases' => array('nc'),
    'arguments'   => array(
      'title'     => "Title of node",
    ),
    'options' => array(
      'repeat' => 'Number nodes to create.',
    ),
    'examples' => array(
      'drush nc error' => 'Prints error as node title is blank.',
      'drush nc Test --repeat=5' => 'Creates 5 nodes with title Test.',
    ),
  );
  return $items;
}

Running the Drush help command for our own command drush help nc will list some useful information about this command (arguments, options, description, aliases, examples etc)

Callback Function

As we have written callback function, Drush expects a function to be declared called drush_create_node(). This default naming structure starts with drush followed by the name of the command all connected with underscores.

function MYMODULE_create_node($title) {
  $repeat = drush_get_option('repeat', 1);
  for ($i=0; $i < $repeat; $i++) {
    $node = new stdClass();
    $node->type = "page";
    $node->title = $title;
    $node->language = LANGUAGE_NONE;
    $node->uid = 1;
    $node = node_submit($node);
    node_save($node);
  }
  drupal_set_message(t('Created ' . $repeat . ' node with title ' . $title));
}

Now clear the drush cache: drush cc drush

And run command: drush nc OR drush nodecreate

Arguments and options

-> Arguments are mandatory whereas options are not.

-> Arguments are passed as function parameters (in order) while options are retrieved in the callback using a special helper function (drush_get_option).

We declared 1 argument (called title) and one option called repeat.

-> The argument type will be the first string that gets written after the command name in the terminal (drush nodecreate or drush nc).

-> The option will be an integer value that gets assigned to the --repeat flag in the command.

Ex. drush nc Test --repeat=2

This will create 5 nodes, with title “Test”

User input

Let’s make it so that if a user doesn’t pass an argument, we ask them what argument they’d like to pass and use the value they provide interactively.

This goes to the top of the command callback function before checking whether the correct argument was passed.

// Check for existence of argument
if (!$title) {
  $options = array(
    'Test' => t('Test'),
    '0' => t('Error'),
  );
  $title = drush_choice($options, t('Please choose a option.'));
}
…
  1. Everything happens only if the user has not passed an argument.
  2. We create an array of key-value pairs that will represent the choices we give the user. The array keys represent the machine name of the choice while the values, the human readable name.
  3. We pass this array along side a question string to the drush_choice() function that will return the machine name of the choice the user makes. And that becomes our new $title variable (the argument).

If the title is not set or error is returned, we can add code to print error in terminal.

…
  if(!$title || $title='error') {
    drupal_set_message(t('Error! No title set.'));
  }
…

Full Code will look something like this:

<?php
 
function MYMODULE_drush_command() {
  $items  = array();
  $items['nodecreate'] = array(
    'callback'    => 'custom_drush_create_node',
    'description' => dt('Triggers a node-save'),
    'aliases' => array('nc'),
    'arguments'   => array(
      'title'     => "Title of node",
    ),
    'options' => array(
      'repeat' => 'Number nodes to create.',
    ),
    'examples' => array(
      'drush nc error' => 'Prints error as node title is blank.',
      'drush nc Test --repeat=5' => 'Creates 5 nodes with title Test.',
    ),
  );
  return $items;
}
 
function MYMODULE_create_node($title) {
  if (!$title) {
    $options = array(
      'Test' => t('Test'),
      '0' => t('Error'),
    );
    $title = drush_choice($options, t('Please choose a option.'));
  }
  if(!$title || $title='error') {
    drupal_set_message(t('Error! No title set.'));
  }
  else {
    $repeat = drush_get_option('repeat', 1);
    for ($i=0; $i < $repeat; $i++) {
      $node = new stdClass();
      $node->type = "page";
      $node->title = $title;
      $node->language = LANGUAGE_NONE;
      $node->uid = 1;
      $node = node_submit($node);
      node_save($node);
    }
    drupal_set_message(t('Created ' . $repeat . ' node with title ' . $title));
  }
}

Feel free to drop your any queries/concern related to this blog. For Drupal Web Development we are always ready to help :) Stay tuned!