A l'heure ou j'écris ces lignes le plugin Uninstaller n'est disponible que sur mon github et uniquement à partir de Dotclear 2.26-dev et PHP 8.1+. Il va permettre lorsque l'on veut supprimer un module (plugin ou thème) de le faire de manière plus complète, on va pouvoir lors de sa suppression également supprimer ses traces comme par exemples ses paramètres, ses éventuelles tables, des fichiers Var, ses Logs, etc... Tout cela de manière simplissime.
Je vous explique comment intégrer cela à vos plugins et thèmes si ils en ont besoin.
Prenons l'exemple du plugin Scronch qui sera écrit pour les dernières évolutions de Dotclear 2.26, c'est à dire qu'il utilisera l'arborescence en espace de nom, ou encore dit autrement qu'il aura un dossier src et que ces fichiers PHP commenceront par namespace Dotclear\Plugin\Scronch;. Ce plugin utilise plusieurs paramètres regroupés dans un espace de nom de paramètres portant son nom. (càd: dcCore::app()->blog->settings->Scronch ) Notre plugin va également enregistrer des logs dans la base de Dotclear, ils seront également regroupés sous son nom.
Le décor est posé. Pour ajouter des fonctions de désinstallation il faut ajouter dans le dossier src un fichier du nom de Uninstall.php qui intègrera donc la classe Uninstall, cette class devra étendre la classe dcNsProcess qui est très utilisée maintenant dans Dotclear. Comme partout la première méthode init() de cette classe va permettre de faire des testes afin de savoir si on peut l'utiliser par la suite. Puis la seconde méthode process() va permettre d'enregistrer les actions de désinstallation à mener. (Elle va également permettre de traiter d'éventuelles actions non standards, j'en reparlerais dans un deuxième exemple). Quand à la troisième méthode render() elle ne servira que si on a besoin d'ajouter un champs de formulaire. (idem on verra ça en deuxième exemple.). Donc si vous suivez, il va falloir dire dans la méthode process() que nous voulons supprimer les logs et les paramètres. Suivons le premier exemple du fichier complet de désinstallation de notre plugin Scronch :
<?php
declare(strict_types=1);
namespace Dotclear\Plugin\Scronch;
use dcCore;
use dcNsProcess;
use Dotclear\Plugin\Uninstaller\Uninstaller;
class Uninstall extends dcNsProcess
{
public static function init(): bool
{
static::$init = defined('DC_CONTEXT_ADMIN');
return static::$init;
}
public static function process(): bool
{
if (!static::$init || !dcCore::app()->plugins->moduleExists('Uninstaller')) {
return false;
}
Uninstaller::instance()
->addUserAction(
'settings',
'delete_all',
'Scronch'
)
->addUserAction(
'logs',
'delete_all',
'Scronch'
)
->addUserAction(
'plugins',
'delete',
'Scronch'
)
->addUserAction(
'versions',
'delete',
'Scronch'
)
->addDirectAction(
'settings',
'delete_all',
'Scronch'
)
->addDirectAction(
'logs';
'delete_all',
'Scronch'
)
->addDirectAction(
'plugins',
'delete',
'Scronch'
)
->addDirectAction(
'versions',
'delete',
'Scronch'
)
;
// no custom action
return false;
}
}
Que voit-on ici ? On va d'abord chercher le désinstalleur avec Uninstaller::instance() Puis on ajoute 4 actions qui sont effacer les paramètres, effacer les logs, effacer le plugin, effacer la version. Mais alors pourquoi y sont-ils deux fois ? Car il y a deux manières de supprimer un module, soit directement (Direct) avec un clic sur supprimer dans la liste des plugins ou thèmes et là les actions seront menées sans aucune question ! Soit en faisant appelle à l'utilisateur (User) avec une liste de choix comme dans l'exemple suivant :

Je laisse seul juge le développeur si il souhaite ou non proposer les actions directes, on m'a déjà fait remarquer que nombre de gens préfère garder ces traces au cas ou il faille réinstaller le module plus tard, on pour sauvegarde... Si toutefois vous souhaitez désactiver les actions directes sur votre plateforme de blogs, il suffit de se rendre dans about:config et de mettre à oui l'entrée system => no_direct_uninstall.
Voici à l'instant T toutes les actions prédéfinies suivi de l'ID du nettoyeur et de son action :
- effacer le dossier de cache sélectionné : caches - delete
- vider le dossier de cache sélectionné : caches - empty
- effacer la table de logs sélectionnée : logs - delete_all
- supprimer le numéro de version sélectionné : versions - delete
- supprimer le dossier VAR sélectionné : vars - delete
- supprimer les fichiers et dossiers du thème sélectionné : themes - delete
- supprimer les fichiers et dossiers du plugin sélectionné : plugins - delete
- supprimer la table de base de données sélectionnée : tables - delete
- vider la table de base de données sélectionnée : tables - empty
- supprimer les paramètres globaux sélectionnés : settings - delete_global
- supprimer les paramètres locaux (blog) sélectionnés : settings - delete_local
- supprimer tous les paramètres sélectionnés : settings: -dellete_all
- supprimer les paramètres relatifs (cf code) : settings - delete_related
- supprimer les préférences globales sélectionnées : preferences - delete_global
- supprimer les préférences locales (utilisateurs) sélectionnées : preferences - delete_local
- supprimer toutes les préférences sélectionnées : preferences - dellete_all
- supprimer les préférences relatives (cf code) : preferences - delete_related
<?php
declare(strict_types=1);
namespace Dotclear\Plugin\Scronch;
use dcCore;
use dcNsProcess;
use Dotclear\Plugin\Uninstaller\Uninstaller;
class Uninstall extends dcNsProcess
{
public static function init(): bool
{
static::$init = defined('DC_CONTEXT_ADMIN');
return static::$init;
}
public static function process(): bool
{
if (!static::$init || !dcCore::app()->plugins->moduleExists('Uninstaller')) {
return false;
}
if (!empty($_POST['mon_action_perso']) {
// Ici on exécute la tache de supprimer la choucroute
}
// on retourne true pour indiquer qu'on a un formulaire
return true;
}
public static function render(): void
{
if (!static::$init) {
return;
}
return (new Para())->items([
(new Checkbox('mon_action_perso', true))->value(1),
(new Label('supprimer la choucroute', Label::OUTSIDE_LABEL_AFTER))->for('mon_action_perso')->class('classic'),
]);
}
}
J'ai supprimé le code des actions prédéfinies dans l'exemple pour le rendre plus clair mais bien entendu on peut les mixer.
Voila, pour l'instant ce plugin est tout jeune et va surement évoluer, mais ces quelques lignes permettent un première approche de ce qui pourra être proposé à tous.
1 De Franck -
Un futur candidat à la distribution intégrée dans Dotclear celui-là !
Une question, ligne 41 du dernier exemple de code, la variable
$action
, c'est quoi ?2 De Jean-Christian Paul Denis -
C'est un oubli 😂
Je corrige
3 De zonetuto -
Merci pour le code !