Existem três diferentes ganchos. Eles acionam nos seguintes casos:
- Desinstalar
- Desativação
- Ativação
Como disparar funções com segurança durante os cenários
O seguinte mostra as maneiras certas de enganchar com segurança as 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
- funções simples,
- uma turma ou
- uma classe externa,
Vou mostrar três plugins de demonstração diferentes que você pode inspecionar e depois implementar o código em seu (s) próprio (s) plug-in (s).
Nota importante antecipadamente!
Como este tópico é extremamente difícil e muito detalhado e tem uma dúzia de casos + de borda, esta resposta nunca será perfeita. Eu vou continuar melhorando ao longo do tempo, então volte em uma base regular.
(1) Ativar / desativar / desinstalar plug-ins.
Os callbacks de configuração do plugin são acionados pelo core e você tem não influência sobre como o core faz isso. Existem algumas coisas para ter em mente:
-
Nunca , sempre
echo/print
anything (!) durante os retornos de chamada de configuração. Isso levará aheaders already sent
mensagem e núcleo irá recomendar para desativar e excluir o seu plugin ... não pergunte: eu sei ... - Você não verá qualquer saída visual. Mas Adicionei
exit()
declarações a todos os diferentes retornos de chamada para que você possa obter algumas informações sobre o que realmente está acontecendo. Apenas descomente-os para ver as coisas funcionando. - É extremamente importante que você verifique se
__FILE__ != WP_PLUGIN_INSTALL
e (se não: abortar!) para ver se está realmente desinstalando o plugin. Eu recomendaria simplesmente acionaron_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. - Eu também faço algumas coisas de segurança. Alguns são feitos pelo núcleo também, mas ei! Melhor prevenir do que remediar! .
- Primeiro, eu desautorizo o acesso direto a arquivos quando o núcleo não está carregado:
defined( 'ABSPATH' ) OR exit;
- Depois, verifico se o usuário atual pode realizar essa tarefa.
- Como última tarefa, verifico o referenciador. Observação: pode haver resultados inesperados com uma tela
wp_die()
solicitando permissões adequadas (e se você quiser tentar novamente ... sim, com certeza ), quando tiver um erro. Isso acontece quando o núcleo o redireciona, define o% atual$GLOBALS['wp_list_table']->current_action();
paraerror_scrape
e, em seguida, verifica o referenciador paracheck_admin_referer('plugin-activation-error_' . $plugin);
, em que$plugin
é$_REQUEST['plugin']
. Assim, o redirecionamento acontece na metade do carregamento da página e você obtém essa barra de rolagem com fio e a tela da matriz insight a caixa de mensagem / aviso do administrador amarelo. Se isso acontecer: mantenha a calma e apenas procure o erro com algumexit()
e depuração passo a passo.
- Primeiro, eu desautorizo o acesso direto a arquivos quando o núcleo não está carregado:
(A) Plugin de funções simples
Lembre-se de que isso pode não funcionar se você ligar os callbacks 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' );
(B) Uma arquitetura baseada em classes / OOP
Este é o exemplo mais comum nos plugins de hoje em dia.
<?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) Uma arquitetura baseada em classe / OOP com um objeto de configuração externo
Este cenário pressupõe que você tenha um arquivo de plug-in principal e um segundo arquivo chamado setup.php
em um subdiretório do plug-in denominado inc
: ~/wp-content/plugins/your_plugin/inc/setup.php
. Isso funcionará também quando a pasta do plug-in estiver fora da estrutura de pastas padrão do 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. Apenas a pasta inc
precisa ter o mesmo nome & localização relativa do diretório raiz dos plugins.
Nota: Você pode simplesmente pegar as três funções register_*_hook()*
e as classes e soltá-las no seu plugin.
O arquivo principal do 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 configuraçã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 ) );
}
}
(2) Atualizações de plug-ins
Se você escrever um plug-in que tenha sua própria tabela ou opções do banco de dados, poderá haver cenários em que você precisará alterar ou atualizar as coisas.
Infelizmente, até agora não há possibilidade de executar algo na instalação do plugin / theme ou atualizar / atualizar. Com prazer, há uma solução alternativa: ligar 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 tão bom / bem escrito, mas como dito: É um exemplo e a técnica funciona bem. Melhorará isso com uma atualização posterior.