Estou fazendo um plugin wordpress. Quais são as coisas típicas que devo incluir no recurso de desinstalação?
Por exemplo, devo excluir as tabelas que criei na função de instalação?
Eu limpo minhas entradas de opção?
Algo mais?
Estou fazendo um plugin wordpress. Quais são as coisas típicas que devo incluir no recurso de desinstalação?
Por exemplo, devo excluir as tabelas que criei na função de instalação?
Eu limpo minhas entradas de opção?
Algo mais?
Respostas:
A seguir, mostramos as maneiras corretas de conectar com segurança funções de retorno de chamada que são acionadas durante as ações mencionadas.
Como você pode usar esse código em um plug-in que usa
Mostrarei três plugins de demonstração diferentes que você pode inspecionar e, posteriormente, implementará o código em seus próprios plug-ins.
Como esse tópico é extremamente difícil e muito detalhado e tem uma dúzia de casos extremos, essa resposta nunca será perfeita. Vou continuar aprimorando-o com o tempo, portanto, verifique regularmente.
Os retornos de chamada de configuração do plug-in são acionados pelo núcleo e você não tem influência sobre como o núcleo faz isso. Há algumas coisas a serem lembradas:
echo/print
coisa (!) Durante retornos de chamada de instalação. Isso levará à headers already sent
mensagem e o núcleo recomendará desativar e excluir seu plug-in ... não pergunte: eu sei ...exit()
declarações a todos os retornos de chamada diferentes para que você possa ter uma ideia do que realmente está acontecendo. Apenas descomente-os para ver as coisas funcionando.__FILE__ != WP_PLUGIN_INSTALL
e (se não: abortar!) Para ver se alguém realmente está desinstalando o plug-in. Eu recomendaria simplesmente acionar on_deactivation()
retornos de chamada durante o desenvolvimento, para que você economize o tempo necessário para recuperar tudo. Pelo menos é o que eu faço.defined( 'ABSPATH' ) OR exit;
wp_die()
tela solicitando permissões adequadas (e se você quiser tentar novamente ... sim, com certeza ), quando ocorrer um erro. Isso acontece quando o núcleo o redireciona, define a corrente $GLOBALS['wp_list_table']->current_action();
como error_scrape
e, em seguida, verifica o referenciador check_admin_referer('plugin-activation-error_' . $plugin);
, onde $plugin
está $_REQUEST['plugin']
. Portanto, o redirecionamento acontece na metade do carregamento da página e você obtém essa barra de rolagem com fio e a tela de matriz visualiza a caixa de aviso / mensagem amarela do administrador. Se isso acontecer: mantenha a calma e procure o erro com alguma exit()
depuração passo a passo.Lembre-se de que isso pode não funcionar se você ligar os retornos de chamada antes da definição da função.
<?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' );
Este é o exemplo mais comum nos plugins atuais.
<?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
}
}
Este cenário pressupõe que você tem um arquivo plugin principal e um segundo arquivo chamado setup.php
em um subdiretório do plugin chamado inc
: ~/wp-content/plugins/your_plugin/inc/setup.php
. Isso funcionará também quando a pasta do plug-in estiver fora da estrutura padrão da pasta WP, bem como quando o diretório de conteúdo for renomeado ou nos casos em que o arquivo de instalação tiver um nome diferente. Somente a inc
pasta precisa ter o mesmo nome e localização em relação ao diretório raiz dos plug-ins.
Nota: Você pode simplesmente pegar as três register_*_hook()*
funções e as classes e soltá-las no seu plugin.
O principal arquivo de plug-in:
<?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;
}
}
O arquivo de instalação:
<?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 ) );
}
}
Se você escrever um plug-in que tenha sua própria tabela ou opções de banco de dados, poderá haver cenários em que você precise alterar ou atualizar as coisas.
Infelizmente até agora não há possibilidade de executar algo na instalação do plugin / tema ou atualização / atualização. Felizmente, há uma solução alternativa: conecte uma função personalizada a uma opção personalizada (sim, é ruim - mas funciona).
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' );
Esta função de atualização é um exemplo não muito agradável / bem escrito, mas como dito: é um exemplo e a técnica funciona bem. Melhorará isso com uma atualização posterior.
check_admin_referer()
. Eles não precisam ser higienizados porque o núcleo não faz isso sozinho e o compararia com $_REQUEST
valores não higienizados . Mas se eles começarem a chorar como menininhas por causa disso, use filter_var()
ou use esc_attr()
.
Para testar o sistema atual quanto às características necessárias, como a versão PHP ou extensões instaladas, você pode usar algo assim:
<?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__ ) );
}
Teste com uma verificação do PHP 5.5:
register_activation_hook
aqui - por que não usá-lo? Também disparará antes ou depois register_activation_hook
e register_activation_hook
disparará mesmo que o acima não passe?
add_action( 'admin_notices', 't5_check_admin_notices', 0 );
para um gancho de ativação e o plug-in é ativado sem realizar as verificações. . .
admin_notices
.