Usando register_activation_hook em classes

3

Estou tentando desenvolver um plugin para fins básicos de SEO, já que muitas pessoas que conheço não gostam de usar o Yoast. Eu literalmente iniciei o plug-in e estou construindo a mensagem de ativação exibida ao usuário quando eles ativam o plug-in. Eu estou tendo problemas com uma mistura entre OOP e funções internas do Wordpress, e não tenho certeza onde estou errado.

A única maneira de fazer isso funcionar é criar uma nova instância da classe SEO_Plugin_Activation dentro do meu construtor de arquivos principais e, em seguida, chamar o método activatePlugin nessa classe. Eu sinto que isso é desnecessário. Eu também acho que como eu estou executando minhas funções no arquivo de classe de ativação não faz muito sentido também. Mas é a única maneira de fazer isso funcionar agora.

Eu não tenho certeza se o que estou fazendo é porque eu não estou agarrando 100% das técnicas de OOP, ou se eu não estou usando a API do Wordpress corretamente. Eu incluí três exemplos de código na seguinte ordem:

  1. Arquivo de plug-in principal
  2. Arquivo de classe que lida com meus requisitos de ativação
  3. O que eu realmente esperava que pudesse ser feito.

seo.php (arquivo principal do plugin)

<?php
/*
... generic plugin info
*/

require_once(dirname(__FILE__) . '/admin/class-plugin-activation.php');

class SEO {
  function __construct() {
    $activate = new SEO_Plugin_Activation();
    $activate->activatePlugin();
  }

}

new SEO();
?>

class-plugin-activation.php

<?php
class SEO_Plugin_Activation {

  function __construct() {
    register_activation_hook(__FILE__ . '../seo.php', array($this, 'activatePlugin'));
    add_action('admin_notices', array($this, 'showSitemapInfo'));
  }

  function activatePlugin() {
    set_transient('show_sitemap_info', true, 5);
  }

  function showSitemapInfo() {
    if(get_transient('show_sitemap_info')) {
      echo '<div class="updated notice is-dismissible">' .
              'Your sitemap files can be found at these following links: ' .
            '</div>';
      delete_transient('show_sitemap_info');
    }
  }

}
?>

seo.php (O que eu estava esperando)

<?php
/*
 ... blah blah blah
*/

require_once(dirname(__FILE__) . '/admin/class-plugin-activation.php');

class SEO {
  function __construct() {
    register_activation_hook(__FILE__, array($this, 'wp_install'));
  }

  function wp_install() {
    $activate = new SEO_Plugin_Activation();
    // Execute some method(s) here that would take care 
    // of all of my plugin activation bootstrapping
  }

}

new SEO();
?>

Eu tentei fazer isso do jeito que eu delineio no terceiro script, mas não estou tendo sucesso. A partir de agora, a mensagem é exibida corretamente, sem mensagens de erro.

    
por Dan Zuzevich 10.08.2017 / 15:36

3 respostas

6

Depois de reler sua pergunta, acho que vejo o problema, e isso decorre de um equívoco de como register_activation_hook funciona, combinado com alguma confusão sobre como você está inicializando seu código e o que significa inicializar

Parte 1: register_activation_hook

Esta função leva 2 parâmetros:

  

register_activation_hook (string $ file, função $ solicitável)

O primeiro parâmetro, $file é o arquivo de plug-in principal, não o arquivo que contém o que você deseja executar. Ele é usado da mesma maneira que plugins_url , então você precisa do valor de __FILE__ , especificamente seu valor no arquivo do plugin raiz com o cabeçalho do seu plugin.

O segundo parâmetro é um callable e funciona como esperado, mas é apenas usando add_action internally

  

Quando um plug-in é ativado, o gancho de ação "activate_PLUGINNAME" é chamado. No nome desse gancho, PLUGINNAME é substituído pelo nome do plug-in, incluindo o subdiretório opcional. Por exemplo, quando o plug-in estiver localizado em wp-content / plugins / sampleplugin / sample.php, o nome desse gancho se tornará "activate_sampleplugin / sample.php".

Parte 2: Bootstrapping e __FILE__

Um problema fundamental aqui é que __FILE__ terá valores diferentes em locais diferentes e você precisa de um valor específico.

Você também tem um problema, esse bootstrapping deve montar o gráfico do objeto, mas você não faz isso. Todos os seus objetos são criados assim que são definidos ou criados dentro de si, tornando difícil ou impossível passar valores para eles.

Como exemplo, eu poderia escrever um plugin como este:

plugin.php :

<?php
/**
 * Plugin Name: My Plugin
 * Version: 0.1
 */

// loading step
require_once( 'php/app.php' );

// bootstrapping step
$app = new App( __FILE__ );

// execution step
$app->run();

Eu defini todas as minhas classes na subpasta php e as carreguei todas no mesmo lugar. PHP agora sabe quais são minhas classes, seus nomes, etc, mas nada aconteceu ainda.

Eu então crio todos os meus objetos, passando o que eles precisam, neste caso, o App precisa do valor de __FILE__ , então eu o passo adiante. Observe que isso cria os objetos na memória, mas não faz nenhum trabalho. O aplicativo plugins está pronto para entrar em ação, mas está na fase de preparação.

O próximo passo pode ser canalizar esses objetos em um conjunto de testes de unidade, mas agora eu vou executá-los. Eu terminei o processo de bootstrapping, e o aplicativo está pronto para ser executado, então eu acionar o método run . Eu não deveria precisar passar nada para run , já que tudo que é necessário foi passado para os construtores. Durante o método run , adiciono todos os meus filtros e ganchos. É durante esses ganchos que todas as outras partes do plugin são executadas.

A parte importante é que eu tenho uma estrutura definida, e passo o que é necessário durante a fase de construção / bootstrapping, com um ciclo de vida definido

    
por Tom J Nowell 10.08.2017 / 16:02
1

Você realmente precisa registrar seus ganchos de ativação / desativação / desinstalação fora de sua classe de plug-in, conforme resposta do Kaiser aqui , que fornece um resumo muito melhor sobre o assunto que eu poderia escrever.

Isso deve abranger você se você quiser escrever este plugin como um exercício de aprendizado. Se tudo o que você procura é um plug-in de SEO que funcione bem e não seja repleto de anúncios brutos como o Yoast, recomendo o SEO Framework.

    
por Chris Cox 10.08.2017 / 15:52
1

Tom McFarlin criou um extenso boilerplate (agora mantido por Devin Vinson), tudo escrito em OOP, que você pode usar para criar seu novo plugin, ou apenas estude o fluxo de aplicativos para responder sua pergunta. Eu tenho usado para vários plugins personalizados, e eu tenho que dizer que realmente abriu meus olhos para alguns dos mistérios da OOP.

    
por Gary D 10.08.2017 / 16:38