wpengine / wp-graphql-content-blocks

Plugin that extends WPGraphQL to support querying (Gutenberg) Blocks as data
https://faustjs.org/docs/gutenberg/wp-graphql-content-blocks
GNU General Public License v2.0
112 stars 14 forks source link

Allow get_block_context_interfaces to be filtered #147

Closed jasonbahl closed 1 year ago

jasonbahl commented 1 year ago

Problem

I'm using ACF PRO and ACF Extended PRO to create Block Types.

ACF Extended allows Block Types to be limited to specific post types.

i.e.:

CleanShot 2023-08-17 at 13 01 44

Under the hood, this translates to blocks being registered with a post_types property.

This is not a property of block registration that WordPress core respects (at least not yet 🤷🏻‍♂️ ).

ACF Extended uses this post_types property to limit the inclusion of the block in the editor interface, but WPGraphQL Content Blocks is applying the ${PostType}EditorBlock to blocks registered by ACF Extended.

For example, even though I've limited my block to 1 post type (see screenshot above), we can see that it has interfaces applied for all the post types:

CleanShot 2023-08-17 at 14 19 16

These interfaces are applied here: https://github.com/wpengine/wp-graphql-content-blocks/blob/main/includes/Registry/Registry.php#L87-L129

Proposal

We should add a filter that allows for external code to determine whether any given ${PostType}EditorBlock interface should not be implemented on a block.

Something like:

/**
 * Filter before applying per-post_type Interfaces to blocks. This allows 3rd parties to control
 * whether the interface(s) should or should not be applied based on custom logic.
 *
 * @param bool $should                                          Whether to apply the ${PostType}EditorBlock Interface. If the filter returns false, the default
 *                                                              logic will not execute and the ${PostType}EditorBlock will not be applied.
 * @param string.                                               The name of the block Interfaces will be applied to
 * @param \WP_Block_Editor_Context                              The context of the Block Editor
 * @param \WP_Post_Type $post_type                              The Post Type an Interface might be applied to the block for
 * @param array         $all_registered_blocks                  Array of all registered blocks
 * @param array         $supported_blocks_for_post_type_context Array of all supported blocks for the context
 * @param array         $block_and_graphql_enabled_post_types   Array of Post Types that have block editor and GraphQL support
 */
$should_apply_post_type_editor_block_interface = apply_filters( 'wpgraphql_content_blocks_should_apply_post_type_editor_blocks_interfaces', true, $block_name, $block_editor_context, $post_type, $all_registered_blocks, $supported_blocks_for_post_type_context, $block_and_graphql_enabled_post_types );

if ( true !== $should_apply_post_type_editor_block_interface ) {
  continue;
}

This would allow 3rd party code, such as ACF Extended (or WPGraphQL for ACF) to filter here and add support for respecting the "post_types" property of blocks.

A 3rd party codebase could filter like so:

add_filter( 'wpgraphql_content_blocks_should_apply_post_type_editor_blocks_interfaces', function( $should, $block_name, $block_editor_context, $post_type, $all_registered_blocks, $supported_blocks_for_post_type_context, $block_and_graphql_enabled_post_types ) {
    if ( ! empty( $all_registered_blocks[ $block_name ]->post_types ) && ! in_array( $post_type->name, $all_registered_blocks[ $block_name ]->post_types, true ) ) {
        return false;
    }
    return $should;
}, 10, 7 );

Thus resulting in the Block, limited to a singular post type, having only that Post Type's EditorBlock Interface implemented:

CleanShot 2023-08-17 at 14 31 29

jasonbahl commented 1 year ago

related #120