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/