4

I've made a Gutenberg block which is only appropriate to show on hierarchical post types, so I want to disable it from the block inserter for non-hierarchical post types.

I thought about how to achieve this in PHP, but the WordPress documentation on registering blocks seems to suggest that blocks should be registered in PHP on the init hook and not a later hook where you could check if the post being edited is hierarchical. At the time the init hook fires, the currently viewed post is not yet available via e.g. get_post(), so I can't check its post_type.

I also thought about how to achieve this in the (JavaScript) script that I register with the editor_script property passed to register_block_type, but I don't know how to check the post type being edited to make it possible to halt the block registration in the case of non-hierarchical post types. It also seems a bit silly to enqueue and run the block script only for the script to decide that it shouldn't do anything, so ideally I would like to implement this checking in PHP.

Is there some standard way to make a block available only for specific post types, ideally in PHP?

4 Answers 4

7

You can use the allowed_block_types hook:

<?php
function wpse_allowed_block_types($allowed_block_types, $post) {
    // Limit blocks in 'post' post type
    if($post->post_type == 'post') {
        // Return an array containing the allowed block types
        return array(
            'core/paragraph',
            'core/heading'
        );
    }
    // Limit blocks in 'page' post type
    elseif($post->post_type == 'page') {
        return array(
            'core/list'
        );
    }
    // Allow defaults in all other post types
    else {
        return $allowed_block_types;
    }
}
add_filter('allowed_block_types', 'wpse_allowed_block_types', 10, 2);
?>

Tweak with as many or as few conditions as you need. You can also enable non-Core blocks by identifying their namespace and name and putting those in the array.

4
  • Thank you, but is there a way though to explicitly disallow a block, instead of having to provide a whitelist? As far as I understand this filter provides true by default, i.e. all blocks, instead of an actual list of block names which I could remove mine from. I'd rather not have to update my plugin every time a new core block is added, or remove other plugins' blocks by not adding them to my whitelist this sort of function.
    – Sean
    Commented Oct 3, 2019 at 16:43
  • 1
    As of January there was not yet a way to blacklist. See related wordpress.stackexchange.com/questions/326959/…
    – WebElaine
    Commented Oct 3, 2019 at 17:15
  • 1
    Thanks. That's unfortunate. I hope the developers add some whitelist mechanism in the future.
    – Sean
    Commented Oct 4, 2019 at 7:25
  • Thank you for this. EXACTLY what I was looking for & totally nailed my use-case.
    – indextwo
    Commented Sep 11, 2020 at 19:16
1

I know this is an older post, but I was trying to do something similar. I have created a post type, and rather than use custom meta boxes to add/save post meta, I'm using blocks. Given the purpose of such a block, it should really only show for the relevant post type.

I found the following works. You can use the unregisterBlockType() function to unregister your block for any post types that are not your own.

There are two steps.

  1. Enqueue a JS file when not on your post type.
function my_function() {
    if ( get_post_type() != 'my-post-type' ) {
        wp_enqueue_script(
            'my-script',
            'path/to/js/my-script.js',
            array( 'original-block-js' ),
            '1.0.0',
            true
        );
    }
}
add_action( 'admin_enqueue_scripts', 'my_function' );

Note 'original-block-js' as a dependency. This refers to the JS file that's registering your block in the first place. We are ensuring the code to unregister the block is loaded after the code that registers it.

  1. Add the following to your JS file.
const { unregisterBlockType } = wp.blocks;

wp.domReady( function() {
    unregisterBlockType( 'my-name-space/block-name' );
} );

Replace my-name-space/block-name with your block name.

UPDATE

The original poster wanted to hide the block on any non-hierarchical post types. That's a slightly different use case. But you can get there by just adjusting the conditional with is_post_type_hierarchical().

1

To disable specific blocks, you can use the allowed_block_types_all hooks. Follow the approach below and make sure to replace the post type name for your needs.

<?php
function disable_specific_blocks( $allowed_block_types, $post ) {
    // An array of block names to disable
    $disabled_blocks = array(
        'core/table',
        'core/image',
        'core/gallery',
    );
  
    // Use this condition to disable blocks on certain post types, otherwise you can remove this IF condition
    if ( $post->post_type === 'post' ) {
        $allowed_block_types = array_diff( $allowed_block_types, $disabled_blocks );
    }

    return $allowed_block_types;
}
add_filter( 'allowed_block_types_all', 'disable_specific_blocks', 10, 2 );
?>

For complete guide, you can follow this tutorial on how to disable specific blocks on the WordPress block editor.

1
0

If you need to whitelist the blocks that you want to use on your post you can use this method from the WordPress handbook https://developer.wordpress.org/block-editor/developers/filters/block-filters/#using-a-whitelist

// my-plugin.js
var allowedBlocks = [
    'core/paragraph',
    'core/image',
    'core/html',
    'core/freeform'
];

wp.blocks.getBlockTypes().forEach( function( blockType ) {
    if ( allowedBlocks.indexOf( blockType.name ) === -1 ) {
        wp.blocks.unregisterBlockType( blockType.name );
    }
} );

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.