Как сделать плагин зависимым от другого плагина?

28 дек. 2013 г., 11:15:18
Просмотры: 42.7K
Голосов: 42

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

1
Комментарии

А что насчёт использования: is_plugin_active() ?

Например:

`if (is_plugin_active('path/to/plugin.php')) {
// Сделать что-то
}`
TomC TomC
28 дек. 2013 г. 11:29:19
Все ответы на вопрос 5
2
60

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

Метод 1 - Использование register_activation_hook:

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

<?php
/*
Plugin Name: Родительский плагин
Description: Демонстрационный плагин с зависимым дочерним плагином.
Version: 1.0.0
*/

Создаем дочерний плагин в plugins/child-plugin/child-plugin.php:

<?php
/*
Plugin Name: Дочерний плагин
Description: Для работы этого плагина должен быть установлен и активирован Родительский плагин.
Version: 1.0.0
*/
register_activation_hook( __FILE__, 'child_plugin_activate' );
function child_plugin_activate(){

    // Проверяем наличие родительского плагина
    if ( ! is_plugin_active( 'parent-plugin/parent-plugin.php' ) and current_user_can( 'activate_plugins' ) ) {
        // Прерываем активацию и показываем ошибку
        wp_die('Извините, но этот плагин требует установки и активации Родительского плагина. <br><a href="' . admin_url( 'plugins.php' ) . '">&laquo; Вернуться к списку плагинов</a>');
    }
}

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

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

  • Простое решение, не создающее дополнительной нагрузки на базу данных по сравнению со вторым методом

Недостатки:

  • Экран wp_die выглядит некрасиво
  • Экран wp_die ВСЕ РАВНО появится, если вы активируете Родительский и Дочерний плагины одновременно, используя чекбоксы на экране управления плагинами.

Метод 2 - Использование admin_init и admin_notices

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

<?php
/*
Plugin Name: Родительский плагин
Description: Демонстрационный плагин с зависимым дочерним плагином.
Version: 1.0.0
*/

Создаем дочерний плагин в plugins/child-plugin/child-plugin.php:

<?php
/*
Plugin Name: Дочерний плагин
Description: Для работы этого плагина должен быть установлен и активирован Родительский плагин.
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>Извините, но Дочерний плагин требует установки и активации Родительского плагина.</p></div><?php
}

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

  • Работает при одновременной активации Родительского и Дочернего плагинов через чекбоксы

Недостатки:

  • Создает дополнительную нагрузку на базу данных, так как плагин сначала активируется, а затем деактивируется при выполнении 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>Активировать</span>';

    return $links;
}

Однако это оказалось крайне непрактичным, так как НЕГДЕ разместить этот код. Я не мог разместить его в родительском плагине, так как родительский плагин должен быть активен для выполнения этого кода. Определенно не подходит для дочернего плагина или functions.php. Поэтому я отказался от этой идеи.

28 янв. 2014 г. 08:43:56
Комментарии

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

Collin Price Collin Price
17 июл. 2014 г. 21:32:50

Могу ли я также использовать это для подключения плагинов из директории WordPress? Я хочу создать плагин для публикации вакансий, но использовать существующий плагин форм (например Formidable или Caldera Forms) для создания формы заявки.

Thessa Verbruggen Thessa Verbruggen
14 янв. 2020 г. 11:17:05
0

Начиная с версии WordPress 6.5, вы можете определять зависимости плагинов в основном файле плагина с помощью заголовка Requires Plugins. Например:

/**
 * Plugin Name: My Plugin
 * Requires Plugins: plugin-one, plugin-two
 */

Просто добавьте список слаг-идентификаторов плагинов из репозитория WP.org через запятую, и всё готово.

Зависимости отображаются в карточке плагина на экранах Плагины → Все плагины и Плагины → Добавить новый.

Плагины, не размещённые на WordPress.org, также можно указывать, но их потребуется установить вручную.

Обратите внимание, что эта функция работает только для плагинов, но не для тем. Также нельзя указать конкретные версии плагинов, и все перечисленные плагины будут обязательными. Невозможно сделать так, чтобы требовался только один из списка.

Подробнее об этом нововведении читайте в соответствующем посте блога make.wordpress.org.

1 мар. 2024 г. 19:34:18
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 Проверка родительского плагина

    /**
     * Проверяет, активирован ли родительский плагин (не обязательно загружен).
     *
     * @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;
    }

    /**
     * Проверяет, активен и загружен ли родительский плагин.
     *
     * @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__ ) );

            // Сообщение об ошибке + ссылка "назад".
            wp_die( __( 'Для работы дополнения My Add-on требуется установленный и активированный плагин My Plugin.' ), __( 'Ошибка' ), array( 'back_link' => true ) );
        }
    }

    #endregion Проверка родительского плагина
}

if (My_Addon::_is_parent_active_and_loaded())
{
    // Если родительский плагин уже загружен, инициализируем дополнение.
    My_Addon::init();
}
else if (My_Addon::_is_parent_activated())
{
    // Инициализируем дополнение только после загрузки родительского плагина.
    add_action( 'my_plugin_loaded', array( __CLASS__, 'init' ) );
}
else
{
    // Даже если родительский плагин не активирован, выполняем дополнение для хуков активации/удаления.
    My_Addon::init();
}

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

26 мар. 2016 г. 21:58:12
Комментарии

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

kosinix kosinix
29 мар. 2016 г. 06:14:14

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

cr0ybot cr0ybot
15 авг. 2018 г. 22:22:30
0

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

<?php
register_activation_hook( __FILE__, 'myplugin_activate' ); // Регистрируем функцию myplugin_activate при активации
function myplugin_activate() {
    $plugin = plugin_basename( __FILE__ ); // Получаем базовое имя плагина, например 'myplugin'
    if ( is_plugin_active( 'plugin-directory/first-plugin.php' ) ) {
        // Если плагин активен, выполняем хуки для 'myplugin'
    } else {
        // Если плагин неактивен, запрещаем активацию текущего плагина
        deactivate_plugins( $plugin ); // Деактивируем 'myplugin'
    }
}
?> 

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

28 дек. 2013 г. 11:48:06
0

Думаю, вам понадобится TGM Plugin Activation.

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

8 окт. 2018 г. 19:53:28