Created
February 12, 2016 14:51
-
-
Save Maximilianos/b21020ecceaa67650d01 to your computer and use it in GitHub Desktop.
Register custom page templates in WordPress programmatically in a plugin or in the theme without even requiring real template files.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* | |
*/ | |
/** | |
* Class MCF_Templater | |
* | |
* Based on work by Harri Bell-Thomas <https://github.com/HarriBellThomas> | |
* @link http://www.wpexplorer.com/wordpress-page-templates-plugin/ | |
* | |
* @author Max GJ Panas <https://github.com/Maximilianos> | |
*/ | |
class MCF_Templater { | |
/** | |
* The array of templates that this plugin tracks. | |
*/ | |
protected $templates; | |
/** | |
* The directory where the templates are located | |
*/ | |
protected $template_dir; | |
/** | |
* MCF_Templates constructor. | |
* | |
* Initializes the plugin by setting filters and administration functions. | |
* | |
* @param array $templates | |
* @param string $template_dir | |
*/ | |
public function __construct( $templates = array(), $template_dir = null ) { | |
$this->templates = $templates; | |
$this->template_dir = $template_dir; | |
add_filter( 'page_attributes_dropdown_pages_args', array( &$this, 'add_to_wp_cache' ) ); | |
add_filter( 'wp_insert_post_data', array( &$this, 'add_to_wp_cache' ) ); | |
// interop with Advanced Custom Fields | |
add_filter( 'acf/location/rule_values/page_template', array( &$this, 'add_to_acf_rules' ) ); | |
if ( $this->template_dir ) { | |
// 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, 'get_template_path' ) ); | |
} | |
} | |
/** | |
* Adds the templates to the pages cache in order to trick WordPress | |
* into thinking the template files exists where they do not really | |
* exist. | |
* | |
* @param $attributes | |
* | |
* @return mixed | |
*/ | |
public function add_to_wp_cache( $attributes ) { | |
// 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 $attributes; | |
} | |
/** | |
* Adds the templates to the Advanced Custom Fields | |
* Page Template rule | |
* | |
* @param array $choices | |
* | |
* @return array | |
*/ | |
public function add_to_acf_rules( $choices = array() ) { | |
return array_merge( (array) $choices, (array) $this->templates ); | |
} | |
/** | |
* Checks if the template is assigned to the page | |
* and makes sure to render the correct template | |
* | |
* @param $template | |
* | |
* @return string | |
*/ | |
public function get_path( $template ) { | |
global $post; | |
$page_template = get_post_meta( $post->ID, '_wp_page_template', true ); | |
if ( ! isset( $this->templates[$page_template] ) ) { | |
return $template; | |
} | |
$file = $this->template_dir . $page_template; | |
return file_exists( $file ) ? $file : $template; | |
} | |
} |
Won't run in Wordpress 4.6.1 custom plugin
True, doesn't work on 4.7.x either.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
The actual reason I wrote this is for a (headless) WordPress setup where the site is not rendered by the theme, but by a js based client somewhere else.
I wanted to leverage some of the builtin WordPress functionality surrounding Page Templates (like how they work well as location rules for Advanced Custom Fields), but I did not want to actually create them in the theme as I was creating them already in the js client. So, I use the above code simply to "trick" WordPress into believing my custom page templates exist and are valid.
The way I actually use the above is in a plugin where I simply call it something like so:
Then in the js client which leverages the wp-json api, I simply check the page's
template
key and try to match it against one the defined templates in my js app.