WP - Use file in plugin directory as custom Page Template? - wordpress

Is it possible for a file in the plugin directory to be used as a custom Page Template?
Also, how do you make a plugin create a page?
I'm developing a plugin for a client based on a theme, he wants this plugin to make sales pages while being able to use his theme on the homepage. This is a product that I'm making for him to market so it needs to be automated all through the plugin.
Is this possible?
EDIT
I have the activation/deactivation hooks in my plugins main file, and it's not working. Here's the code:
$filename = __FILE__;
register_activation_hook($filename, 'superActivation');
register_deactivation_hook($filename, 'superDeactivation');
global $myFile; global $fh; global $stringData; global $filename;
$myFile = "testFile.txt";
$stringData = "Testing\n";
$fh = fopen($myFile, 'w') or die("can't open file");
function superActivation() {
global $myFile; global $fh; global $stringData; global $filename;
fwrite($fh, $stringData);
fclose($fh);
}
function superDeactivation() {
$myFile = "testFile.txt";
unlink($myFile);
}

You can do this with the template_redirect hook. Here's my code to manually replace the template for a custom post type with one in the theme if there isn't one in the template folder. Put this in your plugin file and then put a folder underneath your plugin called themefiles with your default theme files.
//Template fallback
add_action("template_redirect", 'my_theme_redirect');
function my_theme_redirect() {
global $wp;
$plugindir = dirname( __FILE__ );
//A Specific Custom Post Type
if ($wp->query_vars["post_type"] == 'product') {
$templatefilename = 'single-product.php';
if (file_exists(TEMPLATEPATH . '/' . $templatefilename)) {
$return_template = TEMPLATEPATH . '/' . $templatefilename;
} else {
$return_template = $plugindir . '/themefiles/' . $templatefilename;
}
do_theme_redirect($return_template);
//A Custom Taxonomy Page
} elseif ($wp->query_vars["taxonomy"] == 'product_categories') {
$templatefilename = 'taxonomy-product_categories.php';
if (file_exists(TEMPLATEPATH . '/' . $templatefilename)) {
$return_template = TEMPLATEPATH . '/' . $templatefilename;
} else {
$return_template = $plugindir . '/themefiles/' . $templatefilename;
}
do_theme_redirect($return_template);
//A Simple Page
} elseif ($wp->query_vars["pagename"] == 'somepagename') {
$templatefilename = 'page-somepagename.php';
if (file_exists(TEMPLATEPATH . '/' . $templatefilename)) {
$return_template = TEMPLATEPATH . '/' . $templatefilename;
} else {
$return_template = $plugindir . '/themefiles/' . $templatefilename;
}
do_theme_redirect($return_template);
}
}
function do_theme_redirect($url) {
global $post, $wp_query;
if (have_posts()) {
include($url);
die();
} else {
$wp_query->is_404 = true;
}
}

You CAN add page templates from a plugin very easily by manipulating the page cache.
To customise, simply edit the following code block within the __construct method;
$this->templates = array(
'goodtobebad-template.php' => 'It\'s Good to Be Bad',
);
This is designed for a plugin (the template files are searched for in the root directory of the plugin). This can be changed if desired - check out my full tutorial http://www.wpexplorer.com/wordpress-page-templates-plugin/ for greater detail on this solution. These files are also in exactly the same format as if they were to be included directly in a theme.
Full code;
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' ) );
Check out my tutorial on this for more info.
http://www.wpexplorer.com/wordpress-page-templates-plugin/
I hope this helps you in what you want to do :)

