Esistono tre diversi ganci. Si innescano nei seguenti casi:
- Disinstallare
- Disattivazione
- Attivazione
Come attivare le funzioni in modo sicuro durante gli scenari
Quanto segue mostra i modi giusti per agganciare in modo sicuro le funzioni di callback che vengono attivate durante le azioni menzionate.
Come è possibile utilizzare questo codice in un plug-in che utilizza
- funzioni semplici,
- una classe o
- una classe esterna,
Mostrerò tre diversi plug-in demo che è possibile controllare e successivamente implementare il codice nei propri plug-in.
Nota importante in anticipo!
Poiché questo argomento è estremamente difficile e molto dettagliato e ha una dozzina di casi limite, questa risposta non sarà mai perfetta. Continuerò a migliorarlo nel tempo, quindi ricontrolla su base regolare.
(1) Attiva / Disattiva / Disinstalla plugin.
I callback di installazione del plug-in sono attivati da core e non si ha alcuna influenza su come core fa questo. Ci sono alcune cose da tenere a mente:
- Mai e poi mai
echo/print
niente (!) Durante i callback di installazione. Questo porterà a un headers already sent
messaggio e core raccomanderà di disattivare ed eliminare il plugin ... non chiedere: lo so ...
- Non vedrai alcun output visivo. Ma ho aggiunto delle
exit()
dichiarazioni a tutti i diversi callback in modo da poter ottenere alcune informazioni su ciò che sta realmente accadendo. Basta decommentarli per vedere le cose che funzionano.
- È estremamente importante controllare se
__FILE__ != WP_PLUGIN_INSTALL
e (in caso contrario: interrompere!) Per vedere se si sta realmente disinstallando il plugin. Consiglio di attivare semplicemente i on_deactivation()
callback durante lo sviluppo, così ti risparmierai il tempo necessario per riavere tutto. Almeno questo è quello che faccio.
- Anch'io faccio alcune cose di sicurezza. Alcuni vengono eseguiti anche dal core, ma hey! Meglio prevenire che curare! .
- Per prima cosa non posso accedere direttamente ai file quando il core non è caricato:
defined( 'ABSPATH' ) OR exit;
- Quindi controllo se l'utente corrente è autorizzato a svolgere questa attività.
- Come ultima attività, controllo il referrer. Nota: ci possono essere risultati imprevisti con una
wp_die()
schermata che richiede le autorizzazioni appropriate (e se si desidera riprovare ... sì, certo ), quando si riceve un errore. Questo accade quando il core ti reindirizza, imposta la corrente $GLOBALS['wp_list_table']->current_action();
su error_scrape
e quindi controlla il referrer per check_admin_referer('plugin-activation-error_' . $plugin);
dove si $plugin
trova $_REQUEST['plugin']
. Quindi il reindirizzamento avviene a metà del caricamento della pagina e ottieni questa barra di scorrimento cablata e la schermata del dado visualizza la finestra di avviso / messaggio gialla dell'amministratore. Se ciò accade: mantieni la calma e cerca l'errore con alcuni exit()
e debug passo-passo.
(A) Plugin di funzioni semplici
Ricordare che questo potrebbe non funzionare se si agganciano i callback prima della definizione della funzione.
<?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) Un'architettura basata su classe / OOP
Questo è l'esempio più comune nei plugin di oggi.
<?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) Un'architettura basata su classe / OOP con un oggetto di installazione esterno
Questo scenario presuppone che hai un file plugin principale e un secondo file denominato setup.php
in una sottodirectory del plugin di nome inc
: ~/wp-content/plugins/your_plugin/inc/setup.php
. Funzionerà anche quando la cartella del plug-in si trova al di fuori della struttura di cartelle WP predefinita, nonché quando la directory del contenuto viene rinominata o nei casi in cui il file di installazione ha un nome diverso. Solo la inc
cartella deve avere lo stesso nome e posizione relativi dalla directory principale dei plugin.
Nota: puoi semplicemente prendere le tre register_*_hook()*
funzioni e le classi e rilasciarle nel tuo plugin.
Il file del plugin principale:
<?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;
}
}
Il file di installazione:
<?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) Aggiornamenti plug-in
Se si scrive un plug-in che ha una propria tabella DB o opzioni, potrebbero esserci scenari in cui è necessario modificare o aggiornare le cose.
Purtroppo finora non c'è possibilità di eseguire qualcosa sull'installazione di plugin / temi o sull'aggiornamento / aggiornamento. Volentieri c'è una soluzione: agganciare una funzione personalizzata a un'opzione personalizzata (sì, è zoppa - ma funziona).
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' );
fonte
Questa funzione di aggiornamento è un esempio non così bello / ben scritto, ma come detto: è un esempio e la tecnica funziona bene. Lo migliorerà con un aggiornamento successivo.