wordpress-themingwordpress-gutenbergwordpress-block-theme

Is there a function to convert Block Editor content to a template array for use in register_block_type?


I want to be able to take blocks designed in the Gutenberg editor or saved as an .html template file and convert them to a template which I can use while registering a custom block.json or post type.

For example this is what I have in the editor:

<!-- wp:heading {"level":1,"className":"display-4"} -->
<h1 class="wp-block-heading display-4">Hello World</h1>
<!-- /wp:heading -->

Next I have to type out all the blocks with supports and attributes, and it's pretty gnarly if there's lots of nested blocks:

function myplugin_register_book_post_type() {
    $args = array(
        ...
        'template' => array(
            array( 'core/heading', array(
                'placeholder' => 'Add Author...',
            ) )
        ),
        template_lock => 'insert';
    );
    register_post_type( 'book', $args );
}
add_action( 'init', 'myplugin_register_book_post_type' );

I'm looking for a function, in PHP or JS that would translate from Block HTML to Template array.

Since you can use the FSE theme editor to create templates for specific posts, I assume there is a function that does what I'm looking for somewhere.

I tried to use parse_blocks:

function myplugin_register_book_post_type() {
    $args = array(
        'template' => parse_blocks('<!-- wp:heading {"level":1,"className":"display-4"} -->
<h1 class="wp-block-heading display-4">Hello World</h1>
<!-- /wp:heading -->'),
        template_lock => 'insert';
    );
    register_post_type( 'book', $args );
}
add_action( 'init', 'myplugin_register_book_post_type' );

But that didn't result in the same format.

I poked around the WordPress core code but couldn't seem to find something that did those kinds of transformations.

I checked the documentation in the Codex, searched Github and Google. But it's hard to get meaningful results because "Template" in the context of WordPress usually refers to a theme template file, not block registration. So far the most useful resource amidst all the changing documentation has been this awesome site: https://fullsiteediting.com/lessons/creating-block-templates-for-custom-post-types/

Thanks for any help! This is my first post here, and I'm sure I'm missing something obvious. It just seems harder to get Google to return the results I'm actually looking for these days.


Solution

  • I still have no idea how to convert blocks from HTML to PHP, but I found two workarounds to avoid having to do it. Not sure yet which method I prefer.

    The core/pattern block

    As described here, you can save your HTML as a pattern and use that as the template. Register the pattern however you like, either entirely in PHP:

    register_block_pattern( 'my_theme/my_pattern_slug', array(
        'title' => 'Custom Post Type Template',
        'content' => '{HTML FROM EDITOR}'
    ) );
    

    or save the HTML in your theme's /patterns directory with a PHP comment for the pattern file header:

    <?php
    /**
     * Title: Custom Post Type Template
     * Slug: my_theme/my_pattern_slug
     */
    ?>
    
    {HTML FROM EDITOR}
    

    Then you can set your custom post type template to be a core/pattern block that loads your new pattern.

    $args = array(
        ...
        'template' => array(
            array(
                'core/pattern',
                array(
                    'slug' => 'my_theme/my_pattern_slug'
                ),
            )
        )
    );
    

    The default_content filter

    As described here, you can use the default_content filter instead of setting a template at all:

    function my_custom_post_type_template( $content, $post ) {
        if ( $post->post_type === 'my_custom_post_type' ) {
            $content = '{HTML FROM EDITOR}';
        }
        return $content;
    }
    
    add_filter('default_content', 'my_custom_post_type_template', 10, 2);