In this tutorial we're going to investigate how you can override a theme template files from your WordPress plugins. For this we're going to be using two filters:
By attaching to a filter in WordPress it allows you to pass in a parameter to modify before moving on to the next section of the code. theme_page_templates is a filter used to add files to the page template dropdown. * template_include* is used to change the template WordPress uses to display the content.
Add File To Template Dropdown
The page template list is what the user can use to specifically choose a page template to display the content. This option is only available on the page post type, as it's normally reversed to be used on more static content such as About us pages, Contact us page etc. Therefore if you're building a Contact us plugin you could use this to technique to add your contact form to the list of page templates.
add_filter( 'theme_page_templates', 'add_page_template_to_dropdown' );
/**
* Add page templates.
*
* @param array $templates The list of page templates
*
* @return array $templates The modified list of page templates
*/
function add_page_template_to_dropdown( $templates )
{
$templates[plugin_dir_path( __FILE__ ) . 'templates/plugin-page.php'] = __( 'Plugin Page Template', 'plugin-slug' );
return $templates;
}
First you call the filter theme_page_templates we need to modify the $templates variable, this is an array of page templates the user can choose from. All we need to do is add an extra element to the array with the key being the template location and the value being the name of the page template.
Change The Template File
Now we have the page template selected we need to change the template file WordPress uses to display the content. As WordPress can't find the selected file it will default to the template hierarchy and display something like the theme page.php file or index.php file. Using the filter template_include you can return a new template file WordPress uses to display the content. When the page template is saved in WordPress admin area it's value is stored on the post meta database table under the key _wp_page_template, therefore we will need to search in the post meta to get the selected page template.
$meta = get_post_meta( get_the_ID() );
if(!empty($meta['_wp_page_template'][0]) && $meta['_wp_page_template'][0] != $template)
{
$template = $meta['_wp_page_template'][0];
}
To use this technique to override the single.php file you'll need to do something different, because there is no dropdown for the user to select you'll need to decide how you want this to behave. There are a number of options you can either create a settings page to change the single.php file to one in plugin directory or you can create a post meta box to add your own dropdown to the post. In this example we're demoing how you can change the template so we're simply going to check for the plugin-single.php file in the plugin directory, if this exists then we're going to use this template instead.
$fileTemplate = plugin_dir_path( __FILE__ ) . 'templates/plugin-single.php';
if(file_exists($fileTemplate))
{
$template = $fileTemplate;
}
Below is the full code for the filter to change the template depending on the post type.
add_filter( 'template_include', 'change_page_template', 99 );
/**
* Change the page template to the selected template on the dropdown
* Change the single template to the fixed template in the plugin
*
* @param $template
*
* @return mixed
*/
public function change_page_template( $template )
{
if(is_page())
{
$meta = get_post_meta( get_the_ID() );
if(!empty($meta['_wp_page_template'][0]) && $meta['_wp_page_template'][0] != $template)
{
$template = $meta['_wp_page_template'][0];
}
} else if(is_single()) {
$fileTemplate = plugin_dir_path( __FILE__ ) . 'templates/plugin-single.php';
if(file_exists($fileTemplate))
{
$template = $fileTemplate;
}
}
return $template;
}
It's important to note that you should be careful when changing the theme template from a plugin. The plugin template files will have no relation to the layout of the page, or the styling it's expecting to use. Above I used the example of a contact form plugin but as you don't know the layout of the theme the plugin template file could look completely different to the theme.