the code david posted above almost works for me. but it seems to blanket over all posts and pages for me. This code below works great for adding a template to a single post type that is created by my main plugin file
function get_book_post_type_template($single_template) {
global $post;
if ($post->post_type == 'books') {
$single_template = dirname( __FILE__ ) . '/themefiles/single-books.php';
}
return $single_template;
}
add_filter( "single_template", "get_book_post_type_template" ) ;
but I'm having trouble getting it to work with a custom page templates that don't have a post_type or has a post_type = page for instance lets say the custom page is an auxiliary member login page to see my custom posts. in my case this file is called myaccount.php and i've included it in a subfolder within my plugin folder named themefiles.
//Add Page and Post Template Files to Current Theme
add_action("template_redirect", 'my_account_redirect');
function my_account_redirect() {
global $wp;
//Set myAccount Custom Page Template
if (isset($wp->query_vars['pagename'] ) == "myaccount") {
$templatefilename = 'myAccount.php';
if (file_exists(dirname( __FILE__ ) . '/themefiles/' . $templatefilename)) {
$return_template = dirname( __FILE__ ) . '/themefiles/' . $templatefilename;
}
do_account_redirect($return_template);
}
}
//Finishing setting templates
function do_account_redirect($url) {
global $post, $wp_query;
if (have_posts()) {
include($url);
die();
} else {
$wp_query->is_404 = true;
}
}
when i do the above code the myaccount template shows up on all pages except for home which i believe is because it is set to a blogroll instead of a static page

I cannot reply to user1912899, but their recommendation seems to be the most elegant solution. To use a custom template to override single-post.php, I've implemented the following code. This will work for any custom single-****.php file you add to your plugin. If it doesn't exist, it just falls back to what WordPress normally uses.
add_action('template_include', 'my_template_include');
function my_template_include($template) {
$file = dirname( __FILE__ ).'/theme/single-'.get_post_type().'.php';
if(file_exists($file)) {
$template = $file;
}
return $template;
}

Related

How do I replace the OOTB woo customer completed order email?

In a plugin I'm working on, I'm trying to replace the OOTB customer-completed-order email with a template in the plugin
Constructor:
define( 'BKF_WC_EMAIL_PATH', plugin_dir_path( __FILE__ ) );
add_filter('wc_get_template', array($this, 'bkf_customer_completed_order_template'), PHP_INT_MAX, 5);
Function:
function bkf_customer_completed_order_template($template, $template_name, $args, $template_path, $default_path) {
if( $template_name == 'emails/customer-completed-order.php' ) {
$template = trailingslashit(BKF_WC_EMAIL_PATH) . 'templates/' . $template_name;
return $template;
}
}
note the template is still pulling the default woo one
Any thoughts/ideas are welcome!
Worked it out!
Instead of the method used in my original question, here's what worked for me:
I created a new class (similar to woocommerce/includes/emails/class-wc-email-customer-completed-order.php) - for demo purposes we'll call it My_Custom_Class
I then called like so in my constructor for the parent class I was working on:
add_action('woocommerce_email_classes', array( $this, 'bk_register_email' ), PHP_INT_MAX, 1 );
And added this function:
public function bk_register_email( $emails ) {
require_once 'emails/my-custom-class.php';
$emails['WC_Email_Customer_Completed_Order'] = new My_Custom_Class();
return $emails;
}

How to conditionally check a custom single post template in WordPress

I am using the following function to call a custom single post overriding the default one single.php
function call_different_single_post($single_template)
{
global $post;
$path = get_stylesheet_directory() . '/includes/templates' . '/';
$single_template = $path. 'single-1.php';
return $single_template;
}
add_filter('single_template', 'call_different_single_post');
It's calling the single-1.php template for the single posts.
Now I want to check this template conditionally so that I can call some other js files like
function call_cust_js_single(){
if( /*..this is single-1.php template..*/){
wp_register_script('cust-js', get_stylesheet_directory_uri() . 'custom.js', false, '1.0.0');
wp_enqueue_script('cust-js');
}
}
add_action('wp_enqueue_scripts', 'call_cust_js_single');
There's a post similar to this but it doesn't quite cover your request. Here's the link here
Here's the valuable code:
add_filter( 'template_include', 'var_template_include', 1000 );
function var_template_include( $t ){
$GLOBALS['current_theme_template'] = basename($t);
return $t;
}
function get_current_template( $echo = false ) {
if( !isset( $GLOBALS['current_theme_template'] ) )
return false;
if( $echo )
echo $GLOBALS['current_theme_template'];
else
return $GLOBALS['current_theme_template'];
}
Now you have the function get_current_template that will return the filename of the template file.
Now edit your header.php file, here's an example:
<?php if('single-1.php' == get_current_template())
{
//load your scripts here
} ?>
It's not as clean as what you were looking for but I think it will help you.

