Как сделать плагин обязательным в теме wp без использования условных операторов php при вызове отдельной функции из этого плагина?

9

Одна из моих тем Wordpress требует нескольких сторонних плагинов для правильной работы.

В большинстве случаев я использовал для вызова функций из сторонних плагинов, используя условные операторы, такие как

    if(function_exist('plugin_function')) {
             plugin_function() // do something
    }

Предположим, хотя мне нужно широко использовать один плагин во многих файлах моей темы ... Я бы хотел избежать использования многих условий IF ... Есть ли правильный способ требовать установки определенного определенного плагина в WP или, что еще лучше, установить их? если они отсутствуют до активации темы?

Спасибо

unfulvio
источник

Ответы:

7

is_plugin_active()является довольно хрупким: он сломается, когда автор плагина переименует основной файл или когда пользователь переименует каталог или основной файл плагина. Лучше проверить, существует ли определенная публичная функция.

Чтобы не выполнять эту проверку каждый раз, когда вам нужны некоторые функции плагина, вы можете показать сообщение в области администратора:

add_action( 'admin_notices', 'my_theme_dependencies' );

function my_theme_dependencies() {
  if( ! function_exists('plugin_function') )
    echo '<div class="error"><p>' . __( 'Warning: The theme needs Plugin X to function', 'my-theme' ) . '</p></div>';
}

Другая альтернатива - использовать что-то вроде http://tgmpluginactivation.com/

scribu
источник
Если автор плагина меняет имя функции, с которой вы спрашиваете function_exists, то обычный пользователь просто получит сообщение, что он не установил плагин, на который полагается другой плагин. Проблема заключается в том , что пользователь действительно будет установлен плагин , а затем просто интересно , почему это doens't работы . О, и я не собираюсь понижать тебя за это.
Кайзер
Если вам небезразличны голоса, то вам следует проголосовать за Q, так как он хороший.
Кайзер
Если автор плагина изменит имя функции, он получит жалобы от гораздо большего числа пользователей, чем если бы он изменил имя файла.
scribu
И я отклонил ваш ответ, потому что он не касался вопроса, ИМО. Или вы бы предпочли скрытое голосование без объяснения причин?
scribu
Я просто говорил о понижении, а не о комментарии. С самим комментарием все в порядке, так как эта тема требует обсуждения. Я добавлю еще один ответ, так как мои мысли превысят длину комментария. Пожалуйста, просто отредактируйте ответ, чтобы мы могли сохранить результаты обсуждения в исправлениях для всех. Спасибо.
Кайзер
1

Хотя это не помешало бы нарушить тему, когда плагин отключен, я бы посмотрел эту замечательную статью о плагине «Как отобразить уведомление администратора для необходимых тем» . Меня никогда не устраивала идея, заставляющая плагин быть установленным, и поэтому это кажется следующим лучшим вариантом.

Еще одна быстрая мысль: я никогда не пробовал этого, но мне интересно, не могли бы вы придумать какой-нибудь умный способ разместить несколько хуков в одном условии. Возможно, вы могли бы выделить все условные функции в другом файле и требовать его только при if( function_exists( 'plugin_function' ) )возврате true(при том понимании, что это несовершенная проверка.

mrwweb
источник
0

Если вам нужна только плагинная страница, то есть is_plugin_active(). Если вам это нужно снаружи, лучше скопируйте / вставьте базовую функцию в вашу тему, а затем снова используйте ее:

if ( ! is_admin() )
{
/**
 * Check whether the plugin is active by checking the active_plugins list.
 *
 * @since 2.5.0
 *
 * @param string $plugin Base plugin path from plugins directory.
 * @return bool True, if in the active plugins list. False, not in the list.
 */
function is_plugin_active( $plugin ) {
    return in_array( $plugin, (array) get_option( 'active_plugins', array() ) ) || is_plugin_active_for_network( $plugin );
}
}

Условное исключает любые ошибки с двойным определением функции.

кайзер
источник
Это на самом деле не отвечает на вопрос. Он просто заменяется if(function_exist('plugin_function'))наif(is_plugin_active('plugin-file.php'))
scribu
0

Примечание. Этот ответ только для того, чтобы облегчить обсуждение между @scribu и @kaiser. Моды: пожалуйста, не удаляйте. Пользователи / Читатели: Пожалуйста, не голосуйте. Если вы хотите следить за обсуждением, посмотрите журнал изменений / редактирования. Если вы хотите присоединиться к обсуждению, отредактируйте ответ. Если обсуждение имеет результат, то оно будет помечено как таковое. Спасибо.


Сценарии

Существуют также разные сценарии, которые имеют разный вес, где вы можете иметь зависимость от плагина. (Примеры только вымышленные). Слово «(родительский) плагин» можно заменить на «тему» ​​с родительской точки зрения.

  1. (сложно) Дочерний плагин, который только расширяет функциональность или изменяет отображение (и аналогичное) существующего плагина и поэтому не может существовать без родителя. Пример: BuddyPress »BuddyPress-FunkyCommentDisplay
  2. (обычный) Плагин, который имеет расширенные функциональные возможности при активации дочернего плагина. Пример: jQueryAttachmentCarousel »jQuerySlideDeck
  3. (мягкий) Плагин, который просто добавляет функцию. Пример: DisneyWonderlandTheme »MickeysSocialLinks

Далее я попытаюсь набросать, что происходит, когда вы обновляете «другой» плагин и проверка больше не работает.

  • Объявление 1) Плагин не может существовать без активации BuddyPress »Материал полностью сломан.
  • Объявление 2) Плагин не может предложить вариант переключения с карусели на SlideDeck »Отображает проводной (я предполагаю, что стили изменены на SlideDeck).
  • Объявление 3) MickeysSocialLinks исчезают.

Проверьте

Есть три возможности проверить, если вы хотите знать, активен ли плагин:

  • A. Папка существует?
  • B. Существует ли основной файл - опция 'active_plugins'- существует?
  • C. Существует ли конкретная функция?

Если я сейчас возьму свой плагин Internal Link Checker в качестве примера, который не предлагает общедоступный API и не предназначен для расширения, то я бы не увидел причин (как автора) не изменять именование внутренних функций по требованию или только по желанию , Так что, если кто-то попытается использовать этот плагин, он просто сломается (в зависимости от функциональности и жесткости комплектации) при обновлении. То же самое касается имен файлов. У меня не было бы реальной причины (кроме того, что плагин будет деактивирован при обновлении), чтобы не изменять имя файла. Единственное, что могло бы удержать меня от изменения имени папки, - это то, что проверка обновлений и уведомление выполняются для имени файла - если оно размещено в официальном репозитории.

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

функция »имя основного файла» папка


Когда я сказал, что проверка функции менее хрупкая, чем использование, is_plugin_active()я предположил, что рассматриваемая функция - это та, которую явно поддерживает автор плагина. Конечным примером этого будет wp_pagenavi()тег шаблона, предлагаемый плагином WP-PageNavi.

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

Больше мыслей на эту тему:

http://wordpress.org/support/topic/plugin-plugin-dependencies-unreliable-plugin-namingidentifying-scheme


Я думаю, мы можем подвести итог в трех пунктах:

  • Мы говорили о немного разных темах
  • Мы согласны с тем, что нет пуленепробиваемого способа обойти то, что я думал, что тема будет
  • Исходя из вашего понимания вопроса, вы предложили правильный путь

(Пока) самый умный способ, который я могу придумать, который я уже видел в некоторых (слишком много) плагинах:

// inside the plugin file:
add_action( 'plugin_custom_hook', 'plugin_trigger' );
// inside some template:
do_action( 'plugin_custom_hook' );

Не думая слишком подробно об этом, но я думаю, вы могли бы подключить свое уведомление к проверке «все» фильтра и проверить внутри текущего фильтра, если он был запущен, когда вы находитесь на shutdownкрючке ...?


Использование хуков хорошо работает для «нормальных» и «слабых» зависимостей. Единственным недостатком является то, что вам все равно придется использовать function_exists()или is_plugin_active()если вы хотите остановить, если зависимость не встречается. Использование фильтра «все» для этого было бы слишком дорого IMO.

@scibu Это было нацелено на "вашу" тему. (Я уже бросил говорить о моем). :)

Так что, в принципе, если вам нужна зависимость - и у вас есть хороший автор - тогда он может предложить вместо этого хук в качестве замены тега шаблона. Потому что плагин будет подключаться к нему только в том случае, если он будет присутствовать или просто ничего не делать. А с другой стороны у вас не будет ошибки, когда плагины отсутствуют.

Вот трудная часть (или более Q): Чтобы написать уведомление администратора для информирования пользователя о зависимости «Вам нужно установить» DisneyWonderLinks «», вы можете проверить array_keys( $GLOBALS['wp_filter']['template_tag_like_hook'] ). Я не уверен, что это будет работать, но на самом деле массив должен быть доступен с обеих сторон (public / admin).


Это не сработает. Тот факт, что обратный вызов зарегистрирован для ловушки, не означает, что ловушка будет срабатывать, когда ожидается. Единственная вещь, которая могла бы работать подобным образом, - это использовать хук 'shutdown', о котором вы упоминали ранее:

add_action( 'shutdown', function() {
  if ( !did_action( 'template_tag_like_hook' ) )
    echo 'Problem.';
} );

Конечно, это будет напечатано в самом низу, после </html>тега, во внешнем интерфейсе (поскольку там обычно используются теги шаблонов), что не очень полезно.

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

кайзер
источник
Кстати, это довольно неортодоксальный способ использования функциональности сайта. Это напоминает мне о c2.com/cgi/wiki
scribu
Да, это так. Но я понятия не имел, как мы могли бы продолжить обсуждение, не скрывая его от более поздних читателей.
Кайзер
Я бы не подумал, что публикация вопроса вызвала бы настоящую дискуссию :) Но это действительно интересно, и я благодарю вас и за ваши усилия и за время, которые вы дали советы и за вдумчивые дебаты. Я думаю, что совет от scribu (один из многих) использовать класс активации TGM мог бы предложить решение моего ответа, по крайней мере, с чисто практической точки зрения, я его рассмотрю. Тем не менее, я все еще слежу за всем обсуждением, потому что и другие предложенные методы имеют смысл в определенных сценариях и мне очень интересно читать, спасибо!
unfulvio