Es gibt drei verschiedene Haken. Sie lösen in folgenden Fällen aus:
- Deinstallieren
- Deaktivierung
- Aktivierung
Sicheres Auslösen von Funktionen während der Szenarien
Im Folgenden werden die richtigen Methoden zum sicheren Verknüpfen von Rückruffunktionen gezeigt, die während der genannten Aktionen ausgelöst werden.
Da könntest du diesen Code in einem Plugin verwenden, das benutzt
- einfache funktionen,
- eine Klasse oder
- eine externe Klasse,
Ich werde drei verschiedene Demo-Plugins zeigen , die Sie überprüfen und später in Ihren eigenen Plugins implementieren können.
Wichtiger Hinweis vorab!
Da dieses Thema extrem schwierig und sehr detailliert ist und über ein Dutzend Randfälle verfügt, wird diese Antwort niemals perfekt sein. Ich werde es im Laufe der Zeit weiter verbessern, schauen Sie also regelmäßig vorbei.
(1) Plugins aktivieren / deaktivieren / deinstallieren.
Die Setup-Callbacks des Plugins werden von core ausgelöst und Sie haben keinen Einfluss darauf, wie core dies tut. Es gibt einige Dinge zu beachten:
- Nie , nie
echo/print
etwas (!) Während der Installation Rückrufe. Dies wird zu einer headers already sent
Meldung führen und Core wird empfehlen, Ihr Plugin zu deaktivieren und zu löschen ... fragen Sie nicht: Ich weiß ...
- Sie sehen keine visuelle Ausgabe. Aber ich
exit()
habe allen verschiedenen Rückrufen Anweisungen hinzugefügt , damit Sie einige Einblicke in das bekommen, was wirklich passiert. Kommentieren Sie sie einfach aus, um zu sehen, wie etwas funktioniert.
- Es ist äußerst wichtig, dass Sie prüfen, ob
__FILE__ != WP_PLUGIN_INSTALL
und (falls nicht: Abbrechen!), Ob das Plugin wirklich deinstalliert wird. Ich würde empfehlen, on_deactivation()
während der Entwicklung einfach Rückrufe auszulösen , damit Sie sich die Zeit sparen, die Sie benötigen, um alles wieder in den Griff zu bekommen. Zumindest ist es das, was ich tue.
- Ich mache auch ein paar Sicherheitsaufgaben. Einige werden auch vom Kern erledigt, aber hey! Sicher ist sicher! .
- Zuerst erlaube ich keinen direkten Dateizugriff, wenn der Core nicht geladen ist:
defined( 'ABSPATH' ) OR exit;
- Dann überprüfe ich, ob der aktuelle Benutzer diese Aufgabe ausführen darf.
- Als letzte Aufgabe überprüfe ich den Referrer. Hinweis: Es kann zu unerwarteten Ergebnissen kommen,
wp_die()
wenn ein Bildschirm nach den richtigen Berechtigungen fragt (und wenn Sie es erneut versuchen möchten ... ja, sicher ), wenn ein Fehler auftritt. Dies geschieht als Kern leitet Sie, setzt die aktuelle $GLOBALS['wp_list_table']->current_action();
zu error_scrape
und überprüft dann die Referrer für check_admin_referer('plugin-activation-error_' . $plugin);
, wo $plugin
ist $_REQUEST['plugin']
. Die Weiterleitung erfolgt also bei der Hälfte des Seitenaufwands, und Sie erhalten diese verdrahtete Bildlaufleiste und auf dem Bildschirm einen Einblick in das gelbe Benachrichtigungs- / Meldungsfeld für Administratoren. Wenn dies passiert: Bleiben Sie ruhig und suchen Sie einfach nach dem Fehler mit einigem exit()
und schrittweisem Debuggen.
(A) Einfaches Funktions-Plugin
Beachten Sie, dass dies möglicherweise nicht funktioniert, wenn Sie die Rückrufe vor der Funktionsdefinition einbinden.
<?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) Eine klassenbasierte / OOP-Architektur
Dies ist das häufigste Beispiel für heutige Plugins.
<?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) Eine klassenbasierte / OOP-Architektur mit einem externen Setup-Objekt
Dieses Szenario geht davon aus, dass Sie eine Haupt-Plugin - Datei und eine zweite Datei mit dem Namen bekamen setup.php
in einem Unterverzeichnis des Plugins genannt inc
: ~/wp-content/plugins/your_plugin/inc/setup.php
. Dies funktioniert auch, wenn sich der Plugin-Ordner außerhalb der standardmäßigen WP-Ordnerstruktur befindet, wenn das Inhaltsverzeichnis umbenannt wird oder wenn Ihre Setup-Datei einen anderen Namen hat. Nur der inc
Ordner muss den gleichen Namen und Speicherort im Stammverzeichnis des Plugins haben.
Hinweis: Sie können die drei register_*_hook()*
Funktionen und Klassen einfach übernehmen und in Ihr Plugin einfügen.
Die Haupt-Plugin-Datei:
<?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;
}
}
Die Setup-Datei:
<?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) Plugin-Updates
Wenn Sie ein Plugin mit einer eigenen DB-Tabelle oder eigenen Optionen schreiben, müssen Sie möglicherweise Änderungen oder Upgrades vornehmen.
Leider gibt es bisher keine Möglichkeit, etwas über Plugin / Theme-Installation oder Update / Upgrade auszuführen. Gerne gibt es eine Abhilfe: Verknüpfen Sie eine benutzerdefinierte Funktion mit einer benutzerdefinierten Option (ja, es ist lahm - aber es funktioniert).
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' );
Quelle
Diese Update-Funktion ist ein nicht so schönes / gut geschriebenes Beispiel, aber wie gesagt: Es ist ein Beispiel und die Technik funktioniert gut. Wird das mit einem späteren Update verbessern.