Pasar al contenido principal

Implementar un comando custom en Drush

En uno de los proyectos en los que estamos trabajando actualmente se requiere hacer login mediante un servicio externo. Esto produce una serie de problemas secundarios como por ejemplo la necesidad de crear un paso específico de Behat para los tests automáticos que requieran logar al usuario. Otro problema menor es que los desarrolladores se ven obligados a logarse manualmente usando un usuario y contraseña en el sistema externo, lo que puede llegar a ser muy tedioso.

¿Cómo hacer que esto sea más sencillo y menos molesto para el desarrollador? Fácil, siguiendo el ejemplo de gigantes y creando un comando Drush similar al existente que devuelve un enlace de login en Drupal, drush uli. Dado que ya teníamos el código que generaba enlaces de login usando el mecanismo externo (que usamos en los tests automáticos), solo necesitábamos envolver dicho código en un comando propio de Drush. El proceso es sencillo y destacamos aquí los pasos esenciales para la creación de tu propio comando de Drush.

Lo primero que hay que hacer es crear el archivo que contendrá el código y descripción del comando. Para ello, creamos el archivo COMMANDFILE.drush.inc donde COMMANDFILE será el nombre identificativo del comando. El nombre debe acabar en .drush.inc para que sea reconocido por Drush como comando.

Dentro del archivo, implementamos la función COMMANDFILE_drush_command(). Esta función contiene la descripción del comando, cómo debe llamarse y cómo se comporta.  Devolverá un array con un elemento cuyo índice será el comando que queremos implementar. Contendrá la información principal del comando organizada en diferentes propiedades. Entre las principales encontramos:

  • description: Descripción breve del comando.
  • aliases: Un array que contiene tantos aliases como queramos para nuestro comando.
  • arguments (opcional): Array con argumentos y su descripción para el comando.
  • options (opcional):  Un array con opciones que se le puede pasar al comando.

Existen bastante más propiedades definibles que se pueden encontrar en la documentación de Drush sobre la implementación de COMMANDFILE_drush_command, pero las cuatro mencionadas son suficientes para empezar a crear tus propios comandos.

Luego implementamos la función drush_COMMANDFILE_COMMANDNAME() donde COMMANDNAME es el nombre del comando que hemos definido en la función anterior (Ojo con los comandos que contienen guiones. En el nombre de la función, hay que sustituirlos por guiones bajos). Ésta función es la que ejecutará el comando cuando sea llamado por Drush.

Para terminar, situamos el archivo en un directorio donde Drush lo detecte. Dependiendo de cuando queremos utilizar el comando. Podemos hacerlo disponible a distintos niveles:

  • Directorios listados en la directiva include de Drush.
  • En el directorio /usr/share/drush/commands para todo el sistema.
  • En el directorio ~/.drush para solo un usuario.
  • En la carpeta /drush y /sites/all/drush de una instalación de Drupal para usarlo solo ese proyecto.
  • También podemos añadir la versión de Drush al nombre del archivo o al nombre de los directorios para que el comando sólo pueda utilizarse con la versión de Drush indicada.

El siguiente código es un ejemplo de cómo implementar un simple comando que devuelve una cadena de texto. En éste caso, se guarda en archivo.drush.inc en alguno de los directorios mencionados anteriormente:

<?php

/**
 * @file
 * Comando de Drush para saludar al mundo.
 */

/**
 * Implements hook_drush_command().
 */
function archivo_drush_command() {
  $items = [];
  $items['saludo'] = [
    'description' => 'Devuelve un saludo',
    'aliases' => ['hola'],
    'options' => [
      'nombre' => [
        'description' => 'El nombre de la persona a quien saludar. Por defecto saluda al mundo',
        'example-value' => 'Peter',
      ],
    ],
    'examples' => [
      'drush hola' => 'Devuelve: Hola Mundo!',
    ],
  ];
  return $items;
}

/**
 * Implements drush_hook_COMMAND().
 */
function drush_archivo_saludo() {
  $opcion = drush_get_option('nombre');
  $sujeto = !empty($opcion) ? $opcion : 'Mundo';
  return sprintf('Hola %s!', $sujeto);
}

Como nota final hay que tener en cuenta que está implementación nos sirve para Drush 8.x que es, en el momento de la creación de este artículo, la versión estable. En Drush 9.x cambia la forma de implementar comandos.

Para más información sobre comandos en Drush 8, visitar este enlace y para ver cómo cambia en Drush 9.x visitar este otro enlace.