Устаревшие функции в классе плагинов

8

Я обновляю один из моих плагинов, и я немного застрял с устаревшими функциями.

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

$GLOBALS['my_custom_plugin'] = new my_custom_plugin();

Затем, например, в моем FAQ я имел код, который показал, как удалить одну из функций моего класса из определенной ловушки и добавить к другой ловушке:

function move_input(){ 
    global $my_custom_plugin;
    remove_action( 'before_main_content', array( $my_custom_plugin, 'display_input') );
    add_action( 'after_main_content', array( $my_custom_plugin, 'display_input' ) );
}
add_action( 'wp_head' , 'move_input' );

Теперь в моем обновлении display_input()функция была перемещена в другой класс, и я хочу, чтобы люди знали, как получить к ней доступ. Я попытался заменить исходную функцию (в основном классе плагина) следующим уведомлением об устаревании:

public function display_input() { 
    _deprecated_function( 'display_price', '2.0', 'my_custom_plugin()->display->display_input' );
    return $this->display->display_input();
}

Тем не менее, add_actionи remove_actionфункция , кажется, не вызвать устаревание уведомления. Как ни странно, полное удаление функции также не вызывает ошибку, даже если array( $my_custom_plugin, 'display_input')ее не существует.

Если кто-то пытается получить доступ к функции напрямую:

$my_custom_plugin->display_input();

Затем я вижу уведомления об отладке. Это ожидаемый результат для _deprecated_function()? или я что-то упустил? Можно ли показать сообщение об отладке, когда кто-то пытается удалить или добавить действие, используя устаревшую функцию?

Обновить

Я понял, что просто не вижу сообщения отладки для этого, add_actionпоскольку добавляю его довольно низко на странице. #facepalm! Тем не менее, я до сих пор не вижу отладочного уведомления для remove_action.

helgatheviking
источник
Интересные call_user_func(function(){trigger_error('hello?');});работы, но это не удается при обратном вызове, зарегистрированном для add_action.
fuxia
Готовимся к лицевой маске, но это вопрос или утверждение?
helgatheviking
Просто результат теста. Я тоже удивлен.
fuxia
Хорошо, так что я ничего не упустил, просто так оно и есть ?
helgatheviking
2
О, Query Monitor скрыл сообщение в моей настройке. Сообщение для add_action()было на самом деле там. remove_action()не может быть обработан таким образом.
fuxia

Ответы:

2

Несуществующие обратные вызовы

Одна из приятных вещей заключается в том, что ни то do_action(), ни другое не apply_filters()вызывают ошибку, если обратного вызова нет. Это означает, что это самый безопасный способ вставить данные плагина в шаблоны: если плагин выключен и do_action()/ apply_filters()не находит обратный вызов в глобальном $wp_filtersмассиве, ничего не происходит.

Ошибка вывода

Теперь, когда вы вызываете remove_filter()функцию / метод, который первоначально перехватил обратный вызов, обратный вызов просто будет удален из глобального массива, что означает, что обратный вызов никогда не будет выполнен, поскольку он больше не зарегистрирован.

Решение простое: удалите обратный вызов после его запуска, удалив его из самого обратного вызова.

Удаление обратных вызовов

Мы все знаем, что плагин WPs "API" - это боль, когда дело доходит до удаления. Проблема главным образом заключается в странной конструкции для добавления «уникальных» имен к ключам в global $wp_filter;массиве. Очень простое решение , чтобы просто использовать __METHOD__и вызов фильтры , которые вы хотите удалить в статическом контексте:

class FOoooo
{
    public function __construct()
    {
        add_filter( 'hook', array( __CLASS__, 'bar' ) );
    }
    public static function bar( $baz )
    {
        remove_filter( current_filter(), __METHOD__ );

        return $baz;
    }
}

Хотя это нехорошо, это ... своего рода решение для некоторых случаев использования. Но даже не думайте о снятии крышки.

Выше просто удаляет обратный вызов, все равно выполняет его. Тем не менее вы можете пойти дальше и использовать remove_all_actions()(или remove_all_filters()).

// Check if a callback is attached and tell about the deprecated stuff
if ( has_action( 'before_main_content' ) )
    _deprecated_function( 'display_price', '2.0', 'my_custom_plugin()->display->display_input' );
// Remove the callback
remove_all_actions( 'before_main_content' );

Возможно, вы могли бы даже пойти дальше, извлечь обратный вызов из массива глобальных фильтров и повторно присоединить его к новому хуку / фильтру (если они совместимы).

кайзер
источник
Спасибо, Кайзер! Это удивительный и подробный ответ. Я постараюсь проверить это завтра.
helgatheviking