I need a page template to be used with my plugin. I don't need to replace a theme template such as single or archive.

Normally I'd use

/*
* Template Name: Blah Blah Blah
*/

to add a template to the page options, however, this isn't working in the plugin, as expected. I know how to add a template for a custom post type in a plugin. However, I need this to be an option the templates dropdown in the page options.

Here is a fairly simple approach I was able to get working within a plugin. You'll want to reference https://developer.wordpress.org/reference/hooks/theme_page_templates/ and https://developer.wordpress.org/reference/hooks/template_include/ as you review the code below.

<?php
//Add our custom template to the admin's templates dropdown
add_filter( 'theme_page_templates', 'pluginname_template_as_option', 10, 3 );
function pluginname_template_as_option( $page_templates, $this, $post ){

    $page_templates['template-landing.php'] = 'Example Landing Page';

    return $page_templates;

}

//When our custom template has been chosen then display it for the page
add_filter( 'template_include', 'pluginname_load_template', 99 );
function pluginname_load_template( $template ) {

    global $post;
    $custom_template_slug   = 'template-landing.php';
    $page_template_slug     = get_page_template_slug( $post->ID );

    if( $page_template_slug == $custom_template_slug ){
        return plugin_dir_path( __FILE__ ) . $custom_template_slug;
    }

    return $template;

}

There is no straight forward way to this, as per my knowledge. I have tried to search as well, and did not find any better solution than the below one.

Below codes will provide you exactly what you are looking for:

class PageTemplater {

    /**
     * A Unique Identifier
     */
     protected $plugin_slug;

    /**
     * A reference to an instance of this class.
     */
    private static $instance;

    /**
     * The array of templates that this plugin tracks.
     */
    protected $templates;


    /**
     * Returns an instance of this class. 
     */
    public static function get_instance() {

            if( null == self::$instance ) {
                    self::$instance = new PageTemplater();
            } 

            return self::$instance;

    } 

    /**
     * Initializes the plugin by setting filters and administration functions.
     */
    private function __construct() {

            $this->templates = array();


            // Add a filter to the attributes metabox to inject template into the cache.
            add_filter(
                'page_attributes_dropdown_pages_args',
                 array( $this, 'register_project_templates' ) 
            );


            // Add a filter to the save post to inject out template into the page cache
            add_filter(
                'wp_insert_post_data', 
                array( $this, 'register_project_templates' ) 
            );


            // Add a filter to the template include to determine if the page has our 
            // template assigned and return it's path
            add_filter(
                'template_include', 
                array( $this, 'view_project_template') 
            );


            // Add your templates to this array.
            $this->templates = array(
                    'goodtobebad-template.php'     => 'It\'s Good to Be Bad',
            );

    } 


    /**
     * Adds our template to the pages cache in order to trick WordPress
     * into thinking the template file exists where it doens't really exist.
     *
     */

    public function register_project_templates( $atts ) {

            // Create the key used for the themes cache
            $cache_key = 'page_templates-' . md5( get_theme_root() . '/' . get_stylesheet() );

            // Retrieve the cache list. 
            // If it doesn't exist, or it's empty prepare an array
            $templates = wp_get_theme()->get_page_templates();
            if ( empty( $templates ) ) {
                    $templates = array();
            } 

            // New cache, therefore remove the old one
            wp_cache_delete( $cache_key , 'themes');

            // Now add our template to the list of templates by merging our templates
            // with the existing templates array from the cache.
            $templates = array_merge( $templates, $this->templates );

            // Add the modified cache to allow WordPress to pick it up for listing
            // available templates
            wp_cache_add( $cache_key, $templates, 'themes', 1800 );

            return $atts;

    } 

    /**
     * Checks if the template is assigned to the page
     */
    public function view_project_template( $template ) {

            global $post;

            if (!isset($this->templates[get_post_meta( 
                $post->ID, '_wp_page_template', true 
            )] ) ) {

                    return $template;

            } 

            $file = plugin_dir_path(__FILE__). get_post_meta( 
                $post->ID, '_wp_page_template', true 
            );

            // Just to be safe, we check if the file exist first
            if( file_exists( $file ) ) {
                    return $file;
            } 
            else { echo $file; }

            return $template;

    } 


}
add_action( 'plugins_loaded', array( 'PageTemplater', 'get_instance' ) );

Here is the full tutorial with details of what is happening and why.

You can use the theme_page_templates filter to inject your page template.

For example:

add_filter( 'theme_page_templates', 'filter_inject_page_templates' );

filter_inject_page_templates( $templates ) {
    $path               = 'path/to/the/template/relative/to/the/theme/folder';
    $templates[ $path ] = 'Name of the template that displays in dropdown;
    return $templates;
}

You may have to play around with the $path value to get it correct but that should work.

Hope it helps!

Your Answer

 
discard

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

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