WordPress.org

Make WordPress Core

Opened 5 months ago

Last modified 6 weeks ago

#47637 new defect (bug)

Enhance excerpt_remove_blocks to handle more types of group blocks

Reported by: kuchenundkakao Owned by:
Milestone: Future Release Priority: normal
Severity: normal Version: 5.2.2
Component: Posts, Post Types Keywords: needs-patch
Focuses: Cc:
PR Number:

Description

The function excerpt_remove_blocks only considers top-level Blocks in an allowed list for the autogeneration of excerpts. However, since there is now a Group Block in Core (and a lot of self-developed Grouping Blocks out there), this can lead to autogenerated Excerpts being empty although there is plenty of content within the Post.

I propose to add a new filterable "group blocks" array, which adds another level to be included in the autogeneration. Additionally, there should be a possibility to register a callback which can be used to generate a custom excerpt dynamically if needed for custom blocks.

Change function excerpt_remove_blocks to this:

function excerpt_remove_blocks($content){
    $allowed_inner_blocks = array(
        // Classic blocks have their blockName set to null.
        null,
        'core/freeform',
        'core/heading',
        'core/html',
        'core/list',
        'core/media-text',
        'core/paragraph',
        'core/preformatted',
        'core/pullquote',
        'core/quote',
        'core/table',
        'core/verse',
    );
	$group_block_excerpt_functions = array(
		'core/group' => 'parse_group_block_excerpt',
	);
    $allowed_blocks = array_merge( $allowed_inner_blocks, array( 'core/columns' ) );
    /**
     * Filters the list of blocks that can contribute to the excerpt.
     *
     * If a dynamic block is added to this list, it must not generate another
     * excerpt, as this will cause an infinite loop to occur.
     *
     * @since 4.4.0
     *
     * @param array $allowed_blocks The list of allowed blocks.
     */
    $allowed_blocks = apply_filters( 'excerpt_allowed_blocks', $allowed_blocks );
    $group_blocks   = apply_filters('excerpt_allowed_group_blocks',$group_block_excerpt_functions);
    $blocks         = parse_blocks( $content );
    $output         = '';
    foreach ( $blocks as $block ) {
		if(in_array($block['blockName'],$group_blocks,true)){
			//We have a group Block with no extra excerpt function
			$output.= parse_group_block_excerpt($block,$allowed_inner_blocks);
		} elseif(in_array($block['blockName'],array_keys($group_blocks),true)){
			//The Block registered a custom callback for autogenerating an Excerpt
			$output.=call_user_func($group_blocks[$block['blockName']],$block,$allowed_inner_blocks);
		} elseif( in_array( $block['blockName'], $allowed_blocks, true ) ) {
            if ( ! empty( $block['innerBlocks'] ) ) {
                if ( 'core/columns' === $block['blockName'] ) {
                    $output .= _excerpt_render_inner_columns_blocks( $block, $allowed_inner_blocks );
                    continue;
                }
                // Skip the block if it has disallowed or nested inner blocks.
                foreach ( $block['innerBlocks'] as $inner_block ) {
                    if (
                        ! in_array( $inner_block['blockName'], $allowed_inner_blocks, true ) ||
                        ! empty( $inner_block['innerBlocks'] )
                    ) {
                        continue 2;
                    }
                }
            }
            $output .= render_block( $block );
        }
    }
    return $output;
}

Add a function parse_group_block_excerpt

function parse_group_block_excerpt($block,$allowed_blocks){
	$output = "";
	if(!empty($block['innerBlocks'])) {
		foreach($block['innerBlocks'] as $inner_block){
			if('core/columns' === $inner_block['blockName']){
				$output .= _excerpt_render_inner_columns_blocks( $inner_block, $allowed_inner_blocks );
				continue;
			}
			// Skip the block if it has disallowed or nested inner blocks.
			foreach($inner_block['innerBlocks'] as $inner_inner_block){
				if (
					! in_array( $inner_inner_block['blockName'], $allowed_inner_blocks, true ) ||
					! empty( $inner_inner_block['innerBlocks'] )
				){
					continue 2;
				}
			}
		}
	}
	return $output;
}

After that, a custom block can register itself as an group block just by using


add_filter('excerpt_allowed_group_blocks','add_my_awesome_group_block_to_excerpt');
 
function add_my_awesome_group_block_to_excerpt($allowed_blocks=array()){
   $allowed_blocks[] = 'my-awesome/groupblock';
   return $allowed_blocks;
 }

or even by using a custom excerpt function for dynamic blocks by using

add_filter('excerpt_allowed_group_blocks','add_my_awesome_group_block_to_excerpt');
 
function add_my_awesome_group_block_to_excerpt($allowed_blocks=array()){
   $allowed_blocks['my-awesome/groupblock'] = 'my_awesome_group_block_custom_excerpt';
   return $allowed_blocks;
 }

(I hope i did this right as this is my first ticket)

Change History (4)

#1 @noisysocks
4 months ago

  • Keywords needs-patch added; 2nd-opinion removed
  • Milestone changed from Awaiting Review to Future Release
  • Summary changed from Enhance excerpt_remove_blocks: add group Blocks and give Block Developers the ability to define excerpts for their Blocks to Enhance excerpt_remove_blocks to handle more types of group blocks

See #46133 for necessary context here. @azaozz wrote a patch that has an exception for columns blocks, but this solution needs to be expanded to cover all core and non-core group blocks. This is especially important now that Gutenberg is adding different kinds of group blocks e.g. Group, Cover, Media & Text.

Yeah, thinking we will need to keep enhancing the way we auto-generate excerpts for posts and include all blocks that may have relevant text.

The challenge is that we only want "static text" and need to exclude dynamic blocks as they may cause infinite loop if trying to generate an excerpt, and in most cases they are not particularly relevant to the rest of the post.

Ideally we should parse all "text containing blocks" regardless if they are wrapped in "container" blocks. The current patch only looks one level deep in all whitelisted blocks, and has an exception for core/columns where it looks inside each column. This can be enhanced and perhaps can be done better. Planning to look at it again for 5.3.

#2 @noisysocks
4 months ago

#47602 was marked as a duplicate.

This ticket was mentioned in Slack in #core-editor by talldanwp. View the logs.


3 months ago

#4 @eherman24
6 weeks ago

It would be nice if there were a filter added to allow other blocks, beyond the core/columns block, to output excerpts. Some further discussion was going on in our CoBlocks Github repo https://github.com/godaddy/coblocks/issues/735

Adding a filter in wp-includes/blocks.php line 163 https://github.com/WordPress/WordPress/blob/master/wp-includes/blocks.php#L163 would be beneficial to allowing additional blocks to be run through _excerpt_render_inner_columns_blocks().

Note: See TracTickets for help on using tickets.