Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Block Hooks: Allow passing block definitions to hooked_block_types filter (and thus, hooking patterns) #5837

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
123 changes: 60 additions & 63 deletions src/wp-includes/blocks.php
Original file line number Diff line number Diff line change
Expand Up @@ -758,9 +758,9 @@ function get_hooked_blocks() {
}

/**
* Conditionally returns the markup for a given hooked block type.
* Conditionally returns the markup for a given hooked block.
*
* Accepts two arguments: A reference to an anchor block, and the name of a hooked block type.
* Accepts two arguments: A hooked block, and a reference to an anchor block.
* If the anchor block has already been processed, and the given hooked block type is in the list
* of ignored hooked blocks, an empty string is returned.
*
Expand All @@ -769,15 +769,16 @@ function get_hooked_blocks() {
* @since 6.5.0
* @access private
*
* @param array $anchor_block The anchor block. Passed by reference.
* @param string $hooked_block_type The name of the hooked block type.
* @return string The markup for the given hooked block type, or an empty string if the block is ignored.
* @param array $hooked_block The hooked block, represented as a parsed block array.
* @param array $anchor_block The anchor block. Passed by reference.
* @return string The markup for the given hooked block, or an empty string if the block is ignored.
*/
function get_hooked_block_markup( &$anchor_block, $hooked_block_type ) {
function get_hooked_block_markup( $hooked_block, &$anchor_block ) {
if ( ! isset( $anchor_block['attrs']['metadata']['ignoredHookedBlocks'] ) ) {
$anchor_block['attrs']['metadata']['ignoredHookedBlocks'] = array();
}

$hooked_block_type = $hooked_block['blockName'];
if ( in_array( $hooked_block_type, $anchor_block['attrs']['metadata']['ignoredHookedBlocks'] ) ) {
return '';
}
Expand All @@ -786,7 +787,55 @@ function get_hooked_block_markup( &$anchor_block, $hooked_block_type ) {
// However, its presence does not affect the frontend.
$anchor_block['attrs']['metadata']['ignoredHookedBlocks'][] = $hooked_block_type;

return get_comment_delimited_block_content( $hooked_block_type, array(), '' );
return get_comment_delimited_block_content( $hooked_block_type, $hooked_block['attrs'], '' );
}

/**
* Returns the markup for blocks hooked to the given anchor block in a specific relative position.
*
* @since 6.5.0
*
* @param array $anchor_block The anchor block.
* @param string $relative_position The relative position of the hooked blocks.
* Can be one of 'before', 'after', 'first_child', or 'last_child'.
* @param array $hooked_blocks An array of blocks hooked to the given anchor block.
* @param WP_Block_Template|array $context The block template, template part, or pattern that the anchor block belongs to.
* @return string
*/
function insert_hooked_blocks( &$anchor_block, $relative_position, $hooked_blocks, $context ) {
$anchor_block_type = $anchor_block['blockName'];
$hooked_block_types = isset( $hooked_blocks[ $anchor_block_type ][ $relative_position ] )
? $hooked_blocks[ $anchor_block_type ][ $relative_position ]
: array();

/**
* Filters the list of hooked block types for a given anchor block type and relative position.
*
* @since 6.4.0
*
* @param string[] $hooked_block_types The list of hooked block types.
* @param string $relative_position The relative position of the hooked blocks.
* Can be one of 'before', 'after', 'first_child', or 'last_child'.
* @param string $anchor_block_type The anchor block type.
* @param WP_Block_Template|array $context The block template, template part, or pattern that the anchor block belongs to.
*/
$hooked_block_types = apply_filters( 'hooked_block_types', $hooked_block_types, $relative_position, $anchor_block_type, $context );
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@gziolo had another suggestion:

Suggested change
$hooked_block_types = apply_filters( 'hooked_block_types', $hooked_block_types, $relative_position, $anchor_block_type, $context );
$hooked_block_types = apply_filters( "hooked_blocks_{$anchor_block_type}", $hooked_blocks, $relative_position, $anchor_block, $context );

or even

Suggested change
$hooked_block_types = apply_filters( 'hooked_block_types', $hooked_block_types, $relative_position, $anchor_block_type, $context );
$hooked_block_types = apply_filters( "hooked_blocks_{$relative_position}_{$anchor_block_type}", $hooked_blocks, $anchor_block, $context );

which would allow a syntax like

add_filter( 'hooked_blocks_before_ockham/like-button', ... );


$markup = '';
foreach ( $hooked_block_types as $hooked_block_type ) {
if ( is_array( $hooked_block_type ) && isset( $hooked_block_type['blockName'] ) && isset( $hooked_block_type['attrs'] ) ) {
$hooked_block = $hooked_block_type;
} else {
$hooked_block = array(
'blockName' => $hooked_block_type,
'attrs' => array(),
);
}

$markup .= get_hooked_block_markup( $hooked_block, $anchor_block );
}

return $markup;
}

/**
Expand Down Expand Up @@ -826,40 +875,10 @@ function make_before_block_visitor( $hooked_blocks, $context ) {

if ( $parent_block && ! $prev ) {
// Candidate for first-child insertion.
$relative_position = 'first_child';
$anchor_block_type = $parent_block['blockName'];
$hooked_block_types = isset( $hooked_blocks[ $anchor_block_type ][ $relative_position ] )
? $hooked_blocks[ $anchor_block_type ][ $relative_position ]
: array();

/**
* Filters the list of hooked block types for a given anchor block type and relative position.
*
* @since 6.4.0
*
* @param string[] $hooked_block_types The list of hooked block types.
* @param string $relative_position The relative position of the hooked blocks.
* Can be one of 'before', 'after', 'first_child', or 'last_child'.
* @param string $anchor_block_type The anchor block type.
* @param WP_Block_Template|array $context The block template, template part, or pattern that the anchor block belongs to.
*/
$hooked_block_types = apply_filters( 'hooked_block_types', $hooked_block_types, $relative_position, $anchor_block_type, $context );
foreach ( $hooked_block_types as $hooked_block_type ) {
$markup .= get_hooked_block_markup( $parent_block, $hooked_block_type );
}
$markup .= insert_hooked_blocks( $parent_block, 'first_child', $hooked_blocks, $context );
}

$relative_position = 'before';
$anchor_block_type = $block['blockName'];
$hooked_block_types = isset( $hooked_blocks[ $anchor_block_type ][ $relative_position ] )
? $hooked_blocks[ $anchor_block_type ][ $relative_position ]
: array();

/** This filter is documented in wp-includes/blocks.php */
$hooked_block_types = apply_filters( 'hooked_block_types', $hooked_block_types, $relative_position, $anchor_block_type, $context );
foreach ( $hooked_block_types as $hooked_block_type ) {
$markup .= get_hooked_block_markup( $block, $hooked_block_type );
}
$markup .= insert_hooked_blocks( $block, 'before', $hooked_blocks, $context );

return $markup;
};
Expand Down Expand Up @@ -895,33 +914,11 @@ function make_after_block_visitor( $hooked_blocks, $context ) {
* @return string The serialized markup for the given block, with the markup for any hooked blocks appended to it.
*/
return function ( &$block, &$parent_block = null, $next = null ) use ( $hooked_blocks, $context ) {
$markup = '';

$relative_position = 'after';
$anchor_block_type = $block['blockName'];
$hooked_block_types = isset( $hooked_blocks[ $anchor_block_type ][ $relative_position ] )
? $hooked_blocks[ $anchor_block_type ][ $relative_position ]
: array();

/** This filter is documented in wp-includes/blocks.php */
$hooked_block_types = apply_filters( 'hooked_block_types', $hooked_block_types, $relative_position, $anchor_block_type, $context );
foreach ( $hooked_block_types as $hooked_block_type ) {
$markup .= get_hooked_block_markup( $block, $hooked_block_type );
}
$markup = insert_hooked_blocks( $block, 'after', $hooked_blocks, $context );

if ( $parent_block && ! $next ) {
// Candidate for last-child insertion.
$relative_position = 'last_child';
$anchor_block_type = $parent_block['blockName'];
$hooked_block_types = isset( $hooked_blocks[ $anchor_block_type ][ $relative_position ] )
? $hooked_blocks[ $anchor_block_type ][ $relative_position ]
: array();

/** This filter is documented in wp-includes/blocks.php */
$hooked_block_types = apply_filters( 'hooked_block_types', $hooked_block_types, $relative_position, $anchor_block_type, $context );
foreach ( $hooked_block_types as $hooked_block_type ) {
$markup .= get_hooked_block_markup( $parent_block, $hooked_block_type );
}
$markup .= insert_hooked_blocks( $parent_block, 'last_child', $hooked_blocks, $context );
}

return $markup;
Expand Down
18 changes: 15 additions & 3 deletions tests/phpunit/tests/blocks/getHookedBlockMarkup.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,15 @@ class Tests_Blocks_GetHookedBlockMarkup extends WP_UnitTestCase {
* @covers ::get_hooked_block_markup
*/
public function test_get_hooked_block_markup_adds_metadata() {
$hooked_block = array(
'blockName' => 'tests/hooked-block',
);

$anchor_block = array(
'blockName' => 'tests/anchor-block',
);

$actual = get_hooked_block_markup( $anchor_block, 'tests/hooked-block' );
$actual = get_hooked_block_markup( $hooked_block, $anchor_block );
$this->assertSame( array( 'tests/hooked-block' ), $anchor_block['attrs']['metadata']['ignoredHookedBlocks'] );
$this->assertSame( '<!-- wp:tests/hooked-block /-->', $actual );
}
Expand All @@ -32,6 +36,10 @@ public function test_get_hooked_block_markup_adds_metadata() {
* @covers ::get_hooked_block_markup
*/
public function test_get_hooked_block_markup_if_block_is_already_hooked() {
$hooked_block = array(
'blockName' => 'tests/hooked-block',
);

$anchor_block = array(
'blockName' => 'tests/anchor-block',
'attrs' => array(
Expand All @@ -41,7 +49,7 @@ public function test_get_hooked_block_markup_if_block_is_already_hooked() {
),
);

$actual = get_hooked_block_markup( $anchor_block, 'tests/hooked-block' );
$actual = get_hooked_block_markup( $hooked_block, $anchor_block );
$this->assertSame( array( 'tests/hooked-block' ), $anchor_block['attrs']['metadata']['ignoredHookedBlocks'] );
$this->assertSame( '', $actual );
}
Expand All @@ -52,6 +60,10 @@ public function test_get_hooked_block_markup_if_block_is_already_hooked() {
* @covers ::get_hooked_block_markup
*/
public function test_get_hooked_block_markup_adds_to_ignored_hooked_blocks() {
$other_hooked_block = array(
'blockName' => 'tests/other-hooked-block',
);

$anchor_block = array(
'blockName' => 'tests/anchor-block',
'attrs' => array(
Expand All @@ -61,7 +73,7 @@ public function test_get_hooked_block_markup_adds_to_ignored_hooked_blocks() {
),
);

$actual = get_hooked_block_markup( $anchor_block, 'tests/other-hooked-block' );
$actual = get_hooked_block_markup( $other_hooked_block, $anchor_block );
$this->assertSame( array( 'tests/hooked-block', 'tests/other-hooked-block' ), $anchor_block['attrs']['metadata']['ignoredHookedBlocks'] );
$this->assertSame( '<!-- wp:tests/other-hooked-block /-->', $actual );
}
Expand Down
34 changes: 34 additions & 0 deletions tests/phpunit/tests/blocks/insertHookedBlocks.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<?php
/**
* Tests for the insert_hooked_blocks function.
*
* @package WordPress
* @subpackage Blocks
*
* @since 6.5.0
*
* @group blocks
* @group block-hooks
*/
class Tests_Blocks_InsertHookedBlocks extends WP_UnitTestCase {
/**
* @covers ::insert_hooked_blocks
*/
public function test_insert_hooked_blocks() {
$anchor_block_name = 'tests/anchor-block';
$anchor_block = array(
'blockName' => $anchor_block_name,
);

// Maybe move to class level and include other relative positions?
// And/or data provider?
$hooked_blocks = array(
$anchor_block_name => array(
'after' => array( 'tests/hooked-before' ),
),
);

$actual = insert_hooked_blocks( $anchor_block, 'after', $hooked_blocks, array() );
$this->assertSame( '<!-- wp:tests/hooked-before /-->', $actual );
}
}
Loading