Atualize um Plugin enquanto mantém a compatibilidade: general

4

Como posso fazer atualizações de um plugin público meu sem quebrar o plugin para todos os usuários existentes.

Em primeiro lugar , eu gostaria de mudar a classe / namespace do plugin principal, porque eu gostaria que ele fosse similar a outras classes no plugin que ele estende.

Então, eu gostaria de mudar

class some_class(){}

para

class Some_Class(){}

Em segundo lugar , toda a classe é instanciada e salva em uma variável global.

global $some_class;
$some_class = new some_class();

Em algum lugar aqui, vi um bom exemplo de como instanciar uma classe sem um global (não é possível encontrá-la agora, é claro, #doh). O global pode ser usado pelos usuários para adicionar / remover alguns modelos. Existe uma maneira de se livrar do global sem quebrar completamente os temas de pessoas que poderiam usá-lo para manipular os modelos?

Em terceiro lugar , relacionado ao acima, meu arquivo de plug-in principal ficou muito grande e eu gostaria de dividi-lo em partes para minha própria sanidade. No entanto, se o método some_templates() estiver no some_class() , é possível movê-lo para o front_end_class() sem quebrar os itens para os usuários?

Por exemplo

Para desengatar uma ação no meu plug-in

function remove_method(){
  global $some_class;
  remove_action('wp_head', array($someclass, 'some_templates'));
}
add_action('init','remove_method');

A estrutura da classe e a configuração da variável global podem ser ajustadas sem quebrar isso. Como posso alertar as pessoas que isso mudou? _doing_it_wrong() ?

Finalmente , venho salvando alguns posts meta como "sim" versus "não" no lugar de um booleano. Faz sentido mudar isso?

    
por helgatheviking 02.03.2013 / 23:31

1 resposta

4

Os nomes das classes não diferenciam maiúsculas de minúsculas no PHP (com uma exceção ), então isso não deve ser um problema.

É possível acessar sua instância do plug-in principal para uma classe com um método estático get_instance() ( exemplo ). Você não precisa construir um Singleton para isso. E não deve quebrar a compatibilidade com versões anteriores.

Se você tivesse métodos públicos em seu código antigo e esses métodos fossem usados por código de terceiros, você precisa manter a assinatura exata. Portanto, mantenha o método e passe a chamada para a instância da nova classe ou, se houver muitos desses métodos, use __call() para capturar todos esses métodos em um.

(Update) Dado o seu exemplo de remove_action() … isso é complicado. Se você adicionar esse retorno de chamada de outra turma agora, não há uma maneira segura de permanecer compatível com versões anteriores, porque você não pode "assistir" remove_action() chamadas.
Você pode registrar o antigo callback e implementar um Observer a ser observado se ele for removido .

Uma ideia que tenho usado para projetos futuros: separar a API pública da lógica interna.

Exemplo: crie uma classe Plugin_API e passe todos os objetos do seu código trabalhando para essa classe quando eles estiverem configurados. Quando um método dessa API é chamado, passe essa chamada para o objeto responsável internamente , sem expor sua estrutura de plug-in ao público.

Código de amostra

add_action( 'wp_loaded', array ( Plugin_Controller::get_instance(), 'plugin_setup' ) );

class Plugin_Controller
{
    protected static $instance = NULL;

    public static function get_instance()
    {
        NULL === self::$instance and self::$instance = new self;

        return self::$instance;
    }

    public function plugin_setup()
    {
        $api = Plugin_API::get_instance();
        $api->add_object( 'post_type',    new Plugin_Custom_Post_Type );
        $api->add_object( 'taxonomy',     new Plugin_Custom_Taxonomy );
        $api->add_object( 'options_page', new Plugin_Options_Page );

        add_action( 'wp_head', array ( $api, 'wp_head' ) );
    }
}

class Plugin_Custom_Post_Type {}
class Plugin_Custom_Taxonomy {}
class Plugin_Options_Page {}

class Plugin_API
{
    protected static $instance = NULL;

    protected $objects;

    public static function get_instance()
    {
        NULL === self::$instance and self::$instance = new self;

        return self::$instance;
    }

    public function add_object( $name, $object )
    {
        $this->objects[ $name ] = $object;
    }

    public function wp_head()
    {
        $this->objects['post_type']->wp_head_callback();
        $this->objects['taxonomy']->wp_head_callback();
    }
}

Agora, outro plug-in pode remover essa ação com…

remove_action( 'wp_head', array ( Plugin_API::get_instance(), 'wp_head' ) );

... e você ainda está livre para mudar sua estrutura de plugins sempre que quiser.

Esta é apenas uma ideia, eu não a usei. Mas pode valer a pena tentar um plugin complexo com muitas classes. Não tenho certeza de como isso funcionará com os filtros, mas esses são mais fáceis de serem movidos de qualquer maneira.

A atualização de um número desconhecido de campos pós meta pode ser dispendiosa. Eu não tocaria nisso.

    
por fuxia 02.03.2013 / 23:59