Turning Off Reusable Blocks

Reusable blocks are great! But they can be a problem. Sadly there is no neat off button, but we can get very close.

Why remove them? On a shared site with user created content, reusable blocks could be modified and manipulated maliciously. It might also be a moderation concern, with users creating lewd content in reusable blocks that then appear in the UI.

Removing The Reusable Blocks Tab

Gutenberg adds a reusable blocks tab to the inserter that looks like this:

After some digging, it appears that this tab does not have an off switch or tooggle, but it only shows if there are reusable blocks to select. This is also true of block patterns.

The list of reusable blocks is stored in the block editors main settings object in the __experimentalReusableBlocks key. We can fool the editor into believing this is the case with this javascript snippet:

wp.data.dispatch('core/block-editor').updateSettings( { __experimentalReusableBlocks: [] } )

Now that there are no reusable blocks in the settings, the tab immediately disappears:

But what if a new reusable block is created? What if the editor makes a request to the API and discovers the truth? We can enforce the lie by subscribing to the main data store with this javascript:

// Erase the existence of any reusable blocks.
wp.data.subscribe( () => {
	const settings = wp.data.select( 'core/block-editor' ).getSettings();
	if ( settings.__experimentalReusableBlocks && settings.__experimentalReusableBlocks.length > 0 ) {
		wp.data.dispatch('core/block-editor').updateSettings( { __experimentalReusableBlocks: [] } );
	}
});

By using subscribe our function is called whenever the data store is changed. We then fetch the settings, check for reusable blocks, and reset it if needed. Without the if statement, our dispatch would cause an infinite loop ( I realise in hindsight it might not be necessary to check the length as WP will only notify listeners if the store values change ).

What About Adding Reusable Blocks?

I spent some time trying to figure this out. Capabilities for reusable blocks ( wp_block are set to those of the post so they can’t be filtered specifically, and the meta capabilities have unique handling of block capabilities that replace them with post equivalents. I even considered filtering post insertion to prevent their creation, but this would still leave the Add to reusable blocks user interface that can’t be hidden with CSS:

Thankfully, when registering a block, you can declare that it does or does not support various features, e.g. HTML editing, can it have multiple instances, does it support full width, etc. One of these is if the block can be made reusable or not.

To exploit this, I added a filter to block registration, and forced all blocks to be non-re-usable:

/**
 * Remove supported features from all blocks
 *
 * @param {*} settings
 * @param {*} name
 */
function filterBlockSupports( settings, name ) {
	// ensure there is a supports section
	if ( undefined == settings.supports ) {
		settings.supports = {}
	}
	settings.supports.reusable = false;
	return settings;
}
wp.hooks.addFilter( 'blocks.registerBlockType', 'tomjn/disable-reusability', filterBlockSupports );

The Last Traces of UI

There is one last location for the reusable blocks UI in the main menu in the top right:

While this anchor tag doesn’t have a CSS selector, it does lead to an admin page, and we can select the href attribute to hide it:

.components-menu-item__button[href="edit.php?post_type=wp_block"] {
    display: none;
}

With this, all traces are removed. Currently no keyboard shortcuts are listed for creating reusable blocks, but reusable blocks already in content will need to be removed, and can be copy pasted into place.

Putting it All Together

If we put this all together, we get this plugin:

<?php
/**
 * Plugin Name:       Disable Reusable blocks
 * Plugin URI:        https://tomjn.com/2021/04/05/turning-off-reusable-blocks/(opens in a new tab)
 * Description:       Hides the reusable blocks interface in the block editor
 * Author:            Tom J Nowell
 * Author URI:        https://tomjn.com
 * License:           GPLv2
 * Version:           1.0
 * Requires at least: 5.2
 * Requires PHP:      7.2
 */

/**
 * Disable reusable blocks.
 *
 * @return void
 */
function tomjn_disable_reusable_blocks() : void {
	$js = <<<JSCODE
wp.domReady( function() {
	wp.data.dispatch('core/block-editor').updateSettings( { __experimentalReusableBlocks: [] } );
	wp.data.subscribe( () => {
		const settings = wp.data.select( 'core/block-editor' ).getSettings();
		if ( settings.__experimentalReusableBlocks && settings.__experimentalReusableBlocks.length > 0 ) {
			wp.data.dispatch('core/block-editor').updateSettings( { __experimentalReusableBlocks: [] } );
		}
	});
	/**
	* Remove supported features from all blocks
	*
	* @param {*} settings
	* @param {*} name
	*/
	function filterBlockSupports( settings, name ) {
		// ensure there is a supports section
		if ( undefined == settings.supports ) {
			settings.supports = {}
		}
		settings.supports.reusable = false;
		return settings;
	}
	wp.hooks.addFilter( 'blocks.registerBlockType', 'tomjn/disable-reusability', filterBlockSupports );
} );
JSCODE;
	$css = <<<CSSCODE
.components-menu-item__button[href="edit.php?post_type=wp_block"] {
    display: none;
}
CSSCODE;
	wp_add_inline_script(
		'wp-block-editor',
		$js
	);
	wp_add_inline_style(
		'wp-block-editor',
		$css
	);
}
add_action( 'enqueue_block_editor_assets', 'tomjn_disable_reusable_blocks' );

Now that you’ve removed reusable blocks, why not remove the block directory install prompts too?

One thought on “Turning Off Reusable Blocks

  1. Pingback: WP Weekly 40 / Noise / Headphones, Speed Focus, Celebrity WP Websites

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.