Opened 3 years ago
Last modified 3 weeks ago
#56519 new defect (bug)
Inner blocks serialization bug in serialize_block function
| Reported by: |
|
Owned by: | |
|---|---|---|---|
| Milestone: | Awaiting Review | Priority: | normal |
| Severity: | normal | Version: | 5.3.1 |
| Component: | Editor | Keywords: | has-patch reporter-feedback |
| Focuses: | Cc: |
Description
Hi,
The serialize_block function https://developer.wordpress.org/reference/functions/serialize_block/ fails when the number of inner blocks increases.
The following custom function solved it for me.
<?php function custom_serialize_block( $block ) { $block_content = ''; foreach ( $block['innerContent'] as $chunk ) { if ( is_string( $chunk ) ) { $block_content .= $chunk; } else { foreach ( $block['innerBlocks'] as $inner_block ) { $block_content .= custom_serialize_block( $inner_block ); } } } if ( ! is_array( $block['attrs'] ) ) { $block['attrs'] = []; } return get_comment_delimited_block_content( $block['blockName'], $block['attrs'], $block_content ); }
Attachments (1)
Change History (7)
#1
@
3 years ago
- Focuses performance coding-standards removed
- Keywords needs-patch added; has-patch removed
#3
@
8 months ago
- Keywords has-patch added; needs-patch removed
I've created a patch from the fix provider by @saqibsarwar and attached it here, happy to assist if any further testing is required.
This ticket was mentioned in PR #8973 on WordPress/wordpress-develop by @dontfeedthecode.
8 months ago
#5
This PR introduces a fix provided by saqibsarwar 3 years ago or so, ticket attached to the PR. I've created a patch for this and am providing this PR as the issue has become dormant with no further input from the reporter however the solution itself is sound.
### Problem
The original serialize_block() function relied on index-based matching between innerContent and innerBlocks. This approach breaks when there are nested blocks within non-string innerContent elements, leading to incorrect or incomplete serialization of deeply nested structures.
### Solution
The updated serialize_block() function iterates over innerContent and dynamically processes nested innerBlocks without relying on positional indexing. For each non-string chunk in innerContent, it recursively serializes all child innerBlocks, ensuring accurate rendering and output for arbitrarily nested blocks.
### Benefits
Fixes serialization issues for complex/nested block layouts
Removes dependency on matching innerContent and innerBlocks indexes
Ensures consistent and correct block output, especially for custom blocks with dynamic inner structures
Trac ticket: https://core.trac.wordpress.org/ticket/56519
#6
@
3 weeks ago
- Keywords reporter-feedback added; needs-testing removed
Reproduction Report
Environment
- WordPress: 7.0-alpha-61215-src
- PHP: 8.2.29
- Server: nginx/1.29.4
- Database: mysqli (Server: 8.4.7 / Client: mysqlnd 8.2.29)
- Browser: Chrome 144.0.0.0
- OS: macOS
- Theme: Twenty Twenty-Five 1.4
- MU Plugins: None activated
- Plugins:
- Code Snippets 3.9.4
- Test Reports 1.2.1
Steps taken
- Add the following snippet via Code Snippets plugin or
functions.phpto test theserialize_block()function
add_action( 'init', function() {
if ( isset( $_GET['reproduce_bug'] ) ) {
echo "<h1>Reproduce Inner Blocks Serialization Bug</h1>";
// Create a block with 3 inner blocks
$test_block = array(
'blockName' => 'core/group',
'attrs' => array(),
'innerBlocks' => array(
array(
'blockName' => 'core/paragraph',
'attrs' => array(),
'innerBlocks' => array(),
'innerHTML' => '<p>First</p>',
'innerContent' => array( '<p>First</p>' ),
),
array(
'blockName' => 'core/paragraph',
'attrs' => array(),
'innerBlocks' => array(),
'innerHTML' => '<p>Second</p>',
'innerContent' => array( '<p>Second</p>' ),
),
array(
'blockName' => 'core/paragraph',
'attrs' => array(),
'innerBlocks' => array(),
'innerHTML' => '<p>Third</p>',
'innerContent' => array( '<p>Third</p>' ),
),
),
'innerHTML' => '<div class="wp-block-group"></div>',
'innerContent' => array(
'<div class="wp-block-group">',
null,
null,
null,
'</div>',
),
);
echo "<h2>Test Case:</h2>";
echo "<p>Group block with 3 inner paragraph blocks</p>";
echo "<p>innerContent has 3 null placeholders</p>";
echo "<h2>Calling Core serialize_block():</h2>";
$result = serialize_block( $test_block );
echo "<pre>" . htmlspecialchars( $result ) . "</pre>";
echo "<h2>Bug Check:</h2>";
$first_count = substr_count( $result, 'First' );
$second_count = substr_count( $result, 'Second' );
$third_count = substr_count( $result, 'Third' );
$para_count = substr_count( $result, 'wp:paragraph' ) / 2;
echo "<table border='1'>";
echo "<tr><th>Expected</th><th>Actual</th><th>Status</th></tr>";
echo "<tr><td>3 paragraphs total</td><td>{$para_count} paragraphs</td><td>" . ($para_count == 3 ? '✓' : '✗ BUG') . "</td></tr>";
echo "<tr><td>'First' appears 1x</td><td>{$first_count} times</td><td>" . ($first_count == 1 ? '✓' : '✗ BUG') . "</td></tr>";
echo "<tr><td>'Second' appears 1x</td><td>{$second_count} times</td><td>" . ($second_count == 1 ? '✓' : '✗ BUG') . "</td></tr>";
echo "<tr><td>'Third' appears 1x</td><td>{$third_count} times</td><td>" . ($third_count == 1 ? '✓' : '✗ BUG') . "</td></tr>";
echo "</table>";
if ( $para_count > 3 || $first_count > 1 || $second_count > 1 || $third_count > 1 ) {
echo "<h2 style='color:red;'>✗ BUG CONFIRMED: Content is duplicated!</h2>";
echo "<p>The serialize_block() function is duplicating inner blocks.</p>";
} else {
echo "<h2 style='color:green;'>✓ Bug NOT present in this WordPress version</h2>";
echo "<p>The issue appears to be already fixed.</p>";
}
exit;
}
});
- Visit http://localhost:8889/?reproduce_bug=1
- ❌ Bug is not occurring
Expected behavior
- Ticket reports
serialize_block()fails when the number of inner blocks increases.

Patch created from saqibsarwar's resolution to ticket 56519