WordPress / gutenberg

The Block Editor project for WordPress and beyond. Plugin is available from the official repository.
https://wordpress.org/gutenberg/
Other
10.3k stars 4.11k forks source link

Allow/deny block use based on post-type or template context #41062

Open boonebgorges opened 2 years ago

boonebgorges commented 2 years ago

What problem does this address?

It's sometimes desirable to limit blocks to certain post-type contexts (or, in a parallel fashion, to prevent a specific block from being used in a given context). As far as I can see, the current recommendation is to use unregisterBlockType() to unregister a given block based on getCurrentPostType(), etc. See eg #27607.

While the semantics of this technique are not entirely straightforward ("unregister" rather than "hide", or better still, "prevent from showing in this context"), it pretty much works in the post editor. However, it's not workable in the Site Editor. It's possible to fetch the currently edited template using wp.data.select( 'core/edit-site' ).getEditedPostId(), and to unregisterBlockType() based on this. But it's possible to switch the currently-edited template without a page reload, meaning that you'd have to re-registerBlockType(). Moreover, setting up a subscribe() callback for getEditedPostId() to determine the current context is pretty clumsy.

What is your proposed solution?

I propose that, as part of their registration metadata, a block can specify allow or deny contexts. Maybe something like:

allowForPostTypes: [ 'post', 'page', 'my_custom_post_type' ],
allowForTemplates: [ 'archive', 'single', 'page', 'archive-my_custom_post_type', 'single-my_custom_post_type' ],

postTypes would specify the contexts for the post editor, while templates would be for the site editor. Or it might be better to have a single declaration that covers both cases, depending on the overall strategy for merging the editing experience.

Similarly, it might be nice to have deny declarations that work similarly (though of course there are problems with allowing both).

Apologies in advance if this idea's already in circulation - I searched but couldn't find anything.

gigitux commented 2 years ago

For https://github.com/woocommerce/woocommerce-blocks/issues/5193 we are trying the solution with a subscribe callback. Maybe, could we try to contribute upstream to support these APIs? I guess that could be useful for other plugins too.

noisysocks commented 2 years ago

When designing the parent attribute in the block schema there was discussion about allowing you to specify post types as well as block types. I could see it working for templates too.

Regarding a deny list, there was a proposal about allowing you to pass an object to parent which lets you control which blocks are explicitly allowed, explicitly denied, and what the default is. Have a look at https://github.com/WordPress/gutenberg/issues/5540#issuecomment-386192518.

Maybe can revisit some of this 😀

gziolo commented 1 year ago

Regarding a deny list, there was a proposal about allowing you to pass an object to parent which lets you control which blocks are explicitly allowed, explicitly denied, and what the default is. Have a look at #5540 (comment).

Good point. I know about a similar discussion when ancestor field was in development: https://github.com/WordPress/gutenberg/issues/37181#issuecomment-1079194941. There are more thoughts on how parent and ancestor could intersect with more complex use cases. It could also get extended to deny list.

This issue is related to https://github.com/WordPress/gutenberg/issues/46900, which proposes adding a way to register a block only in a specific editor. In some cases, providing a post type would be equivalent to limiting access to the post editor, and providing a template would be equivalent to limiting access to the site/template editor.

gigitux commented 1 year ago

It would be very interesting to have this setting for the variations too. Regarding the variations, I created an issue about the support for the ancestor/parent https://github.com/WordPress/gutenberg/issues/48424

bph commented 8 months ago

@gigitux @boonebgorges What do you think about the approach to handling this on a post type level, as @mtias suggests in his comment.

We should probably discuss some default_blocks, allow_blocks, disallow_blocks properties in register_post_type instead. Consider post types already allow specifying a template property.

mikejolley commented 4 months ago

We have use cases where we need to limit the available blocks within a specific Block Template. allowed_block_types_all is not suitable because it only runs once in the site editor, and there is no context that changes based on the edited template.

Something like this could deregister blocks based on template, but then there is no good way to restore the block types once the user switches to another template or view.

``` wp_add_inline_script('wp-edit-site', " wp.domReady( () => { let currentTemplateId; wp.data.subscribe(function(){ const previousTemplateId = currentTemplateId; currentTemplateId = wp.data.select( 'core/edit-site' )?.getEditedPostId(); if ( previousTemplateId === currentTemplateId ) { return; } const allowedBlocks = [ 'core/heading', 'core/image', 'core/list', 'core/paragraph', ]; if ( currentTemplateId === 'mailpoet/mailpoet//email-general' ) { wp.blocks.getBlockTypes().forEach( function ( blockType ) { if ( allowedBlocks.indexOf( blockType.name ) === -1 ) { console.log(blockType.name); wp.blocks.unregisterBlockType( blockType.name ); } } ); } }); } ); ", 'before'); ```

Ideally we'd like some additional context passed to allowed_block_types_all which gives us the name of the edited template. And this would hopefully get ran every time the user switches views.

ndiego commented 1 month ago

Something like this could deregister blocks based on template, but then there is no good way to restore the block types once the user switches to another template or view.

Thanks for this additional context @mikejolley. Dynamically restricting blocks in the Site/Template Editor is definitely more complicated than the Post Editor and we currently lack the tools to do so.

Also, not sure why I removed the "Blocks Adoption" tag in the past 🤦‍♂️, but added it back.