Anonymiser les données de PrestaShop

Pour créer un environnement de développement, on duplique celui de production. Sauf qu’il ne faut pas garder les infos personnelles des clients. Déjà c’est dangereux, si vous gérez mal votre affaire vous risquez d’envoyer des mails aux clients et ça force tous les développeurs et intervenants à faire attention au RGPD.

Donc on anonymise tout, c’est plus simple.

Voici un script MariaDB qui anonymise les données clients : noms, prénoms, adresses, téléphones, e-mails, ip, communications. Il remplace les lettres par xxx en respectant la casse, les n° de téléphone par 0 en respectant le format et passe les IP en 127.0.0.1.

UPDATE ps_address pa
SET pa.alias = REGEXP_REPLACE(REGEXP_REPLACE(pa.alias, '(?-i)[a-z]', 'x'), '(?-i)[A-Z]', 'X'),
pa.lastname = REGEXP_REPLACE(REGEXP_REPLACE(pa.lastname, '(?-i)[a-z]', 'x'), '(?-i)[A-Z]', 'X'),
pa.firstname = REGEXP_REPLACE(REGEXP_REPLACE(pa.firstname, '(?-i)[a-z]', 'x'), '(?-i)[A-Z]', 'X'),
pa.address1 = REGEXP_REPLACE(REGEXP_REPLACE(pa.address1, '(?-i)[a-z]', 'x'), '(?-i)[A-Z]', 'X'),
pa.address2 = REGEXP_REPLACE(REGEXP_REPLACE(pa.address2, '(?-i)[a-z]', 'x'), '(?-i)[A-Z]', 'X'),
pa.city = REGEXP_REPLACE(REGEXP_REPLACE(pa.city, '(?-i)[a-z]', 'x'), '(?-i)[A-Z]', 'X'),
pa.other = REGEXP_REPLACE(REGEXP_REPLACE(pa.other, '(?-i)[a-z]', 'x'), '(?-i)[A-Z]', 'X'),
pa.company = REGEXP_REPLACE(REGEXP_REPLACE(pa.company, '(?-i)[a-z]', 'x'), '(?-i)[A-Z]', 'X'),
pa.phone = REGEXP_REPLACE(pa.phone, '[0-9]', '0'),
pa.phone_mobile = REGEXP_REPLACE(pa.phone_mobile, '[0-9]', '0'),
pa.vat_number = REGEXP_REPLACE(REGEXP_REPLACE(REGEXP_REPLACE(pa.vat_number, '[0-9]', '0'), '(?-i)[a-z]', 'x'), '(?-i)[A-Z]', 'X'),
pa.dni = REGEXP_REPLACE(REGEXP_REPLACE(REGEXP_REPLACE(pa.dni, '[0-9]', '0'), '(?-i)[a-z]', 'x'), '(?-i)[A-Z]', 'X');

UPDATE ps_customer c
SET c.lastname = REGEXP_REPLACE(REGEXP_REPLACE(c.lastname, '(?-i)[a-z]', 'x'), '(?-i)[A-Z]', 'X'),
c.firstname = REGEXP_REPLACE(REGEXP_REPLACE(c.firstname, '(?-i)[a-z]', 'x'), '(?-i)[A-Z]', 'X'),
c.email = CONCAT(c.id_customer, '@example.com');

UPDATE ps_customer c 
SET c.ip_registration_newsletter = '127.0.0.1' 
WHERE c.ip_registration_newsletter IS NOT NULL AND c.ip_registration_newsletter != '0';

UPDATE ps_customer_message cm
SET cm.message = REGEXP_REPLACE(REGEXP_REPLACE(cm.message, '(?-i)[a-z]', 'x'), '(?-i)[A-Z]', 'X'),
cm.ip_address = '2130706433';

UPDATE ps_customer_thread ct
SET ct.email = CONCAT(IF(ct.id_customer > 0, ct.id_customer, '0'), '@example.com');
Langage du code : SQL (Structured Query Language) (sql)

La syntaxe de REGEXP_REPLACE n’est pas la même pour MySQL et MariaBD, donc il faudra adapter.

Autoriser les images avec des longs ID dans PrestaShop

Par construction PrestaShop ne peut pas gérer les images avec des ID supérieurs à 9 999 999 (7 chiffres). C’est déjà beaucoup et on a pas souvent besoin de plus mais j’ai eu affaire à un script d’import qui impose les ID d’images et donc ça arrive.

Pourquoi PrestaShop ne les gèrent pas ?

En fait, PrestaShop n’a pas de soucis avec les ID de 8 chiffres ou plus, tant que la base de données l’accepte, lui aussi. Le problème vient de la façon d’accéder aux images.

L’URL d’une image est https://example.com/123-large/mon-image.jpg soit [url de la boutique]/[ID de l'image]-[format à afficher]/[texte pour le référencement].jpg et le fichier .htaccess explique au serveur que quand on a une url de ce type, il faut aller chercher le fichier qu’il faut dans le dossier des images /img/p/

Le fichier .htaccess de PrestaShop ressemble à ça

RewriteRule ^([0-9])(\-[_a-zA-Z0-9-]*)?(-[0-9]+)?/.+\.jpg$ %{ENV:REWRITEBASE}img/p/$1/$1$2$3.jpg [L]
RewriteRule ^([0-9])([0-9])(\-[_a-zA-Z0-9-]*)?(-[0-9]+)?/.+\.jpg$ %{ENV:REWRITEBASE}img/p/$1/$2/$1$2$3$4.jpg [L]
RewriteRule ^([0-9])([0-9])([0-9])(\-[_a-zA-Z0-9-]*)?(-[0-9]+)?/.+\.jpg$ %{ENV:REWRITEBASE}img/p/$1/$2/$3/$1$2$3$4$5.jpg [L]
RewriteRule ^([0-9])([0-9])([0-9])([0-9])(\-[_a-zA-Z0-9-]*)?(-[0-9]+)?/.+\.jpg$ %{ENV:REWRITEBASE}img/p/$1/$2/$3/$4/$1$2$3$4$5$6.jpg [L]
RewriteRule ^([0-9])([0-9])([0-9])([0-9])([0-9])(\-[_a-zA-Z0-9-]*)?(-[0-9]+)?/.+\.jpg$ %{ENV:REWRITEBASE}img/p/$1/$2/$3/$4/$5/$1$2$3$4$5$6$7.jpg [L]
RewriteRule ^([0-9])([0-9])([0-9])([0-9])([0-9])([0-9])(\-[_a-zA-Z0-9-]*)?(-[0-9]+)?/.+\.jpg$ %{ENV:REWRITEBASE}img/p/$1/$2/$3/$4/$5/$6/$1$2$3$4$5$6$7$8.jpg [L]
RewriteRule ^([0-9])([0-9])([0-9])([0-9])([0-9])([0-9])([0-9])(\-[_a-zA-Z0-9-]*)?(-[0-9]+)?/.+\.jpg$ %{ENV:REWRITEBASE}img/p/$1/$2/$3/$4/$5/$6/$7/$1$2$3$4$5$6$7$8$9.jpg [L]Langage du code : JavaScript (javascript)

Donc quand le serveur reçoit l’URL https://example.com/123-large/mon-image.jpg il affiche le fichier /img/p/1/2/3/123-large.jpg. C’est rapide et ça ne demande pas de ressource, PrestaShop n’est même pas appelé quand on veut afficher une image produit.

Mais on ne peut pas utiliser $10 dans un fichier .htaccess, il est interprété comme $1 puis le caractère 0. Comme dans la dernière ligne de l’extrait ci-dessus on utilise $9, on ne peut pas aller plus loin.

Ma solution

Si on appelle l’URL https://example.com/123456789-large/mon-image.jpg, le serveur ne reconnait pas ce format et essaye simplement d’afficher le fichier /123456789-large/mon-image.jpg qui n’existe pas et renvoie donc une erreur 404. PrestaShop affiche donc une jolie page pour dire que le fichier n’a pas été trouvée.

L’astuce consiste à utiliser cette page pour afficher l’image demandée en complétant le controller PageNotFound.

<?php
class PageNotFoundController extends PageNotFoundControllerCore
{
    public function initContent()
    {
        list($filename) = explode('?', $_SERVER['REQUEST_URI']);
        if (preg_match('/([0-9]+)(\-[_a-zA-Z0-9-]*)?\/.*\.jpg/', $filename, $matches)) {
            $path = _PS_ROOT_DIR_.'/img/p/'.implode('/', str_split($matches[1], 1)).'/'.$matches[1].$matches[2].'.jpg';
            if (file_exists($path)) {
                header('Content-Type: '.mime_content_type($path)?:'image/jpg');
                readfile($path);
                die();
            } else {
                header('HTTP/1.1 404 Not Found');
                header('Status: 404 Not Found');
                header('Content-Type: image/gif');
                readfile(_PS_ROOT_DIR_.'/img/404.gif');
                die();
            }
        }
        return parent::initContent();
    }
}Langage du code : PHP (php)

Code à placer dans /override/controllers/front/PageNotFoundController.php

Le principe est le suivant :

  • quand le controller PageNotFound est appelé, on regarde si l’URL correspond à celle d’une image produit,
  • si oui on regarde si elle existe,
    • si oui on l’affiche et c’est terminé
    • si non on affiche une image d’erreur
  • si non on laisse le controller gérer

Sources :

Supprimer les notices du mode debug de PrestaShop

Le mode debug de PrestaShop 1.7 fonctionne trop bien. Par défaut il s’arrête sur toutes les erreurs, avertissement ou notice, ce qui fait que quand un problème, même minime, se trouve en amont de ce que vous voulez corriger, le système s’arrête avant la partie qui vous intéresse.

Par exemple avec PHP 7.4, Doctrine utilisé par PrestaShop affiche un Warning : https://github.com/doctrine/DoctrineORMModule/issues/579 ce qui empêche tout débogage.

Pour corriger tout cela, il faut dire à Symfony quelles erreurs afficher :

On a 2 fichiers à modifier « classes/controller/FrontController.php » et « admin/index.php » dans les deux cas il faut remplacer

Debug::enable();Langage du code : CSS (css)

par

Debug::enable(E_ALL & ~E_NOTICE & ~E_STRICT & ~E_DEPRECATED & ~E_WARNING);Langage du code : PHP (php)

en adaptant le paramètre à ce qu’on veut. La documentation est ici : https://www.php.net/error_reporting

Il peut être utile de modifier aussi « config/defines.inc.php » en remplaçant

@error_reporting(E_ALL | E_STRICT);Langage du code : PHP (php)

par

@error_reporting(E_ALL & ~E_NOTICE & ~E_STRICT & ~E_DEPRECATED & ~E_WARNING);Langage du code : PHP (php)

Activer les hooks dans une page CMS PrestaShop

Normalement le contenu des pages CMS est statique dans PrestaShop mais il peut être utile d’y afficher un module pour mettre les dernières réductions, un formulaire d’inscription ou n’importe quoi.

Pour cela il faut modifier le fichier cms.tpl du thème de la boutique.

{$cms->content}

devient

{assign var="cms_content" value=$cms->content}
{include file="string:$cms_content"}

ça permet au contenu d’être interprété par Smarty avant l’affichage et on peut donc mettre les appels aux hooks dans sa page CMS sous la forme {hook h=’displayCarousel’}  (voir la doc).

En fait cela permet aussi d’utiliser toute la syntaxe de Smarty, les foreach , include  et tout le reste

Supprimer une boutique PrestaShop

Voici un script qui supprime une boutique PrestaShop. Il suffit de le placer à la racine de sa boutique en FTP ou autre et de le visiter avec son navigateur.

⚠ Le script supprime le répertoire de PrestaShop avec tous ses fichiers et sous répertoires et toutes les tables de la base de données qui ont le préfixe de PrestaShop.

⚠⚠ Le script ne demande pas de confirmation. Vous le lancez, il supprime tout.

<?php
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);

$root = dirname(__FILE__);
$server = false;
$user = false;
$password = false;
$database = false;
$prefix = false;

if (file_exists($root.'/app/config/parameters.php')) {
    $parameters = (include $root.'/app/config/parameters.php');
    $server = $parameters['parameters']['database_host'];
    $user = $parameters['parameters']['database_user'];
    $password = $parameters['parameters']['database_password'];
    $database = $parameters['parameters']['database_name'];
    $prefix = $parameters['parameters']['database_prefix'];
} elseif (file_exists($root.'/config/settings.inc.php')) {
    include $root.'/config/settings.inc.php';
    $server = _DB_SERVER_;
    $user = _DB_USER_;
    $password = _DB_PASSWD_;
    $database = _DB_NAME_;
    $prefix = _DB_PREFIX_;
} else {
    die();
}

if (!$server || !$user || !$database || !$prefix) {
    die();
}

dropTables($server, $user, $password, $database, $prefix);
rrmdir($root);

// https://stackoverflow.com/questions/1589278/sql-deleting-tables-with-prefix#1589324
// https://stackoverflow.com/a/10664265/2530962
function dropTables($server, $user, $password, $database, $prefix)
{
    $link = mysqli_connect($server, $user, $password, $database);
    $query = 'SET SESSION group_concat_max_len = 999999999;
    SELECT CONCAT( \'DROP TABLE \', GROUP_CONCAT(table_name) , \';\' )
        AS statement FROM information_schema.tables
        WHERE table_schema = \''.mysqli_real_escape_string($link, $database).'\'
            AND table_name LIKE \''.mysqli_real_escape_string($link, $prefix).'%\';';
    if (mysqli_multi_query($link, $query)) {
        do {
            if ($result = mysqli_store_result($link)) {
                while ($row = mysqli_fetch_array($result)) {
                    $drop_query = $row[0];
                }
                mysqli_free_result($result);
            }
        } while (mysqli_more_results($link) && mysqli_next_result($link));
    }

    echo 'MySQL "'.$drop_query.'"<br/>';
    mysqli_query($link, $drop_query);
}

// https://stackoverflow.com/questions/3338123/how-do-i-recursively-delete-a-directory-and-its-entire-contents-files-sub-dir#3338133
function rrmdir($dir)
{
    if (is_dir($dir)) {
        $objects = scandir($dir);
        foreach ($objects as $object) {
            if ($object != "." && $object != "..") {
                if (is_dir($dir."/".$object)) {
                    rrmdir($dir."/".$object);
                } else {
                    echo 'Delete '.$dir."/".$object.'    ';
                    if (unlink($dir."/".$object)) {
                        echo 'OK';
                    } else {
                        echo 'ERROR';
                    }
                    echo '<br/>';
                }
            }
        }
        echo 'Delete '.$dir.'    ';
        if (rmdir($dir)) {
            echo 'OK';
        } else {
            echo 'ERROR';
        }
        echo '<br/>';
    }
}

 

Exécuter un script PrestaShop en ligne de commande

Le plus propre pour lancer un script prestashop en ligne de commande est de créer un controller pour ça.

Pour l’appeler voici la syntaxe :

php -f [dossier de la boutique]index.php "fc=module&module=[nom du module]&controller=[nom du controller]"

Soit dans mon cas

php -f /var/www/index.php "fc=module&module=backupdatabase&controller=cron"

Ensuite le code du controller

<?php
class BackupDatabaseCronModuleFrontController extends ModuleFrontController
{
    public function init()
    {
        $this->module->cron();
        die();
    }
}

 

La mauvaise foi du sécuritaire chez Prestashop

Je suis déçu par Prestashop 🙁

  • Les erreurs de jeunesse que la solution traîne comme des boulets, je comprend.
  • Les bugs (d’arrondi) gros comme le monde qui durent depuis la version 1, je tolère.
  • Les publicités de plus en plus présentes et agressives dans le panneau d’administration, je n’aime pas mais je comprend

mais là c’est moche, d’une mauvaise foi évidente et joue sur la peur de ses clients au détriment de ses (anciens ou futurs anciens) partenaires.

Note : J’aime Prestashop et Prestashop Addons c’est un beau projet, une belle plateforme que je suis depuis le début. Ils me font vivre et je leur rend pas assez. Mais il y a des comportements qui me sortent par les yeux.

Donc que ce passe-t-il ?

Depuis la version 1.6.0.9 (dernière à ce jour) si on veut installer un module non présent sur Prestashop Addons, un gros (GROS) message s’affiche avec des couleurs alarmantes, un bouton de validation rouge et un message qui fait trembler :

Le module “XXX” n’a pas pu être identifié en toute sécurité par PrestaShop.

Ceci se produit généralement lorsque le module n’est pas distribué via notre place de marché officielle PrestaShop Addons, ou quand votre serveur n’arrive pas à communiquer avec PrestaShop Addons.

Comme vous n’avez pas téléchargé le module depuis PrestaShop Addons nous ne pouvons pas certifier qu’il est conforme à nos exigences de sécurité (notamment, nous ne pouvons pas certifier qu’il n’ajoute pas de fonctionnalités cachées comme un cheval de troie, des publicités, des liens cachés, du spam, etc.). Vous l’utilisez à vos propres risques.

blablabla peur blablabla vous avez eu tord blablabla Achetez chez nous

Image prise chez webbax qui parle du même sujet : https://www.webbax.ch/2014/08/27/prestashop-alerte-module-non-verifie/

Le message est (presque) vrai, on ne peut rien en dire sauf qu’il est d’une mauvaise foi dégoulinante. Un peu comme quand vous cliquez sur un lien externe sur Facebook : “Attention, vous allez dans le côté obscur du web, là où les pédonazies mangent des chatons en fumant dans les halls de gare. Vous feriez mieux de rester chez nous.”

Pourquoi est-ce de la mauvaise foi ?

  1. Un module malveillant n’attendra pas d’être installé pour faire ses petites affaires. Si vraiment il a besoin d’être installé il peut le faire sans vous. A partir du moment ou il s’affiche dans la liste des modules c’est mort. Donc si vraiment le module est vilain ce message ne sert à rien.
  2. Contourner l’affichage de ce message est trivial. Dans pas longtemps les modules honnêtes mais non présents sur Addons le feront pour ne pas effrayer les commerçants.
  3. Le but n’est pas de protéger le commerçant (cf 1) mais de rediriger vers Addons, C’est évident, c’est moche c’est crade. On accuse le commerçant ( “Comme vous n’avez pas téléchargé” ) de mal agir et que tout sera sa faute ( “Vous l’utilisez à vos propres risques.” ) après l’avoir bardé de mots qui font peur. Ensuite plus sereinement on explique qu’un module similaire existe surement sur Addons et qu’on peut revenir à la sécurité (ouf)

Quel est le vrai but ?

  1. Vendre des modules c’est évident mais pas que.
  2. Supprimer les modules gratuits indépendants. Avez vous remarqué qu’il y a de moins en moins de modules gratuits sur Addons ? ça fait un moment qu’on ne peut plus en ajouter mais les anciens restaient. Pourtant récemment deux des miens ont été effacés car “Pas assez de ventes” (héhéhé). Donc les modules gratuits ne sont plus validés par Addons et auront tous ce message. Mais pas d’inquiétude un payant existe surement sur Addons
  3. Supprimer la concurrence et faire plaisir aux partenaires. Il y a plein de boutiques de modules indépendantes et quelques autres places de marché dédiées. Evidemment le message apparaîtra si leurs modules ne sont pas sur Addons. Mais pourquoi ? Par exemple il est impossible de déposer sur Addons un module de paiement (Crédit Agricole, LCL…) Prestashop a déjà les siens ou un module similaire à un de leurs partenaires (qui payent pour être mis en avant sur Addons). Mais des modules de paiements indépendant il y en a plein (et même des gratuits) et ça c’est pas bon pour les affaires.

Conclusion

Je comprend tout à fait la position de Prestashop et d’Addons.

Addons est ce qui rapporte des sous à Prestashop. Il faut le mettre en avant. La solution gratuite n’est (commercialement parlant) qu’un appel à l’achat sur la plateforme. Pas de problème avec ça. Tuer la concurrence, c’est du commerce. Oui oui ok. Les partenaires veulent un retour sur l’investissement, les vrais clients c’est eux. Normal.

Mais jouer sur la peur des commerçants, et en plus trop tard, quand même c’est crade. A côté de ça les pubs cachées de “Expertise Prestashop” passent pour des enfantillages.

Prestashop tu vaux mieux que ça.

P.S. un cheval de Troie (majuscule, c’est une ville) n’est pas une fonction cachée mais un camouflage, le module peut être un cheval de Troie mais pas en cacher un. Mais bon fallait placer des mots qui parlent aux gens et qui font peur. “Tremmmblez devant les liens cachés, bhooooo”

Un souhait pour Prestashop 2

Prestashop 2 est prévue pour bientôt ou pas, quoi qu’il en soit il y a un truc qu’il faudra absolument améliorer, c’est le système de messages utilisateur (erreur, confirmation, alerte).

Actuellement ça se passe ainsi :

  1. On clique sur un lien d’action. par exemple http://…?send_mail&id_client=42 pour envoyer un mail à un client
  2. on arrive sur la page qui fait l’action (page d’action)
  3. si ça marche, on est redirigé sur une page qui affiche une confirmation http://…?conf=33 conf étant l’id du message de confirmation
  4. si ça échoue, on reste sur la page et on affiche les erreurs.

La redirection est importante car si on restait sur la page d’action, il suffirait de la recharger pour exécuter de nouveau l’action ou de laisser l’onglet ouvert avant de fermer le navigateur. Pour un mail c’est pas trop grave, pour une suppression plus.

Donc tant que qu’il n’y a pas d’erreur ça marche (bin oui) mais sinon on reste sur la page d’action et c’est mal.

Vous allez dire que c’est pas grave puisque ça marche pas, il n’y a pas de risque que le mail soit envoyé si je recharge la page et si ça marche bin c’est cool c’est ce que je voulais.

Non. déjà ça peut être une erreur temporaire donc ça peut très bien fonctionner la seconde fois.

Ensuite on ne sait pas à quel moment ça a échoué. Si il fallait supprimer une commande puis envoyer un mail au client en rechargeant la page vous pouvez supprimer 3 commandes et à chaque fois ne pas réussir à envoyer les mails.

Bref le système est bancal.

En plus il est très limité :

  • Il y a un id de message de confirmation donc il y a une liste prédéfinie de message (31 dans la classe AdminControllerCore) donc si vous voulez utiliser une confirmation personnalisée ça devient compliqué.
  • Vous ne pouvez avoir qu’un seul message. Pour reprendre l’exemple on ne peut pas dire “la commande est supprimée” et “le mail est envoyé” et bien sûr on ne mixe pas (“la commande est supprimée” et “Erreur, le mail n’est pas envoyé”)
  • Si je recharge la page, j’ai de nouveau le message ce qui peut être perturbant et pas joli.

Ce qu’il faudrait c’est un vrai gestionnaire de message.

Quand quelque chose fait une action il dit “Faudra dire à untel/tout le monde/personne que j’ai fait ça” ou “Faudra dire qu’il y a cet erreur/alerte/information” comme pour un système de log (c’est la même chose en fait).

Par exemple

(bon là y a des if partout mais c’est l’idée)
et au prochain affichage d’une page on montre les messages en attente.

Ce serait utile pour les modules aussi. Le module Ebay par exemple met à jour la fiche produit sur ebay.com à chaque fois qu’on en modifie un sur Prestashop mais il peut pas le dire, l’info est perdue à la redirection. Là il pourrait mettre en attente “tel produit est à jour/désactivé/supprimé sur ebay.com” ou “impossible de contacter ebay.com”.

Donc tout ça pour dire que ce serait un truc super pratique.

Exemple d’override pour Prestashop

Ce message se veut être un complément au billet de Webbax

J’ai eu à travailler sur l’override de Prestashop. Ce n’est pas compliqué, en tout cas beaucoup plus simple que de modifier les fichiers “cœurs” de Prestashop et si c’est bien fait beaucoup plus stable.

Le but était de rajouter trois Hooks génériques : un pour l’ajout d’un Objet (produit, fabriquant, bon de réduction…), un pour sa mise à jour et un pour sa suppression.

Dans les versions 1.3 et précédentes j’aurais dû modifier le fichier classes/ObjectModel.php qui est un peu complexe et faire une version pour chaque version de Prestashop.

Mais là que du bonheur, il faut créer un fichier override/classes/ObjectModel.php comme ci-dessous :

<?php

class ObjectModel extends ObjectModelCore
{   
    public function add($autodate = true, $nullValues = false)
    {
        $result = parent::add($autodate, $nullValues);
        if ($result)  Module::hookExec('objectAdd', array('object' => $this));
        return $result;
    }

    public function update($autodate = true, $nullValues = false)
    {
        $result = parent::update($autodate, $nullValues);
        if ($result)  Module::hookExec('objectUpdate', array('object' => $this));
        return $result;
    }

    public function delete($autodate = true, $nullValues = false)
    {
        $result = parent::delete($autodate, $nullValues);
        if ($result)  Module::hookExec('objectDelete', array('object' => $this));
        return $result;
    }
}
?>

C’est petit hein ?

Le principe est simple, pour chaque méthode (add(), update() et delete() ), on laisse l’objet parent faire son travail ( parent::add() ) et en fonction du résultat on appelle ou non le hook.

Ainsi on a pas touché au cœur de Prestashop, le fichier ajouté est simple et facile à maintenir et surtout il sera compatible avec les futures version de Prestashop.