Desarrollando Plugins en Joomla 3.0, parte I

Esto es una serie de artículos donde tratare de explicar como desarrollar un plugin en Joomla 3, explicando como hacer un plugin que nos permita agregar información antes y después del contenido, así como modificarlo, el resultado de un articulo con dicho plugin activado es el siguiente:

Plugin Test Eventos

Resultado tras crear el plugin

Plugins en Joomla ¿Que diablos es un plugin?

Cabe mencionar que un plugin en Joomla es lo que antes eran conocidos como mambots en las primeras versiones de Joomla(cuando heredo de Mambo), menciono esto no por que sea un romántico de lo antaño, si no por que me parece mas fácil entender un plugin desde el concepto de un bot(robot o automata).

Dicho esto un Plugin en Joomla es una extensión que una vez activada dispara funcionalidades en determinados eventos.

Funcionamiento de un Plugin ¿como carajo me pueden servir?

Nos sirve para agregarle funcionalidad y personalizar el comportamiento de nuestro portal Joomla, usando plugins por ejemplo podemos:

  • Detectar y hacer algo en las autenticaciones fallidas.
  • Modificar los contenidos p.e. agregar botones de redes sociales, formularios, etc…
  • Realizar cierta acción cuando el usuario busque determinada información.
  • Enviar un correo electrónico de felicitación al usuario registrado núm 1000.
  • Realizar acciones del sistema como re-direccionamientos o manejo de errores.

Y muchas otras acciones más que pueden llegar a realizar nuestros sitios, solo es cuestión de enganchar el evento adecuado y un poco de imaginación.

Grupos de plugin ¿Como están divididos los plugins?

Cabe mencionar que los Plugins a su vez están divididos en grupos según su funcionalidad:

  • authentication
  • captcha
  • content
  • editors
  • extension
  • finder
  • search
  • system
  • user

Si observas la carpeta /plugins/ encontraras una subcarpeta para cada grupo ahí también encontraras una serie de plugins para cada grupo que te puede servir de ejemplo. Por cada grupo se definen una serie de eventos(disparados en funciones), en este manual voy a explicar el funcionamiento del grupo que corresponde a los contenidos (content).

Los eventos definidos en Content mas comunes son los siguientes:

onContentPrepare Modificando el contenido

Esta función es ejecutada antes de que el artículo se imprima en la pantalla. Si quiere modificar el contenido(ó el titulo) de alguna manera, este sería el mejor lugar para realizar estas modificaciones.

onContentBeforeDisplay Agregando texto previo al contenido

Esta función es disparada antes de que Joomla mande a imprimir el cuerpo de un contenido, aquí podemos devolver algun texto que queramos que se muestre en dicho espacio.

onContentAfterDisplay Agregando texto posterior al contenido

Esta función es disparada depues de que Joomla mande a imprimir el cuerpo de un contenido, aquí podemos devolver algún texto que queramos que se muestre en dicho espacio.

Haciendo nuestro primer plugin de Contenido Ejemplo con los eventos mas comunes

Vamos a desarollar un plugin del tipo contenido que nos sirva para probar los eventos que podemos usar(en realidad los mas comunes).

Definición del archivo instalador

<?xml version="1.0" encoding="utf-8"?>
<extension version="3.0" type="plugin" group="content" method="upgrade">
    <name>Test Eventos de Plugins</name>
    <author>Fitorec</author>
    <creationDate>02-04-2013</creationDate>
    <authorEmail>programacion@mundosica.com</authorEmail>
    <license>GNU/GPL version 2 or later</license>
    <authorUrl>https://mundosica.com</authorUrl>
    <version>1.0</version>
    <description>
        Plugin de prueba que nos muestra un el funcionamiento de los eventos en un Plugin de Joomla!
    </description>
    <files>
        <filename plugin="TestPluginEventos">TestPluginEventos.php</filename>
        <filename>TestPluginEventos.xml</filename>
    </files>
</extension>

El archivo anterior define una extensión para la versión 3.0, del tipo Plugin, que pertenece al grupo Content.

También definimos el nombre que tendrá el plugin y mas datos como autor, descripción, etc..

