Prestashop : Migrer les hooks dépréciés des modules

Ce tutoriel est compatible avec les versions de Prestashop suivantes :
8.1 +

Il existe depuis très longtemps dans le fonctionnement des hooks de prestashop une fonction d’alias qui permets de mettre à jour le nom d’un hook tout en maintenant la compatibilité avec son ancien nom.
Le meilleur exemple de cette fonctionnalité est le hook header qui a été remplacé par displayHeader depuis très longtemps mais qui continue à fonctionner.
Ceci fonctionnait très bien et continue d’ailleurs de fonctionner, mais depuis la version 8.1 de Prestashop , chaque appel à un hook à un ancien alias va générer une erreur de log sur le serveur.
De ce type :

The hook « header » is deprecated, please use « displayHeader » instead in module « moduleName »

En fonction du nombre de modules concernés on peut vite remplir son serveur avec des milliers de lignes inutiles.

Plusieurs solution pour corriger ce point.


Quick & dirty et déconseillée  :  Commenter les lignes suivantes dans la méthode exec de la classe Hook ( via un override )

// We throw an error - aliases are deprecated.
                trigger_error(
                    sprintf(
                        'The hook "%s" is deprecated, please use "%s" instead in module "%s".',
                        $registeredHookName,
                        $hook_name,
                        $hookRegistration['module']
                    ),
                    E_USER_DEPRECATED
                );

La 2ème solution est de corriger les erreurs une par une pour ne plus avoir toutes ces alertes.
C’est possible de le faire manuellement pour chaque module via l’administration et les positions des modules en les supprimant de l’ancien hook et en les ajoutant sur le nouveau.
En fonction de la volumétrie cela peut être plus ou moins chronophage.

Pour ma part en tant que développeur qui n’aime pas faire ce genre de choses manuellement j’ai écrit un script qui le fait de manière automatique 🙂
Avant toute chose sachez que ce script ne gère pas le multi-boutique et que je décline toute responsabilité sur les effets de bords que cela pourrait avoir sur votre site.
Il faut le tester sur un environnement de préproduction au préalable 🙂

class PatchDeprecatedHooks
{
 
    /**
     * Patch des anciens hooks sur les alias pour les mettre sur les nouveaux
     * @return void
     */
    public function patch(): void
    {
        $affectedHooks = $this->getAffectedModulesAndHooks();
        if ( count($affectedHooks)){
            foreach ( $affectedHooks as $affectedHook){
                try {
                    $module = \Module::getInstanceById($affectedHook['id_module']);
                    $module->unregisterHook($affectedHook['current_hook_name']);
                    $module->registerHook($affectedHook['new_hook_name']);
                } catch ( \Exception $e){
                    dump('Unable to patch modules hooks for module '
                        .$affectedHook['name'].' and hook '
                        .$affectedHook['current_hook_name']
                        .' '.$e->getMessage()
                    );
                }
            }
        }
    }
 
    /**
     * Récupération de la liste des hooks dépréciés
     *
     * @return array
     */
    protected function getAffectedModulesAndHooks(): array
    {
        $results = [];
        try {
            $deprecatedHooks = \Db::getInstance()->executeS(
                "SELECT hm.id_module,hm.id_hook,hm.id_shop,hm.position,m.`name`, m.version , h.`name` as current_hook_name, a.name new_hook_name
                    FROM " ._DB_PREFIX_ . "hook_module hm
                    LEFT JOIN " ._DB_PREFIX_ . "module m ON m.id_module = hm.id_module
                    LEFT JOIN " ._DB_PREFIX_ . "hook h ON h.id_hook = hm.id_hook
                    LEFT JOIN " ._DB_PREFIX_ . "hook_alias a ON a.`alias` = h.`name`
                    WHERE hm.id_hook IN (
                    SELECT id_hook
                    FROM " ._DB_PREFIX_ . "hook_alias a
                    INNER JOIN " ._DB_PREFIX_ . "hook h1 ON h1.name = a.alias
                    )
                    ORDER BY hm.id_module"
            );
            if ($deprecatedHooks) {
                $results = $deprecatedHooks;
            }
        } catch ( \PrestaShopDatabaseException $e){
            dump('Query error '.$e->getMessage());
        }
        return $results;
    }
}

Plusieurs possibilité pour éxécuter ce code :

  • Faites une classes spécifique PatchDeprecatedHooks  dans un de vos module et appeller la fonction apply depuis n’importe quel endroit dans votre module
  • Mettre toute cette logique dans un fichier d’upgrade de module 🙂

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *