Désinstaller, Activer, Désactiver un plugin: caractéristiques typiques et procédures

91

Je fais un plugin wordpress. Quelles sont les choses typiques que je devrais inclure dans la fonction de désinstallation?

Par exemple, dois-je supprimer les tables que j'ai créées dans la fonction d'installation?

Est-ce que je nettoie mes options?

Autre chose?

    
posée redconservatory 15.08.2011 - 01:21

2 réponses

139

Il y a trois hooks différents . Ils se déclenchent dans les cas suivants:

  • désinstaller
  • Désactivation
  • Activation

Comment déclencher des fonctions en toute sécurité pendant les scénarios

Ce qui suit montre les actions à droite pour connecter en toute sécurité les fonctions de rappel déclenchées lors des actions mentionnées.

Comme vous pourriez utiliser ce code dans un plugin utilisant

  • fonctions simples,
  • une classe ou
  • une classe externe,

Je vais montrer trois plug-ins de démonstration que vous pouvez inspecter, puis implémenter le code dans vos propres plug-ins.

Remarque importante dès le départ!

Comme ce sujet est extrêmement difficile et très détaillé et comporte une douzaine de cas, cette réponse ne sera jamais parfaite. Je vais continuer à l'améliorer au fil du temps, alors revenez régulièrement.

(1) Activez / Désactivez / Désinstallez les plugins.

Les rappels de configuration du plug-in sont déclenchés par le noyau et vous n’avez pas d’influence sur la manière dont le core le fait. Il y a certaines choses à garder à l'esprit:

  • Jamais , jamais echo/print rien (!) lors des rappels d'installation. Ceci conduira à headers already sent message et le noyau recommandera de désactiver et de supprimer votre plugin ... ne demandez pas: je sais ...
  • Vous ne verrez aucune sortie visuelle. Mais , j'ai ajouté exit() d'instructions à différents rappels afin que vous puissiez avoir un aperçu de ce qui se passe réellement. Ne les commentez pas pour que les choses fonctionnent.
  • Il est extrêmement important de vérifier si __FILE__ != WP_PLUGIN_INSTALL et (si ce n’est pas le cas: abandonnez!) pour voir s’il désinstalle réellement le plugin. Je recommanderais de simplement déclencher on_deactivation() de callbacks pendant le développement, afin de vous faire gagner du temps. Tout au moins, c'est ce que je fais.
  • Je fais aussi des tâches de sécurité. Une partie est faite par noyau aussi, mais bon! Mieux vaut prévenir que guérir! .
    • Je refuse tout d'abord l'accès direct au fichier lorsque le coeur n'est pas chargé: defined( 'ABSPATH' ) OR exit;
    • Je vérifie ensuite si l'utilisateur actuel est autorisé à effectuer cette tâche.
    • En dernier lieu, je vérifie le référant. Remarque: il peut y avoir des résultats inattendus avec un écran wp_die() demandant les autorisations appropriées (et si vous voulez réessayer ... ouais, bien sûr ), lorsque vous recevez une erreur. Cela se produit lorsque Core vous redirige, définit le $GLOBALS['wp_list_table']->current_action(); actuel sur error_scrape , puis vérifie le référent pour check_admin_referer('plugin-activation-error_' . $plugin); , où $plugin correspond à $_REQUEST['plugin'] . Donc, la redirection se produit à la moitié du chargement de la page et vous obtenez cette barre de défilement câblée et l'écran de la puce insight la notification / message jaune de l'administrateur. Si cela se produit: restez calme et recherchez l'erreur avec quelques exit() et un débogage étape par étape.

(A) plug-in de fonctions simples

N'oubliez pas que cela pourrait ne pas fonctionner si vous associez les rappels avant la définition de la fonction.

<?php
defined( 'ABSPATH' ) OR exit;
/**
 * Plugin Name: (WCM) Activate/Deactivate/Uninstall - Functions
 * Description: Example Plugin to show activation/deactivation/uninstall callbacks for plain functions.
 * Author:      Franz Josef Kaiser/wecodemore
 * Author URL:  http://unserkaiser.com
 * Plugin URL:  http://wordpress.stackexchange.com/questions/25910/uninstall-activate-deactivate-a-plugin-typical-features-how-to/25979#25979
 */