Algo muy importante es que definimos que el plugin TestPluginEventos esta ubidado en el archivo TestPluginEventos.php.

Faltaría definir el archivo TestPluginEventos.php donde pondremos el Plugin en cuestión.

<?php
// Restringe el Acceso al archivo si no es desde el Entorno Joomla.
defined('_JEXEC') or die;

/**
 * Plugin test de Eventos.
 */

class plgContentTestPluginEventos extends JPlugin
{
    private $_titulo = '<h3 style="color: %s">%s</h3>';

/**
 * Constructor del objeto
 * 
 * @param object &$subject es una instancia del objeto a construir
 * @param array $config parámetro opcional arreglo asociativo: puede contener las claves
 *                      'name', 'group', 'params', 'language'
 */
    public function __construct(&$subject, $config)
    {
        parent::__construct($subject, $config);
    }//fin constructor

/**
 * Esta función es ejecutada antes de renderizar el articulo
 *
 * @param String $context es el contexto en el cual es ejecutada
 * @param Object $row es un objeto que contiene la información del articulo(como titulo, contenido, url, autor, etc)
 * @param Object $params es un objeto que contiene la información del portal y parametros del plugin
 * @param Integer $limitstart desplazamiento del elemento
 */
    public function onContentPrepare($context, &$row, &$params, $limitstart)
    {
        if($context == 'com_content.article')
            $row->text = '<p>Contenido modificado en el evento <b>onContentPrepare</b></p>' . $row->text;
    }//fin onContentPrepare

/**
 * Esta función es ejecutada antes de mostrar renderizar el cuerpo del articulo
 *
 * @param String $context es el contexto en el cual es ejecutada
 * @param Object $row es un objeto que contiene la información del articulo(como contenido, url, autor, etc)
 * @param Object $params es un objeto que contiene la información del portal y parametros del plugin
 * @param Integer $limitstart desplazamiento del elemento
 */
    public function onContentBeforeDisplay($context, &$row, &$params, $limitstart)
    {
        return sprintf($this->_titulo, '#FF4A00', 'Evento onContentBeforeDisplay');
    }//fin onContentBeforeDisplay

/**
 * Esta función es ejecutada después de mostrar renderizar el cuerpo del articulo
 *
 * @param String $context es el contexto en el cual es ejecutada
 * @param Object $row es un objeto que contiene la información del articulo(como contenido, url, autor, etc)
 * @param Object $params es un objeto que contiene la información del portal y parametros del plugin
 * @param Integer $limitstart desplazamiento del elemento
 */
    public function onContentAfterDisplay($context, &$row, &$params, $limitstart)
    {
            return sprintf($this->_titulo, '#1C9202', 'Evento onContentAfterDisplay');
    }//fin onContentAfterDisplay

}

Como podemos ver un Plugin de Joomla es un Objeto que hereda de JPlugin esta clase esta definida en /libraries/joomla/plugin/plugin.php.

Es importante mencionar que al nombre de la clase se le agrega el prefijo plgContent, ya que es un plugin (plg) del tipo Contenido(Content) quedando finalmente como plgContentTestPluginEventos, si no nombramos correctamente la clase, Joomla no podrá ejecutar el plugin.

Enlaces recomendados y conclusiones

Quizas te preguntes que pasaría si ¿2 plugins(ó extensiones) activados ocuparan el mismo evento?, pues lo que sucede es que Joomla detecta las funciones definidas para determinado evento y va generando una lista de ellas para que una vez que ocurra el evento las ejecute todas, esto lo hace basado en el un patrón conodicido como Observer a continuación presento el diagrama UML del comportamiento de este patrón.

patrón Osbrver

Comportamiento patrón Observer

Si gusta abundar por en el tema le sugiero seguir las siguientes ligas:

Descarga este Plugin y proximos posts

Descargar este plugin | Visualizar el código fuente en Linea

En el siguiente articulo me gustaría hacer un plugin de contenido, ya con alguna funcionalidad mas especifica se me ocurre agregar botones de redes sociales, ocupando parámetros en el plugin.

Calendario joomla

Agregando el Calendario de Joomla a nuestras campos de formularios

