diff --git a/src/wp-includes/blocks.php b/src/wp-includes/blocks.php index f65ddb6c2e..e817286ff7 100644 --- a/src/wp-includes/blocks.php +++ b/src/wp-includes/blocks.php @@ -198,10 +198,38 @@ function parse_blocks( $content ) { * @return string Updated post content. */ function do_blocks( $content ) { + // If there are blocks in this content, we shouldn't run wpautop() on it later. + $priority = has_filter( 'the_content', 'wpautop' ); + if ( false !== $priority && doing_filter( 'the_content' ) && has_blocks( $content ) ) { + remove_filter( 'the_content', 'wpautop', $priority ); + add_filter( 'the_content', '_restore_wpautop_hook', $priority + 1 ); + } + $blocks = parse_blocks( $content ); return _recurse_do_blocks( $blocks, $blocks ); } +/** + * If do_blocks() needs to remove wp_autop() from the `the_content` filter, this re-adds it afterwards, + * for subsequent `the_content` usage. + * + * @access private + * + * @since 5.0.0 + * + * @param string $content The post content running through this filter. + * @return string The unmodified content. + */ +function _restore_wpautop_hook( $content ) { + global $wp_filter; + $current_priority = $wp_filter['the_content']->current_priority(); + + add_filter( 'the_content', 'wpautop', $current_priority - 1 ); + remove_filter( 'the_content', '_restore_wpautop_hook', $current_priority ); + + return $content; +} + /** * Helper function for do_blocks(), to recurse through the block tree. * diff --git a/src/wp-includes/formatting.php b/src/wp-includes/formatting.php index f408b1bfd0..5c974f9a06 100644 --- a/src/wp-includes/formatting.php +++ b/src/wp-includes/formatting.php @@ -458,11 +458,6 @@ function wpautop( $pee, $br = true ) { return ''; } - // We don't need to autop posts with blocks in them. - if ( has_blocks( $pee ) ) { - return $pee; - } - // Just to make things a little easier, pad the end. $pee = $pee . "\n"; diff --git a/tests/phpunit/tests/blocks/render.php b/tests/phpunit/tests/blocks/render.php index a03397bc10..98e42249bc 100644 --- a/tests/phpunit/tests/blocks/render.php +++ b/tests/phpunit/tests/blocks/render.php @@ -75,13 +75,44 @@ class WP_Test_Block_Render extends WP_UnitTestCase { // Block rendering add some extra blank lines, but we're not worried about them. $block_filtered_content = preg_replace( "/\n{2,}/", "\n", $block_filtered_content ); - $this->assertEquals( $classic_filtered_content, $block_filtered_content ); + $this->assertEquals( trim( $classic_filtered_content ), trim( $block_filtered_content ) ); } function handle_shortcode( $atts, $content ) { return $content; } + /** + * @ticket 45290 + */ + public function test_blocks_arent_autopeed() { + $expected_content = 'test'; + $test_content = "\n$expected_content\n"; + + $current_priority = has_action( 'the_content', 'wpautop' ); + + $filtered_content = trim( apply_filters( 'the_content', $test_content ) ); + + $this->assertEquals( $expected_content, $filtered_content ); + + // Check that wpautop() is still defined in the same place. + $this->assertSame( $current_priority, has_action( 'the_content', 'wpautop' ) ); + // ... and that the restore function has removed itself. + $this->assertFalse( has_action( 'the_content', '_restore_wpautop_hook' ) ); + + $test_content = 'test'; + $expected_content = "
$test_content
"; + + $current_priority = has_action( 'the_content', 'wpautop' ); + + $filtered_content = trim( apply_filters( 'the_content', $test_content ) ); + + $this->assertEquals( $expected_content, $filtered_content ); + + $this->assertSame( $current_priority, has_action( 'the_content', 'wpautop' ) ); + $this->assertFalse( has_action( 'the_content', '_restore_wpautop_hook' ) ); + } + /** * @ticket 45109 */