J3.x

Crear un plugin de búsqueda

From Joomla! Documentation

This page is a translated version of the page J3.x:Creating a search plugin and the translation is 100% complete.

Other languages:
English • ‎español • ‎français • ‎Nederlands
Joomla! 
3.x
series

Descripción

Este documento trata sobre cómo crear un Plugin de Búsqueda. Puedes utilizar un Plugin de Búsqueda para buscar a través de la base de datos de tu sitio Joomla!. Para crear un plugin, al menos se necesitan dos archivos, un archivo XML y un archivo PHP. Para la internacionalización es bueno crear un archivo INI también.

Archivo XML

El archivo XML tiene el mismo nombre que el archivo PHP y es uno de los dos archivos necesarios. Siempre empieza con la etiqueta XML y define que está escrito en formato UTF-8.

<?xml version="1.0" encoding="utf-8"?>

Para definir que el plugin tiene que ser un plugin de búsqueda, agrega esta línea

<extension version="3.1" type="plugin" group="search">

El atributo type define que es un plugin y group define que el Plugin está en el grupo de plugins de búsqueda.

Después de eso, agrega un poco de información sobre ti y el plugin:

<name>Name of your search plugin</name>
<creationDate>Creation date</creationDate>
<author>Your name</author>
<authorEmail>Your e-mail address</authorEmail>
<authorUrl>Your website</authorUrl>
<copyright>Copyright information</copyright>
<license>License, for example GNU/GPL</license>
<version>Version of the plugin</version>
<description>Description of the plugin; shown during installation and when editing 
the plugin in the Plugin Manager</description>

Y ahora, incluimos el archivo PHP del Plugin de Búsqueda. El nombre de este archivo debe ser el mismo que el nombre del archivo XML. Hay que poner este nombre también dentro del atributo plugin="".

Puedes agregar más archivos a tu plugin, por ejemplo, una imagen. Sólo tienes que añadir otra fila entre <files> y </files>, y a continuación, coloca el archivo entre las etiquetas <filename>.

<files>
   <filename plugin="nameofplugin">nameofplugin.php</filename>
</files>

Para la internacionalización, vamos a usar los archivos de idioma. Esto no es necesario, pero la gente de otros países aman que se pueda traducir el plugin fácilmente a su propio idioma. Los códigos de idioma se puede encontrar aquí: [1] (usar la columna ISO 639-1) y aquí los códigos de países: [2]

<languages>
   <language tag="en-GB">language/en-GB/en-GB.plg_search_nameofplugin.ini</language>
</languages>

Opcionalmente, puedes añadir algunos parámetros al plugin. Los mismos se parecerán a esto:

	<config>
		<fields name="params">

			<fieldset name="basic">
				<field name="search_limit" type="text"
					default="50"
					description="JFIELD_PLG_SEARCH_SEARCHLIMIT_DESC"
					label="JFIELD_PLG_SEARCH_SEARCHLIMIT_LABEL"
					size="5"
				/>

				<field name="search_content" type="radio"
					default="0"
					description="JFIELD_PLG_SEARCH_ALL_DESC"
					label="JFIELD_PLG_SEARCH_ALL_LABEL"
				>
					<option value="0">JOFF</option>
					<option value="1">JON</option>
				</field>

			</fieldset>
		</fields>
	</config>

No te olvides de terminar su archivo XML con la siguiente etiqueta:

</extension>

Archivo PHP

El archivo PHP de tu plugin es el archivo más importante del plugin. Este es un ejemplo de archivo PHP de un plugin de búsqueda. Se incluyen los comentarios.

<?php
//First start with information about the Plugin and yourself. For example:
/**
 * @package     Joomla.Plugin
 * @subpackage  Search.nameofplugin
 *
 * @copyright   Copyright
 * @license     License, for example GNU/GPL
 */

//To prevent accessing the document directly, enter this code:
// no direct access
defined( '_JEXEC' ) or die( 'Restricted access' );

// Require the component's router file (Replace 'nameofcomponent' with the component your providing the search for
require_once JPATH_SITE .  '/components/nameofcomponent/helpers/route.php';

