6

I am writing a migration script which has to read the post_content of posts and then dynamically change some attributes of some custom Gutenberg blocks.

I was able to read the post_content and then convert them into block objects by using the parse_blocks function. I was also able to dynamically change the attributes of the custom blocks by manipulating the block objects.

But I am not able to convert these block objects into the special HTML comments that Gutenberg uses to serialize them so that I can update the post_content.

I found that the PHP part of WordPress core only has parse_blocks function to parse the special HTML comments into block objects and render_block function to render the blocks, but there is no serialize_block function.

I found that in JavaScript there is a function called serializeBlock which does this. But is there an equivalent of it in PHP which I can call from my migration scripts?

2 Answers 2

5

This markup is generated on the js side of things and saved in the content of the block editor, which is why there doesn't seem to be a native PHP function for this.

However, I found a PHP method that does exactly this in an "experimental" class in the Gutenberg plugin. You can see this here: https://github.com/WordPress/gutenberg/blob/master/lib/class-experimental-wp-widget-blocks-manager.php#L265

You could add it as a method in your own class or convert to a standard function like so:

/**
 * Serializes a block.
 *
 * @param array $block Block object.
 * @return string String representing the block.
 */
function serialize_block( $block ) {
    if ( ! isset( $block['blockName'] ) ) {
        return false;
    }
    $name = $block['blockName'];
    if ( 0 === strpos( $name, 'core/' ) ) {
        $name = substr( $name, strlen( 'core/' ) );
    }
    if ( empty( $block['attrs'] ) ) {
        $opening_tag_suffix = '';
    } else {
        $opening_tag_suffix = ' ' . json_encode( $block['attrs'] );
    }
    if ( empty( $block['innerHTML'] ) ) {
        return sprintf(
            '<!-- wp:%s%s /-->',
            $name,
            $opening_tag_suffix
        );
    } else {
        return sprintf(
            '<!-- wp:%1$s%2$s -->%3$s<!-- /wp:%1$s -->',
            $name,
            $opening_tag_suffix,
            $block['innerHTML']
        );
    }
}
1
  • Awesome. Thanks. I didn't know about this experimental class
    – Sudar
    Jul 21, 2019 at 18:10
6

March 2020 update: Looks like serialize_block() is included with WP since 5.3.1, though i think it's undocumented right now. Here's the source on Trac. The docstring says:

/* [...]
 *
 * Returns the content of a block, including comment delimiters, serializing all
 * attributes from the given parsed block.
 *
 * This should be used when preparing a block to be saved to post content.
 * Prefer `render_block` when preparing a block for display. Unlike
 * `render_block`, this does not evaluate a block's `render_callback`, and will
 * instead preserve the markup as parsed.
 */

It seems to work fine from a few simple tests I did, but I'm not sure if it's intended for public usage yet, because there's also this Trac ticket with a different implementation (marked as "awaiting review" as of 2020.03.20): #47375 - Blocks API: Add server-side serialize_block()

2
  • Thanks. Good to know that the serialize_block function landed in core.
    – Sudar
    Mar 20, 2020 at 6:55
  • Unfortunately I'm not sure if it "landed" quite yet, given that it's undocumented and the trac ticket i linked in the edit, but I'm going to try it out in a migration script and report back
    – uryga
    Mar 20, 2020 at 16:14

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.