skip to Main Content

I needed to override one of the theme TwentyTwentyTwo template from a custom plugin, and I wanted to use one of Gutenberg’s blocks.
I see that in the templates files blocks are used by just writing the corresponding html comment.
So I tried editing the template/single.html file in

<!-- wp:post-title /-->
<!-- wp:custom-block-i-defined /-->
<!-- fest -->
<div>Test</div>

and created a file plugin.template.html with the same content in my plugin.

When I visit a single page with the theme’s template, it renders the blocks fine, but if I do so using

add_filter( 'template_include', 'override_template' );
function override_template( string $template ) {
    return 'path/to/the/plugin.template.html';
}

the rendered page only contains the Fest div, but inspecting the page reveals the comments that didn’t become blocks.

Am I using a wrong filter? Should I call some function to "hydrate" the blocks?

2

Answers


  1. Similarly, I wanted to deliver an archive HTML template in my plugin. So I hope this helps.
    The filter template_include didn’t cut it and after running debug and tracing the template loading route I found a solution with the filter get_block_templates.

    Here’s a simplified version of the key parts of my plugin code:-

    public function setup() {
        add_filter( 'get_block_templates', array( $this, 'manage_block_templates' ), 10, 3 );
    }
    
    public function manage_block_templates( $query_result, $query, $template_type ) {
    
        $theme = wp_get_theme();
    
        $template_contents = file_get_contents( plugin_dir_path( __DIR__ ) . 'templates/archive-ale.html' );
        $template_contents = str_replace( '~theme~', $theme->stylesheet, $template_contents );
    
        $new_block                 = new WP_Block_Template();
        $new_block->type           = 'wp_template';
        $new_block->theme          = $theme->stylesheet;
        $new_block->slug           = 'archive-ale';
        $new_block->id             = $theme->stylesheet . '//archive-ale';
        $new_block->title          = 'archive-ale';
        $new_block->description    = '';
        $new_block->source         = 'custom';
        $new_block->status         = 'publish';
        $new_block->has_theme_file = true;
        $new_block->is_custom      = true;
        $new_block->content        = $template_contents;
    
        $query_result[] = $new_block;
    
        return $query_result;
    }
    

    When the template was in the template folder of the child theme the render was fine, but from inside the plugin I had to force the theme name into the template. To avoid the header and footer failing to display. I was getting

    Template part has been deleted or is unavailable: header

    Hence the str_replace.

    Using this method means I can just deploy a plugin and be totally theme agnostic, but I now can’t edit the template from the site editor. The template needs to be in the theme folder to do that.

    My archive-ale.html template:

    <!-- wp:template-part {"slug":"header","tagName":"header","theme":"~theme~"} /-->
    
    <!-- wp:group {"layout":{"inherit":true}} -->
    <div class="wp-block-group"><!-- wp:query-title {"type":"archive","align":"wide","style":{"typography":{"fontSize":"clamp(2.75rem, 6vw, 3.25rem)"},"spacing":{"margin":{"bottom":"6rem"}}}} /-->
    
        <!-- wp:query {"query":{"perPage":2,"pages":0,"offset":0,"postType":"post","categoryIds":[],"tagIds":[],"order":"desc","orderBy":"date","author":"","search":"","exclude":[],"sticky":"","inherit":true},"tagName":"main","align":"wide","layout":{"inherit":false}} -->
        <main class="wp-block-query alignwide"><!-- wp:post-template {"align":"wide"} -->
        <!-- wp:post-title {"isLink":true,"align":"wide","style":{"typography":{"fontStyle":"normal","fontWeight":"300"}},"fontSize":"var(--wp--custom--typography--font-size--huge, clamp(2.25rem, 4vw, 2.75rem))"} /-->    
        <!-- My block -->
        <!-- wp:multiple-blocks-plugin/hero /-->
    
        <!-- wp:columns {"align":"wide"} -->
        <div class="wp-block-columns alignwide"><!-- wp:column {"width":"650px"} -->
        <div class="wp-block-column" style="flex-basis:650px"><!-- wp:post-excerpt /-->
        
        <!-- wp:post-date {"format":"F j, Y","isLink":true,"style":{"typography":{"fontStyle":"italic","fontWeight":"400"}},"fontSize":"small"} /--></div>
        <!-- /wp:column -->
        
        <!-- wp:column {"width":""} -->
        <div class="wp-block-column"></div>
        <!-- /wp:column --></div>
        <!-- /wp:columns -->
        
        <!-- wp:spacer {"height":112} -->
        <div style="height:112px" aria-hidden="true" class="wp-block-spacer"></div>
        <!-- /wp:spacer -->
        <!-- /wp:post-template -->
        
        <!-- wp:query-pagination {"paginationArrow":"arrow","align":"wide","layout":{"type":"flex","justifyContent":"space-between"}} -->
        <!-- wp:query-pagination-previous {"fontSize":"small"} /-->
        
        <!-- wp:query-pagination-numbers /-->
        
        <!-- wp:query-pagination-next {"fontSize":"small"} /-->
        <!-- /wp:query-pagination --></main>
        <!-- /wp:query --></div>
        <!-- /wp:group -->
        
        <!-- wp:template-part {"slug":"footer","tagName":"footer"} /-->
        
    
    Login or Signup to reply.
  2. My solution, above, is one way to ADD an HTML template residing in the plugin folders.

    To override an existing theme template use the same filter but find the template slug to override and then overwrite the content property, or remove it completely from the array and append your new one.

    I’m still wondering if a template from a plugin should really be copied to the theme template folder on activation so that the user can then use the site editor to make further modifications.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search