Tips para desarrollar la interfaz del usuario en Drupal

June 18, 2021

Drupal cuenta con algunas herramientas que pueden facilitar la construcción de algunos elementos visuales básicos en algunas páginas como vínculos HTML, imágenes, tablas, etc. Algunas son simples funciones que aceptan parámetros y devuelven un código HTML, mientras que otras se basan en hooks y funciones de theming más complejas que pueden, incluso, ayudar a separar totalmente la parte lógica de la parte de presentación, lo cual otorga más orden y escalabilidad a la funcionalidad en la que se esté trabajando. Actualmente, Drupal maneja su arquitectura de software bajo las siguientes capas:

  • Datos: en esta capa se incluye la base de datos y el API de Drupal para abstraerla.
  • Lógica: aquí es donde los módulos trabajan en conjunto con los datos para llevar a cabo cada funcionalidad necesaria.
  • Presentación: esta capa se encarga de mostrar toda la información que el usuario necesita ver para interactuar con el sistema. En esta oportunidad, nos centraremos en hablar acerca de tips para trabajar en esta capa.

Primero, conoceremos algunas funciones sumamente básicas que nos ayudan a construir HTML sin necesidad de usar concatenaciones de cadenas, ni usar HTML en medio del código PHP.

Función L (https://api.drupal.org/api/drupal/includes%21common.inc/function/l/7)

Esta función nos retorna un HTML que representa un vínculo, trae toda una serie de parámetros que permiten ingresar clases, parámetros de URL (URL queries) y también hace todo el trabajo de brindar un formato seguro contra ataques de tipo XSS (cross-site scripting). La comunidad recomienda, de ser posible, usar siempre este código para todos los vínculos internos del sitio en cuestión.

Ejemplo básico:


l('Click aqui','node/35');

Ejemplo completo:


l(
    'Click aqui',
    'node/35',
    array(
        'attributes' => array(
            'class' => array('click-here','click-here-35'),
            'target' => '_blank'
        ),
        'query' => array(
            'destination' => 'user' ,
        )
    )
);

Esta es una función sumamente básica para brindar un renderizado directo a HTML. Sin embargo, esto solamente genera un pedazo de HTML. Lo que muchos no saben cómo responder es, ¿Cómo Drupal genera el resto del HTML?

Vistazo a las herramientas de theming de Drupal

En todos los módulos del núcleo de Drupal (módulos incluidos en la instalación original de Drupal) y en la mayoría de módulos contribuidos se puede presenciar distintos archivos, algunos enfocados en la lógica y el funcionamiento del caso de uso que el módulo se encarga de solventar, y otros archivos dedicados a la presentación. Veamos un ejemplo de un módulo personalizado:

Estructura del módulo

Para aquellos que no estén muy familiarizados con la programación de módulos para Drupal, los archivos “.info” contienen únicamente información básica del módulo, mientras que el archivo “.module” es el archivo principal donde se ejecutan funciones que definen qué es lo que va a tener el módulo. Realizar este trabajo de renderizado de HTML inmerso en la lógica del archivo “.module” ofuscaría mucho el desarrollo, por lo cual se hizo lo siguiente:


function my_module_output_generate() {  

    // Code for logic layer
    // Código para la capa lógica

    /*
     * ...
     * ...
     * ...
     */

    $output_arr = array();
    $output_arr['value_1'] = $val1->title;
    $output_arr['value_2']['title'] = $val2->title;

    $output_arr['value_3'] = field_get_items('node', $item, 'field_val3');
    $output_arr['value_3'] = number_format((float)$output_arr['field_val3']['0']['value'], 2, '.', '');

    $output_arr['value_4'] = field_get_items('node', $item, 'field_val4');
    $output_arr['value_4'] = number_format((float)$output_arr['field_val4']['0']['value'], 2, '.', '');

    // Code for presentation layer
    // Código para la capa de presentación

    $output = theme('my_module_output', $output_arr);
}

La lógica de programación está elaborada para preparar la información que debe ser mostrada. Cuando finalmente se ha generado la información correcta, una theme function llamada a través de la función theme(), realiza el trabajo de transformar la información recibida a HTML.

Para ejemplo mostraremos la función que se llamó para renderizar HTML:


$output = theme('my_module_output', $output_arr);

En este ejemplo, my_module_output, es el theme function. Antes de poder usar un theme function, este debe ser declarado bajo el hook hook_theme. En este hook se define el funcionamiento del tema. Una de las cosas que se puede definir es si éste theme function definirá el código HTML dentro de la función o si usará una herramienta muy potente de Drupal que consiste en guardar archivos HTML con descripciones básicas en PHP. Estos archivos se llaman templates o plantillas y tienen doble extensión “.tpl.php.”


function my_module_theme() {
    $theme = array(
        'my_module_output' => array(
            'template' => 'my-module-output',
            'variables' => array(),
            'path' => drupal_get_path('module', 'my_module') . '/templates',
        ),
    );
    return $theme;
}

La función my_module_theme es una implementación de hook_theme (nótese que se reemplazó la palabra “hook” por el nombre del módulo en cuestión). En esta función se define sobre el theme function my_module_output lo siguiente:

  • my_module_output se manejara a través del template my-module-output.tpl.php.
  • Este template no necesita variables.
  • Este template debe estar ubicado en la carpeta “templates”, dentro de la carpeta original del módulo.

Luego


<div class="my-module-page-header">     
    <div class="my-module-field-wrapper my-module-field-wrapper-info">
        <div class="my-module-field my-module-value-1">
            <span class="label">Value 1: </span>
            <?php print t($value_1); ?>
        </div>
        <div class="my-module-field my-module-value-2">
            <span class="label">Value 2: </span>
            <?php print t($value_2['sub_index']); ?>
        </div>
    </div>
    <div class="my-module-field-wrapper my-module-field-wrapper-extra">
        <div class="my-module-field my-module-value-3">
            <span class="label">Value 3: </span>
            <?php print t($value_3); ?>
        </div>
        <div class="my-module-field my-module-value-4">
            <span class="label">Value 4: </span>
            <?php print t($value_4); ?>
        </div>
    </div>
</div>

Esto es un fragmento del archivo “my-module-output.tpl.php”, el cual contiene HTML y solo algunas líneas bastante básicas de php.

Este fue un ejemplo de un theme function personalizado. Sin embargo, Drupal ya ha construido bastantes theme functions para generar tablas, imágenes, bloques, o incluso renderizar toda una página tanto en sus módulos originales, como en los contribuidos. Una herramienta muy útil para conocer estas funciones aplicadas en una página dada, es el módulo Theme developer. Este módulo brinda una interfaz que facilita la comprensión de cómo Drupal construye una página, y aquí se explica la manera de cómo usar este módulo.

Conclusión

La importancia de separar la parte lógica y operativa, de la parte visual de la aplicación que se está trabajando, radica en mantener la escalabilidad y posibilidad de que muchas personas puedan trabajar en un proyecto al mismo tiempo. Esta arquitectura de software en la que trabaja Drupal permite crear nuevas funcionalidades, sin modificar una sola línea de código del sistema original, y que las mismas puedan desplegarse al usuario de maneras diferentes según la capa de presentación del módulo que lo permita. Esta flexibilidad es una de las razones por las que Drupal se ha convertido en una herramienta para el desarrollo de aplicaciones robustas.