function WCM_Setup_Demo_on_activation()
{
    if ( ! current_user_can( 'activate_plugins' ) )
        return;
    $plugin = isset( $_REQUEST['plugin'] ) ? $_REQUEST['plugin'] : '';
    check_admin_referer( "activate-plugin_{$plugin}" );

    # Uncomment the following line to see the function in action
    # exit( var_dump( $_GET ) );
}

function WCM_Setup_Demo_on_deactivation()
{
    if ( ! current_user_can( 'activate_plugins' ) )
        return;
    $plugin = isset( $_REQUEST['plugin'] ) ? $_REQUEST['plugin'] : '';
    check_admin_referer( "deactivate-plugin_{$plugin}" );

    # Uncomment the following line to see the function in action
    # exit( var_dump( $_GET ) );
}

function WCM_Setup_Demo_on_uninstall()
{
    if ( ! current_user_can( 'activate_plugins' ) )
        return;
    check_admin_referer( 'bulk-plugins' );

    // Important: Check if the file is the one
    // that was registered during the uninstall hook.
    if ( __FILE__ != WP_UNINSTALL_PLUGIN )
        return;

    # Uncomment the following line to see the function in action
    # exit( var_dump( $_GET ) );
}

register_activation_hook(   __FILE__, 'WCM_Setup_Demo_on_activation' );
register_deactivation_hook( __FILE__, 'WCM_Setup_Demo_on_deactivation' );
register_uninstall_hook(    __FILE__, 'WCM_Setup_Demo_on_uninstall' );

(B) Une architecture de classe / OOP

C’est l’exemple le plus courant dans les plugins actuels.

<?php
defined( 'ABSPATH' ) OR exit;
/**
 * Plugin Name: (WCM) Activate/Deactivate/Uninstall - CLASS
 * Description: Example Plugin to show activation/deactivation/uninstall callbacks for classes/objects.
 * Author:      Franz Josef Kaiser/wecodemore
 * Author URL:  http://unserkaiser.com
 * Plugin URL:  http://wordpress.stackexchange.com/questions/25910/uninstall-activate-deactivate-a-plugin-typical-features-how-to/25979#25979
 */


register_activation_hook(   __FILE__, array( 'WCM_Setup_Demo_Class', 'on_activation' ) );
register_deactivation_hook( __FILE__, array( 'WCM_Setup_Demo_Class', 'on_deactivation' ) );
register_uninstall_hook(    __FILE__, array( 'WCM_Setup_Demo_Class', 'on_uninstall' ) );

add_action( 'plugins_loaded', array( 'WCM_Setup_Demo_Class', 'init' ) );
class WCM_Setup_Demo_Class
{
    protected static $instance;

    public static function init()
    {
        is_null( self::$instance ) AND self::$instance = new self;
        return self::$instance;
    }

    public static function on_activation()
    {
        if ( ! current_user_can( 'activate_plugins' ) )
            return;
        $plugin = isset( $_REQUEST['plugin'] ) ? $_REQUEST['plugin'] : '';
        check_admin_referer( "activate-plugin_{$plugin}" );

        # Uncomment the following line to see the function in action
        # exit( var_dump( $_GET ) );
    }

    public static function on_deactivation()
    {
        if ( ! current_user_can( 'activate_plugins' ) )
            return;
        $plugin = isset( $_REQUEST['plugin'] ) ? $_REQUEST['plugin'] : '';
        check_admin_referer( "deactivate-plugin_{$plugin}" );

        # Uncomment the following line to see the function in action
        # exit( var_dump( $_GET ) );
    }

    public static function on_uninstall()
    {
        if ( ! current_user_can( 'activate_plugins' ) )
            return;
        check_admin_referer( 'bulk-plugins' );

        // Important: Check if the file is the one
        // that was registered during the uninstall hook.
        if ( __FILE__ != WP_UNINSTALL_PLUGIN )
            return;

        # Uncomment the following line to see the function in action
        # exit( var_dump( $_GET ) );
    }

