diff --git a/src/wp-includes/blocks.php b/src/wp-includes/blocks.php index a7919090cf..0ab0e7ca6a 100644 --- a/src/wp-includes/blocks.php +++ b/src/wp-includes/blocks.php @@ -813,16 +813,18 @@ function _excerpt_render_inner_blocks( $parsed_block, $allowed_blocks ) { */ function render_block( $parsed_block ) { global $post; + $parent_block = null; /** * Allows render_block() to be short-circuited, by returning a non-null value. * * @since 5.1.0 * - * @param string|null $pre_render The pre-rendered content. Default null. - * @param array $parsed_block The block being rendered. + * @param string|null $pre_render The pre-rendered content. Default null. + * @param array $parsed_block The block being rendered. + * @param WP_Block|null $parent_block If this is a nested block, a reference to the parent block. */ - $pre_render = apply_filters( 'pre_render_block', null, $parsed_block ); + $pre_render = apply_filters( 'pre_render_block', null, $parsed_block, $parent_block ); if ( ! is_null( $pre_render ) ) { return $pre_render; } @@ -834,10 +836,11 @@ function render_block( $parsed_block ) { * * @since 5.1.0 * - * @param array $parsed_block The block being rendered. - * @param array $source_block An un-modified copy of $parsed_block, as it appeared in the source content. + * @param array $parsed_block The block being rendered. + * @param array $source_block An un-modified copy of $parsed_block, as it appeared in the source content. + * @param WP_Block|null $parent_block If this is a nested block, a reference to the parent block. */ - $parsed_block = apply_filters( 'render_block_data', $parsed_block, $source_block ); + $parsed_block = apply_filters( 'render_block_data', $parsed_block, $source_block, $parent_block ); $context = array(); @@ -858,10 +861,11 @@ function render_block( $parsed_block ) { * * @since 5.5.0 * - * @param array $context Default context. - * @param array $parsed_block Block being rendered, filtered by `render_block_data`. + * @param array $context Default context. + * @param array $parsed_block Block being rendered, filtered by `render_block_data`. + * @param WP_Block|null $parent_block If this is a nested block, a reference to the parent block. */ - $context = apply_filters( 'render_block_context', $context, $parsed_block ); + $context = apply_filters( 'render_block_context', $context, $parsed_block, $parent_block ); $block = new WP_Block( $parsed_block, $context ); diff --git a/src/wp-includes/class-wp-block.php b/src/wp-includes/class-wp-block.php index 189ce4e615..ed5b0f0767 100644 --- a/src/wp-includes/class-wp-block.php +++ b/src/wp-includes/class-wp-block.php @@ -57,6 +57,15 @@ class WP_Block { */ protected $available_context; + /** + * Block type registry. + * + * @since 5.9.0 + * @var WP_Block_Type_Registry + * @access protected + */ + protected $registry; + /** * List of inner blocks (of this same class) * @@ -115,6 +124,8 @@ class WP_Block { $registry = WP_Block_Type_Registry::get_instance(); } + $this->registry = $registry; + $this->block_type = $registry->get_registered( $this->name ); $this->available_context = $available_context; @@ -205,10 +216,33 @@ class WP_Block { if ( ! $options['dynamic'] || empty( $this->block_type->skip_inner_blocks ) ) { $index = 0; + foreach ( $this->inner_content as $chunk ) { - $block_content .= is_string( $chunk ) ? - $chunk : - $this->inner_blocks[ $index++ ]->render(); + if ( is_string( $chunk ) ) { + $block_content .= $chunk; + } else { + $inner_block = $this->inner_blocks[ $index ]; + $parent_block = $this; + + /** This filter is documented in wp-includes/blocks.php */ + $pre_render = apply_filters( 'pre_render_block', null, $inner_block->parsed_block, $parent_block ); + + if ( ! is_null( $pre_render ) ) { + $block_content .= $pre_render; + } else { + $source_block = $inner_block->parsed_block; + + /** This filter is documented in wp-includes/blocks.php */ + $inner_block->parsed_block = apply_filters( 'render_block_data', $inner_block->parsed_block, $source_block, $parent_block ); + + /** This filter is documented in wp-includes/blocks.php */ + $inner_block->context = apply_filters( 'render_block_context', $inner_block->context, $inner_block->parsed_block, $parent_block ); + + $block_content .= $inner_block->render(); + } + + $index++; + } } } diff --git a/tests/phpunit/tests/blocks/wpBlock.php b/tests/phpunit/tests/blocks/wpBlock.php index e44a96d8b0..0545babd6a 100644 --- a/tests/phpunit/tests/blocks/wpBlock.php +++ b/tests/phpunit/tests/blocks/wpBlock.php @@ -628,4 +628,44 @@ class Tests_Blocks_wpBlock extends WP_UnitTestCase { $gradient_support = block_has_support( $block_type, array( 'color', 'gradient' ), true ); $this->assertFalse( $gradient_support ); } + + /** + * @ticket 51612 + */ + public function test_block_filters_for_inner_blocks() { + $pre_render_callback = new MockAction(); + $render_block_data_callback = new MockAction(); + $render_block_context_callback = new MockAction(); + + $this->registry->register( + 'core/outer', + array( + 'render_callback' => function( $block_attributes, $content ) { + return $content; + }, + ) + ); + + $this->registry->register( + 'core/inner', + array( + 'render_callback' => function() { + return 'b'; + }, + ) + ); + + $parsed_blocks = parse_blocks( 'ac' ); + $parsed_block = $parsed_blocks[0]; + + add_filter( 'pre_render_block', array( $pre_render_callback, 'filter' ) ); + add_filter( 'render_block_data', array( $render_block_data_callback, 'filter' ) ); + add_filter( 'render_block_context', array( $render_block_context_callback, 'filter' ) ); + + render_block( $parsed_block ); + + $this->assertSame( 2, $pre_render_callback->get_call_count() ); + $this->assertSame( 2, $render_block_data_callback->get_call_count() ); + $this->assertSame( 2, $render_block_context_callback->get_call_count() ); + } }