24 minutos de lectura ( 4850 palabras)

Extendiendo a Joomla! 2.5 con Plugins - Parte 1

Extendiendo a Joomla! 2.5 con Plugins - Parte 1

La estructura de un plugin en Joomla! 2.5 es flexible y potente. Los plugin, no sólo son utilizados para controlar los eventos desencadenados por la aplicación central o las extensiones propias de Joomla!, sino, que también pueden ser utilizados para lograr hacer a extensiones de terceros, extensibles y potentes.

¿Qué es un Plugin?

Un plugin es simplemente un programa PHP que se ejecuta en uno o más puntos predefinidos en el ciclo de ejecución Joomla. Estos puntos se denominan eventos y se activan dentro de Joomla.

Un plugin puede ser muy simple, por ejemplo, para establecer un valor antes de guardar un campo en la base de datos. O puede ser muy complejo, por ejemplo, para convertir todas las direcciones URL en un documento a un formato diferente. Los plugins incluso pueden ser utilizados para anular las clases estándar del core.

Los plugins están unidos a los acontecimientos o eventos en Joomla!. Para entender los plugins, es necesario entender los eventos predefinidos en Joomla y también cómo crear nuestros propios eventos.

¿Cómo funcionan los Plugins?

Los casos en que los plugin se disparan son los siguientes:

  • Uno o más archivos del plugin se incluyen en el script actual, por lo general con el método JPluginHelper::importPlugin(). Debido a que los plugins son normalmente declaraciones de clase, no se ejecuta código en este punto.
  • Un evento se activa, por lo general con el método $dispatcher->trigger() (donde $dispatcher es un objeto JDispatcher). Cada evento tiene un nombre, como onAfterInitialise o onContentBeforeDelete.
  • El código de procesamiento de eventos busca dentro de los plugins habilitados, los que están siendo cargados que tengan un método que coincida con el nombre del evento. Si cualquiera de los métodos coincidentes se encuentran, son ejecutados.

La carga y Ejecución de scripts PHP para declarar clases

La mayoría de los plugins en Joomla sólo contienen una declaración de clase. Esto significa que ellos declaran una clase y definen los métodos de la clase, pero no incluyen las líneas de código fuera de la declaración de clase.

Cuando este tipo de archivo se carga (por ejemplo, con el comando PHP require_once), una nueva clase se crea en la memoria de trabajo, con todos sus métodos. Sin embargo, ninguno de los métodos de la clase en realidad se ejecuta. Un método sólo se ejecuta cuando una línea de código llama a ese método.

Esta es la razón por la que el método JPluginHelper::importPlugin() obtiene el plugin listo para ejecutarse, lo cual no significa ejecutar cualquier código. Los métodos de los plugins sólo se ejecutan cuando se activa el evento, por ejemplo con el método $dispatcher-> trigger().

Convenciones de nombres para Plugins

Para que los plugins sean encontrados por el método JPluginHelper::importPlugin(), tenemos que seguir las convenciones de nomenclatura correcta para el archivo del plugin y nombres de clases.

Los nombres de las carpetas y archivos del plugin se crean de la siguiente manera:

plugins/<tipo de plugin>/<nombre del plugin>/<nombre del plugin>.php

Así, por ejemplo, el archivo de SEF es: plugins/system/sef/sef.php . Los plugins tienen un archivo XML con el mismo nombre (por ejemplo, plugins/system/sef/sef.xml). Este archivo lo veremos con más detenimiento más adelante.

El nombre de la clase del plugin se basa en la convención de nomenclatura.

"plg" + <tipo de plugin> + <nombre del plugin>

Así, por ejemplo, el nombre de la clase del plugin SEF es plgSystemSEF.

Tipo de plugin: ¿Dónde se puede insertar un plugin?

Los plugins se ejecutan cuando los eventos son disparados. Los eventos definidos para los plugins en Joomla, son diferentes de los eventos, en la programación orientada a eventos. En la programación orientada a eventos, el programa espera por un evento, que es con frecuencia una acción del usuario, como un clic del ratón o la entrada de teclado. Los eventos en Joomla pueden ser vistos como puntos de control a lo largo de las diversas vías del ciclo de ejecución. Cada vez que el ciclo de ejecución llega a un punto de control de eventos, se activa el evento. Los eventos son fijos, aunque diferentes eventos se pueden desencadenar en función del tipo de ciclo de ejecución que se está llevando a cabo. Veamos brevemente cada tipo de evento.