    public function __construct()
    {
        # INIT the plugin: Hook your callbacks
    }
}

(C) Une architecture de classe / OOP avec un objet de configuration externe

Ce scénario suppose que vous disposiez d'un fichier de plug-in principal et d'un second fichier nommé setup.php dans un sous-répertoire du plug-in nommé inc : ~/wp-content/plugins/your_plugin/inc/setup.php . Cela fonctionnera également lorsque le dossier du plug-in se trouve en dehors de la structure de dossier WP par défaut, ainsi que lorsque le répertoire de contenu est renommé ou dans les cas où votre fichier d'installation porte un nom différent. Seul le dossier inc doit avoir le même nom & emplacement relatif par rapport au répertoire racine des plugins.

Remarque: vous pouvez simplement prendre les trois fonctions register_*_hook()* et les classes et les déposer dans votre plugin.

Le fichier du plugin principal:

<?php
defined( 'ABSPATH' ) OR exit;
/**
 * Plugin Name: (WCM) Activate/Deactivate/Uninstall - FILE/CLASS
 * Description: Example Plugin
 * Author:      Franz Josef Kaiser/wecodemore
 * Author URL:  http://unserkaiser.com
 * Plugin URL:  http://wordpress.stackexchange.com/questions/25910/uninstall-activate-deactivate-a-plugin-typical-features-how-to/25979#25979
 */


register_activation_hook(   __FILE__, array( 'WCM_Setup_Demo_File_Inc', 'on_activation' ) );
register_deactivation_hook( __FILE__, array( 'WCM_Setup_Demo_File_Inc', 'on_deactivation' ) );
register_uninstall_hook(    __FILE__, array( 'WCM_Setup_Demo_File_Inc', 'on_uninstall' ) );

add_action( 'plugins_loaded', array( 'WCM_Setup_Demo_File', 'init' ) );
class WCM_Setup_Demo_File
{
    protected static $instance;

    public static function init()
    {
        is_null( self::$instance ) AND self::$instance = new self;
        return self::$instance;
    }

    public function __construct()
    {
        add_action( current_filter(), array( $this, 'load_files' ), 30 );
    }

    public function load_files()
    {
        foreach ( glob( plugin_dir_path( __FILE__ ).'inc/*.php' ) as $file )
            include_once $file;
    }
}

Le fichier d'installation:

<?php
defined( 'ABSPATH' ) OR exit;

class WCM_Setup_Demo_File_Inc
{
    public static function on_activation()
    {
        if ( ! current_user_can( 'activate_plugins' ) )
            return;
        $plugin = isset( $_REQUEST['plugin'] ) ? $_REQUEST['plugin'] : '';
        check_admin_referer( "activate-plugin_{$plugin}" );

        # Uncomment the following line to see the function in action
        # exit( var_dump( $_GET ) );
    }

    public static function on_deactivation()
    {
        if ( ! current_user_can( 'activate_plugins' ) )
            return;
        $plugin = isset( $_REQUEST['plugin'] ) ? $_REQUEST['plugin'] : '';
        check_admin_referer( "deactivate-plugin_{$plugin}" );

        # Uncomment the following line to see the function in action
        # exit( var_dump( $_GET ) );
    }

    public static function on_uninstall()
    {
        if ( ! current_user_can( 'activate_plugins' ) )
            return;
        check_admin_referer( 'bulk-plugins' );

        // Important: Check if the file is the one
        // that was registered during the uninstall hook.
        if ( __FILE__ != WP_UNINSTALL_PLUGIN )
            return;

        # Uncomment the following line to see the function in action
        # exit( var_dump( $_GET ) );
    }
}

(2) Mises à jour du plugin

Si vous écrivez un plug-in qui possède sa propre table de base de données ou ses propres options, il peut arriver que vous deviez modifier ou mettre à niveau des éléments.

