Prestashop : Mettez en avant vos modules dans le listing des modules dans l’administration

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

La nouvelle version 8 de Prestashop rajoute une nouvelle fonction très intéressante qui permets de faire remonter une liste de modules non installés sur le site en question automatiquement dans le listing des module qui est présent dans l’administration.

Globalement cela vous permets de faire comme addons le faisait sur les versions précédentes c’est à dire de rendre installable directement depuis le listing des modules.
En cherchant un peu plus loin cela vous permets donc de créer votre propre marketplace de modules 🙂

Nous n’irons bien sur pas aussi loin dans cet article, mais je vais détailler comment faire cela techniquement.
C’est relativement facile, je me suis inspiré du fonctionnement du module officiel de Prestashop qui fait remonter leur propres modules à partir de la version 8.0 et qui est disponible ici :
https://github.com/PrestaShop/ps_distributionapiclient

Tout passe comme toujours avec Prestashop par la création d’un module, qu’on appellera hhmodulescatalog

 

Fonctionnement technique

Il existe un nouveau hook actionListModules qui est lancé dans le fichier  \PrestaShop\PrestaShop\Core\Module\ModuleRepository
Celui ci permets à chaque module implémentant ce hook, de retourner un tableau qui contient la liste de vos modules spécifiques à afficher dans le listing des modules.
Nous verrons plus loin quel est le format du tableau à renvoyer.

L’autre point à gérer est le téléchargement du fichier zip contenant le module avant son installation, pour cela nous utiliserons le hook actionBeforeInstallModule.
Pour la partie mise à jour du module il  n’y aura rien à faire pour le téléchargement c’est géré automatiquement.

Aperçu

Code du module

Passons maintenant au code du module qui sera dans le fichier  hhmodulescatalog.php
Ajouter également un dossier downloads qui permettra de récupérer stocker les modules téléchargés.

 
<?php
if (!defined('_PS_VERSION_')) {
    exit;
}
 
class Hhmodulescatalog extends Module
{
 
    public function __construct()
    {
        $this->name = 'hhmodulescatalog';
        $this->tab = 'market_place';
        $this->version = '0.1.0';
        $this->author = 'hhennes';
        $this->bootstrap = true;
        $this->ps_versions_compliancy = ['min' => '8.0', 'max' => _PS_VERSION_]; //Version 8.0 au minimum
        parent::__construct();
 
        $this->displayName = $this->trans('Hh Module Catalog', [], 'Modules.Hhmodulescatalog');
        $this->description = $this->trans(
            'List specific modules',
            [],
            'Modules.Hhmodulescatalog'
        );
        $this->configPrefix = strtoupper($this->name) . '_';
    }
 
    /**
     * Installation du module
     * @return bool
     */
    public function install()
    {
        return parent::install()
            && $this->registerHook('actionListModules')
            && $this->registerHook('actionBeforeInstallModule');
    }
 
    /**
     * Défini si on utilise le nouveau système de traduction
     *
     * @return bool
     */
    public function isUsingNewTranslationSystem()
    {
        return true;
    }
 
    /**
     * Hook Récupération d'une liste de modules personnalisés
     *
     * @param array $params
     * @return array
     */
    public function hookActionListModules(array $params): array
    {
        return $this->getModulesList();
    }
 
    /**
     * Exemple avec récupération statique d'une liste de module
     *
     * C'est ici qu'il faut mettre en place une api (ou tout simplement une url basique)
     * qui pourra renvoyer les informations nécessaires pour récupérer les nouveaux modules.
     *
     * @return array
     */
    protected function getModulesList(): array
    {
        return [
            [
                "name" => "hhadmin", //Nom du module
                "version_available" => "0.2.0", //Version disponible pour le module ( génère un updrade si déjà installé )
                "download_url" => "https://shop.h-hennes.fr/upload/hhadmin.zip", //Lien vers le fichier zip
                "displayName" => "Hh admin", //Nom du module
                "description" => "Ce module permets de configurer un bandeau de couleur et un texte dans l'entête de l'administration de prestashop.", //Description du module
                "author" => "hhennes", // Auteur du module
                "version" => Module::isInstalled('hhadmin') ?
                    Module::getInstanceByName('hhadmin')->version : "0.1.0", //Version installée du module
                "img" => "https://shop.h-hennes.fr/upload/logo.png", //Image du module
                "tab" => "administration", // Tab du module
            ]
        ];
    }
 
    /**
     * Hook exécuté avant l'installation d'un module
     *
     * @param array $params
     * @return void
     */
    public function hookActionBeforeInstallModule(array $params): void
    {
 
        //Dans le cas ou il n'y a pas de nom de module ou si il est déjà sur le disque on ne fait rien
        if (!isset($params['moduleName'])
            || $this->get('prestashop.adapter.data_provider.module')->isOnDisk($params['moduleName'])) {
            return;
        }
 
        //Dans le cas de nos modules ajouté dynamiquement ils ne sont pas présents sur le serveur.
        //Il est donc nécessaire de les télécharger avant pour pouvoir les installer
 
        //On se base toujours sur la liste statique pour l'exemple pour ne pas essayer de télécharger n'importe quoi
        foreach ($this->getModulesList() as $module) {
            if ($module['name'] == $params['moduleName'] && array_key_exists('download_url', $module)) {
                $this->downloadModuleFile($module['download_url'], $params['moduleName']);
            }
        }
    }
 
    /**
     * Fonction de téléchargement basique qui va récupérer et extraire le contenu de l'archive
     * vers le dossier du module prestashop
     * On se contente juste de récupérer le fichier / le déziper et supprimer le dossier si il existait déjà
     * Sans vérifications spécifiques.
     *
     * @param string $moduleLink Lien de téléchargement du module
     * @param string $moduleName Nom technique du module
     * @return void
     */
    public function downloadModuleFile(string $moduleLink, string $moduleName): void
    {
        $downloadFilePath = _PS_MODULE_DIR_ . $this->name . '/downloads/' . $moduleName . '.zip';
 
        //Téléchargement du fichier
        $moduleContent = file_get_contents($moduleLink);
        file_put_contents($downloadFilePath, $moduleContent);
 
        $fileSystem = new Symfony\Component\Filesystem\Filesystem();
        //Suppression du module si il existe déjà
        if (is_dir(_PS_MODULE_DIR_ . $moduleName)) {
            $fileSystem->remove(_PS_MODULE_DIR_ . $moduleName);
        }
        //Extraction du fichier
        $zip = new ZipArchive();
        $zip->open($downloadFilePath);
        $zip->extractTo(_PS_MODULE_DIR_);
        $zip->close();
    }
 
}

Pour aller plus loin

L’exemple qui montré est relativement basique, mais on peut aller beaucoup plus loin, comme je le notais en introduction.
On peut tout à fait monter sa propre marketplace qui fera remonter automatiquement via une api une liste de modules achetés par un client sur votre site.
De mon côté j’ai déjà expérimenté la création d’une api spécifique qui fait remonter tout mes modules habituels, pour pouvoir les installer et les mettre à jour en un clic 🙂

N’hésitez pas à partager vos usage sur cette fonctionnalité !

Laisser un commentaire

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