Как сделать, чтобы плагин требовал другого плагина?


30

Я создаю плагин, который добавляет дополнительную функциональность к основному плагину. В идеале на экране администрирования плагинов должна быть отключена ссылка «активировать» и добавлена ​​встроенная заметка, в которой пользователю предлагается сначала установить и активировать основной плагин, прежде чем он / она сможет использовать текущий плагин.


1
Как насчет использования: is_plugin_active ()? например: if (is_plugin_active('path/to/plugin.php')) { // Do something }
TomC

Ответы:


35

Спасибо за ответы, ребята. Хотя оба ответа поставили меня на правильный путь, ни один из них не сработал. Итак, я делюсь своими решениями ниже.

Способ 1 - Использование register_activation_hook:

Создайте Родительский Плагин в plugins / parent-plugin / parent-plugin.php:

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

Создайте дочерний плагин в плагинах / 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>');
    }
}

Обратите внимание, что я не использую, так deactivate_plugins( $plugin );как по какой-то причине это не работает. Поэтому я использовал wp_die для отмены перенаправления активации и информирования пользователя.

Преимущество:

  • Простое решение и не требует дополнительных ударов по сравнению с методом 2

Недостатки:

  • экран wp_die ужасен
  • Экран wp_die по-прежнему будет отображаться, если вы активировали Родительский плагин и Дочерний плагин одновременно, используя флажки на экране администрирования плагинов.

Способ 2 - Использование admin_init и admin_notices

Создайте Родительский Плагин в plugins / parent-plugin / parent-plugin.php:

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

Создайте дочерний плагин в плагинах / 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
}

Преимущество:

  • Работает, когда вы активируете плагин Parent и Child одновременно, используя флажки

Недостаток:

  • Получите дополнительные удары в БД, так как плагин фактически активируется сначала и деактивируется после запуска admin_init

Что касается моего вопроса об отключении ссылки активации, я мог бы использовать:

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;
}

Тем не менее, это оказалось очень непрактичным, так как нет места для размещения этого кода. Я не мог поставить его на родительский плагин, так как родительский плагин должен быть активным для запуска этого кода. Конечно, не принадлежит дочернему плагину или functions.php. Так что я отказываюсь от этой идеи.


1
Метод 2 работал отлично! Я использовал его для расширения чужого плагина.
Коллин Прайс

2

Попробуйте, это прокомментировано, так что это должно помочь вам понять это.

<?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'
    }
}
?> 

Если это выдает ошибку, вы также можете проверить «option» в «myplugin» и установить его в false или не активировать.


2

Оба предложенных решения имеют недостатки.

Способ 1: Как уже упоминалось, экран wp_die () будет по-прежнему отображаться, когда родительский плагин и дочерний плагин активируются одновременно с использованием флажков на экране администрирования плагинов.

Способ 2: В некоторых случаях это не очень хорошо, так как «admin_init» выполняется после «plugins_loaded» ( https://codex.wordpress.org/Plugin_API/Action_Reference ) и после ловушки удаления ( https: // codex. wordpress.org/Function_Reference/register_uninstall_hook ). Так, например, если мы хотим, чтобы надстройка выполняла некоторый код при удалении независимо от того, активен родительский плагин или нет, этот подход НЕ будет работать.

Решение:

Прежде всего, нам нужно добавить следующий код в конец основного файла PHP родительского плагина:

do_action( 'my_plugin_loaded' );

Это отправит событие / сигнал всем подписчикам, сообщая, что основной плагин был загружен.

Тогда класс надстройки должен выглядеть следующим образом:

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();
}

Надеюсь, это поможет :)


4
Этот ответ тоже имеет недостаток. :-) Предполагается, что у вас есть полный контроль над родительским плагином, куда вы можете добавить do_action ('my_plugin_loaded'); в своем коде. Выбранный ответ будет работать с или без контроля над родительским плагином (например, родительский плагин не ваш)
kosinix

Спасибо, это именно то, что я искал. В моем случае у меня есть полный контроль над родительским плагином, и мне нужно было создать такую ​​зависимость.
cr0ybot

0

Я думаю, что вам нужна активация плагина TGM .

Активация плагинов TGM - это библиотека PHP, которая позволяет вам легко запрашивать или рекомендовать плагины для ваших тем WordPress (и плагинов). Он позволяет вашим пользователям устанавливать, обновлять и даже автоматически активировать плагины единичным или массовым способом, используя собственные классы, функции и интерфейсы WordPress. Вы можете ссылаться на связанные плагины, плагины из хранилища плагинов WordPress или даже плагины, размещенные в других местах в Интернете.


Неверная ссылка. Правильная ссылка здесь
XedinUnknown
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.