Last active
January 26, 2022 08:14
-
-
Save gaambo/16c7fb6fd758e4eb72e0f5db3888dd40 to your computer and use it in GitHub Desktop.
UPDATE: No longer needed in WP 5.9 // Fixes Bug #51612 in WordPress Core where block filters (pre_render_block and render_block_data) only get called for top level blocks (not for innerBlocks/nested)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
// phpcs:ignoreFile PSR1.Files.SideEffects | |
namespace CoreFunctionality\BlockEditor; | |
/** | |
* Fixes Bug #51612 in WordPress Core | |
* where block filters (pre_render_block and render_block_data) | |
* only get called for top level blocks (not for innerBlocks/nested) | |
* | |
* Current Workaround is to hook into render_block_data | |
* and render each innerBlock (recursively) with render_block | |
* because core doesn't use render_block for innerBlocks but only WP_Block::render | |
* but pre_render_block and render_block_data only get called in render_block | |
* | |
* Changes in render_block/WP_Block have to be monitored and maybe this won't be required in future | |
* | |
* @see https://core.trac.wordpress.org/ticket/51612 | |
*/ | |
class BlockFilterWorkaround | |
{ | |
public function __construct() | |
{ | |
/** | |
* hook latest possible priority (= PHP_INT_MAX) so other hooks which change data run first | |
* our function doesn't change data, it only renders innerBlocks and stores them | |
*/ | |
add_filter('render_block_data', [$this, 'render_block_data'], PHP_INT_MAX, 2); | |
} | |
/** | |
* Callback for `render_block_data` | |
* | |
* @see wp-includes/blocks.php:687 | |
* @param array $block | |
* @param array $sourceBlock | |
* @return array filtered block data with rendered inner blocks | |
*/ | |
public function render_block_data($block, $sourceBlock) // phpcs:ignore PSR1.Methods.CamelCapsMethodName | |
{ | |
// only run if has innerBlocks, maximum nested block without innerBlocks just returns data | |
if (isset($block['innerBlocks']) && $block['innerBlocks']) { | |
$renderedInnerBlocks = []; | |
/** | |
* call render_block foreach innerBlock | |
* this calls pre_render_block and render_block_data for nested blocks | |
* calling render_block_data on a nested block also | |
* calls this method again recursively (for inner-innerBlocks) | |
*/ | |
foreach ($block['innerBlocks'] as $i => $innerBlock) { | |
$renderedInnerBlocks[] = render_block($innerBlock); | |
} | |
$innerBlockIndex = 0; | |
/** | |
* on WP_Block::render it checks for all chunks of innerContent | |
* and if any of these chunks is a string it outputs that string | |
* instead of calling render on the inner block | |
* see class-wp-block.php::208-212 | |
*/ | |
foreach ($block['innerContent'] as $i => $innerContent) { | |
/** | |
* innerContent has structure of [wrapperDiv, null, endDiv] for most blocks | |
* therefore only put values in the "null" elements | |
* see class-wp-block.php::208-212 | |
*/ | |
if (!is_string($innerContent)) { | |
$block['innerContent'][$i] = $renderedInnerBlocks[$innerBlockIndex++]; | |
} | |
} | |
} | |
return $block; | |
} | |
} | |
new BlockFilterWorkaround(); |
UPDATE: WordPress 5.9 includes a bug fix, so this workaround is no longer required.
See https://core.trac.wordpress.org/ticket/51612
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
See https://core.trac.wordpress.org/ticket/51612