Como fazer um plugin exigir outro plugin?

30

Estou construindo um plugin que adiciona funcionalidade extra a um plugin principal. Idealmente, na tela de administração de plug-ins, o link "ativar" deve ser desativado e uma nota em linha deve ser adicionada informando ao usuário para instalar e ativar o plug-in principal antes de poder usar o plug-in atual.

Kosinix
fonte
1
Que tal usar: is_plugin_active ()? por exemplo: if (is_plugin_active('path/to/plugin.php')) { // Do something }
TomC

Respostas:

35

Obrigado pelas respostas pessoal. Embora ambas as respostas me colocassem no caminho certo, nenhuma funcionou imediatamente. Então, estou compartilhando minhas soluções abaixo.

Método 1 - Usando register_activation_hook:

Crie o plugin pai em plugins / parent-plugin / parent-plugin.php:

<?php
/*
Plugin Name: Parent Plugin
Description: Demo plugin with a dependent child plugin.
Version: 1.0.0
*/

Crie o Child Plugin em plugins / child-plugin / child-plugin.php:

<?php
/*
Plugin Name: Child Plugin
Description: Parent Plugin should be installed and active to use this plugin.
Version: 1.0.0
*/
register_activation_hook( __FILE__, 'child_plugin_activate' );
function child_plugin_activate(){

    // Require parent plugin
    if ( ! is_plugin_active( 'parent-plugin/parent-plugin.php' ) and current_user_can( 'activate_plugins' ) ) {
        // Stop activation redirect and show error
        wp_die('Sorry, but this plugin requires the Parent Plugin to be installed and active. <br><a href="' . admin_url( 'plugins.php' ) . '">&laquo; Return to Plugins</a>');
    }
}

Observe que não estou usando deactivate_plugins( $plugin );, por algum motivo, ele não funciona. Então usei wp_die para cancelar o redirecionamento de ativação e informar o usuário.

Vantagem:

  • Solução simples e não incorre em hits adicionais de banco de dados em comparação com o método 2

Desvantagens:

  • a tela wp_die é feia
  • A tela wp_die AINDA aparecerá se você ativou o plug-in pai e o plug-in filho ao mesmo tempo usando as caixas de seleção na tela de administração dos plugins.

Método 2 - Usando admin_init e admin_notices

Crie o plugin pai em plugins / parent-plugin / parent-plugin.php:

<?php
/*
Plugin Name: Parent Plugin
Description: Demo plugin with a dependent child plugin.
Version: 1.0.0
*/

Crie o Child Plugin em plugins / child-plugin / child-plugin.php:

<?php
/*
Plugin Name: Child Plugin
Description: Parent Plugin should be installed and active to use this plugin.
Version: 1.0.0
*/
add_action( 'admin_init', 'child_plugin_has_parent_plugin' );
function child_plugin_has_parent_plugin() {
    if ( is_admin() && current_user_can( 'activate_plugins' ) &&  !is_plugin_active( 'parent-plugin/parent-plugin.php' ) ) {
        add_action( 'admin_notices', 'child_plugin_notice' );

        deactivate_plugins( plugin_basename( __FILE__ ) ); 

        if ( isset( $_GET['activate'] ) ) {
            unset( $_GET['activate'] );
        }
    }
}

function child_plugin_notice(){
    ?><div class="error"><p>Sorry, but Child Plugin requires the Parent plugin to be installed and active.</p></div><?php
}

Vantagem:

  • Funciona quando você ativa o plug-in Parent e Child ao mesmo tempo usando caixas de seleção

Desvantagem:

  • Incorrer em hits de banco de dados adicionais, pois o plug-in é realmente ativado primeiro e desativado quando o admin_init for executado.

Quanto à minha pergunta sobre a desativação do link de ativação, eu poderia usar:

add_filter( 'plugin_action_links', 'disable_child_link', 10, 2 );
function disable_child_link( $links, $file ) {

    if ( 'child-plugin/child-plugin.php' == $file and isset($links['activate']) )
        $links['activate'] = '<span>Activate</span>';

    return $links;
}

No entanto, acabou sendo altamente impraticável, pois não há lugar para colocar esse código. Não pude colocá-lo no plug-in pai, pois o plug-in pai deve estar ativo para que esse código seja executado. Certamente não pertence ao plugin filho ou functions.php. Então, eu estou descartando essa ideia.

Kosinix
fonte
1
O método 2 funcionou muito bem! Eu usei para estender o plugin de outra pessoa.
Collin Preço
2

Experimente, comentou, para ajudar a entender.

<?php
register_activation_hook( __FILE__, 'myplugin_activate' ); // Register myplugin_activate on
function myplugin_activate() {
    $plugin = plugin_basename( __FILE__ ); // 'myplugin'
    if ( is_plugin_active( 'plugin-directory/first-plugin.php' ) ) {
        // Plugin was active, do hook for 'myplugin'
    } else {
        // Plugin was not-active, uh oh, do not allow this plugin to activate
        deactivate_plugins( $plugin ); // Deactivate 'myplugin'
    }
}
?> 

Se isso gerar um erro, você também poderá verificar a 'opção' de 'myplugin' e configurá-la como falsa ou não ativada.

MrJustin
fonte
2

Ambas as soluções sugeridas têm falhas.

Método 1: Como mencionado, a tela wp_die () AINDA aparecerá quando o plug-in pai e o plug-in filho forem ativados ao mesmo tempo usando as caixas de seleção na tela de administração dos plug-ins.

Método 2: Em alguns casos de uso, não é bom, pois 'admin_init' é executado após 'plugins_loaded' ( https://codex.wordpress.org/Plugin_API/Action_Reference ) e após o gancho de desinstalação ( https: // codex. wordpress.org/Function_Reference/register_uninstall_hook ). Por exemplo, se queremos que o complemento execute algum código na desinstalação, independentemente de o plug-in pai estar ativo ou não, essa abordagem NÃO funcionará.

Solução:

Primeiro, precisamos anexar o seguinte código ao final do arquivo PHP principal do plugin pai:

do_action( 'my_plugin_loaded' );

Isso enviará um evento / sinal para todos os assinantes, informando que o plug-in principal foi carregado.

Em seguida, a classe do complemento deve ter a seguinte aparência:

class My_Addon
{
    static function init ()
    {
        register_activation_hook( __FILE__, array( __CLASS__, '_install' ) );

        if ( ! self::_is_parent_active_and_loaded() ) {
            return;
        }
    }

    #region Parent Plugin Check

    /**
     * Check if parent plugin is activated (not necessarly loaded).
     *
     * @author Vova Feldman (@svovaf)
     *
     * @return bool
     */
    static function _is_parent_activated()
    {
        $active_plugins_basenames = get_option( 'active_plugins' );
        foreach ( $active_plugins_basenames as $plugin_basename ) {
            if ( false !== strpos( $plugin_basename, '/my-plugin-main-file.php' ) ) {
                return true;
            }
        }

        return false;
    }

    /**
     * Check if parent plugin is active and loaded.
     *
     * @author Vova Feldman (@svovaf)
     *
     * @return bool
     */
    static function _is_parent_active_and_loaded()
    {
        return class_exists( 'My_Plugin' );
    }

    /**
     *
     * @author Vova Feldman (@svovaf)
     */
    static function _install()
    {
        if ( ! self::_is_parent_active_and_loaded() ) {
            deactivate_plugins( basename( __FILE__ ) );

            // Message error + allow back link.
            wp_die( __( 'My Add-on requires My Plugin to be installed and activated.' ), __( 'Error' ), array( 'back_link' => true ) );
        }
    }

    #endregion Parent Plugin Check
}

if (My_Addon::_is_parent_active_and_loaded())
{
    // If parent plugin already included, init add-on.
    My_Addon::init();
}
else if (My_Addon::_is_parent_activated())
{
    // Init add-on only after the parent plugins is loaded.
    add_action( 'my_plugin_loaded', array( __CLASS__, 'init' ) );
}
else
{
    // Even though the parent plugin is not activated, execute add-on for activation / uninstall hooks.
    My_Addon::init();
}

Espero que ajude :)

vovafeldman
fonte
4
Essa resposta também tem uma falha. :-) Supõe que você tenha controle total sobre o plug-in pai, onde é possível adicionar do_action ('my_plugin_loaded'); no seu código. A resposta selecionado irá trabalhar com ou sem controle do plugin pai (por exemplo, o plugin pai não é seu)
kosinix
Obrigado, é exatamente isso que eu estava procurando. No meu caso, eu faço tem controle total sobre o plugin pai, e necessário para criar esse tipo de dependência.
precisa saber é
0

Eu acho que você precisa da ativação do TGM Plugin .

O TGM Plugin Activation é uma biblioteca PHP que permite exigir ou recomendar facilmente plugins para seus temas (e plugins) do WordPress. Ele permite que seus usuários instalem, atualizem e ative plugins automaticamente de maneira singular ou em massa usando classes, funções e interfaces nativas do WordPress. Você pode consultar plug-ins incluídos, plugins do WordPress Plugin Repository ou até plugins hospedados em outros lugares na Internet.

Amir Hossein Hossein Zadeh
fonte
Link errado. Link correto aqui
XedinDesconhecido