En ocasiones requerimos en nuestros sitios datos insertados por los usuarios, afortunadamente Joomla! cuenta con una serie de elementos que hacen mas amena esta tarea, el día de hoy quiero explicar como insertar el calendario de Joomla! tal y como lo vemos en la parte administrativa en las opciones de publicación al editar un articulo.

Calendario joomla

Calendario joomla

Bueno como indique Joomla! cuenta con un calendario el cual es el «The New Coolest DHTML Calendar» como lo pueden ver en el archivo ubicado en: JOOMLA/media/system/js/calendar-uncompressed.js.

Agregando el calendario a un modulo Manos a la obra

Para explicar como agregar el calendario voy a crear un simple modulo, si el lector no esta familiazidado con esto le suguiero revisar el articulo creando un simple modulo para que se contextualice(aunque tratare de explicar a detalle cada parte del modulo que vamos a crear). Este modulo es solo para fines de muestra por lo cual su funcionamiento es casi nulo, los archivos que los conforman son los siguientes:

 .
├── mod_example_calendar.php     <-- Este es el modulo
├── mod_example_calendar.xml     <-- Archivo de la declaración del modulo
└── tmpl
    └── default.php              <-- Vista por defecto del modulo

Bueno el archivo mod_example_calendar.xml esta conformado por la declaración del modulo, este archivo es usado en el momento en el que instalamos el modulo desde el manejador de extensiones, también aquí se declaran los archivos que utiliza, los archivos de traducción, también contiene información acerca la versión y del desarrollador.

El archivo mod_example_calendar.php es el modulo en sí, es lo que visualizamos, sin embargo aquí se suele agregar lógica de pre-procesamiento y por lo general se suele apoyar de Helpers ó ayudantes(el cual no es el caso ya que es un modulo muy simple), veamos el código que contendrá nuestro modulo:

 <?php
/**
 * @package     Joomla.Site
 * @subpackage  mod_example_calendar
 *
 * @copyright   Copyright (C) 2005 - 2012 Open Source Matters, Inc. All rights reserved.
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

require JModuleHelper::getLayoutPath('mod_example_calendar', $params->get('layout', 'default'));

No hay mucho que explicar en dicho código solo que la linea defined('_JEXEC') or die; nos indica que para que se pueda ejecutar el archivo se deberá mandar a llamar desde el entorno de ejecución de Joomla! (_JEXEC) y en caso contrario el script detiene su ejecución(se muere die).

La siguiente linea require JModuleHelper::getLayoutPath('mod_example_calendar', $params->get('layout', 'default')); nos indica que va a mandar a cargar una vista por defecto(el default layout).

Finalmente hemos llegado a la parte mas interesante de la explicación, la cual corresponde al archivo vista por defecto el archivo ubicado en /tmpl/default.php. Lo primero que hacemos es mandar a cargar todo lo necesario para la ejecución del calendario:

// Agregamos el calendario
JHTML::_('behavior.calendar');

Ahora imaginemos que tenemos un formulario con el siguiente código HTML :

<input id="mod-ex-cal" type="text" name="fecha" tabindex="1" size="18" placeholder="Fecha" />
<a href="#" id='mod-ex-cal-ctrl' title="Inserte la fecha">Insertar fecha</a>

Lo queremos es que el calendario funcione sobre el input con con ID mod-ex-cal  y que el enlace que dice «Insertar fecha» sea el control que dispare el calendario (el que tiene un ID mod-ex-cal-ctrl), veamos como se hace esto:

//En el domready mandamos a viculamos el evento del click del calendario
$doc =& JFactory::getDocument();
$doc->addScriptDeclaration('window.addEvent(\'domready\', function() {Calendar.setup({
     inputField     :    "mod-ex-cal",        // ID del input en donde vamos a instanciar el calendario
     ifFormat       :    "%Y-%m-%d",          // Formato de la Fecha
     button         :    "mod-ex-cal-ctrl",   // ID del control el cual dispara el calendario
     align          :    "Tr",                // Alineación (Top right - Esquina superior Derecha)
     singleClick    :    true
});});'
);

descargar código fuente del ejemplo | Visualizar el código fuente en Linea

Fuentes de referencia: ¿De donde me base?