Conditionally Registering Patterns in Themes with Third-Party Blocks

What happens when a theme registers a pattern with a third-party block? If the user has the block plugin installed, it appears as it should. WordPress also does a good job at handling the flipside of this scenario: the user does not have the block installed.

When users attempt to use such a pattern in the editor, they will see an error like the following for self-closing blocks:

Your site doesn’t include support for the “pluginslug/test” block. You can leave this block intact or remove it entirely.

If the block encompasses some HTML, the user will see a different message sitting above the HTML output:

Your site doesn’t include support for the “pluginslug/test” block. You can leave this block intact, convert its content to a Custom HTML block, or remove it entirely.

On the front end, self-closing blocks are simply not shown. However, if the block has HTML, its output will appear. This system is better than something like a fatal PHP error on the front end. However, it is often not ideal.

Last week, WordPress.org began showing pattern previews in the theme directory, as shown in the following screenshot from the Bright Mode theme page:

WordPress directory theme page that shows a three-column grid of pattern previews with bright colors.

This change is a huge win in showing off a theme’s design. In the past, users could not see the patterns without manually installing and testing.

However, it brought back that original question about dealing with third-party blocks in patterns. WordPress.org’s preview system does not have these blocks installed, so it has no way of showing them. There is currently an open Meta ticket to address this issue, and the ideal solution would be for the theme directory to simply not attempt to preview patterns for unsupported blocks.

Regardless of how things are handled in the theme directory, WordPress theme authors have control over whether their patterns appear. Plus, it is generally good practice to not clutter the UI with patterns that do not work.

The easiest way to disable a pattern, keeping it from showing in the UI, is by checking if a particular plugin is active. All you need to know is a function or class name from the plugin.

Themes can register patterns either via the register_block_pattern() function or by placing headered files into the /patterns subfolder. I will cover each scenario in this tutorial. Then, I will offer a couple of alternative solutions that may work, depending on the scenario.

When Registered via register_block_pattern()

If registering a pattern via the register_block_pattern() function, you should only need to check if a plugin is active before calling the function. The simplest way to do this is to conditionally check for the plugin via function_exists() or class_exists().

add_action( 'init', function() {
    if ( function_exists( 'pluginslug_some_function' ) ) {
        register_block_pattern( 'themeslug/pattern-abc' );
    }
} );Code language: PHP (php)

This method is no different from classic PHP-based themes when calling a function or class from a third-party plugin.

When Registered via the /patterns Folder

Patterns housed in the /patterns folder are auto-registered by WordPress on the init action hook. There is currently no filter to short-circuit this process. This method requires unregistering the pattern instead.

Once again, you must conditionally check if a function or class exists. If not, unregister the pattern:

add_action( 'init', function() {
    if ( ! function_exists( 'pluginslug_some_function' ) ) {
        unregister_block_pattern( 'themeslug/pattern-abc' );
    }
} );Code language: PHP (php)

An Alternative: Conditionally Adding Blocks to Patterns

It is possible to register a pattern while conditionally supporting a particular block. For example, suppose your theme supports a contact form block named pluginslug/contact that you want to display in a “Contact” pattern. Further suppose that the contact form only makes up one section of the pattern but isn’t necessarily a requirement for the layout to work.

This method allows all users to make use of the pattern but does not require the third-party block to be installed. It will simply not be a part of the pattern if the user doesn’t have it.

Since we have access to PHP when building patterns, we can do the same conditional check within the pattern itself. The following is an example of a such a pattern:

<?php
/*
 * Title: Contact
 * Slug: themeslug/contact
 */
?>
<!-- some core WordPress blocks -->

<?php if ( function_exists( 'pluginslug_some_function' ) ) : ?>
	<!-- wp:pluginslug/contact /-->
<?php endif ?>

<!-- some other core WordPress blocks -->Code language: PHP (php)

This method can grow complex quickly for themes that require multiple third-party blocks in a pattern or need to perform checks in dozens of pattern files. It is more suited to simple or one-off uses. Otherwise, it may become a management headache.

Alternative to function/class_exists()

It is also possible to check if a specific block is registered instead of relying on a plugin function/class name. However, this only works if the block is registered on the server-side.

WordPress does not have a dedicated is_block_type() or is_registered_block_type() helper function, but the WP_Block_Type_Registry class does have a public is_registered() method that you can use to check if a block exists:

if ( WP_Block_Type_Registry::get_instance()->is_registered( 'pluginslug/test' ) ) {
    register_block_pattern( 'themeslug/pattern-abc' );
}Code language: PHP (php)

1 Comment

I have used more alternative way to conditionally include WooCommerce Featured Product category block with if ( defined( 'WC_PLUGIN_FILE' ) ) (no ‘class_exists’ or ‘function_exists’ …