Filter the content of single blocks with WordPress

August 19, 2021 Posted by Editorial Staff

WordPress provides you two hooks to filter the content of the single blocks. Let’s see how to use them in this short article.

A brief introduction

Each time a post is displayed in the front-end, the render_block() function generates the HTML of the block starting from the block object.

This function include the following filters:

At the end of this function, the block object is parsed with the render() method of the class-wp-block.php class. Inside this method two filters are applied. The render_block and the render_block_{$this->name} filters.

These two filters are similar. The render_block filter hooks a function to all the blocks included in the post, while the render_block_{$this->name} filter hooks only the blocks of the specified type.

The render_block filter

This filter allows you to hook a function that modifies the content of a single block.

Example 1: Modify a block based on the value of a block attribute

You can use this filter to modify the blocks based on the value of specific block attributes.

In the example that follows, when the hideBlock custom block attribute is equal to “1” an empty string is returned instead of the block 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($block_content, $block)
{

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

        return '';

    } else {

        return $block_content;

    }

}

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

We used this technique while developing Restricted Blocks, a plugin that applies restrictions on specific blocks based on custom conditions. In this plugin, the user sets the type of restriction with a selector saved as a block attribute. The plugin then uses the render_block filter to read this block attribute and modify the block content accordingly.

Example 2: Modify only specific block types

In this second example, we will add an advertising element before each heading of the article. To identify the block type, we verify the value of the $block['blockName'] index.

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

    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 );

The render_block_{$this->name} filter

This dynamic filter allows you to hook a function that modifies the blocks of a specific type.

The name of this filter is composed of the fixed part “render_block_” followed by the variable part with the block name. (E.g. “core/paragraph”, “core/image”, “plugin-name/custom-block”, etc.)

It’s worth noting that this filter has been added in version WordPress 5.7. You can find additional details in this official announcement.

Example 1: Remove all the images from a post

In this example, we use the render_block_core/image hook to hide all the images included in the article.

More in detail, the hide_images() function, which always returns an empty string, is invoked with the blocks registered as “core/image”. As a consequence, the HTML of all the images will be removed from the article.

/**
 * 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($block_content, $block)
{

    return '';

}

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

Example 2: Collect the headings data

In this case, with the help of a regular expression, we collect the headings data in a global variable. The collected data can later be used to create an automatic table of contents or for other purposes.

The hook used to filter all the headings blocks is 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($block_content, $block)
{

    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);

Conclusions

I hope this tutorial helped with filtering the content of single blocks.

For more information on this subject, I recommend you to inspect the WordPress core, in particular, the following files:

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