WordPress: как получить все зарегистрированные функции для фильтра 'the_content'

38

У меня вопрос о WordPress, в частности версии 3.0 и новее.

Кто-нибудь знает, как получить массив или список всех функций, которые будут применяться или "зарегистрированы" в фильтре the_content?

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

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

Теги:
filter

2 ответа

95
Лучший ответ

Простая функция для печати из массива фильтров?

function print_filters_for( $hook = '' ) {
    global $wp_filter;
    if( empty( $hook ) || !isset( $wp_filter[$hook] ) )
        return;

    print '<pre>';
    print_r( $wp_filter[$hook] );
    print '</pre>';
}

Позвоните туда, где вам это нужно.

print_filters_for( 'the_content' );
  • 3
    Потрясающие. Спасибо за ответ, я понятия не имел о глобальном wp_filter, но теперь все это имеет смысл. Ура :)
  • 0
    работает как шарм! Спасибо!
16

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

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

  • имя функции (в зависимости от синтаксиса обратных вызовов):
    • функция обратного вызова: 'function_name'
    • метод объекта: array( $object, 'function_name' )
    • метод статического класса: array( 'class_name', 'function_name' ) и 'class_name::function_name'
    • закрытие: function() {}
    • относительный статический класс: array( 'class_name', 'parent::function_name' )
  • принят args
  • имя файла
  • стартовая строка
  • ID
  • приоритет

function list_hooks( $hook = '' ) {
    global $wp_filter;

    if ( isset( $wp_filter[$hook]->callbacks ) ) {      
        array_walk( $wp_filter[$hook]->callbacks, function( $callbacks, $priority ) use ( &$hooks ) {           
            foreach ( $callbacks as $id => $callback )
                $hooks[] = array_merge( [ 'id' => $id, 'priority' => $priority ], $callback );
        });         
    } else {
        return [];
    }

    foreach( $hooks as &$item ) {
        // skip if callback does not exist
        if ( !is_callable( $item['function'] ) ) continue;

        // function name as string or static class method eg. 'Foo::Bar'
        if ( is_string( $item['function'] ) ) {
            $ref = strpos( $item['function'], '::' ) ? new ReflectionClass( strstr( $item['function'], '::', true ) ) : new ReflectionFunction( $item['function'] );
            $item['file'] = $ref->getFileName();
            $item['line'] = get_class( $ref ) == 'ReflectionFunction' 
                ? $ref->getStartLine() 
                : $ref->getMethod( substr( $item['function'], strpos( $item['function'], '::' ) + 2 ) )->getStartLine();

        // array( object, method ), array( string object, method ), array( string object, string 'parent::method' )
        } elseif ( is_array( $item['function'] ) ) {

            $ref = new ReflectionClass( $item['function'][0] );

            // $item['function'][0] is a reference to existing object
            $item['function'] = array(
                is_object( $item['function'][0] ) ? get_class( $item['function'][0] ) : $item['function'][0],
                $item['function'][1]
            );
            $item['file'] = $ref->getFileName();
            $item['line'] = strpos( $item['function'][1], '::' )
                ? $ref->getParentClass()->getMethod( substr( $item['function'][1], strpos( $item['function'][1], '::' ) + 2 ) )->getStartLine()
                : $ref->getMethod( $item['function'][1] )->getStartLine();

        // closures
        } elseif ( is_callable( $item['function'] ) ) {     
            $ref = new ReflectionFunction( $item['function'] );         
            $item['function'] = get_class( $item['function'] );
            $item['file'] = $ref->getFileName();
            $item['line'] = $ref->getStartLine();

        }       
    }

    return $hooks;
}

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

print_r пример для фильтра the_content:

Array
(
    [0] => Array
        (
            [id] => 000000004c8a4a660000000011808a14run_shortcode
            [priority] => 8
            [function] => Array
                (
                    [0] => WP_Embed
                    [1] => run_shortcode
                )

            [accepted_args] => 1
            [file] => C:\xampp\htdocs\wordpress\wp-includes\class-wp-embed.php
            [line] => 58
        )

    [1] => Array
        (
            [id] => wptexturize
            [priority] => 10
            [function] => wptexturize
            [accepted_args] => 1
            [file] => C:\xampp\htdocs\wordpress\wp-includes\formatting.php
            [line] => 41
        )

    [2] => Array
        (
            [id] => 0000000006c5dc6d0000000064b1bc8e
            [priority] => 10
            [function] => Closure
            [accepted_args] => 1
            [file] => C:\xampp\htdocs\wordpress\wp-content\plugins\plugin\plugin.php
            [line] => 16
        )

    .....

Изменить: 2017-05-05

  • адаптирован для WP_Hook класса
  • добавленный приоритет
  • исправлено: ошибка возникает, если обратный вызов не существует, хотя WordPress также вызывает предупреждение для этого
  • fixed: hook с тем же идентификатором, но другой приоритет перезаписывает предыдущий
  • 4
    Потрясающий инструмент для отладки - хорошо сделано.
  • 0
    К вашему сведению - я пытался использовать это в своем плагине, но ему нужно немного больше ловить ошибки, поскольку он генерирует фатальную ошибку, если кто-то добавляет функцию / метод, который не существует: Fatal error: Uncaught exception 'ReflectionException' with message 'Function Walker_Nav_Menu() does not exist'
Показать ещё 4 комментария

Ещё вопросы

Сообщество Overcoder
Наверх
Меню