Extendiendo a Joomla! 2.5 con Plugins - Parte 3

Escrito por | 01 Agosto 2013 | Publicado en Agosto 2013
Tercera parte y última del desarrollo de plugins dentro de Joomla 2.5 . En esta parte tocaremos algunos temas un tanto avanzado, como la sobreescritura de las clases del core de Joomla. También daremos algunas mejores prácticas con los plugin, culminando así esta interesante serie.

Les recomiendo si no lo han hecho ya, que lean tanto la primera parte como la segunda de esta serie para un mayor entenndimiento de esta.

Usando los plugins para hacer un override a las clases de núcleo de Joomla

Se puede usar el framework de los plugin para hacer un override a la mayoría de las clases básicas de Joomla. Este es un tema avanzado y no es algo que le recomiendo hacer a menos que realmente lo necesite. Sin embargo, es útil conocer en caso de que lo necesite.

Como son importados los Plugins

Hemos visto que, para activar un plugin, primero se utiliza el método JPluginHelper::importPlugin() para importar el plugin. Esto agrega la clase y sus métodos en la memoria de trabajo. Si echamos un vistazo más de cerca cómo funciona este método, vemos que el código que realmente hace la importación es el método privado import() de la clase JPluginHelper (libraries / joomla / plugin / helper.php), de la siguiente manera:

if (!isset($paths[$path])) {
   require_once $path;
}
$paths[$path] = true;

La primera línea comprueba si este plugin en específico ya ha sido añadido. La variable $paths es una matriz asociativa que contiene todos los plugins que ya han sido importados. La clave de la matriz es la ruta completa de cada archivo de los plugin y el valor de cada elemento es el nombre de la clase. Usamos la función isset() de PHP para comprobar si este elemento se encuentra en la matriz. Si no, entonces el comando de PHP require_once incluye este archivo. 

Por último, el valor booleano de este elemento se establece a true, que asegura que la próxima vez este elemento se encuentre en la matriz, por lo que el require_once no será llamado de nuevo para el mismo archivo.

Hay dos puntos importantes que debes comprender acerca de este proceso:

  • Como se mencionó anteriormente, normalmente los plugin declaran clases, así que no hay código ejecutandose en ese momento. La única cosa que sucede es que la clase y sus métodos se cargan en la memoria de modo que sus métodos pueden ser llamados más adelante en el ciclo. En ese caso ningún código se ejecuta realmente como resultado del método JPluginHelper::importPlugin()
  • Nada en Joomla requiere de un plugin para ser una declaración de clase. Un plugin puede ser un sencillo script PHP, es decir, uno que se ejecuta cuando es incluido. Si hacemos un plugin de este modo, se ejecutará de inmediato, tan pronto como el método JPluginHelper::importPlugin es ejecutado (y no cuando se activa el evento).

Esto proporciona un mecanismo para cargar cualquier script PHP cada vez que importamos plugins.

Como las clases de Joomla son cargadas

A continuación, tenemos que entender un punto importante acerca de cómo se cargan en la memoria de trabajo las clases del núcleo de Joomla. Si nos fijamos en la función jimport que normalmente se utiliza para cargar estas clases, vemos que es una función que esta definida en libraries/loader.php . Tenga en cuenta que esta es una función independiente, no es un método de clase. Es por eso que se invoca simplemente con el nombre de la función y no hay nombre de clases. El código para esta función se muestra a continuación:

function jimport($path)
{
return JLoader::import($path);
}

Simplemente llama al método JLoader::import(). Las primeras líneas de código en el método JLoader::import() son las siguientes:

// Only import the library if not already attempted.
if (!isset(self::$imported[$key]))

Aquí se comprueba si ya esta importada esta clase. El valor self::$imported es un matriz asociativa estática con la clave (la variable $key) igual al argumento pasado a jimport (por ejemplo, "joomla.plugin.plugin") y un valor booleano true o false. Cuando es importada una clase, se añade un elemento a este array, y el valor se establece en true si la importación se realizó correctamente y false en caso contrario. Así que, una vez que la clase ha sido importada, Joomla no tratará de importarla otra vez.

