-
-
Save seant100/44afa477efa8d62bf3b9 to your computer and use it in GitHub Desktop.
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 | |
/* | |
* Virtual Themed Page class | |
* | |
* This class implements virtual pages for a plugin. | |
* | |
* It is designed to be included then called for each part of the plugin | |
* that wants virtual pages. | |
* | |
* It supports multiple virtual pages and content generation functions. | |
* The content functions are only called if a page matches. | |
* | |
* The class uses the theme templates and as far as I know is unique in that. | |
* It also uses child theme templates ahead of main theme templates. | |
* | |
* Example code follows class. | |
* | |
* August 2013 Brian Coogan | |
* | |
*/ | |
// There are several virtual page classes, we want to avoid a clash! | |
// | |
// | |
class Virtual_Themed_Pages_BC | |
{ | |
public $title = ''; | |
public $body = ''; | |
private $vpages = array(); // the main array of virtual pages | |
private $mypath = ''; | |
public $blankcomments = "blank-comments.php"; | |
function __construct($plugin_path = null, $blankcomments = null) | |
{ | |
if (empty($plugin_path)) | |
$plugin_path = dirname(__FILE__); | |
$this->mypath = $plugin_path; | |
if (! empty($blankcomments)) | |
$this->blankcomments = $blankcomments; | |
// Virtual pages are checked in the 'parse_request' filter. | |
// This action starts everything off if we are a virtual page | |
add_action('parse_request', array(&$this, 'vtp_parse_request')); | |
} | |
function add($virtual_regexp, $contentfunction) | |
{ | |
$this->vpages[$virtual_regexp] = $contentfunction; | |
} | |
// Check page requests for Virtual pages | |
// If we have one, call the appropriate content generation function | |
// | |
function vtp_parse_request(&$wp) | |
{ | |
//global $wp; | |
if (empty($wp->query_vars['pagename'])) | |
return; // page isn't permalink | |
//$p = $wp->query_vars['pagename']; | |
$p = $_SERVER['REQUEST_URI']; | |
$matched = 0; | |
foreach ($this->vpages as $regexp => $func) | |
{ | |
if (preg_match($regexp, $p)) | |
{ | |
$matched = 1; | |
break; | |
} | |
} | |
// Do nothing if not matched | |
if (! $matched) | |
return; | |
// setup hooks and filters to generate virtual movie page | |
add_action('template_redirect', array(&$this, 'template_redir')); | |
add_filter('the_posts', array(&$this, 'vtp_createdummypost')); | |
// we also force comments removal; a comments box at the footer of | |
// a page is rather meaningless. | |
// This requires the blank_comments.php file be provided | |
add_filter('comments_template', array(&$this, 'disable_comments'), 11); | |
// Call user content generation function | |
// Called last so it can remove any filters it doesn't like | |
// It should set: | |
// $this->body -- body of the virtual page | |
// $this->title -- title of the virtual page | |
// $this->template -- optional theme-provided template | |
// eg: page | |
// $this->subtemplate -- optional subtemplate (eg movie) | |
// Doco is unclear whether call by reference works for call_user_func() | |
// so using call_user_func_array() instead, where it's mentioned. | |
// See end of file for example code. | |
$this->template = $this->subtemplate = null; | |
$this->title = null; | |
unset($this->body); | |
call_user_func_array($func, array(&$this, $p)); | |
if (! isset($this->body)) //assert | |
wp_die("Virtual Themed Pages: must save ->body [VTP07]"); | |
return($wp); | |
} | |
// Setup a dummy post/page | |
// From the WP view, a post == a page | |
// | |
function vtp_createdummypost($posts) | |
{ | |
// have to create a dummy post as otherwise many templates | |
// don't call the_content filter | |
global $wp, $wp_query; | |
//create a fake post intance | |
$p = new stdClass; | |
// fill $p with everything a page in the database would have | |
$p->ID = -1; | |
$p->post_author = 1; | |
$p->post_date = current_time('mysql'); | |
$p->post_date_gmt = current_time('mysql', $gmt = 1); | |
$p->post_content = $this->body; | |
$p->post_title = $this->title; | |
$p->post_excerpt = ''; | |
$p->post_status = 'publish'; | |
$p->ping_status = 'closed'; | |
$p->post_password = ''; | |
$p->post_name = 'movie_details'; // slug | |
$p->to_ping = ''; | |
$p->pinged = ''; | |
$p->modified = $p->post_date; | |
$p->modified_gmt = $p->post_date_gmt; | |
$p->post_content_filtered = ''; | |
$p->post_parent = 0; | |
$p->guid = get_home_url('/' . $p->post_name); // use url instead? | |
$p->menu_order = 0; | |
$p->post_type = 'page'; | |
$p->post_mime_type = ''; | |
$p->comment_status = 'closed'; | |
$p->comment_count = 0; | |
$p->filter = 'raw'; | |
$p->ancestors = array(); // 3.6 | |
// reset wp_query properties to simulate a found page | |
$wp_query->is_page = TRUE; | |
$wp_query->is_singular = TRUE; | |
$wp_query->is_home = FALSE; | |
$wp_query->is_archive = FALSE; | |
$wp_query->is_category = FALSE; | |
unset($wp_query->query['error']); | |
$wp->query = array(); | |
$wp_query->query_vars['error'] = ''; | |
$wp_query->is_404 = FALSE; | |
$wp_query->current_post = $p->ID; | |
$wp_query->found_posts = 1; | |
$wp_query->post_count = 1; | |
$wp_query->comment_count = 0; | |
// -1 for current_comment displays comment if not logged in! | |
$wp_query->current_comment = null; | |
$wp_query->is_singular = 1; | |
$wp_query->post = $p; | |
$wp_query->posts = array($p); | |
$wp_query->queried_object = $p; | |
$wp_query->queried_object_id = $p->ID; | |
$wp_query->current_post = $p->ID; | |
$wp_query->post_count = 1; | |
return array($p); | |
} | |
// Virtual Movie page - tell wordpress we are using the given | |
// template if it exists; otherwise we fall back to page.php. | |
// | |
// This func gets called before any output to browser | |
// and exits at completion. | |
// | |
function template_redir() | |
{ | |
// $this->body -- body of the virtual page | |
// $this->title -- title of the virtual page | |
// $this->template -- optional theme-provided template eg: 'page' | |
// $this->subtemplate -- optional subtemplate (eg movie) | |
// | |
if (! empty($this->template) && ! empty($this->subtemplate)) | |
{ | |
// looks for in child first, then master: | |
// template-subtemplate.php, template.php | |
get_template_part($this->template, $this->subtemplate); | |
} | |
elseif (! empty($this->template)) | |
{ | |
// looks for in child, then master: | |
// template.php | |
get_template_part($this->template); | |
} | |
elseif (! empty($this->subtemplate)) | |
{ | |
// looks for in child, then master: | |
// template.php | |
get_template_part($this->subtemplate); | |
} | |
else | |
{ | |
get_template_part('page'); | |
} | |
// It would be possible to add a filter for the 'the_content' filter | |
// to detect that the body had been correctly output, and then to | |
// die if not -- this would help a lot with error diagnosis. | |
exit; | |
} | |
// Some templates always include comments regardless, sigh. | |
// This replaces the path of the original comments template with a | |
// empty template file which returns nothing, thus eliminating | |
// comments reliably. | |
function disable_comments($file) | |
{ | |
if (file_exists($this->blankcomments)) | |
return($this->mypath.'/'.$blankcomments); | |
return($file); | |
} | |
} // class | |
// Example code - you'd use something very like this in a plugin | |
// | |
if (0) | |
{ | |
// require 'BC_Virtual_Themed_pages.php'; | |
// this code segment requires the WordPress environment | |
$vp = new Virtual_Themed_Pages_BC(); | |
$vp->add('#/mypattern/unique#i', 'mytest_contentfunc'); | |
// Example of content generating function | |
// Must set $this->body even if empty string | |
function mytest_contentfunc($v, $url) | |
{ | |
// extract an id from the URL | |
$id = 'none'; | |
if (preg_match('#unique/(\d+)#', $url, $m)) | |
$id = $m[1]; | |
// could wp_die() if id not extracted successfully... | |
$v->title = "My Virtual Page Title"; | |
$v->body = "Some body content for my virtual page test - id $id\n"; | |
$v->template = 'page'; // optional | |
$v->subtemplate = 'billing'; // optional | |
} | |
} | |
// end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment