Skip navigation.
Sushi Knights

Tutorial: Creando módulos de drupal

::

Drupal es la plataforma de contenido que utilizamos para crear SushiKnights. Es usado por millones de sitios web en el mundo y es una herramienta muuuuy estable e infinitamente configurable. Drupal lleva ya varios años de desarrollo y la calidad de su código es muy buena. En mi trabajo constantemente debo crear sitios complejos y utilizo Drupal como base, lo cual me ahorra muchisimo trabajo. Drupal funciona a base de módulos, la misma idea de los plugins de firefox.

La instalación de drupal es facilísima y por ello no voy a escribir sobre ella. Para los que hayan trabajado un poco con Drupal, decidí crear una pequeña guía para mostra como crear nuevos módulos y así extender las funcionalidades. Esta es una serie de dos artículos, el primero vamos a crear un módulo que provee una nueva clase de bloque. En el segundo (proximamente) mostraremos como crear páginas, formularios y guardar información.

Seguir leyendo

En el ejemplo vamos a crear un nuevo módulo que nos va a ofrecer un nuevo tipo de bloque (las cajitas que aparecen por los lados del sitio). Lo primero es tener un Drupal funcionando. Esto, como ya dije, no lo veremos aquí. Si veo interés por el tema, puedo escribir un nuevo artículo detallando la instalación.

Nuestro bloque mostrará una imagen al azar eligiéndola de un directorio configurado previamente. Para esto, es necesario configurar la ruta de las imágenes, su ancho y su alto.

Creando los directorios necesarios y archivos necesarios.

Lo primero es entrar al directorio de instalación de drupal, supongamos que es 'midrupal'. Luego entramos a modules y ahí crearemos un directorio llamado rimage (por 'random image en' ingles). Dentro de este directorio debemos crear dos archivos: rimage.info y rimage.module

En rimage.info pondremos estas lineas

; $Id$
name = Imagenes al azar
description = "Provee un bloque de imagenes al azar"
core = 6.x

La primera línea es necesaria para los módulos, siempre deben ponerla. En name va el nombre del módulo y en descripción pueden poner una pequeña reseña de lo que hace el módulo (un poco más de detalle). A partir de drupal 6, es obligatorio que un módulo indique la versión de drupal que necesita para correr. En nuestro ejemplo usaremos drupal 6 porque es la más moderna.

Luego en el archivo rimage.module incluimos esta línea:

<?php

Notarán que no incluyo el ?> de cierre. Esto es porque la guía de desarrolladores pide que así sea. No se todavía el motivo :D

Activando el módulo

Ahora, entra a tu instalación del Drupal y ve a "administración > construcción del sitio > bloques ", busca tu módulo y actívalo. Nuestro módulo ya funciona!!!! no hace nada más que usar espacio en nuestro disco duro y ciclos de CPU, pero ya es tu primer módulo de drupal.

nota: Si no ves tu módulo en la lista de módulos, entonces revisa el archivo .info porque cualquier error hará que no aparezca.

Ahora vamos a lo realmente entretenido

Un poco de trasfondo: Los hooks

El sistema de módulos de drupal se basa en "hooks", o "ganchos" como se traduce al español. (No, no me manden mails de odio por usar una traducción literal... solo lo hice por completitud :)

Un hook es una función que podríamos, o no, escribir en nuestro módulo. Dependiendo de cuales funciones escribamos nuestro módulo ofrecerá nuevas funcionalidades. Drupal ofrece una GRAN cantidad de Hooks con lo cual un módulo de drupal podría modificar cualquier parte del funcionamiento del sitio. Pero vamos calmadamente.

Primero implementaremos el hook help. Agregamos las siguientes lineas a rimage.module

function rimage_help($section='') {
  
$output '';
  switch (
$section) {
    case 
"admin/help#rimage":
      
$output '<p>'.  t("Un bloque de imagenes al azar"). '</p>';
      break;
  }

  return $output;
}

Fijate que el nombre de la función es rimage_help. Es muy importante que cada ves que implementas un hook la función tiene que tener por nombre "NombreDeModulo_nombreDeHook". Así pues, todos nuestros hooks comenzarán con rimage_.

Luego cuando vayamos a la ayuda en drupal, aparecerá una entrada nueva con el nombre de nuestro módulo. Al hacer click en ella veremos el texto de ayuda que es devuelto por esta función. Ya hemos agregado una funcionalidad nueva a nuestro módulo. Vamos un poco más adelante.

Implementando el hook block

Para nuestro ejemplo nos interesa implementar el hook form, pues el que usan los módulos para informar a drupal que ofrecen nuevos bloques. Primero veamos la cabecera de nuestra función.

function rimage_block($op 'list'$delta 0$edit = array())

El primer parametro nos dice que tipo de operación quiere hacer drupal sobre nuestro módulo. Estos son los valores que $op puede tomar y lo que espera drupal que nuestra funcion devuelva en cada caso:

* 'list': Debemos devolver una lista de los bloques que este módulo entrega. Un módulo de drupal puede ofrecer muchos bloques distintos
* 'configure': Un formulario de configuración para cada bloque distinto
* 'save': El usuario a apretado "enviar" en la configuración del bloque y drupal nos pasa los valores para que los guardemos
* 'view': Debemos devolver el bloque dibujado en html para que drupal lo despliegue en forma correcta

Los parámetros $delta y $edit solo tienen sentido para algunos valores de $op. Lo primero será decirle a drupal que nosotros proveemos un bloque llamado "imagenes al azar". Agreguemos estas lineas a nuestro rimage.module

function rimage_block($op 'list'$delta 0$edit = array()) {
  if (
$op == 'list') {
    
$blocks[0] = array(
        
'info' => t('Despliega una imagen al azar')
        , 
'weight' => 0
        
'status' => 1
        
'cache' => BLOCK_NO_CACHE
        
'region' => 'left');
    return 
$blocks;
  } 

Esto quiere decir que cuando drupal nos pida 'list', nosotros entregaremos un arreglo el cual contiene en cada elemento la definición de un bloque. La definición de un bloque es muy sencilla, consite en un arreglo asociativo con algunos parametros prellenos. Veamo:

* info: Es la descripción del bloque, tal como aparecerá en el listado de bloques en la administración
* weight: es el peso por default. El peso se refiere al orden dentro de la columna. Mientras mayor sea el número, más se hundirá. El defecto es 0.
* status: Si lo ponemos en 1, el bloque aparecerá cuando activemos el módulo sin necesidad de configurar nada.
* cache: Este parámetro es muy hardcore de drupal. No viene al caso explicarlo aquí. Para evitar cualquier problema, déjalo en BLOCK_NO_CACHE.
* region: Donde debe aparecer el bloque. Nosotros elegimos 'left' (izquierda) pero podría haber sido 'right'. Esto depende del tema gráfico que estés usando.

Y por último, devolvemos el arreglo de bloques. Con estas lineas hacemos que nuestro bloque aparezca en el listado de bloques que podemos agregar al sitio.

Ahora vamos a crear el formulario de configuración del módulo.

else if ($op == 'configure' && $delta == 0) {
    
$form['title'] = array(
      
'#type' => 'textfield',
      
'#title' => t('Titulo'),
      
'#default_value' => variable_get('rimage_title'''),
    );
    
$form['directory'] = array(
      
'#type' => 'textfield',
      
'#title' => t('Directorio'),
      
'#default_value' => variable_get('rimage_directory'''),
    );
    
$form['prefix'] = array(
      
'#type' => 'textfield',
      
'#title' => t('Prefijo'),
      
'#default_value' => variable_get('rimage_prefix'''),
    );
    
$form['width'] = array(
      
'#type' => 'textfield',
      
'#title' => t('ancho'),
      
'#default_value' => variable_get('rimage_width'''),
    );
    
$form['height'] = array(
      
'#type' => 'textfield',
      
'#title' => t('altura'),
      
'#default_value' => variable_get('rimage_height'''),
    );
    return 
$form;
  }

Puede parecer un poco complejo, pero en realidad es muy fácil. Cuando $op es 'configure', drupal espera que especifiquemos un formulario web para los valores que querramos guardar. El valor de $delta nos dice que tipo de bloque estamos tratando de configurar. Un formulario en drupal consiste en un arreglo de arreglos. Cada arreglo esta asociado al nombre de un campo. Veamos un ejemplo, el campo de configuración del directorio que contiene las imagenes.

    $form['directory'] = array(
      
'#type' => 'textfield',
      
'#title' => t('Directorio'),
      
'#default_value' => variable_get('rimage_directory'''),
    );

El nombre del campo es la llave del arreglo, en este caso directory. El arreglo asociado tiene los siguientes campos:

* #type: dice que tipo de campo es. textfield es un campo de texto. puede ser select, textarea, etc.
* #title: El título de nuestro campo.
* #default_value: El valor que tendrá nuestro campo cuando aparezca la página de configuración

Aquí voy a hacer un alto para mostrar dos funciones muy útiles de drupal. La primera es la función t(). Esta función debemos usarla cada ves que queramos escribir texto que vallan a ver nuestros usuarios. Y "para que?" se preguntarán... bueno, drupal permite que cualquier texto que está envuelto en esta función sea traducido de formaautomática si el valor está en las traducciones de drupal (módulos que se bajan por separado). Además drupal permite cambiar desde la misma configuración el valor de cualquier string que se haya puesto en esta función. MUUUUY util si piensas traducir tu módulo a otros idiomas.

La segunda función es variable_get(). Esta función recibe una llave y buscará dentro de drupal un valor asociado a esa llave. Se usa en conjunto con variable_set() que sirve para guardar valores. Es una manera sencilla de guardar valores de configuración sin tener que recurrir a la base de datos. Variable_get recibe dos argumentos, la llave y el valor que debe devolver si la llave no contiene valor alguno.

Volviendo a los formularios, este es un tema bastante simple, pero también bastante extenso. Por eso, si quieren saber más al respecto pueden ver la api de formularios en drupal

Ahora vamos a guardar los valores que estábamos configurando.

 else if ($op == 'save' && $delta == 0) {
    
variable_set('rimage_directory'$edit['directory']);
    
variable_set('rimage_title'$edit['title']);
    
variable_set('rimage_prefix'$edit['prefix']);
    
variable_set('rimage_width'$edit['width']);
    
variable_set('rimage_height'$edit['height']);
  }

Como en el caso anterior, $delta trae el número del bloque que queremos configurar. recuerda que este número es el índice en el arreglo que creamos cuando $op valía 'list'. En $edit vienen los valores del formulario de configuración indexados por el mismo nombre que cuando lo creamos. Nota también que utilizamos la función variable_set para guardar los valores

Si tu módulo está activo, puedes ir a configurar tu bloque. Aparecerá un formulario con cinco campos que podrás modificar.

Lo único que nos queda es mostrar nuestro bloque.

 else if ($op == 'view') {
    switch(
$delta) {
      case 
0:
        
$block = array(
        
'subject' => variable_get('rimage_title''')
        , 
'content' => rimage_random_image());
        break;
    }
    return 
$block;
  }

Si $op es igual a 'view' es porque drupal quiere mostrar nuestro nuevo bloque. Generalmente aquí haremos un "switch" para elegir que bloque queremos mostrar basados en $edit.

Debemos devolver un arreglo con las propiedades del bloque. Estas propiedades son:

* subject: El título del bloque.
* content: El cuerpo de nuestro bloque.

Si te das cuenta, en content ponemos el valor de retorno de una nueva función solo para que sea más claro.

Por último, dibujamos nuestro bloque utilizando los parámetros que hemos configurado

function rimage_random_image(){
    if (
$handle opendir(variable_get('rimage_directory'''))) {
        
$files = array();
        while (
false !== ($file readdir($handle))) {
            if (
$file != '.' && $file != '..') {
                
$files[] =  $file;
            }
        }
    
        
closedir($handle);
        
$index rand(0count($files) - 1); 
        
$file $files[$index];

        $width  variable_get('rimage_width''');
        
$height variable_get('rimage_height''');
        return 
'<img src="'.variable_get('rimage_prefix''')
            .
'/'.variable_get('rimage_directory''').'/'
            
.$file.'"'
            
. ($width " width=\"$width\""'') . ( $height " height=\"$height\""'').'>';
    }
    return 
'El directorio no contiene imagenes. Puede configurarlo en '.l(t('la pagina de configuracion'), 'admin/build/block/configure/rimage/0');
}

Lo más importante de aquí es ver que recuperamos nuestros valores de configuración usando variable_get y utilizamos estos para dibujar nuestro bloque. El valor de retorno será el HTML que dibuja un elemento IMG. Si no encontramos imágenes el directorio, mostraremos un mensaje que indica como configurar el módulo. En este último caso utilizamos la funcion l(). Esta función sirve para crear links en drupal. Debes usarla si quieres crear un link a otra sección de drupal (como por ejemplo "node/21" o algo así). Si estás utilizando la opción de urls limpias, esta función se encarga de que no aparezca q= en tus urls.

Y ahora... que?

Bueno, espero que haya sido claro y simple. Pueden preguntar lo que necesiten en los comentarios. Les dejo los archivos originales para que los revisen y no tengan que estar escribiendo más de la cuenta.

* archivo .module
* archivo .info

Les dejo dos url donde podrán encontrar toda la información necesaria para crear módulos (en ingles):

* Como contribuir a Drupal
* La API de drupal

No se pierdan la siguiente entrega, donde veremos como crear páginas de drupal, llenar formularios y guardarlos en la base de datos.

Tremendo...

Muchas gracias!!

Esta realmente interesante, sobre todo para los que son como yo.... limitaditos con el ingles.

Gracias!!

Grandioso

He usado Drupal por muchos años y siempre he tenido ganas de hacer mis propios modulos. Bueno.. ya empecé.

Gracias!

Ok

Muy buena ayuda. Muchas gracias Jefe!

Hola, No salen las imagenes.

Hola,
No salen las imagenes. Na da ingun error. Solo me sale un cuadro en blamco sin imagenes.

En files/u2 tengo las images (*.jpeg)

En el campo prefijo hay que poner algo?
lo he dejado en blanco.

Siguiente entrega

Hola,

Donde puedo encontrar la siguiente entrega?

Saludos, Luis

Enviar un comentario nuevo

El contenido de este campo se mantiene como privado y no se muestra públicamente.
  • Etiquetas HTML permitidas: <a> <em> <strong> <pre> <ul> <ol> <li> <img> <blockquote> <br> <div> <h2>
  • Saltos automáticos de líneas y de párrafos.

Más información sobre opciones de formato

Cuanto es 42 + 20?
Para combatir el spam, por favor resuelva la pregunta anterior.