As already described in the comments, many WordPress Gutenberg plugins do not use the strict JSON format as WordPress prescribes… (and poorly documented) So it comes to two problems:
- Sometimes the data is in a JSON format, which parse_blocks() cannot
read. If no change is made here, for example, the value attr will be
NULL (example in the first post) - serialize_blocks() converts all special characters to Unicode, which causes the plugin block to stop working properly and results in error messages in the Gutenberg UI: “This block contains unexpected or invalid content.”.
Especially for the plugins Advanced-Gutenberg and Kadence-Blocks the bugs have already been reported. I have developed the following workaround, which is quick and dirty, but it works. If anyone has comments, additions or improvements, please let me know!
function change_post_data_before_save( $data ) {
$post_data = $data['post_content'];
$post_data = str_replace('\\"', '"', $post_data); //parse_blocks() need " to parse $blocks[]['attr'] correctly
$blocks = parse_blocks($post_data);
$post_content = implode( '', array_map( 'serialize_block2', $blocks ) ); //serialize_block() replacement because serialize_block_attributes() does not support JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE
$post_content = str_replace('"', '\\"', $post_content); //undo " correction from above
$data['post_content'] = $post_content;
return $data;
}
add_filter( 'wp_insert_post_data', 'change_post_data_before_save', 10, 2 );
//only sub method calls has been changed
function serialize_block2( $block ) {
$block_content="";
$index = 0;
foreach ( $block['innerContent'] as $chunk ) {
$block_content .= is_string( $chunk ) ? $chunk : serialize_block2( $block['innerBlocks'][ $index++ ] ); //change
}
if ( ! is_array( $block['attrs'] ) ) {
$block['attrs'] = array();
}
return get_comment_delimited_block_content2(
$block['blockName'],
$block['attrs'],
$block_content
);
}
//only sub method calls has been changed
function get_comment_delimited_block_content2( $block_name, $block_attributes, $block_content ) {
if ( is_null( $block_name ) ) {
return $block_content;
}
$serialized_block_name = strip_core_block_namespace( $block_name );
$serialized_attributes = empty( $block_attributes ) ? '' : serialize_block_attributes2( $block_attributes ) . ' '; //change
if ( empty( $block_content ) ) {
return sprintf( '<!-- wp:%s %s/-->', $serialized_block_name, $serialized_attributes );
}
return sprintf(
'<!-- wp:%s %s-->%s<!-- /wp:%s -->',
$serialized_block_name,
$serialized_attributes,
$block_content,
$serialized_block_name
);
}
//change gutenberg json_encoding to keep plugin block formats and prevent issue "This block contains unexpected or invalid content."
function serialize_block_attributes2( $block_attributes ) {
$encoded_attributes = json_encode( $block_attributes, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE ); //change
$encoded_attributes = preg_replace( '/--/', '\\u002d\\u002d', $encoded_attributes );
$encoded_attributes = preg_replace( '/</', '\\u003c', $encoded_attributes );
$encoded_attributes = preg_replace( '/>/', '\\u003e', $encoded_attributes );
$encoded_attributes = preg_replace( '/&/', '\\u0026', $encoded_attributes );
// Regex: /\\"/
$encoded_attributes = preg_replace( '/\\\\"/', '\\u0022', $encoded_attributes );
return $encoded_attributes;
}