Я роблю плагін WordPress. Які типові речі я повинен включати в функцію видалення?
Наприклад, чи слід видалити будь-які таблиці, створені у функції встановлення?
Чи я очищую свої параметри?
Ще щось?
Я роблю плагін WordPress. Які типові речі я повинен включати в функцію видалення?
Наприклад, чи слід видалити будь-які таблиці, створені у функції встановлення?
Чи я очищую свої параметри?
Ще щось?
Відповіді:
Нижче показано правильні способи безпечного підключення функцій зворотного виклику, які спрацьовують під час згаданих дій.
Як ви могли використовувати цей код у плагіні, який використовує
Я покажу три різні демо-плагіни, які ви можете перевірити, а потім пізніше впроваджуйте код у свої власні плагіни.
Оскільки ця тема є надзвичайно складною та дуже детальною і має десяток + крайових випадків, ця відповідь ніколи не буде ідеальною. Я з часом продовжуватиму вдосконалюватись, тому перевіряйте регулярно.
Зворотні виклики налаштування плагінів ініціюються ядром, і ви не впливаєте на те, як це робить ядро. Слід пам’ятати про деякі речі:
echo/print
нічого (!) Під час налаштування зворотних дзвінків. Це призведе до headers already sent
повідомлення, а ядро порекомендує деактивувати та видалити ваш плагін ... не питайте: я знаю ...exit()
заяви до всіх різних зворотних дзвінків, щоб ви могли отримати деяку інформацію про те, що відбувається насправді. Просто коментуйте їх, щоб побачити, як вони працюють.__FILE__ != WP_PLUGIN_INSTALL
та (якщо ні: перервати!), Щоб побачити, чи дійсно деінсталяція плагіна. Я рекомендую просто запустити on_deactivation()
зворотні дзвінки під час розробки, щоб ви заощадили час, який вам знадобиться, щоб повернути все. Принаймні, це я і роблю.defined( 'ABSPATH' ) OR exit;
wp_die()
екрані із запитом належних дозволів (і якщо ви хочете спробувати ще раз ... так, звичайно ) можуть виникнути несподівані результати , коли ви отримали помилку. Це відбувається, коли ядро перенаправляє вас, встановлює струм $GLOBALS['wp_list_table']->current_action();
на, error_scrape
а потім перевіряє референс на те check_admin_referer('plugin-activation-error_' . $plugin);
, де $plugin
є $_REQUEST['plugin']
. Тож переспрямування відбувається при половині завантаження сторінки, і ви отримуєте цю дротову смугу прокрутки та екран екрану, щоб побачити жовте вікно повідомлення адміністратора / повідомлення. Якщо це трапиться: Залишайтеся спокійними і просто шукайте помилку за допомогою деякої exit()
та покрокової налагодження.Пам'ятайте, що це може не спрацювати, якщо підключити зворотні дзвінки перед визначенням функції.
<?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' );
Це найпоширеніший приклад сучасних плагінів.
<?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
}
}
Цей сценарій передбачає , що ви отримали головний файл плагіна , і другий файл з ім'ям setup.php
в підкаталозі плагіна під назвою inc
: ~/wp-content/plugins/your_plugin/inc/setup.php
. Це буде добре працювати, коли папка плагінів знаходиться поза структурою папки WP за замовчуванням, а також, коли вміст dir перейменовано або у випадках, коли ваш файл налаштування названий іншим. Тільки inc
папка має мати те саме ім’я та розташування щодо кореневого каталогу плагінів.
Примітка. Ви можете просто взяти три register_*_hook()*
функції та класи та залишити їх у свій плагін.
Основний файл плагіна:
<?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;
}
}
Файл налаштування:
<?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 ) );
}
}
Якщо ви пишете плагін, який має власну таблицю або параметри БД, можуть бути сценарії, коли вам потрібно змінити або оновити речі.
На жаль, поки що немає можливості запустити щось із встановлення плагіна / теми чи оновлення / оновлення. Радість, що тут є робота: підключіть спеціальну функцію до спеціальної опції (так, це кульгаво, але вона працює).
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' );
Ця функція оновлення є не дуже приємним / добре написаним прикладом, але як сказано: Це приклад, і техніка працює добре. Поліпшимо це з наступним оновленням.
check_admin_referer()
. Їм не потрібно піддаватися санітарній обробці, тому що ядро не робить це самостійно і все одно порівнюватиме їх з несанітованими $_REQUEST
значеннями. Але якщо вони починають плакати як маленькі дівчатка через це, просто використовуйте filter_var()
або esc_attr()
на цьому.
Для тестування поточної системи на необхідні функції, такі як версія PHP або встановлені розширення, ви можете використовувати щось подібне:
<?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__ ) );
}
Тест з чеком на PHP 5.5:
register_activation_hook
- чому б не використати його? Чи буде цей вогонь до або після, register_activation_hook
і він буде register_activation_hook
горіти, навіть якщо вищезгадане не пройде?
add_action( 'admin_notices', 't5_check_admin_notices', 0 );
в гачок активації, і плагін активується, не виконуючи перевірок. . .
admin_notices
.