Malheureusement, il n’existe jusqu’à présent aucune possibilité d’exécuter quelque chose sur l’installation ou la mise à jour / mise à niveau du plugin / thème. Heureusement, il existe un moyen de contourner le problème: associez une fonction personnalisée à une option personnalisée (oui, c'est nul, mais cela fonctionne).

function prefix_upgrade_plugin() 
{
    $v = 'plugin_db_version';
    $update_option = null;
    // Upgrade to version 2
    if ( 2 !== get_option( $v ) ) 
    {
        if ( 2 < get_option( $v ) )
        {
            // Callback function must return true on success
            $update_option = custom_upgrade_cb_fn_v3();

            // Only update option if it was an success
            if ( $update_option )
                update_option( $v, 2 );
        }
    }

    // Upgrade to version 3, runs just after upgrade to version 2
    if ( 3 !== get_option( $v ) ) 
    {
        // re-run from beginning if previous update failed
        if ( 2 < get_option( $v ) )
            return prefix_upgrade_plugin();

        if ( 3 < get_option( $v ) )
        {
            // Callback function must return true on success
            $update_option = custom_upgrade_cb_fn_v3();

            // Only update option if it was an success
            if ( $update_option )
                update_option( $v, 3 );
        }
    }

    // Return the result from the update cb fn, so we can test for success/fail/error
    if ( $update_option )
        return $update_option;

return false;
}
add_action('admin_init', 'prefix_upgrade_plugin' );

Source

Cette fonction de mise à jour est un exemple pas très agréable / bien écrit, mais comme dit: C’est un exemple et la technique fonctionne bien. Améliorera cela avec une mise à jour ultérieure.

    
réponse donnée kaiser 15.08.2011 - 20:18
15

Pour tester les fonctionnalités requises du système actuel, telles que la version de PHP ou les extensions installées, vous pouvez utiliser quelque chose comme ceci:

<?php  # -*- coding: utf-8 -*-
/**
 * Plugin Name: T5 Check Plugin Requirements
 * Description: Test for PHP version and installed extensions
 * Plugin URI:
 * Version:     2013.03.31
 * Author:      Thomas Scholz
 * Author URI:  http://toscho.de
 * Licence:     MIT
 * License URI: http://opensource.org/licenses/MIT
 */

/*
 * Don't start on every page, the plugin page is enough.
 */
if ( ! empty ( $GLOBALS['pagenow'] ) && 'plugins.php' === $GLOBALS['pagenow'] )
    add_action( 'admin_notices', 't5_check_admin_notices', 0 );

/**
 * Test current system for the features the plugin needs.
 *
 * @return array Errors or empty array
 */
function t5_check_plugin_requirements()
{
    $php_min_version = '5.4';
    // see http://www.php.net/manual/en/extensions.alphabetical.php
    $extensions = array (
        'iconv',
        'mbstring',
        'id3'
    );
    $errors = array ();

    $php_current_version = phpversion();

    if ( version_compare( $php_min_version, $php_current_version, '>' ) )
        $errors[] = "Your server is running PHP version $php_current_version but
            this plugin requires at least PHP $php_min_version. Please run an upgrade.";

    foreach ( $extensions as $extension )
        if ( ! extension_loaded( $extension ) )
            $errors[] = "Please install the extension $extension to run this plugin.";

    return $errors;

}

/**
 * Call t5_check_plugin_requirements() and deactivate this plugin if there are error.
 *
 * @wp-hook admin_notices
 * @return  void
 */
function t5_check_admin_notices()
{
    $errors = t5_check_plugin_requirements();

    if ( empty ( $errors ) )
        return;

    // Suppress "Plugin activated" notice.
    unset( $_GET['activate'] );

    // this plugin's name
    $name = get_file_data( __FILE__, array ( 'Plugin Name' ), 'plugin' );

    printf(
        '<div class="error"><p>%1$s</p>
        <p><i>%2$s</i> has been deactivated.</p></div>',
        join( '</p><p>', $errors ),
        $name[0]
    );
    deactivate_plugins( plugin_basename( __FILE__ ) );
}

Testez avec un contrôle pour PHP 5.5:

    
réponse donnée fuxia 09.04.2013 - 20:45

Lire d'autres questions sur les étiquettes