Le WordPress d'aujourd'hui, décodé pour les développeurs

Extensions

Désinstallation d’une extension : laisser le client garder ses données

Supprimer un plugin ne devrait jamais effacer d'un coup et sans confirmation des années de données saisies par un client, même si le code de suppression est techniquement irréprochable.

Par WordPress Développement • 30 septembre 2026 • 7 min de lecture • Aucun commentaire
Désinstallation d'une extension : laisser le client garder ses données

Une extension de gestion d’adhérents pour clubs sportifs est retirée du site d’une association après le changement de prestataire informatique du club. Le nouvel administrateur clique sur « Supprimer » depuis l’écran des extensions, sans réaliser que cette action déclenche également l’exécution du fichier uninstall.php de l’extension, qui supprime intégralement les tables personnalisées contenant huit ans d’historique de cotisations et de présences aux entraînements. Aucun écran de confirmation spécifique n’avertit l’administrateur de cette conséquence, au-delà du message générique de WordPress qui prévient simplement que les fichiers du plugin seront supprimés.

Ce scénario, loin d’être rare, pousse à repenser l’expérience de désinstallation d’une extension qui accumule des données métier significatives, au-delà de la simple question technique du choix entre uninstall.php et register_uninstall_hook(), déjà largement traitée par ailleurs.

Le problème d’expérience, pas seulement de code

Techniquement, un fichier uninstall.php bien écrit fonctionne parfaitement : il supprime proprement les tables, les options et les métadonnées créées par l’extension, sans rien laisser traîner en base après coup, ce qui est en soi une bonne pratique d’hygiène pour ne pas polluer indéfiniment la base d’un site qui n’utilise plus l’extension. Le problème n’est pas la propreté de la suppression, mais l’absence totale de garde-fou avant qu’elle ne se déclenche, pour des données qui, contrairement à un simple réglage d’affichage, représentent un travail de saisie de plusieurs années.

Construire un écran de confirmation adapté

L'essentiel à retenir : Un écran de confirmation avant suppression coûte peu et évite des drames ; Proposer un export avant la suppression rassure sans complexité technique ; Une option pour conserver les données doit rester lisible et non cochée par défaut

Plutôt que de laisser uninstall.php s’exécuter silencieusement dès le clic sur « Supprimer » dans l’écran natif des extensions, la solution consiste à intercepter ce moment plus tôt, en désactivant d’abord l’extension normalement, puis en proposant, avant toute suppression effective, un écran dédié accessible depuis les réglages de l’extension elle-même :

add_action( 'admin_menu', 'clubadh_menu_donnees' );

function clubadh_menu_donnees() {
    add_options_page(
        'Données de l\'extension',
        'Gestion des adhérents',
        'manage_options',
        'clubadh-donnees',
        'clubadh_page_donnees'
    );
}

function clubadh_page_donnees() {
    if ( ! current_user_can( 'manage_options' ) ) {
        return;
    }

    if ( isset( $_POST['clubadh_enregistrer'] ) ) {
        check_admin_referer( 'clubadh_donnees' );
        update_option(
            'clubadh_supprimer_donnees',
            isset( $_POST['clubadh_supprimer'] ) ? '1' : '0'
        );
        echo '<div class="notice notice-success"><p>Choix enregistré.</p></div>';
    }

    $supprimer   = '1' === get_option( 'clubadh_supprimer_donnees', '0' );
    $url_export  = wp_nonce_url( admin_url( 'admin-post.php?action=clubadh_export' ), 'clubadh_export' );
    ?>
    <div class="wrap">
        <h1>Données de l'extension</h1>
        <p>Par défaut, la suppression de l'extension <strong>conserve</strong> toutes vos données (adhérents, cotisations, présences).</p>
        <p><a class="button button-primary" href="<?php echo esc_url( $url_export ); ?>">Exporter mes données (CSV)</a></p>
        <form method="post">
            <?php wp_nonce_field( 'clubadh_donnees' ); ?>
            <label>
                <input type="checkbox" name="clubadh_supprimer" value="1" <?php checked( $supprimer ); ?>>
                Supprimer définitivement toutes les données lors de la suppression de l'extension
            </label>
            <p><button class="button" name="clubadh_enregistrer" value="1">Enregistrer</button></p>
        </form>
    </div>
    <?php
}

Trois choix de conception y sont visibles. Par défaut, la valeur de l’option est '0' : rien n’est supprimé tant que quelqu’un n’a pas fait un geste explicite. La case qui autorise la suppression est libellée sans ambiguïté, avec le mot « définitivement », et n’est jamais cochée d’office. Enfin, le bouton d’export se trouve sur le même écran, juste au-dessus : on propose la sauvegarde avant de demander la décision.

Proposer un export avant tout

