Skip to content

Commit

Permalink
Block Supports: Ensure consistent output in different PHP versions (#…
Browse files Browse the repository at this point in the history
…25240)

Get DOM root and extract substring contents

In some versions of PHP (< 7.3) the `DOMDocument::saveHtml( $node )`
method would format HTML introducing whitespace that could result in
different rendered results in the browser.

Avoid using the `DOMDocument::saveHtml( $node )` to ensure consistent
behavior with supported PHP versions.

Mentioned here:
#25028 (comment)
  • Loading branch information
sirreal committed Sep 11, 2020
1 parent 5dc434c commit 6671cef
Show file tree
Hide file tree
Showing 2 changed files with 23 additions and 6 deletions.
15 changes: 9 additions & 6 deletions lib/block-supports/index.php
Original file line number Diff line number Diff line change
Expand Up @@ -104,12 +104,15 @@ function gutenberg_apply_block_supports( $block_content, $block ) {
$block_root->setAttribute( 'style', implode( '; ', $new_styles ) . ';' );
}

$result = '';
// phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase
foreach ( $body_element->childNodes as $child_node ) {
$result .= $dom->saveHtml( $child_node );
}
return $result;
// Avoid using `$dom->saveHtml( $node )` because the node results may not produce consistent
// whitespace for PHP < 7.3. Saving the root HTML `$dom->saveHtml()` prevents this behavior.
$full_html = $dom->saveHtml();

// Find the <body> open/close tags. The open tag needs to be adjusted so we get inside the tag
// and not the tag itself.
$start = strpos( $full_html, '<body>', 0 ) + strlen( '<body>' );
$end = strpos( $full_html, '</body>', $start );
return trim( substr( $full_html, $start, $end - $start ) );
}
add_filter( 'render_block', 'gutenberg_apply_block_supports', 10, 2 );

Expand Down
14 changes: 14 additions & 0 deletions phpunit/class-block-supported-styles-test.php
Original file line number Diff line number Diff line change
Expand Up @@ -880,6 +880,20 @@ public function test_render_block_includes_appended_html() {
$this->assertEquals( '<p class="wp-block-example">Hello from the block content!</p><div>Appended</div>', $result );
}

/**
* Ensure that HTML is correctly extracted with multibyte contents.
*/
public function test_render_block_mb_html() {
$this->register_block_type(
'core/example',
array( 'render_callback' => true )
);

$result = do_blocks( '<!-- wp:core/example --><ul><li>🙂</li><li>😕</li><li>😵</li><li>😎</li></ul><!-- /wp:core/example -->' );

$this->assertEquals( '<ul class="wp-block-example"><li>🙂</li><li>😕</li><li>😵</li><li>😎</li></ul>', $result );
}

/**
* Should not error when the rendered block is text only.
*/
Expand Down

0 comments on commit 6671cef

Please sign in to comment.