Los métodos JLoader::load() y JLoader::_autoload() también comprueban si la clase ya ha sido cargada antes de intentar cargar una clase.

Así que lo importante es esto: si la clase ya existe, lo que significa que ya está cargada en la memoria de trabajo, nos saltamos cargar esta clase. El método sólo devuelve un valor true y finaliza. Ninguno de los métodos de carga de Joomla intentará cargar una clase por segunda vez.

Esto significa que podemos utilizar un plugin para cargar una clase en la memoria de trabajo, siempre y cuando lo hagamos antes de que se cargue por el núcleo de Joomla. Si hacemos esto, se utilizarán los métodos de nuestra clase en lugar de los métodos de la clase del núcleo.

Da la casualidad que los plugins del sistema se cargan en la memoria de trabajo muy temprano en el ciclo de ejecución de Joomla, antes de que la mayoría (pero no todas) de las clases del núcleo de Joomla.

Ejemplo: Reemplazar la Clase JTableNested

Vamos a hacer un ejemplo rápido para ilustrar esto. Vamos a sustituir la clase JTableNested del núcleo. Esta clase es la clase padre de todas las clases de tablas anidadas en Joomla (por ejemplo, JTableCategories para la tabla #__categories). En este ejemplo, vamos a demostrar cómo reemplazar esta clase, pero les dejo a su imaginación que parte del código y comportamiento desean cambiar.

Estos son los pasos:

1-   Cree una nueva carpeta llamada plugins/system/myclasses y copie el archivo libraries/joomla/database/tablenested.php para esta nueva carpeta. Esto le dará un archivo llamado plugins/system/myclasses/tablenested.php . (Recuerde que debe añadir los archivos index.html a todas las nuevas carpetas que vayamos a crear.)

2-   Edite el nuevo archivo y sustituya el método existente rebuild() con el siguiente código:

public function rebuild($parentId = null, $leftId = 0, $level = 0, $path = '')
{
   exit('Desde mi archivo myclasses/tabelnested.php');
}

Este código simplemente demuestra que estamos ejecutando nuestra clase en lugar de la clase del núcleo. Cuando pulsamos la opción "Reconstruir" (por ejemplo, en el Gestor de categorías), si estamos ejecutando nuestro método, el programa debe salir con el mensaje que mostramos.

3-   Ahora tenemos que añadir el plugin para cargar nuestra clase en lugar de la clase del núcleo. Vamos a llamar el plugin "myclasses". Para hacer esto, cree un nuevo archivo llamado myclasses.php en la carpeta plugins/system/myclasses.

4-   En el nuevo archivo (plugins/system/myclasses/myclasses.php), agregue el código siguiente:

<?php
/**
* Demostración de un plugin para reemplazar las clases del núcleo.
* Se dispara en la primera importación del sistema (antes
* del evento onBeforeInitialise).
*/
// No permitir el acceso directo
defined('_JEXEC') or die;
// Reemplazar JTableNested del núcleo con esta versión de override
include_once JPATH_ROOT.'/plugins/system/myclasses/tablenested.php';

Tenga en cuenta que este código no está declarando una clase. El simplemente ejecuta un script. Esto significa que se ejecutará tan pronto como se importen los plugins del sistema, antes del primer evento del sistema. Este código sólo incluye nuestro nuevo archivo tablenested.php.

5-   Crea el archivo XML para este plugin (plugins/system/myclasses/myclasses.xml) con lo siguiente:

<?xml version="1.0" encoding="utf-8"?>
<extension version="2.5" type="plugin" group="system">
     <name>plg_system_myclasses</name>
     <author>Carlos Rodríguez</author>
     <creationDate>Junio 7</creationDate>
     <copyright>Copyright (C) 2013</copyright>
     <license>GPL2</license>
     <authorEmail> Esta dirección de correo electrónico está siendo protegida contra los robots de spam. Necesita tener JavaScript habilitado para poder verlo. </authorEmail>
     <authorUrl>www.joomla-plus.org</authorUrl>
     <version>2.5</version>
     <description>Plugin MyClasses de muestra</description>
     <files>
          <filename plugin="myclasses">myclasses.php</filename>
          <filename>index.html</filename>
     </files>
     <config>
     </config>
</extension>

6-   Vaya al backend de Joomla y Descubra e Instale el plugin como hemos hecho antes en los ejemplos anteriores. Recuerde también "Activar" el plugin en el Gestor de Plugin.

7-   Vaya al Contenido → Gestor de categorías en el back-end de Joomla y haga clic en el icono de "Reconstruir". Joomla se debe detener y deberías de ver el mensaje del archivo myclasses/tabelnested.php . Esto indica que tuvimos éxito sobreescribiendo la clase del núcleo de Joomla.

Esta técnica se puede utilizar para sobreescribir las clases del núcleo de Joomla, a excepción de aquellas que ya están cargadas antes de que se importen los plugins del sistema.

Si sobreescribes una clase del núcleo de esta manera, no tienes que preocuparte durante la actualización de Joomla. Así que esta técnica es mucho mejor que los hack a los archivos del núcleo. Sin embargo, una palabra de precaución está en orden aquí. Si hay correcciones de errores para las clases del núcleo que tienes sobreescritas, tendrás que comprobar si estas soluciones se aplican a las clases del override. Si es así, tendrás que aplicar las correcciones tú mismo. Esto será especialmente importante si el fallo corrige problemas de seguridad.

Plugin Mejores Prácticas

Lo más importante acerca de los plugins es saber cuándo usarlos. Esto significa entender los eventos disponibles en Joomla y qué estándar de comportamientos se pueden reemplazar. En muchos casos, cuando estás teniendo un momento difícil encontrando la manera de resolver un problema con un módulo o un componente, un plugin puede hacer el trabajo mucho más fácil.

Aquí están algunos consejos acerca de los plugins:

  • Los plugins se ejecutan en el orden en que aparecen en la columna Orden en el Gestor de plugins. En la mayoría de los casos, el orden no importa. Sin embargo, en algunos casos, cuando tienes más de un plug-in que se activa con el mismo evento, y donde los resultados de un plug-in pueden afectar el procesamiento de otro posterior, el orden puede ser importante. En este caso, puedes cambiar el orden en el Gestor de plugins mediante el ajuste de los valores que controlan el Ordenamiento de los mismo, poniendo así un orden de ejecución.
  • Normalmente, usamos las convenciones de nomenclatura para los nombres de las clases de los plugin y el nombre del método. De lo contrario, los los plugins no se llamarán correctamente. La excepción es, si desea que un script sea ejecutado cuando el plugin es importado, en cuyo caso sólo el archivo y nombre de la carpeta es importante (como en el ejemplo anterior).
  • Diferentes eventos requieren diferentes firmas de método. Asegúrese de que es consciente de los valores que están disponibles para cada evento y qué valores, en su caso, el método debe devolver.
  • Trate de elegir el mejor evento para el trabajo a mano. Si necesitas de un nuevo evento, por ejemplo en un componente  propio, puede crearlo y accionarlo en el lugar que desee en el programa. Si crees que necesita el núcleo de Joomla un nuevo evento, pregunte acerca de ello en una de las listas de desarrollo. Si otros están de acuerdo, el evento puede ser añadido al núcleo.

Conclusión

En esta serie de artículos, hemos aprendido acerca de los plugins. Comenzamos por analizar en detalle algunos plugins del núcleo. Entonces creamos algunos plugins propios, Incluido uno que nos permite fácilmente personalizar el proceso de registro de usuario en Joomla.

En el camino, vimos como los plugins nos permiten hacer mucho con poco código y la forma en que proporcionan al administrador del sitio un alto grado de flexibilidad. Incluso vimos cómo podemos utilizar los plugins, si es necesario, para sobreescribir la mayoría de las clases básicas de Joomla.

Con todo esto espero que puedan comenzar a realizar sus propios plugin, personalizando así,  aún más sus sitios Joomla.

Visto 3806 veces Etiquetado como Spanish, Desarrollador