Crear Hooks en Prestashop

Crear Hooks mediante código en Prestashop

Tenemos una guía, que quedo publicada en este blog en Julio del 2013Crear un nuevo hook en Prestashop 1.5, la guía sigue siendo válida hoy en día.

Crear hooks mediante el módulo de Vekia

Módulo desarrollado por Vekia: https://mypresta.eu/modules/administration-tools/hooks-manager.html

(Link alternativo  de descarga, por si la dirección de descarga del módulo falla en algún momento, recordar que el módulo siempre debe ser descargado desde la web del desarrollador, ya que es donde está actualizado)

Módulo instalado
Módulo instalado

Instalación y subida del módulo desde la pestaña módulos -> módulos

En la configuración del módulo, accedemos a una especie de formulario donde nos pedirá los datos de creación del nuevo hook.

Creando Hook en Prestashop 1.7
  • Hook Name -> Nombre del hook (debe ser único, es decir no puedes colocar un nombre de un hook que ya existe)
  • Hook Title -> Nombre público del hook (por ejemplo aparece en el panel de administración para identificar a este nuevo hook)
  • Hook Description -> Descripción del Hook
  • Visibility -> Si la activas podremos ver el hook en la lista de posiciones de la pestaña módulos -> posiciones
  • Live Edit -> Si la activas tendrás posibilidad de usar en este hook el modo Live Edit que usas para mover los módulos de posición gráficamente.

En nuestro caso, hemos colocado los siguientes datos:

  • Hook name -> nadie
  • Hook title -> Hook de Nadie
  • Hook Description -> Hook que vamos a colocar en el sitio X
  • Visibility -> SÍ
  • Live Edit -> Sí
Rellenando los datos de creación del Hook

Ahora, veremos que en la misma configuración del módulo en cuestión que ademas de añadir nuevos hooks, podemos ver el listado de los hooks creados, que se ha creado el nuevo hook con éxito.

Listado de Hooks en Prestashop

Por cierto, desde el mismo listado, podemos eliminar el Hook, si no estamos interesados en conservarlo.

Insertar en el TPL el nuevo Hook que hemos creado

Si por ejemplo, queremos mostrar el nuevo hook en la página 404 de Prestashop

En Prestashop 1.6 (usando la plantilla por defecto), editamos el fichero:

/themes/default-bootstrap/404.tpl

Y añadimos la siguiente línea de código:

{hook h='nadie'}

Por ejemplo, vamos añadirla debajo del título: “ESTA PÁGINA NO ESTÁ DISPONIBLE”

Página 404 en Prestashop 1.6

Añadimos en nuestro caso particular la siguiente línea:

{hook h='nadie'}

debajo de:

<h1>{l s='This page is not available'}</h1>
Agregando hook al fichero 404.tpl en Prestashop

Modificar clase del módulo (en caso de que sea necesario) para mostrar el módulo en el nuevo hook

Por ejemplo, en Prestashop 1.6, editamos la clase del módulo, imaginemos que queremos mostrar el módulo “Bloque fuentes RSS (blockrss)” justo en esa parte.

Editamos el fichero:

modules/blockrss/blockrss.php

y escribimos:

public function hookNadie($params) {

}

