Hero

Como crear comandos de Drush para modulos custom de Drupal

Junio 10, 2013

estebanvalerioh
PHP
Programación
Drupal
Desarrollo de Modulos
Drush

Las personas que trabajan con Drupal y han usado Drush, pueden garantizar que es una herramienta súmamente útil. Con está entrada de blog voy a dar una introducción de como crear comandos personalizados para Drush, de manera que sigamos haciendo de nuestro trabajo con Drupal, más sencillo.

A continuación veamos la creación paso a paso:

  1. Definir archivo de drush

Debemos crear y colocar un archivo en la raíz de nuestro módulo un nuevo archivo NOMBREMODULO.drush.inc respetando el estándar para el nombre de archivos, para que este sea reconocido por Drush.

drush01

En mi caso, el módulo que utilizo se llama pruebas, por lo tanto el nombre del archivo pruebas.drush.inc, como vimos en la imagen anterior.

  1. Definir comandos.

Debemos Implementar el hook hook_drush_command(), la definición de esta función retorna un arreglo asociativo con la información de nuestros comandos, como vemos a continuación:

/**
 * Implements hook_drush_command().
 */
function pruebas_drush_command() {
  $items = array();

  $items['mostrar-node'] = array(
    'description' => 'Muestra un nodo específico.',
    'aliases' => array('pruebas-mn'),
  );

  $items['mostrar-usuario'] = array(
    'description' => 'Muestra un usuario.',
    'aliases' => array('pruebas-mu'),
    'arguments' => array(
      'uid' => 'Identificador del usuario.',
    ),
    'required-arguments' => TRUE,
    'options' => array(
      'campos' => 'Lista separada por comas de campos del objeto para mostrar (e.g. uid, mail, status)',
    ),
    'examples' => array(
      'drush pruebas-mu  1 --campos=uid,mail,status' => 'Muestra los campos indicados para el usuario con id.',
    ),
  );

  return $items;
}

En este ejemplo, estoy creando dos comandos, uno llamado mostrar-node y el otro mostrar-usuario. Es muy importarte notar que el índice de cada ítem en nuestro arreglo asociativo equivale al nombre de nuestro comando, basado en este nombre es que vamos a crear las funciones que implementan las acciones que nuestros comandos van a ejecutar.

Para el comando mostrar-node, estoy definiendo dos atributos, la descripción del mismo y el atributo aliases, que define abreviaturas con las cuales puedo ejecutar mi comando. De esta manera, puedo ejecutar mi comando, escribiendo cualquiera de las dos siguientes opciones:

$ drush mostrar-node
$ drush pruebas-mn

Podemos notar en el comando mostrar-usuario, que estoy usando más atributos en la definición, los explico a continuación:

* arguments: Arreglo asociativo donde el índice es el nombre de la variable que voy a recibir como parámetro y el valor es la descripción de la variable. Con este atributo definimos explícitamente los parámetros que va a recibir el comando.

* required-arguments: Por defecto este parámetro es FALSE, en mi caso estoy colocándole como TRUE de manera que el comando valide que esté recibiendo el parámetro necesario para poder ejecutarse.

* options: Arreglo asociativo donde el índice corresponde al nombre de la opción y el valor es la descripción de la opción. Define opciones adicionales que podemos utilizar en la ejecución de nuestro comando.

* examples: Arreglo con ejemplos de las formas en cómo podemos utilizar nuestro comando. Así cuando ejecutamos drush NOMBRECOMANDO —help, logramos ver esos ejemplos, como vemos a continuación:

$ drush pruebas-mu --help
Muestra un usuario.

Examples:
 drush pruebas-mu  1       Muestra los campos indicados para el usuario con id. 
 --campos=uid,mail,status                                                       


Arguments:
 uid                                       Identificador del usuario. 


Options:
 --campos                                  Lista separada por comas de campos del objeto para mostrar (e.g. uid, mail, status) 


Aliases: pruebas-mu
  1. Implementación del comando

Como mencioné en el paso dos, el índice de cada ítem definido en el arreglo asociativo, es el nombre base para crear la función que implementa la acción de nuestro comando. Debemos seguir el siguiente estándar para definir nuestra función: drush_NOMBREMODULO_NOMBRECOMANDO().

Vemos a continuación la implementación del primer comando:

function drush_pruebas_mostrar_node($nid = NULL) {
  if (!isset($nid)) {
    print "Ningún argumento fue proporcionado. \n";
    return;
  }

  print "Nodo:\n" . print_r(node_load($nid),1) . "\n";
  return;
}

Si enviamos un identificador de nodo cuando ejecutamos este comando, nos va a mostrar el objecto del nodo, de lo contrario un mensaje donde nos indica que no proporcionamos ningún argumento. Recordemos que en la definición de este comando, no estoy usando el atributo arguments, esto lo hago apropósito para la demostrar que podemos enviar argumentos extra y sin necesidad de definiros, pero indicando al usuario de alguna forma que podemos hacerlo.

Vemos el comando en acción, con y sin argumento, a continuación:

