-
-
Save Maximilianos/b21020ecceaa67650d01 to your computer and use it in GitHub Desktop.
<?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; | |
} | |
} |
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:
// Note that there is no $template_dir passed to the constructor.
// Here we only care about tricking WordPress into thinking our templates exist.
// We are going to do the actual rendering of the templates in the js app.
new MCF_Templater( array(
'Home' => 'Homepage Template',
'Contact' => 'Contact Template',
...
) );
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.
Won't run in Wordpress 4.6.1 custom plugin
True, doesn't work on 4.7.x either.
To use it just include it in a plugin or a theme and initialize it giving it your custom templates and optionally where those templates are located
A rough example: