2

I need to dynamically create posts from arbitrary content using wp_insert_post() and wp_update_post(). The post type I'm working with has a simple block template associated with it, so my goal is to get the block template attached to the post type object, insert my post content into the template using innerContent, and then use serialize_blocks to turn the template into renderable post_content markup (e.g. with markup).

My problem is that block templates are defined in PHP as indexed arrays:

$post_object->template = array(
   array( 'core/image', array(
        'align' => 'left',
   ) ),
   array( 'core/heading', array(
        'placeholder' => 'Add Author...',
   ) ),
   array( 'core/paragraph', array(
        'placeholder' => 'Add Description...',
    ) ),
);

While serialize_blocks() appears to require associative arrays similar to what parse_blocks returns:

$blocks = parse_blocks( $post->post_content );
var_dump( $blocks );
// array(
//   array( 'blockName' => 'core/image', 'attrs' => array(
//      'align' => 'left',
// ) ),
//  array( 'blockName' => 'core/heading', 'attrs' => array(
//       'placeholder' => 'Add Author...',
// ) ),
// array( 'blockName' => 'core/paragraph', 'attrs' => array(
//      'placeholder' => 'Add Description...',
//  ) ),
//);

Attempting to define a block template as an associative array breaks the editor, and attempting to serialize blocks using an indexed array results in undefined index and invalid argument warnings from wp-includes/blocks.php with nothing being returned by the function.

Is there something I'm missing here? Some other intermediary function to transpose an indexed block template array into the associative array format that parse_blocks returns?

1
  • 1
    Note that serialize_blocks can't run the javascript of the save components of a block, it can only generate the HTML for PHP rendered blocks. There is no foolproof way for rendering blocks in PHP as a result of this, not without installing PHP extensions that give you a node environment that you can then load the block editor and the blocks JS in to render the output
    – Tom J Nowell
    Commented Dec 9, 2021 at 15:27

1 Answer 1

2

This comment on another post sent me off in the right direction for a solution that converts the indexed array of a block template to an associative array that resembles the output of parse_blocks (below).

But the larger question still remains: why would block templates not follow the same structure and format that parse_blocks uses? Are they not meant to be used in similar ways? Is there some other native solution for converting a block template into renderable post content or even rendered html?

Here's a stop gap solution that converts the indexed array of a block template into the associative array that serialize_blocks requires:

function block_template_to_associative_array( $blocks ){
    $blocks_array = [];
    foreach( $blocks as $block ):
        $blocks_array[] = [
            'blockName' => $block[0],
            'attrs' => $block[1] ?? [],
            'innerBlocks' => isset( $block[2] ) ? block_template_to_associative_array( $block[2] ) : [],
            'innerHTML' => $block[3] ?? [],
            'innerContent' => $block[4] ?? []
        ];
    endforeach;
    return $blocks_array;
}

Edit: unfortunately this is only a partial solution. It results in something close to what parse_blocks creates from post_content, but lacking the innerHTML and innerContent necessary to properly render in the editor. Using serialize_blocks and then inserting into post_content results in "This block contains unexpected or invalid content" errors, but attempting Block Recovery successfully restores all blocks and inner blocks.

3
  • Is this intended as the solution to your question or as a follow up reply?
    – Tom J Nowell
    Commented Dec 9, 2021 at 15:29
  • @TomJNowell it turns out it's only a partial solution. It results in something close to what parse_blocks creates from post_content, but lacking the innerHTML and innerContent necessary to properly render in the editor. Inserting this with post_content results in "This block contains unexpected or invalid content" errors, but attempting Block Recovery successfully restores all blocks and inner blocks. It's not ideal but it's a stop gap, I guess.
    – John Ryan
    Commented Dec 9, 2021 at 18:08
  • if you're going to craft the HTML it has to match exactly what the editor would have produced to pass validation, you're best creating the content in the editor and copy pasting it to extract HTML that way, although this means you can't dynamically generate content
    – Tom J Nowell
    Commented Dec 9, 2021 at 18:10

Your Answer

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

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