/**
 * All functions need to get wrapped in a class
 *
 * The class name should start with 'PlgSearch' followed by the name of the plugin. Joomla calls the class based on the name of the plugin, so it is very important that they match
 */
class PlgSearchNameofplugin extends JPlugin
{
	/**
	 * Constructor
	 *
	 * @access      protected
	 * @param       object  $subject The object to observe
	 * @param       array   $config  An array that holds the plugin configuration
	 * @since       1.6
	 */
	public function __construct(& $subject, $config)
	{
		parent::__construct($subject, $config);
		$this->loadLanguage();
	}

	// Define a function to return an array of search areas. Replace 'nameofplugin' with the name of your plugin.
	// Note the value of the array key is normally a language string
	function onContentSearchAreas()
	{
		static $areas = array(
			'nameofplugin' => 'Nameofplugin'
		);
		return $areas;
	}

	// The real function has to be created. The database connection should be made. 
	// The function will be closed with an } at the end of the file.
	/**
	 * The sql must return the following fields that are used in a common display
	 * routine: href, title, section, created, text, browsernav
	 *
	 * @param string Target search string
	 * @param string mathcing option, exact|any|all
	 * @param string ordering option, newest|oldest|popular|alpha|category
	 * @param mixed An array if the search it to be restricted to areas, null if search all
	 */
	function onContentSearch( $text, $phrase='', $ordering='', $areas=null )
	{
		$user	= JFactory::getUser(); 
		$groups	= implode(',', $user->getAuthorisedViewLevels());

		// If the array is not correct, return it:
		if (is_array( $areas )) {
			if (!array_intersect( $areas, array_keys( $this->onContentSearchAreas() ) )) {
				return array();
			}
		}

		// Now retrieve the plugin parameters like this:
		$nameofparameter = $this->params->get('nameofparameter', defaultsetting );

		// Use the PHP function trim to delete spaces in front of or at the back of the searching terms
		$text = trim( $text );

		// Return Array when nothing was filled in.
		if ($text == '') {
			return array();
		}

		// After this, you have to add the database part. This will be the most difficult part, because this changes per situation.
		// In the coding examples later on you will find some of the examples used by Joomla! 3.1 core Search Plugins.
		//It will look something like this.
		$wheres = array();
		switch ($phrase) {

			// Search exact
			case 'exact':
				$text		= $this->db->Quote( '%'.$this->db->escape( $text, true ).'%', false );
				$wheres2 	= array();
				$wheres2[] 	= 'LOWER(a.name) LIKE '.$text;
				$where 		= '(' . implode( ') OR (', $wheres2 ) . ')';
				break;

			// Search all or any
			case 'all':
			case 'any':

			// Set default
			default:
				$words 	= explode( ' ', $text );
				$wheres = array();
				foreach ($words as $word)
				{
					$word		= $this->db->Quote( '%'.$this->db->escape( $word, true ).'%', false );
					$wheres2 	= array();
					$wheres2[] 	= 'LOWER(a.name) LIKE '.$word;
					$wheres[] 	= implode( ' OR ', $wheres2 );
				}
				$where = '(' . implode( ($phrase == 'all' ? ') AND (' : ') OR ('), $wheres ) . ')';
				break;
		}

		// Ordering of the results
		switch ( $ordering ) {

			//Alphabetic, ascending
			case 'alpha':
				$order = 'a.name ASC';
				break;

			// Oldest first
			case 'oldest':

			// Popular first
			case 'popular':

			// Newest first
			case 'newest':

			// Default setting: alphabetic, ascending
			default:
				$order = 'a.name ASC';
		}

		// Replace nameofplugin
		$section = JText::_( 'Nameofplugin' );

		// The database query; differs per situation! It will look something like this (example from newsfeed search plugin):
		$query	= $this->db->getQuery(true);
		$query->select('a.name AS title, "" AS created, a.link AS text, ' . $case_when."," . $case_when1);
				$query->select($query->concatenate(array($this->db->Quote($section), 'c.title'), " / ").' AS section');
				$query->select('"1" AS browsernav');
				$query->from('#__nameofcomponent AS a');
				$query->innerJoin('#__categories as c ON c.id = a.catid');
				$query->where('('. $where .')' . 'AND a.published IN ('.implode(',', $state).') AND c.published = 1 AND c.access IN ('. $groups .')');
				$query->order($order);

		// Set query
		$this->db->setQuery( $query, 0, $limit );
		$rows = $this->db->loadObjectList();

		// The 'output' of the displayed link. Again a demonstration from the newsfeed search plugin
		foreach($rows as $key => $row) {
			$rows[$key]->href = 'index.php?option=com_newsfeeds&view=newsfeed&catid='.$row->catslug.'&id='.$row->slug;
		}

	//Return the search results in an array
	return $rows;
	}
}

Hay cuatro variables que se pasan. Son evidentes por sus nombres y su uso en el código de arriba. Lo que no es obvio es lo que la función debe devolver: un array de objetos que la herramienta de búsqueda utiliza para mostrar los resultados. Los resultados pueden, alternativamente, ser reunidos de esta forma:

$rows[] = (object) array(
			'href'        => 'index.php?option=com_newsfeeds&view=newsfeed&catid='.$row->catslug.'&id='.$row->slug,
			'title'       => $row['name'],
			'section'     => $nameofcomponent,
			'created'     => $row['date'],
			'text'        => $row['name'],
			'browsernav'  => '1'
		);

Archivo(s) INI

Para la internacionalización es bueno utilizar los archivos INI. Puedes agregar al archivo de idioma todas las salidas de texto para el usuario, en este orden:

  • Etiqueta de descripción XML
  • Etiqueta y descripción de los atributos de parámetros XML
  • JText::_( 'cadena' ) que utiliza el plugin

Inicia tu archivo INI con algo como esto:

# $Id: en-GB.plg_search_nameofplugin.ini
# Joomla! Project
# Copyright (C) 2005 - 2007 Open Source Matters. All rights reserved.
# License http://www.gnu.org/licenses/gpl-2.0.html GNU/GPL, see LICENSE.php
# Note : All ini files need to be saved as UTF-8 - No BOM

Por supuesto, también puedes agregar otro tipo de información, como el autor.

Por ejemplo, este parámetro:

<field name="search_limit" type="text"
  default="50"
  description="JFIELD_PLG_SEARCH_SEARCHLIMIT_DESC"
  label="JFIELD_PLG_SEARCH_SEARCHLIMIT_LABEL"
  size="5"
/>

Hará la siguiente salida en el archivo INI:

JFIELD_PLG_SEARCH_SEARCHLIMIT_DESC=Search Limit
JFIELD_PLG_SEARCH_SEARCHLIMIT_LABEL=Number of Search items to return

El archivo parece repetitivo, pero será muy útil para los traductores.

Cuando deseas hacer su plugin de búsqueda disponible en más idiomas, primero lo agregas en la etiqueta languages en el archivo XML. Luego de crea el mismo archivo INI y cambiar la parte después del =, por ejemplo para la versión holandesa sería:

JFIELD_PLG_SEARCH_SEARCHLIMIT_DESC=Zoek limiet
JFIELD_PLG_SEARCH_SEARCHLIMIT_LABEL=Aantal weer te geven zoekresultaten

Consejos rápidos

  • En el archivo PHP, la gente a menudo se olvida de colocar un punto y coma (;) al final de una línea. Esto causa errores. Comprobar esto antes de probar el plugin.
  • Asegúrate que los parámetros en el archivo XML están cerrados correctamente. Cuando se agrega una opción, por ejemplo, se necesita cerrar con </param>.
  • Es fácil probar en localhost cuando se edita el plugin.
  • Al crear el archivo zip,no te olvides de hacer los directorios para los archivos de idioma. Un archivo zip típico contendrá lo siguiente:
    • nameofplugin.xml
    • nameofplugin.php
    • language\en-GB\en-GB.plg_search_nameofplugin.ini