WordPress how to create templates and url in custom plugin

I know how to create a single page and archive page but now I am trying to move everything into a custom plugin. So far I created my custom post type, 'location' and I created my files
/templates/archive-location.php
/templates/single-location.php
How can I get mysite.com/locations to read my archive-location.php all within my custom plugin.
***Update****
I was able to get my single page to work. Now how do I make it so this can be included in any site? For instance I don't know their layout, should I include header and footer?
I need it so if I remove my plugin, mysite.com/locations doesn't exist anymore.
Here is a code for dynamically create custom templates during custom plugin is activated.
suppose i want to create two page first and second and i would like to assign custom templates to it.
Put below the code in your custom plugin's main file like index file of your custom plugin.
/* Runs when plugin is activated */
register_activation_hook(__FILE__,'news_plugin_install');
/* Runs on plugin deactivation*/
register_deactivation_hook( __FILE__, 'news_plugin_remove' );
function news_plugin_install() {
$newsGagPages = array(
'First Page',
'Second Page'
);
foreach ($newsGagPages as $postTitle) {
$my_post = array(
'post_title' =>$postTitle,
'post_status' => 'publish',
'post_author' => 1,
'post_type' => 'page',
'post_status'=>'publish');
if(!get_page_by_title($postTitle))
{
$pageID = wp_insert_post($my_post,true);
}
if($postTitle =="First Page" ){
add_post_meta( $pageID, '_wp_page_template', 'template-first.php' );
}
if($postTitle =="Second Page" ){
add_post_meta( $pageID, '_wp_page_template', 'template-second.php' );
}
}
}
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(
'template-first.php' => 'First',
'template-second'=>'Second ',
);
}
/**
* 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' ) );

adding custom page template from plugin

I'm working on building my first plugin for wordpress and am needing it to dynamically add a custom page for a login screen among other things.
The only thing I've been able to find that's anywhere near what I'm needing is here: WP - Use file in plugin directory as custom Page Template? & Possible to add Custom Template Page in a WP plugin?, but they're still not quite what I'm looking for.
Here is the code that I currently have running in my plugin...
// Add callback to admin menu
add_action( 'template_redirect', 'uploadr_redirect' );
// Callback to add menu items
function uploadr_redirect() {
global $wp;
$plugindir = dirname( __FILE__ );
// A Specific Custom Post Type
if ( $wp->query_vars["post_type"] == 'uploadr' ) {
$templatefilename = 'custom-uploadr.php';
if ( file_exists( TEMPLATEPATH . '/' . $templatefilename )) {
$return_template = TEMPLATEPATH . '/' . $templatefilename;
} else {
$return_template = $plugindir . '/themefiles/' . $templatefilename;
}
do_theme_redirect( $return_template );
}
}
function do_theme_redirect( $url ) {
global $post, $wp_query;
if ( have_posts ()) {
include( $url );
die();
} else {
$wp_query->is_404 = true;
}
}
Using this would require that my client create new page... what I'm needing is for the pluging to auto create a custom page (with a customized path, meaning .com/custompathhere) using a template file from the plugin folder, which will then contain all actions the plugin performs.
Note: This plugin is designed to run on one page, therefore reducing load-time and etc.
Thanks in advance!
Here is my code solution for adding page templates from a Wordpress plugin (inspired by Tom McFarlin).
This is designed for a plugin (the template files are searched for in the root directory of the plugin). These files are also in exactly the same format as if they were to be included directly in a theme. This can be changed if desired - check out my full tutorial http://www.wpexplorer.com/wordpress-page-templates-plugin/ for greater detail on this solution.
To customise, simply edit the following code block within the __construct method;
$this->templates = array(
'goodtobebad-template.php' => 'It\'s Good to Be Bad',
);
Full code;
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' ) );
Check out my tutorial on this for more info.
http://www.wpexplorer.com/wordpress-page-templates-plugin/
I hope this helps you in what you want to do :)
I actually was able to talk to a developer friend of mine after revising the code quite a bit.
Here it is...
<?php
register_activation_hook( __FILE__, 'create_uploadr_page' );
function create_uploadr_page() {
$post_id = -1;
// Setup custom vars
$author_id = 1;
$slug = 'event-photo-uploader';
$title = 'Event Photo Uploader';
// Check if page exists, if not create it
if ( null == get_page_by_title( $title )) {
$uploader_page = array(
'comment_status' => 'closed',
'ping_status' => 'closed',
'post_author' => $author_id,
'post_name' => $slug,
'post_title' => $title,
'post_status' => 'publish',
'post_type' => 'page'
);
$post_id = wp_insert_post( $uploader_page );
if ( !$post_id ) {
wp_die( 'Error creating template page' );
} else {
update_post_meta( $post_id, '_wp_page_template', 'custom-uploadr.php' );
}
} // end check if
}
add_action( 'template_include', 'uploadr_redirect' );
function uploadr_redirect( $template ) {
$plugindir = dirname( __FILE__ );
if ( is_page_template( 'custom-uploadr.php' )) {
$template = $plugindir . '/templates/custom-uploadr.php';
}
return $template;
}
?>
I'm providing a general solution for those that want to add a template to a post from the their plugin. Use the single_template filter.
<?php
add_filter( 'single_template', 'add_custom_single_template', 99 );
function add_custom_single_template( $template ) {
return plugin_dir_path( __FILE__ ) . 'path-to-page-template-inside-plugin.php';
}
?>
Also, if you want to use the template in a specific post type, then:
<?php
add_filter( 'single_template', 'add_custom_single_template', 99 );
function add_custom_single_template( $template ) {
if ( get_post_type() == 'post-type-name'; ) {
return plugin_dir_path( __FILE__ ) . 'path-to-page-template-inside-plugin.php';
}
return $template;
}
?>

Is there any way to override a WordPress template with a plugin?

I'd like to make a landing page. If plugin detects some GET or POST requests it should override wordpress theme and show its own.
It would work somehow like that:
if (isset($_GET['action']) && $_GET['action'] == 'myPluginAction'){
/* do something to maintain action */
/* forbid template to display and show plugin's landing page*/
}
I'm familiar with WP Codex, but I don't remember if there is any function to do that. Of course, I googled it with no results.
Thanks for any ideas in advance.
You need the hook template_include. It doesn't seem documented in the Codex, but you can find more examples here in SO or in WordPress StackExchange
Plugin file
<?php
/**
* Plugin Name: Landing Page Custom Template
*/
add_filter( 'template_include', 'so_13997743_custom_template' );
function so_13997743_custom_template( $template )
{
if( isset( $_GET['mod']) && 'yes' == $_GET['mod'] )
$template = plugin_dir_path( __FILE__ ) . 'my-custom-page.php';
return $template;
}
Custom Template in Plugin folder
<?php
/**
* Custom Plugin Template
* File: my-custom-page.php
*
*/
echo get_bloginfo('name');
Result
Visiting any url of the site with ?mod=yes will render the plugin template file, e.g.: http://example.com/hello-world/?mod=yes.
you need to create a folder '/woocommerce/' inside your plugin directory, inside woocommerce you need to add a folder say, for email 'emails' and put the required template inside '/emails/' to override. just copy paste this code in the main.php of your plugin.
<?php
/**
* Plugin Name: Custom Plugin
*/
function myplugin_plugin_path() {
// gets the absolute path to this plugin directory
return untrailingslashit( plugin_dir_path( __FILE__ ) );
}
add_filter( 'woocommerce_locate_template', 'myplugin_woocommerce_locate_template', 10, 3 );
function myplugin_woocommerce_locate_template( $template, $template_name, $template_path ) {
global $woocommerce;
$_template = $template;
if ( ! $template_path ) $template_path = $woocommerce->template_url;
$plugin_path = myplugin_plugin_path() . '/woocommerce/';
// Look within passed path within the theme - this is priority
$template = locate_template(
array(
$template_path . $template_name, $template_name
)
);
// Modification: Get the template from this plugin, if it exists
if ( ! $template && file_exists( $plugin_path . $template_name ) )
$template = $plugin_path . $template_name;
// Use default template
if ( ! $template )
$template = $_template;
// Return what we found
return $template;
}
?>
for reference template override using plugin

Resources