Authentication

Existe un único evento para la autenticación:

  • onUserAuthenticate: Este evento se activa cuando un usuario intenta iniciar sesión en el front-end o en el back-end del sitio.

Captcha

Captcha es una manera de prevenir el spam, al exigir que el usuario escriba algún texto en base a una imagen distorsionada de letras. Joomla versión 2.5 añade la capacidad de utilizar captcha para validar el registro del usuario. Esto se implementa a través de tres eventos: onInit, onDisplay, y onCheckAnswer.

Content

Los eventos para el contenido se activan cuando el contenido es mostrado o editado. Esto incluye artículos, contactos, y otros tipos de contenido.

Editors

Los editores están implementados en Joomla como plugins. Sin embargo, no se ajustan al patrón de plugins como se ha ido explicando hasta ahora. Para añadir un nuevo editor en Joomla, requiere un profundo conocimiento de JavaScript y no es una tarea fácil.

Editors-XTD

Los plugins Editores-XTD se utilizan para crear los botones que aparecen debajo de los editores (por ejemplo, imágenes, Salto de página y Leer Más).

Extension

Este tipo de plugin fue introducido en la versión Joomla 1.6. Aquí los eventos se activan cuando las extensiones se instalan, desinstalan o se editan y se guardan en el gestor de módulos, complementos, plantillas, o idioma.

Search

Los plugins de búsqueda implementan la funcionalidad de búsqueda en Joomla. Los plugins del core de Joomla son: categories, contacts, content, news feeds, y Weblinks. Los eventos de búsqueda son onContentSearchAreas y onContentSearch. El evento onContentSearchAreas se utiliza para crear un array de elementos de contenido a buscar, y el evento onContentSearch se utiliza para ejecutar la búsqueda de cada uno de los tipos de contenido. Los desarrolladores de extensiones pueden incluir plugins de búsqueda para permitir que la búsqueda en Joomla trabaje con sus componentes.

Smart Search (Finder)

Los plugins de búsqueda inteligente se encuentran en la carpeta plugins/finder. Estos plugins se utilizan para indexar el contenido del sitio para su uso con Smart Search. Un plugin está disponible para cada tipo de contenido (categories, contacts, content, news feeds, y Weblinks) y pueden activarse para permitir la indexación del mismo. Los eventos previstos son onFinderAfterDelete, onFinderAfterSave, onFinderBeforeSave, onFinderCategoryChangeState y onFinderChangeState.

System

Los plugins del sistema proporcionan los eventos que se desencadenan durante cada ciclo de ejecución Joomla. Estos incluyen onAfterInitialise, el primer evento desencadenado en Joomla, además de otros vinculados a los métodos render(), dispatch(), y route(). Los eventos del sistema se deben utilizar para los plugins que necesitan ser activados durante cada ciclo de ejecución, independientemente de la tarea que se esté realizando.

User

Los eventos de usuario se activan durante dos tareas diferentes. Un grupo de eventos está vinculado a la edición de la información del usuario en el Administrador de usuarios. Estos incluyen a onUserAfterDelete, onUserAfterSave. Un segundo grupo de eventos está relacionado con la iniciación o finalización de la sesión en el sitio. Estos incluyen onUserLogin y onUserLogout.

Recorrido por algunos plugins seleccionados del core

Una cosa confusa acerca de los plugins es que varían mucho. Lo único que tienen en común es de la forma que son llamados. Teniendo en cuenta esto, vamos a comenzar con una mirada rápida a un par de plugins del core. Estos ejemplos le darán una idea de la variedad de tareas que se pueden realizar con los plugins.

System: SEF

Nuestro primer ejemplo es el plugin SEF. Esta es una clase llamada plgSystemSef en el archivo plugins/system/sef/sef.php que permite en Joomla utilizar el motor de búsqueda amigable (SEF) URL.

¿Dónde se desencadena?

Vamos a empezar con la forma en que este plugin se ejecuta, es decir, el código que incluye la clase del plugin y desencadena el evento de este plugin.

El plugin SEF es un plugin del sistema y se activa con el evento onAfterRender. Antes de activar el evento, tenemos que incluir el archivo del plugin.