$ drush pruebas-mn
Ningún argumento fue proporcionado. 
$ drush pruebas-mn 1
Nodo:
stdClass Object
(
    [vid] => 1
    [uid] => 1
    [title] => Página de prueba
    [log] => 
    [status] => 1
    [comment] => 1
    [promote] => 0
    [sticky] => 0
    [nid] => 1
    [type] => page
    [language] => und
    [created] => 1370310353
    [changed] => 1370310392
    [tnid] => 0
    [translate] => 0
    [revision_timestamp] => 1370310392
    [revision_uid] => 1
    [body] => Array
        (
            [und] => Array
                (
                    [0] => Array
                        (
                            [value] => Página de prueba de nuestro plugin de jQuery.

Hola, estoy probando.

Texto número 2.

Basic page
                            [summary] => 
                            [format] => full_html
                            [safe_value] => <p>Página de prueba de nuestro plugin de jQuery.</p>
<p>Hola, estoy probando.</p>
<p>Texto número 2.</p>
<p>Basic page</p>

                            [safe_summary] => 
                        )

                )

        )

    [field_archivos] => Array
        (
        )

    [rdf_mapping] => Array
        (
            [rdftype] => Array
                (
                    [0] => foaf:Document
                )

            [title] => Array
                (
                    [predicates] => Array
                        (
                            [0] => dc:title
                        )

                )

            [created] => Array
                (
                    [predicates] => Array
                        (
                            [0] => dc:date
                            [1] => dc:created
                        )

                    [datatype] => xsd:dateTime
                    [callback] => date_iso8601
                )

            [changed] => Array
                (
                    [predicates] => Array
                        (
                            [0] => dc:modified
                        )

                    [datatype] => xsd:dateTime
                    [callback] => date_iso8601
                )

            [body] => Array
                (
                    [predicates] => Array
                        (
                            [0] => content:encoded
                        )

                )

            [uid] => Array
                (
                    [predicates] => Array
                        (
                            [0] => sioc:has_creator
                        )

                    [type] => rel
                )

            [name] => Array
                (
                    [predicates] => Array
                        (
                            [0] => foaf:name
                        )

                )

            [comment_count] => Array
                (
                    [predicates] => Array
                        (
                            [0] => sioc:num_replies
                        )

                    [datatype] => xsd:integer
                )

            [last_activity] => Array
                (
                    [predicates] => Array
                        (
                            [0] => sioc:last_activity_date
                        )

                    [datatype] => xsd:dateTime
                    [callback] => date_iso8601
                )

        )

    [cid] => 0
    [last_comment_timestamp] => 1370310353
    [last_comment_name] => 
    [last_comment_uid] => 1
    [comment_count] => 0
    [name] => admin
    [picture] => 0
    [data] => b:0;
)

Ahora la implementación del segundo comando:

function drush_pruebas_mostrar_usuario($uid = NULL) {

  $output = '';
  $account = user_load($uid);

  if ($campos = drush_get_option('campos')) {
    $list = explode(',', $campos);
    foreach ($list as $key => $value) {
      $output .= "$value: {$account->$value} \n";
    }
  }
  else {
    $output .= print_r($account,1) . "\n";
  }

  print $output;
  return;
}

Mostramos el objeto de un usuario de Drupal, basado en el identificador de usuario enviado como parámetro. Recordemos que en este comando el argumento es requerido, por lo tanto, sino lo hacemos, veremos un mensaje de error.

Además, verificamos si alguna opción fue enviada, para mostrar sólo los fields especificados en las opciones, de lo contrario, mostramos el objeto total. Lo vemos a continuación:

$ drush pruebas-mu
Missing required argument: 'uid'.  See `drush help mostrar-usuario` for information on usage.                                                                                                [error]
$ drush pruebas-mu 1
stdClass Object
(
    [uid] => 1
    [name] => admin
    [pass] => $S$D6p2XbX7GqgI7RN7dpUeTAbr2ndOnQWi6I6qJ6BggngpQjdnQ2TY
    [mail] => estebanvalerio.h@gmail.com
    [theme] => 
    [signature] => 
    [signature_format] => 
    [created] => 1368918558
    [access] => 1370730160
    [login] => 1370305748
    [status] => 1
    [timezone] => America/Costa_Rica
    [language] => 
    [picture] => 
    [init] => estebanvalerio.h@gmail.com
    [data] => 
    [roles] => Array
        (
            [2] => authenticated user
            [3] => administrator
        )

    [rdf_mapping] => Array
        (
            [rdftype] => Array
                (
                    [0] => sioc:UserAccount
                )

            [name] => Array
                (
                    [predicates] => Array
                        (
                            [0] => foaf:name
                        )

                )

            [homepage] => Array
                (
                    [predicates] => Array
                        (
                            [0] => foaf:page
                        )

                    [type] => rel
                )

        )

)
$ drush pruebas-mu  1 --campos=uid,mail,status,name
uid: 1 
mail: estebanvalerio.h@gmail.com 
status: 1 
name: admin 

Espero les sea de mucha utilidad.

Saludos!

Recibe consejos y oportunidades de trabajo 100% remotas y en dólares de weKnow Inc.