L’export n’a pas besoin d’être sophistiqué : un fichier CSV que le club peut ouvrir dans un tableur et conserver suffit. Le traitement s’appuie sur admin-post.php, le point d’entrée prévu pour les actions d’administration, avec vérification de la capacité et du jeton de sécurité :

add_action( 'admin_post_clubadh_export', 'clubadh_exporter_csv' );

function clubadh_exporter_csv() {
    if ( ! current_user_can( 'manage_options' ) ) {
        wp_die( 'Accès refusé.', 403 );
    }
    check_admin_referer( 'clubadh_export' );

    global $wpdb;
    $table  = $wpdb->prefix . 'clubadh_cotisations';
    $lignes = $wpdb->get_results( "SELECT * FROM {$table}", ARRAY_A );

    nocache_headers();
    header( 'Content-Type: text/csv; charset=utf-8' );
    header( 'Content-Disposition: attachment; filename="cotisations-' . gmdate( 'Y-m-d' ) . '.csv"' );

    $sortie = fopen( 'php://output', 'w' );
    fwrite( $sortie, "\xEF\xBB\xBF" ); // Marque d'ordre des octets, pour l'ouverture dans un tableur.

    if ( $lignes ) {
        fputcsv( $sortie, array_keys( $lignes[0] ), ';' );
        foreach ( $lignes as $ligne ) {
            fputcsv( $sortie, $ligne, ';' );
        }
    }

    fclose( $sortie );
    exit;
}

Le nom de la table n’est pas une saisie de l’utilisateur : il est construit à partir du préfixe de l’installation, ce qui rend la requête sûre. Le séparateur point-virgule correspond aux réglages habituels des tableurs en français. Pour une table volumineuse, on écrirait le fichier par tranches de quelques milliers de lignes plutôt qu’en une seule lecture.

Faire dépendre uninstall.php du choix de l’utilisateur

Le fichier uninstall.php devient alors conditionnel. Il ne détruit les tables que si le choix explicite a été enregistré :

<?php
// uninstall.php
if ( ! defined( 'WP_UNINSTALL_PLUGIN' ) ) {
    exit;
}

// Choix par défaut : conserver les données.
if ( '1' !== get_option( 'clubadh_supprimer_donnees', '0' ) ) {
    return;
}

global $wpdb;
$wpdb->query( "DROP TABLE IF EXISTS {$wpdb->prefix}clubadh_cotisations" );
$wpdb->query( "DROP TABLE IF EXISTS {$wpdb->prefix}clubadh_presences" );

delete_option( 'clubadh_supprimer_donnees' );

Le contrôle de la constante WP_UNINSTALL_PLUGIN reste indispensable : il empêche l’exécution directe du fichier par une requête HTTP. Le return précoce laisse en place les tables et les options quand le client n’a rien demandé.

Rappeler l’export au bon moment

Un dernier détail aide beaucoup : placer, sur la ligne de l’extension dans la liste des extensions, là où se trouve le lien « Supprimer », un lien « Mes données » qui renvoie directement vers l’écran de réglages et l’export. Le filtre plugin_action_links_{$fichier} s’en charge, que l’extension soit active ou désactivée :

add_filter( 'plugin_action_links_' . plugin_basename( __FILE__ ), 'clubadh_lien_donnees' );

function clubadh_lien_donnees( $liens ) {
    $url = admin_url( 'options-general.php?page=clubadh-donnees' );
    array_unshift( $liens, '<a href="' . esc_url( $url ) . '">Mes données</a>' );
    return $liens;
}

Supprimer du code est un geste technique ; supprimer des années de saisie est une décision, et elle appartient à celui qui a saisi.

Les pièges à éviter

  • Présenter la suppression comme le choix par défaut. Une case pré-cochée qui détruit les données transforme un oubli en perte sèche.
  • Promettre un export incomplet. Si l’export ne couvre que la moitié des tables, le client croit tout avoir sauvegardé : documentez ce qu’il contient.
  • Oublier le multisite. Sur un réseau, uninstall.php s’exécute une fois pour l’extension, mais les tables sont propres à chaque site : parcourez les sites du réseau si nécessaire.
  • Compter sur la mémoire du prestataire suivant. Le texte de l’écran de réglages doit se suffire à lui-même, sans documentation à part.

Conclusion

Une désinstallation propre n’est pas seulement une désinstallation qui ne laisse aucune trace : c’est aussi une désinstallation qui ne détruit rien sans l’accord clair de celui à qui appartiennent les données. Un écran de réglages lisible, un export à portée de clic et un uninstall.php qui respecte le choix enregistré coûtent peu de code, et évitent des années de travail effacées par un simple clic.

Laisser un commentaire

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

Partager :

À propos de l'auteur

WordPress Développement

Développeur WordPress, passionné par Elementor, le FSE et l’automatisation par IA.

Voir tous ses articles

Dans la même veine

À lire aussi