{"id":3128,"date":"2023-06-21T22:31:56","date_gmt":"2023-06-21T20:31:56","guid":{"rendered":"https:\/\/www.h-hennes.fr\/blog\/?p=3128"},"modified":"2023-06-22T08:21:50","modified_gmt":"2023-06-22T06:21:50","slug":"prestashop-mettez-en-avant-vos-modules-dans-le-listing-des-modules-dans-ladministration","status":"publish","type":"post","link":"https:\/\/www.h-hennes.fr\/blog\/2023\/06\/21\/prestashop-mettez-en-avant-vos-modules-dans-le-listing-des-modules-dans-ladministration\/","title":{"rendered":"Prestashop : Mettez en avant vos modules dans le listing des modules dans l&rsquo;administration"},"content":{"rendered":"\n<p>La nouvelle version 8 de Prestashop rajoute une nouvelle fonction tr\u00e8s int\u00e9ressante qui permets de faire remonter une liste de <strong>modules non install\u00e9s sur le site<\/strong> en question automatiquement dans le listing des module qui est pr\u00e9sent dans l&rsquo;administration.<\/p>\n<p>Globalement cela vous permets de faire comme addons le faisait sur les versions pr\u00e9c\u00e9dentes c&rsquo;est \u00e0 dire de rendre installable directement depuis le listing des modules.<br>En cherchant un peu plus loin cela vous permets donc de cr\u00e9er <strong>votre propre marketplace de modules<\/strong> \ud83d\ude42 <br><br>Nous n&rsquo;irons bien sur pas aussi loin dans cet article, mais je vais d\u00e9tailler comment faire cela techniquement.<br>C&rsquo;est relativement facile, je me suis inspir\u00e9 du fonctionnement du module officiel de Prestashop qui fait remonter leur propres modules \u00e0 partir de la version 8.0 et qui est disponible ici : <br><a href=\"https:\/\/github.com\/PrestaShop\/ps_distributionapiclient\" target=\"_blank\" rel=\"noopener\">https:\/\/github.com\/PrestaShop\/ps_distributionapiclient<\/a> <br><br><\/p>\n<p>Tout passe comme toujours avec Prestashop par la cr\u00e9ation d&rsquo;un module, qu&rsquo;on appellera <strong>hhmodulescatalog<\/strong><\/p>\n<p>&nbsp;<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Fonctionnement technique<\/h2>\n\n\n\n<p>Il existe un nouveau hook <strong>actionListModules<\/strong> qui est lanc\u00e9 dans le fichier&nbsp; \\PrestaShop\\PrestaShop\\Core\\Module\\ModuleRepository<br>Celui ci permets \u00e0 chaque module impl\u00e9mentant ce hook, de retourner un tableau qui contient la liste de vos modules sp\u00e9cifiques \u00e0 afficher dans le listing des modules.<br>Nous verrons plus loin quel est le format du tableau \u00e0 renvoyer.<\/p>\n<p>L&rsquo;autre point \u00e0 g\u00e9rer est le t\u00e9l\u00e9chargement du fichier zip contenant le module avant son installation, pour cela nous utiliserons le hook <strong>actionBeforeInstallModule.<br><\/strong>Pour la partie mise \u00e0 jour du module il&nbsp; n&rsquo;y aura rien \u00e0 faire pour le t\u00e9l\u00e9chargement c&rsquo;est g\u00e9r\u00e9 automatiquement.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Aper\u00e7u<\/h2>\n\n\n\n<figure class=\"wp-block-image size-full\"><a href=\"https:\/\/www.h-hennes.fr\/blog\/wp-content\/uploads\/2023\/06\/image.png\"><img loading=\"lazy\" decoding=\"async\" width=\"939\" height=\"418\" src=\"https:\/\/www.h-hennes.fr\/blog\/wp-content\/uploads\/2023\/06\/image.png\" alt=\"\" class=\"wp-image-3129\" srcset=\"https:\/\/www.h-hennes.fr\/blog\/wp-content\/uploads\/2023\/06\/image.png 939w, https:\/\/www.h-hennes.fr\/blog\/wp-content\/uploads\/2023\/06\/image-300x134.png 300w, https:\/\/www.h-hennes.fr\/blog\/wp-content\/uploads\/2023\/06\/image-768x342.png 768w\" sizes=\"auto, (max-width: 939px) 100vw, 939px\" \/><\/a><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">Code du module<\/h2>\n\n\n\n<p>Passons maintenant au code du module qui sera dans le fichier&nbsp; <strong>hhmodulescatalog.php<\/strong><br>Ajouter \u00e9galement un dossier <strong>downloads<\/strong> qui permettra de r\u00e9cup\u00e9rer stocker les modules t\u00e9l\u00e9charg\u00e9s.<\/p>\n\n\n\n<pre lang=\"php\" escaped=\"true\">\n\n<?php\nif (!defined('_PS_VERSION_')) {\n    exit;\n}\n\nclass Hhmodulescatalog extends Module\n{\n\n    public function __construct()\n    {\n        $this->name = 'hhmodulescatalog';\n        $this->tab = 'market_place';\n        $this->version = '0.1.0';\n        $this->author = 'hhennes';\n        $this->bootstrap = true;\n        $this->ps_versions_compliancy = ['min' => '8.0', 'max' => _PS_VERSION_]; \/\/Version 8.0 au minimum\n        parent::__construct();\n\n        $this->displayName = $this->trans('Hh Module Catalog', [], 'Modules.Hhmodulescatalog');\n        $this->description = $this->trans(\n            'List specific modules',\n            [],\n            'Modules.Hhmodulescatalog'\n        );\n        $this->configPrefix = strtoupper($this->name) . '_';\n    }\n\n    \/**\n     * Installation du module\n     * @return bool\n     *\/\n    public function install()\n    {\n        return parent::install()\n            && $this->registerHook('actionListModules')\n            && $this->registerHook('actionBeforeInstallModule');\n    }\n\n    \/**\n     * D\u00e9fini si on utilise le nouveau syst\u00e8me de traduction\n     *\n     * @return bool\n     *\/\n    public function isUsingNewTranslationSystem()\n    {\n        return true;\n    }\n\n    \/**\n     * Hook R\u00e9cup\u00e9ration d'une liste de modules personnalis\u00e9s\n     *\n     * @param array $params\n     * @return array\n     *\/\n    public function hookActionListModules(array $params): array\n    {\n        return $this->getModulesList();\n    }\n\n    \/**\n     * Exemple avec r\u00e9cup\u00e9ration statique d'une liste de module\n     *\n     * C'est ici qu'il faut mettre en place une api (ou tout simplement une url basique)\n     * qui pourra renvoyer les informations n\u00e9cessaires pour r\u00e9cup\u00e9rer les nouveaux modules.\n     *\n     * @return array\n     *\/\n    protected function getModulesList(): array\n    {\n        return [\n            [\n                \"name\" => \"hhadmin\", \/\/Nom du module\n                \"version_available\" => \"0.2.0\", \/\/Version disponible pour le module ( g\u00e9n\u00e8re un updrade si d\u00e9j\u00e0 install\u00e9 )\n                \"download_url\" => \"https:\/\/shop.h-hennes.fr\/upload\/hhadmin.zip\", \/\/Lien vers le fichier zip\n                \"displayName\" => \"Hh admin\", \/\/Nom du module\n                \"description\" => \"Ce module permets de configurer un bandeau de couleur et un texte dans l'ent\u00eate de l'administration de prestashop.\", \/\/Description du module\n                \"author\" => \"hhennes\", \/\/ Auteur du module\n                \"version\" => Module::isInstalled('hhadmin') ?\n                    Module::getInstanceByName('hhadmin')->version : \"0.1.0\", \/\/Version install\u00e9e du module\n                \"img\" => \"https:\/\/shop.h-hennes.fr\/upload\/logo.png\", \/\/Image du module\n                \"tab\" => \"administration\", \/\/ Tab du module\n            ]\n        ];\n    }\n\n    \/**\n     * Hook ex\u00e9cut\u00e9 avant l'installation d'un module\n     *\n     * @param array $params\n     * @return void\n     *\/\n    public function hookActionBeforeInstallModule(array $params): void\n    {\n\n        \/\/Dans le cas ou il n'y a pas de nom de module ou si il est d\u00e9j\u00e0 sur le disque on ne fait rien\n        if (!isset($params['moduleName'])\n            || $this->get('prestashop.adapter.data_provider.module')->isOnDisk($params['moduleName'])) {\n            return;\n        }\n\n        \/\/Dans le cas de nos modules ajout\u00e9 dynamiquement ils ne sont pas pr\u00e9sents sur le serveur.\n        \/\/Il est donc n\u00e9cessaire de les t\u00e9l\u00e9charger avant pour pouvoir les installer\n\n        \/\/On se base toujours sur la liste statique pour l'exemple pour ne pas essayer de t\u00e9l\u00e9charger n'importe quoi\n        foreach ($this->getModulesList() as $module) {\n            if ($module['name'] == $params['moduleName'] && array_key_exists('download_url', $module)) {\n                $this->downloadModuleFile($module['download_url'], $params['moduleName']);\n            }\n        }\n    }\n\n    \/**\n     * Fonction de t\u00e9l\u00e9chargement basique qui va r\u00e9cup\u00e9rer et extraire le contenu de l'archive\n     * vers le dossier du module prestashop\n     * On se contente juste de r\u00e9cup\u00e9rer le fichier \/ le d\u00e9ziper et supprimer le dossier si il existait d\u00e9j\u00e0\n     * Sans v\u00e9rifications sp\u00e9cifiques.\n     *\n     * @param string $moduleLink Lien de t\u00e9l\u00e9chargement du module\n     * @param string $moduleName Nom technique du module\n     * @return void\n     *\/\n    public function downloadModuleFile(string $moduleLink, string $moduleName): void\n    {\n        $downloadFilePath = _PS_MODULE_DIR_ . $this->name . '\/downloads\/' . $moduleName . '.zip';\n\n        \/\/T\u00e9l\u00e9chargement du fichier\n        $moduleContent = file_get_contents($moduleLink);\n        file_put_contents($downloadFilePath, $moduleContent);\n\n        $fileSystem = new Symfony\\Component\\Filesystem\\Filesystem();\n        \/\/Suppression du module si il existe d\u00e9j\u00e0\n        if (is_dir(_PS_MODULE_DIR_ . $moduleName)) {\n            $fileSystem->remove(_PS_MODULE_DIR_ . $moduleName);\n        }\n        \/\/Extraction du fichier\n        $zip = new ZipArchive();\n        $zip->open($downloadFilePath);\n        $zip->extractTo(_PS_MODULE_DIR_);\n        $zip->close();\n    }\n\n}\n\n<\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Pour aller plus loin<\/h2>\n\n\n\n<p>L&rsquo;exemple qui montr\u00e9 est relativement basique, mais on peut aller beaucoup plus loin, comme je le notais en introduction.<br \/>On peut tout \u00e0 fait monter sa propre marketplace qui fera remonter automatiquement via une api une liste de modules achet\u00e9s par un client sur votre site.<br \/>De mon c\u00f4t\u00e9 j&rsquo;ai d\u00e9j\u00e0 exp\u00e9riment\u00e9 la cr\u00e9ation d&rsquo;une api sp\u00e9cifique qui fait remonter tout mes modules habituels, pour pouvoir les installer et les mettre \u00e0 jour en un clic \ud83d\ude42<br \/><br \/>N&rsquo;h\u00e9sitez pas \u00e0 partager vos usage sur cette fonctionnalit\u00e9 !<\/p>\n","protected":false},"excerpt":{"rendered":"<p>La nouvelle version 8 de Prestashop rajoute une nouvelle fonction tr\u00e8s int\u00e9ressante qui permets de faire remonter une liste de modules non install\u00e9s sur le site en question automatiquement dans le listing des module qui est pr\u00e9sent dans l&rsquo;administration. Globalement cela vous permets de faire comme addons le faisait sur les versions pr\u00e9c\u00e9dentes c&rsquo;est \u00e0 [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"site-sidebar-layout":"default","site-content-layout":"","ast-site-content-layout":"default","site-content-style":"default","site-sidebar-style":"default","ast-global-header-display":"","ast-banner-title-visibility":"","ast-main-header-display":"","ast-hfb-above-header-display":"","ast-hfb-below-header-display":"","ast-hfb-mobile-header-display":"","site-post-title":"","ast-breadcrumbs-content":"","ast-featured-img":"","footer-sml-layout":"","ast-disable-related-posts":"","theme-transparent-header-meta":"","adv-header-id-meta":"","stick-header-meta":"","header-above-stick-meta":"","header-main-stick-meta":"","header-below-stick-meta":"","astra-migrate-meta-layouts":"default","ast-page-background-enabled":"default","ast-page-background-meta":{"desktop":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"tablet":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"mobile":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""}},"ast-content-background-meta":{"desktop":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"tablet":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"mobile":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""}},"footnotes":""},"categories":[245],"tags":[596,595,361,104],"class_list":["post-3128","post","type-post","status-publish","format-standard","hentry","category-prestashop-2","tag-actionlistmodules","tag-marketplace","tag-modules","tag-prestashop","prestashop-1-7-8","prestashop-8-0"],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/www.h-hennes.fr\/blog\/wp-json\/wp\/v2\/posts\/3128","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.h-hennes.fr\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.h-hennes.fr\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.h-hennes.fr\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/www.h-hennes.fr\/blog\/wp-json\/wp\/v2\/comments?post=3128"}],"version-history":[{"count":5,"href":"https:\/\/www.h-hennes.fr\/blog\/wp-json\/wp\/v2\/posts\/3128\/revisions"}],"predecessor-version":[{"id":3134,"href":"https:\/\/www.h-hennes.fr\/blog\/wp-json\/wp\/v2\/posts\/3128\/revisions\/3134"}],"wp:attachment":[{"href":"https:\/\/www.h-hennes.fr\/blog\/wp-json\/wp\/v2\/media?parent=3128"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.h-hennes.fr\/blog\/wp-json\/wp\/v2\/categories?post=3128"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.h-hennes.fr\/blog\/wp-json\/wp\/v2\/tags?post=3128"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}