Y dentro de la función del hook -> nadie, vamos en nuestro caso particular a retornar el contenido que se muestra en el hook de la columna izquierda (este módulo en particular tiene nombrada la función del hook así hookLeftColumn($params) depende displayLeftColumn($params) por eso retornamos la función hookLeftColumn($params), lo comento para evitar confusiones.

public function hookNadie($params) {
return $this->hookLeftColumn($params);
}

Ahora, nos vamos a la pestaña módulos -> posiciones de los módulos, pulsamos en el botón superior llamado “Insertar un hook”

Insertar módulo en Hook en Prestashop

Y en el formulario, señalamos:

Módulo: Bloque de fuentes RSS
Mover a: nadie

Insertando Bloque fuente RSS al hook nadie

Al pulsar en guardar, nos saldrá un mensaje diciendo: “El módulo fue copiado exitosamente en el hook

Módulo insertado con éxito en el hook nadie

Sí, ahora vamos a la ver la página 404, veremos que se ha insertado el módulo “Bloque fuentes RSS (blockrss)” en dicha página justo debajo del título “ESTA PÁGINA NO ESTÁ DISPONIBLE”

Bloque fuentes RSS (blockrss) en página 404 en Prestashop
Bloque fuentes RSS (blockrss) en página 404 en Prestashop

 

Sobreescribir clase del módulo y no editar la clase original del módulo

En la actualidad Prestashop, permite hacer override de las clases de los módulos, antiguamente no lo permitía.

¿Cómo podemos hacer un override del fichero “blockrss.php” indicando la función del nuevo hook?

Creamos el siguiente fichero: (lo llamamos: blockrss.php (no confundir con el original, porque este fichero lo vamos a dejar en otra ruta distinta))

<?php
if (!defined('_PS_VERSION_'))
exit;
class BlockrssOverride extends Blockrss
{
public function hookNadie($params) {
return $this->hookLeftColumn($params);
}
}

Y lo guardamos en /overrides/modules/blockrss/ (si la carpeta blockrss no está creada, la podéis crear)

Aquí, simplemente hemos realizado un override de la clase del módulo blockrss, heredando de dicha clase y añadiendo una nueva función, que en nuestro caso es la función del hook -> nadie, de esta manera nos ahorramos modificar la clase original, y queda todo más organizado.

¿Crear hook en Prestashop 1.7?

El funcionamiento del módulo de Vekia es muy parecido, así que no voy a volver a pegar la explicación 🙂

Añadir hook en la página 404 de Prestashop 1.7

En el fichero:

/themes/classic/templates/errors/404.tpl

Añadimos:

{hook h='nadie'}

El módulo Fuentes RSS no viene en el paquete por defecto de Prestashop 1.7, pero si lo buscáis en el panel de administración desde la pestaña módulos -> módulos -> servicios, os saldrá el módulo (buscarlo con el nombre de: ps_rssfeed) para instalarlo.

Curiosamente, no usa el nuevo sistema de widget de Prestashop 1.7 que evita que tengamos que añadir código en el PHP del módulo para mover el módulo a nuevos hooks.

En esta ocasión, vemos en el código que el módulo al instalarse queda registrado en el displayFooter y que tenemos dentro del módulo la función del hook -> displayFooter, pues simplemente en el hook -> nadie, vamos a retornar la función displayFooter

Accediendo a la clase del módulo /modules/ps_rssfeed/ps_rssfeed.php, me he encontrado con el siguiente código:

<?php
* 2007-2016 PrestaShop
*
* NOTICE OF LICENSE
*
* This source file is subject to the Academic Free License (AFL 3.0)
* that is bundled with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://opensource.org/licenses/afl-3.0.php
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* DISCLAIMER
*
* Do not edit or add to this file if you wish to upgrade PrestaShop to newer
* versions in the future. If you wish to customize PrestaShop for your
* needs please refer to http://www.prestashop.com for more information.
*
* @author PrestaShop SA <contact@prestashop.com>
* @copyright 2007-2016 PrestaShop SA
* @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0)
* International Registered Trademark &amp; Property of PrestaShop SA
*/
if (!defined('_PS_VERSION_')) {
exit;
}
class Ps_Rssfeed extends Module
{
protected $templateFile;
public function __construct()
{
$this->name = 'ps_rssfeed';
$this->author = 'PrestaShop';
$this->version = '1.0.1';
$this->need_instance = 0;
$this->bootstrap = true;
parent::__construct();
$this->displayName = $this->trans('RSS feed block', array(), 'Modules.Rssfeed.Admin');
$this->description = $this->trans('Adds a block displaying a RSS feed.', array(), 'Modules.Rssfeed.Admin');
$this->ps_versions_compliancy = array('min' => '1.7.0.0', 'max' => _PS_VERSION_);
$this->templateFile = 'module:ps_rssfeed/views/templates/hook/ps_rssfeed.tpl';
}
public function install()
{
return (parent::install()
&amp;&amp; Configuration::updateValue('RSS_FEED_TITLE', $this->trans('RSS feed', array(), 'Modules.Rssfeed.Admin'))
&amp;&amp; Configuration::updateValue('RSS_FEED_NBR', 5)
&amp;&amp; $this->registerHook('displayFooter')
);
}
public function uninstall()
{
if (!parent::uninstall() ||
!Configuration::deleteByName('RSS_FEED_TITLE') ||
!Configuration::deleteByName('RSS_FEED_NBR')
) {
return false;
}
return true;
}
public function getContent()
{
$output = '';
if (Tools::isSubmit('submitBlockRss')) {
$errors = array();
$urlfeed = Tools::getValue('RSS_FEED_URL');
$title = Tools::getValue('RSS_FEED_TITLE');
$nbr = (int)Tools::getValue('RSS_FEED_NBR');
if ($urlfeed and !Validate::isAbsoluteUrl($urlfeed)) {
$errors[] = $this->trans('Invalid feed URL', array(), 'Modules.Rssfeed.Admin');
} elseif (!$title or empty($title) or !Validate::isGenericName($title)) {
$errors[] = $this->trans('Invalid title', array(), 'Modules.Rssfeed.Admin');
} elseif (!$nbr or $nbr <= 0 or !Validate::isInt($nbr)) { $errors[] = $this->trans('Invalid number of feeds', array(), 'Modules.Rssfeed.Admin');
} elseif (stristr($urlfeed, $_SERVER['HTTP_HOST'] . __PS_BASE_URI__)) {
$errors[] = $this->trans('You have selected a feed URL from your own website. Please choose another URL.', array(), 'Modules.Rssfeed.Admin');
} elseif (!($contents = Tools::file_get_contents($urlfeed))) {
$errors[] = $this->trans('Feed is unreachable, check your URL', array(), 'Modules.Rssfeed.Admin');
} /* Even if the feed was reachable, We need to make sure that the feed is well formated */
else {
try {
new SimpleXMLElement($contents);
} catch (Exception $e) {
$errors[] = $this->trans('Invalid feed: %message%', array('%message%' => $e->getMessage()), 'Modules.Rssfeed.Admin');
}
}
if (!sizeof($errors)) {
Configuration::updateValue('RSS_FEED_URL', $urlfeed);
Configuration::updateValue('RSS_FEED_TITLE', $title);
Configuration::updateValue('RSS_FEED_NBR', $nbr);
$output .= $this->displayConfirmation($this->trans('The settings have been updated.', array(), 'Admin.Notifications.Success'));
$this->_clearCache($this->templateFile);
} else {
$output .= $this->displayError(implode('
', $errors));
}
} else {
$errors = array();
if (stristr(Configuration::get('RSS_FEED_URL'), $_SERVER['HTTP_HOST'] . __PS_BASE_URI__)) {
$errors[] = $this->trans('You have selected a feed URL from your own website. Please choose another URL.', array(), 'Modules.Rssfeed.Admin');
}
if (sizeof($errors)) {
$output .= $this->displayError(implode('
', $errors));
}
}
return $output . $this->renderForm();
}
public function hookDisplayFooter($params)
{
// Conf
$title = strval(Configuration::get('RSS_FEED_TITLE'));
$url = strval(Configuration::get('RSS_FEED_URL'));
$nb = (int) (Configuration::get('RSS_FEED_NBR')) ? (int) (Configuration::get('RSS_FEED_NBR')) : 5;
$cacheId = $this->getCacheId($this->name . '|' . date("YmdH"));
if (!$this->isCached($this->templateFile, $cacheId)) {
$rss_links = array();
if ($url &amp;&amp; ($contents = Tools::file_get_contents($url))) {
try {
$xml = new SimpleXMLElement($contents);
$loop = 0;
if (!empty($xml->channel->item)) {
foreach ($xml->channel->item as $item) {
if (++$loop > $nb) {
break;
}
$rss_links[] = (array)$item;
}
}
} catch (Exception $e) {
Tools::dieOrLog($this->trans('Error: invalid RSS feed in "%module_name%" module: %message%', array('%module_name%' => $this->name, '%message%' => $e->getMessage()), 'Modules.Rssfeed.Admin'));
}
}
$this->smarty->assign(array(
'title' => ($title ? $title : $this->trans('RSS feed', array(), 'Modules.Rssfeed.Admin')),
'rss_links' => $rss_links
));
}
return $this->fetch($this->templateFile, $cacheId);
}
public function renderForm()
{
$fields_form = array(
'form' => array(
'legend' => array(
'title' => $this->trans('Settings', array(), 'Admin.Global'),
'icon' => 'icon-cogs'
),
'input' => array(
array(
'type' => 'text',
'label' => $this->trans('Block title', array(), 'Modules.Rssfeed.Admin'),
'name' => 'RSS_FEED_TITLE',
'desc' => $this->trans('Create a title for the block (default: \'RSS feed\').', array(), 'Modules.Rssfeed.Admin'),
),
array(
'type' => 'text',
'label' => $this->trans('Add a feed URL', array(), 'Modules.Rssfeed.Admin'),
'name' => 'RSS_FEED_URL',
'desc' => $this->trans('Add the URL of the feed you want to use (sample: http://news.google.com/?output=rss).', array(), 'Modules.Rssfeed.Admin'),
),
array(
'type' => 'text',
'label' => $this->trans('Number of threads displayed', array(), 'Modules.Rssfeed.Admin'),
'name' => 'RSS_FEED_NBR',
'class' => 'fixed-width-sm',
'desc' => $this->trans('Number of threads displayed in the block (default value: 5).', array(), 'Modules.Rssfeed.Admin'),
),
),
'submit' => array(
'title' => $this->trans('Save', array(), 'Admin.Actions'),
)
),
);
$lang = new Language((int)Configuration::get('PS_LANG_DEFAULT'));
$helper = new HelperForm();
$helper->show_toolbar = false;
$helper->table = $this->table;
$helper->default_form_language = $lang->id;
$helper->allow_employee_form_lang = Configuration::get('PS_BO_ALLOW_EMPLOYEE_FORM_LANG') ? Configuration::get('PS_BO_ALLOW_EMPLOYEE_FORM_LANG') : 0;
$helper->identifier = $this->identifier;
$helper->submit_action = 'submitBlockRss';
$helper->currentIndex = $this->context->link->getAdminLink('AdminModules', false) . '&amp;configure=' . $this->name . '&amp;tab_module=' . $this->tab . '&amp;module_name=' . $this->name;
$helper->token = Tools::getAdminTokenLite('AdminModules');
$helper->tpl_vars = array(
'fields_value' => $this->getConfigFieldsValues(),
'languages' => $this->context->controller->getLanguages(),
'id_language' => $this->context->language->id
);
return $helper->generateForm(array($fields_form));
}
public function getConfigFieldsValues()
{
return array(
'RSS_FEED_TITLE' => Tools::getValue('RSS_FEED_TITLE', Configuration::get('RSS_FEED_TITLE')),
'RSS_FEED_URL' => Tools::getValue('RSS_FEED_URL', Configuration::get('RSS_FEED_URL')),
'RSS_FEED_NBR' => Tools::getValue('RSS_FEED_NBR', Configuration::get('RSS_FEED_NBR')),
);
}
}

Creamos un override de la clase del módulo, y lo guardamos en el directorio:

/override/modules/ps_rssfeed/

con el nombre “ps_rssfeed.php” y con el contenido:

<?php
if (!defined('_PS_VERSION_'))
exit;
class Ps_RssfeedOverride extends Ps_Rssfeed
{
public function hookNadie($params) {
return $this->hookDisplayFooter($params);
}
}
Override de la clase del módulo en Prestashop

Por último para mover el módulo al nuevo hook en Prestashop 1.7, lo podemos hacer desde la pestaña Diseño -> Posiciones de los módulos, siguiendo el mismo proceso que habíamos seguido en Prestashop 1.6

¿No detecta Prestashop el override de la clase del módulo?

  • Eliminar el fichero: /cache/class_index.php en Prestashop 1.6 (el fichero se regenera automáticamente, no tengas miedo en borrarlo).
  • En Prestashop 1.7 directamente ve a la pestaña Parámetros Avanzados -> Rendimiento y haz clic en el botón “Limpiar/Borrar caché”.

    Borrar caché