Si están cargando una página en el frontend de nuestro sitio, invocamos el método render() de la clase JSite (en el archivo includes/application.php). Cerca del final de este método, aproximadamente en la línea "262", consulte la siguiente línea de código:

JPluginHelper::importPlugin('system');

Este comando carga los plugins del sistema habilitados, en la memoria de trabajo. (Si un plugin está deshabilitado en el gestor de plugins, no se carga.) Sólo tenemos que hacer este comando una vez durante un determinado método. Después que las clases del plugin de sistema se cargan en la memoria de trabajo, se puede activar uno o más eventos del sistema.

Debido a que estos plugins son declaraciones de clase, no se ejecuta aún ningún código. Más adelante en el método render() de la clase JSite es donde activamos el método onAfterRender():

// Trigger the onAfterRender event.
$this->triggerEvent('onAfterRender');

Esto acciona el evento onAfterRender. Vamos a seguir el código para ver cómo funciona. La variable $this es un objeto de tipo JSite, así que $this->triggerEvent llama al método triggerEvent() de la clase JSite con un argumento, la cadena 'OnAfterRender'.

JSite hereda(extends) de la clase JApplication (libraries/joomla/application/application.php). Debido a que JSite no tiene su propio método triggerEvent() (en otras palabras, no sobreescribe el método heredado de su clase padre), se llama al método desde JApplication.

Así el método triggerEvent() desde JApplication es ejecutado, aproximadamente en la línea "638". Este código es el siguiente:

function triggerEvent($event, $args=null)
{
$dispatcher = JDispatcher::getInstance();
return $dispatcher->trigger($event, $args);
}

Este código crea un objeto de tipo JDispatcher y luego llama al método trigger() para ese objeto. El argumento $event se establece a "onAfterRender" y, debido a que no pasamos un segundo argumento, el argumento $args está establecido en su valor predeterminado NULL.

El resultado es, que se ejecuta el método onAfterRender() de cada plugin habilitado, que está disponible en la memoria de trabajo. En este caso, la búsqueda se limita a los plugins del sistema, ya que especifica el tipo, "system", cuando llamamos a importPlugin('system'), por lo que sólo los plugins del sistema se cargan en la memoria de trabajo.

Normalmente, los nombres de los métodos del plugin deben ser coherentes con el tipo de plugin. Por ejemplo, sólo se debe utilizar el nombre de los métodos para los eventos del sistema en los plugins del sistema. Si seguimos esta convención, no importa si tenemos otro tipo de plugin cargado en la memoria, ya que sólo los métodos apropiados para el tipo de evento se ejecutará.

Nota: Implementación del método disparador:
------
No vamos a entrar en detalles sobre exactamente cómo el método trigger() está implementado en Joomla. Para crear plugins, sólo tenemos que saber lo que hace, que es la ejecución de todos los métodos que coinciden con el nombre del evento. Si estás interesado en investigar más profundamente la forma en que esto funciona, puede explorar el código. Va a encontrar que Joomla utiliza el patrón de diseño "observer", donde los eventos son "observable", y los plugins son "observers".
------ 

¿Qué hace?

Ahora vamos a ver el código del plugin SEF. El código para la primera parte del archivo sef.php es la siguiente:

// no direct access
defined ('_JEXEC') or die;
/**
* Joomla! SEF Plugin
*
* @package Joomla
* @subpackage System
*/
class plgSystemSef extends JPlugin
{
/**
* Converting the site URL to fit to the HTTP request
*/
public function onAfterRender()
{

La primera línea de código (después del bloque de documentación el cual no se muestra) es el comando "defined" estándar, que asegura que se está ejecutando este código dentro de Joomla. Antes de la versión 2.5, es necesaria una declaración jimport para importar las bibliotecas de archivos libraries/joomla/plugin/plugin.php. Desde la versión 2.5, este archivo se carga para nosotros automáticamente, por el autocargador de la plataforma Joomla!. Este contiene la clase JPlugin, que es la clase padre para todos nuestros plugins. La usamos cuando declaramos este nombre de clase, plgSystemSef, como una subclase de la clase JPlugin.

En este caso, el tipo es "system " y el nombre del archivo es "sef", de ahí el nombre completo plgSystemSef. Por último, declaramos el onAfterRender() como función pública.

Nota: Mayúsculas y minúsculas en los nombres de las clases y los métodos:
------
PHP no distingue entre mayúsculas y minúsculas en los nombres de clases y métodos. Sin embargo, normalmente se usa él "camel case" para los nombres de las clases y los métodos. El "camel case" es cuando la primera letra de cada palabra está en mayúscula. Normalmente, los nombres de las clases comienzan con una letra mayúscula y los nombres de los métodos comienzan con una letra minúscula, pero para los nombres de las clases en los plugin empezaremos con minúscula. Esta convención sólo hace que el código sea más fácil de leer para las personas.
------

Este plugin explora el documento HTML en busca de enlaces, para convertirlos en enlaces amigables. De ahí su nombre, Motor de Búsqueda Amigable (SEF -> Search-Engine-Friendly). También reemplaza las direcciones URL relativa con la URL completa de algunos otros tipos de enlaces. No vamos a discutir en detalle el método onAfterRender(), pero echemos un vistazo a dos de sus aspectos.

En primer lugar, echemos un vistazo a este código cerca del principio del método:

if ($app->getName() != 'site' || $app->getCfg('sef')=='0') {
return true;
}

Esto está comprobando dos condiciones. La primera, $app->getName() != 'site', comprueba si no estamos en la parte delantera de nuestro sitio web. La segunda condición, $app->getCfg('sef')=='0', comprueba si tenemos el parámetro URL del motor de búsqueda amigable puesto en cero (apagado) en nuestra configuración global. Si cualquiera de estas condiciones se cumple, entonces salimos del método inmediatamente con un valor de retorno "true" booleano.

¿Por qué hacemos esto? Sólo queremos cambiar las URLs cuando:
Estamos en el frontend del sitio.
Cuando el ajuste de SEF se establece en "Sí".

Sin embargo, tenemos que entender que este plugin se ejecuta cada vez que nos encontramos con el evento onAfterRender, ya sea que estemos en el frontend o en el backend del sitio e independientemente de la configuración de SEF. Es por eso que tenemos que poner la verificación dentro de nuestro plugin, para asegurar las condiciones para el funcionamiento de esta aplicación. Comprobamos que las condiciones se cumplen, y si no, acabamos saliendo del método antes de que hayamos realizado algún cambio en el documento.

El segundo punto importante es que el método onAfterRender() no toma ningún argumento y devuelve un valor booleano para indicar si se ejecuto o no correctamente. Los diferentes tipos de plugins y métodos tienen diferentes firmas de método (conjunto de argumentos que se pasan al método) y devuelven valores diferentes, así que hay que estar al tanto de estos cuando se crea un plugin.

Content: Carpeta Joomla

Este plugin se encuentra en los archivos de plugins/content/joomla/joomla.php y el nombre de la clase es plgContentJoomla.

Se dispone de dos métodos. El método onContentAfterSave() que se utiliza para enviar una notificación por correo electrónico a los usuarios cuando un nuevo artículo se ha grabado. El onContentBeforeDelete() se utiliza para comprobar si una categoría no tiene ningún artículo asignado antes de eliminarla. Echemos un vistazo al método onContentBeforeDelete().

¿Cómo podría ejecutarse?

Cuando un usuario elimina categorías, artículos, contactos u otros elementos en el backend de Joomla, el evento onContentBeforeDelete se dispara. Un lugar donde se hace esto es en la clase JModelAdmin (libraries/joomla/application/component/modeladmin.php). Si examinamos el método delete() , vemos el siguiente código, aproximadamente en la línea 660:

// Trigger the onContentBeforeDelete event.
$result = $dispatcher->trigger($this->event_before_delete, array($context, $table));

En esta clase, el campo event_before_delete se ha establecido en la cadena onContentBeforeDelete en el método constructor de la clase.

Hay dos cosas a tener en cuenta acerca de este código. En primer lugar, se espera un valor de retorno, que se almacena en la variable $result. En segundo lugar, se pasa dos argumentos para el método trigger(): el nombre del evento y un array con dos elementos. El método trigger() descomprime este array y pasa cada uno de sus elementos como argumentos al método onContentBeforeDelete(). En este caso, los dos argumentos son $context y $table. La variable $context está diseñada para decirnos algo acerca del contexto en que se ha disparado el evento (por ejemplo, "com_categories.category"). La variable $table es un array de los datos que están a punto de ser eliminados.

¿Qué hace?

La primera parte del método es como sigue:

public function onContentBeforeDelete($context, $data)
{
// Skip plugin if we are deleting something other than categories
if ($context != 'com_categories.category') {
return true;
}

Como se señaló anteriormente, este plugin se ejecutará cada vez que un usuario está eliminando cualquier tipo de contenido. Debido a que este plugin comprueba si una categoría no tiene ningún artículo asignado, sólo tiene sentido en el contexto de eliminación de una categoría. Así que la primera sentencia if comprueba esto, para asegurarse de que estamos tratando de eliminar una categoría. Si no, podemos salir del plugin, devolviendo un valor booleano "true".

Como se mencionó anteriormente, cada plugin tiene un archivo PHP y un archivo XML. El archivo XML del plugin hace tres cosas. En primer lugar, proporciona información descriptiva sobre el plugin, tal como su nombre, versión, fecha, autor y licencia. En segundo lugar, muestra todos los archivos que necesitan ser instalados o desinstalados. Por último, define los parámetros u opciones que se pueden ajustar cuando se utiliza el plugin. Estas opciones se muestran en la pantalla del gestor de plugins, cuando el plugin se abre para su edición.

Los parámetros en Joomla le permite al administrador de la web, información sobre cómo el sitio lleva a cabo el trabajo sin necesidad de escribir código de programación. En este ejemplo, el plugin Contenido - Joomla (Content → Joomla) permite al administrador controlar si desea comprobar que las categorías estén vacías antes de eliminarlas. Esto se logra con un parámetro con el nombre de check_categories. Vamos hablar de los parámetros con más detalle, más adelante.

El parámetro check_categories permite al administrador desactivar la verificación de la categoría. Esto se logra en el bloque de código siguiente del método:

// Check if this function is enabled.
if (!$this->params->def('check_categories', 1)) {
return true;
}

El objeto $this->params es un objeto JRegistry que contiene los parámetros almacenados en la tabla #__extension para este plugin de la base de datos. El método def() lee el valor del parámetro, utilizando un valor predeterminado de 1 si el parámetro no está definido. Recordemos que en PHP, un cero se evalúa como un valor lógico falso. Aquí tomamos ventaja de esto. El parámetro será cero si no se quiere comprobar las categorías y 1 si lo hacemos. Si el parámetro es cero, la condición (usando en PHP el operador "not" "!") será verdadera, por lo que se detiene el procedimiento y devolverá true. Si el parámetro no está establecido o 1, nos saltamos la instrucción de retorno y continuamos con el método.

La parte siguiente del método siguiente:

$extension = JRequest::getString('extension');

Aquí, obtenemos la $extension basado en el valor de la variable $_REQUEST de PHP. Tenga en cuenta que usamos el método JRequest::getString() de la biblioteca de Joomla. Podríamos simplemente leer el array $_REQUEST directamente, sin embargo, se recomienda siempre utilizar los métodos JRequest para hacer esto, ya que proporcionan un filtrado. En este caso, el método getString() filtra los caracteres hex y con codificación URL. JRequest proporciona una serie de métodos para leer las variables request (getString(), getInt(), getWord(), y así sucesivamente), y siempre queremos utilizar el método más restrictivo que podamos. En otras palabras, si sabemos que el valor de la variable request siempre es un número entero, debemos utilizar getInt.

El bloque de código siguiente se muestra aquí:

// Default to true if not a core extension
$result = true;
$tableInfo = array (
'com_banners' => array('table_name' => '#__banners'),
'com_contact' => array('table_name' => '#__contact_details'),
'com_content' => array('table_name' => '#__content'),
'com_newsfeeds' => array('table_name' => '#__newsfeeds'),
'com_weblinks' => array('table_name' => '#__weblinks')
);

A continuación, ponemos nuestra variable $result en "true" como valor predeterminado. Después se construye un array con los distintos nombres de las tablas, para los distintos tipos de extensión. Este plugin sólo funciona para estas cinco extensiones. Este array nos dice el nombre de la tabla para cada extensión.

La siguiente sección de código es como sigue:

// Now check to see if this is a known core extension
if (isset($tableInfo[$extension])){
// Get table name for known core extensions
$table = $tableInfo[$extension]['table_name'];

// See if this category has any content items
$count = $this->_countItemsInCategory($table, $data->get('id'));

Esto comprueba que nuestra extensión actual se encuentra en el array de las cinco extensiones del core. Si lo es, se ejecuta el código dentro de la instrucción if. Si la extensión actual no es una de las cinco extensiones del core, salta a la parte inferior del método y sólo devuelve la variable $result, que se establecio anteriormente en "true".

Dentro del bloque de código, ponemos la variable $table al nombre de la tabla que hemos definido anteriormente. Luego, establecemos la variable $count, utilizando el método privado _countItemsInCategory(). Este método ejecuta una consulta a la base de datos para ver cuántos ítems (artículos, contactos, etc) pertenecen a esta categoría. Tenga en cuenta que se pasa como argumentos el nombre de la tabla ($table) y el valor data->get('id'), que nos da el campo id de la categoría del objeto $data que se pasa como segundo argumento.

Nota: Nombres de las variables en los métodos y alcance de las mismas:
------
Si eres nuevo en la programación, hay un punto potencialmente confuso aquí, acerca de la variable $table. Recordemos que el código que dio origen a este evento pasa un array definido como array($context, $table) y que este array se descomprime para convertirse en los dos argumentos para el método onContentDelete() de aquí.

Cuando el segundo argumento fue pasado, se llamaba $table. Sin embargo, el segundo argumento de la firma de la función para el método onContentDelete() es llamado $data. A pesar de que estos tienen diferentes nombres, la variable $data en nuestro método actual tiene el mismo valor que la variable $table cuando el evento se activó.

Cuando los argumentos se pasan a las funciones, la posición del argumento es lo que importa, no el nombre de la variable. La primera variable desde el método de llamada se carga en la primera variable en la firma del método, y así sucesivamente. El nombre de la variable en la firma del método es el nombre de esa variable dentro del método.

En la programación, este concepto se denomina "Alcance". El ámbito de una variable es la parte del programa donde esa variable tiene un significado específico. En PHP, la mayoría de las variables son de alcance local. Esto significa que sólo se definen dentro del método o función donde se utilizan. Lo grandioso acerca de las variables locales es que no hay que preocuparse acerca de si podríamos haber utilizado el mismo nombre de variable en otra parte del programa. Sólo tenemos que mantener un registro de nombres de variables dentro de un solo método.

La variable $table es local en el método onContentDelete(), por lo que puede significar algo diferente en ese método de lo que podría significar en algún otro lugar en el programa. Debido a que no se utiliza el nombre de la variable $table en la firma del método de onContentDelete(), somos libres para usarlo en el método y darle un significado diferente para nosotros. En este caso, la variable $table de este método se refiere al nombre de la tabla definida en el array $tableInfo.
------

La siguiente sección de código es la que sigue:

// Return false if db error
if ($count === false){
$result = false;
}

Esto comprueba si conseguimos un resultado válido desde nuestro método _countItemsInCategory(). Este método devuelve un número o un "false" booleano. Tenga en cuenta que se usa el operador "===" triple de comparación para comprobar que $count es un booleano y específicamente "false". Tenemos que hacerlo porque el "0" es un valor válido de retorno de nuestro método countItemsInCategory(). Si el método devuelve "false", entonces por alguna razón, la consulta a la bases de datos ha devuelto un error. En este caso, se establece como valor de retorno "false". Si el método devuelve un resultado válido, entramos en el bloque "else" del código que sigue: 

else
{
// Show error if items are found in the category
if ($count > 0) {
$msg = JText::sprintf('COM_CATEGORIES_DELETE_NOT_ALLOWED', $data->get('title')) .
JText::plural('COM_CATEGORIES_N_ITEMS_ASSIGNED', $count);
JError::raiseWarning(403, $msg);
$result = false;
}
// Check for items in any child categories (if it is a leaf, there are no child categories)
if (!$data->isLeaf()) {
$count = $this->_countItemsInChildren($table, $data->get('id'), $data);
if ($count === false) {
$result = false;
}
elseif ($count > 0){
$msg = JText::sprintf('COM_CATEGORIES_DELETE_NOT_ALLOWED', $data->get('title'));
JText::plural('COM_CATEGORIES_HAS_SUBCATEGORY_ITEMS', $count);
JError::raiseWarning(403, $msg);
$result = false;
}
}
}

La primera sentencia if comprueba si el número es mayor que cero. Si es así, producirá un mensaje de advertencia al usuario y establecerá la variable $result en "false". Un punto importante aquí es que, al devolver falso, este plugin evitará que el usuario elimine la categoría. Otro punto aquí es que en realidad no vamos hacer la declaración de retorno hasta el final del método. Así que continuamos ejecutando el código.

La siguiente sección del código comprueba si hay algunos artículos asignados en las categorías hijas, utilizando el método _CountItemsInChildren(). Tenga en cuenta que se usa un atajo para ahorrar un poco de tiempo de procesamiento. Hay un método en el objeto $data llamado isLeaf(). Este método devuelve un "true" si la categoría actual es una "hoja" en el árbol de categorías, lo que significa que no tiene ninguna categoría hija. Si es así, no tiene que buscar elementos en las categorías hijas. En este caso, se omite el bloque de código entero.

Si hay categorías hijas, y si existe algún artículo dentro de esta categoría, creamos otro mensaje de advertencia y fijamos la variable $result en "false". Tenga en cuenta que si las dos condiciones de advertencia están presentes (lo que significa que tenemos artículos en la categoría actual y en las categorías hijas), entonces emitimos dos advertencias. Usamos el JError::raisewarning() para mostrar la advertencia al usuario, y incluirá el número de elementos en el mensaje de advertencia.

Un método nuevo y genial, llamado plural() fue agregado a la clase JText en la versión Joomla 1.6. Esto permite a Joomla seleccionar automáticamente la etiqueta de idioma correcta en función de si el número que se muestra es 1 o más de 1. Utilizamos esto para mostrar uno u otro en dependencia de nuestro mensaje de advertencia. Por ejemplo, queremos decir "artículo" si hay uno ("1 artículo"), sino "artículos" si hay más de uno ("5 artículos"). El método JText::plural() hace esto por nosotros sin necesidad de una sentencia if. Asimismo, maneja los idiomas, donde hay diferentes formas de una palabra para uno, dos o tres artículos.

El fin de este método es el código "return $result;", que sólo devuelve "true" si no se encontraron artículos o "false" en caso contrario. Como se señaló anteriormente, este método sólo hace un trabajo real cuando estamos eliminando en la tabla #__categories. Por lo que podríamos haber añadido este control en la clase de la tabla "category ", en lugar de usar un plugin. ¿Por qué entonces usar un plugin?

La respuesta es: "La Flexibilidad". Al realizar esta comprobación en un plugin proporciona al administrador una serie de opciones. En primer lugar, se puede desactivar el plugin, lo que permite a un administrador eliminar la comprobación de las categorías. En segundo lugar, los parámetros en el plugin permite controles personalizados, al activar o desactivar algunos de ellos. En tercer lugar, puedes proporcionar tu propio plugin que reemplace o complemente la funcionalidad de este o cualquier otro complemento del core. Por último, este plugin proporciona un modelo fácil a seguir, para los desarrolladores de extensiones de terceros, para proveer un chequeo de categorías a sus extensiones.

Conclusiones

Esta es una gran demostración de la potencia real de los plugins para mejorar la flexibilidad del sistema. Se puede desactivar o reemplazar sin hackear los archivos del core, lo que le permite controlar la cantidad de procesamiento que se está realizando en Joomla.

Hasta aquí vamos a llegar en está primera parte, espero que hayan podido entender la importancia y el funcionamiento de los plugin dentro de Joomla!.

En la segunda parte de este tutorial ya entraremos en materia y construiremos nuestro propio plugin, basado en estos conocimientos adquiridos.

Autor: Carlos Rodríguez
Miembro del: Equipo de Marketing y Difusión de Joomla! en Español 

0
Botones sociales en Gantry
VirtueMart (Plugins stokable variants)
 

Comentarios

¿Ya està registrado? Ingresa Aquí
No hay comentarios por el momento. Sé el primero en enviar un comentario.

By accepting you will be accessing a service provided by a third-party external to https://magazine.joomla.org/