Как отфильтровать контент блока в WordPress

WordPress предоставляет два хука для фильтрации содержимого отдельных блоков. Рассмотрим, как их использовать, в этой небольшой статье.

Краткое введение

Каждый раз, когда запись отображается во фронтенде, функция render_block() генерирует HTML блока, начиная с объекта block.

Данная функция включает в себя следующие фильтры:

В конце этой функции объект блока парсится с помощью метода render() класса class-wp-block.php. Внутри этого метода применяются два фильтра. Это фильтры render_block и render_block_{$this->name}.

Эти два фильтра похожи друг на друга. Фильтр render_block подключает функцию ко всем блокам, входящим в запись, а фильтр render_block_{$this->name} подключает только блоки указанного типа.

Фильтр render_block

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

Пример 1: Модификация блока на основе значения атрибута блока

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

В приведенном ниже примере, когда атрибут hideBlock произвольного блока равен 1, вместо HTML блока возвращается пустая строка.

/**
 * When the "hideBlock" custom block attribute is equal to "1" an empty string is returned.
 *
 * @param $block_content
 * @param $block
 * @return string
 */
function hide_selected_blocks( string $block_content, array $block ): string {

    if ( isset($block['attrs']['hideBlock']) and $block['attrs']['hideBlock'] === 1 ) {

        return '';

    } else {

        return $block_content;

    }

}

add_filter( 'render_block', 'hide_selected_blocks', 10, 2 );

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

Пример 2: Изменение только определенных типов блоков

Во втором примере мы добавим рекламный блок перед каждым заголовком статьи. Чтобы определить тип блока, мы проверяем значение $block['blockName'].

/**
 * An ad is applied before the blocks of type "core/heading".
 *
 * @param $block_content
 * @param $block
 * @return mixed|string
 */
function include_ad_before_heading( string $block_content, array $block ): string {

    if ( $block['blockName'] === 'core/heading' ) {

        return '<div class="my-ad"></div>' . $block_content;

    } else {

        return $block_content;

    }

}

add_filter( 'render_block', 'include_ad_before_heading', 10, 2 );

Фильтр render_block_{$this->name}

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

Имя этого фильтра состоит из фиксированной части render_block_, за которой следует переменная часть с именем блока. Например, core/paragraph, core/image, plugin-name/custom-block и т.д.

Стоит отметить, что данный фильтр был добавлен ещё в версии WordPress 5.7. Дополнительные подробности можно найти в официальном сообщении.

Пример 1: Удаление всех изображений из записи

В данном примере мы используем хук render_block_core/image для скрытия всех изображений, входящих в статью.

Для всех блоков, зарегистрированных как core/image, вызывается функция hide_images(), которая всегда возвращает пустую строку. Как следствие, HTML всех изображений будет удален из записи.

/**
 * This function runs only with blocks of type "core/image" and returns an empty string.
 *
 * @param $block_content
 * @param $block
 * @return string
 */
function hide_images( string $block_content, array $block ): string {
    return '';
}

add_filter( 'render_block_core/image', 'hide_images', 10, 2 );

Пример 2: Сбор данных о всех заголовках

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

Для фильтрации всех блоков с заголовками используется хук render_block_core/heading.

/**
 * This function runs only with blocks of type "core/heading". The headings data are collected in the $headings_data
 * array.
 *
 * Note that the function always returns a string with the original block content.
 *
 * @param $block_content
 * @param $block
 * @return string
 */
function collect_headings_data( string $block_content, block $block ): string {

    global $headings_data;
    $matches = [];

    preg_match( '/<(h[1-6]{1}).*id="(.+)".*>(.*?)</h[1-6]{1}>/', $block['innerHTML'], $matches );

    if (count($matches) === 4 ) {
        $headings_data[] = [
            'tag' => $matches[1],
            'anchor' => $matches[2],
            'text' => $matches[3]
        ];
    }

    return $block_content;

}

add_filter( 'render_block_core/heading', 'collect_headings_data', 10, 2 );

Выводы

Надеюсь, этот урок помог вам в фильтрации содержимого отдельных блоков.

Для получения более подробной информации по этому вопросу я рекомендую ознакомиться с ядром WordPress, в частности, со следующими файлами:

  • wp-includes/class-wp-block.php
  • wp-includes/blocks.php

Источник: Filter the content of single blocks with WordPress

Источник: https://www.kobzarev.com/gutenberg/filter-the-content-of-single-blocks-with-wordpress/

Михаил Кобзарёв

Суровый русский тимлид. Жил в Магадане, в офисе московских веб студий и в Тульской деревне. Виртуозно знает WordPress, PHP, ООП, Vue.js и вот это вот все. Делает крутые высоконагруженные сайты, поэтому уже почти захватил весь рынок WordPress разработки в России. Не дает никому делать сайты без спроса. Ведет блог о разработке, дайджест в телеграмме и в ВК. Любит сиськи, баню и радиоэлектронику. 100% патриот (но это не точно). Тролль 542 уровня. Ездит в отпуск раз в 5 лет.

Добавить комментарий

%d такие блоггеры, как: