How to borrow a post: creating a virtual WordPress page on the fly with the active theme

I build a new plugin recently, and needed to show a page with my custom message. The stickt need was to be used the active theme, and the same way how WP itself use it. This is because plugin must runs on any possible, include the most sophisticated (from code viewpoint) themes. So here is the approach I found.

function question_1($post) {
	global $post_title, $comment_status, $post_content;
	$post->post_title = $post_title;
	$post->comment_status = $comment_status;
	$post->post_content = $post_content;
	return;
}

function question_2($content) {
	global $post_content;
	return $post_content;
}

function question_3($content) {
	return home_url();
}

function my_init() {
	if([conditions to ensure it will run only when it is need]) {
		global $post_title, $comment_status, $post_content;
		$post_title = "My post title";
		$comment_status = "closed";
		$post_content = "My content, including HTML tqags";
		add_action('the_post', 'question_1');
		add_filter('the_content', 'question_2');
		add_filter('the_permalink', 'question_3');
		query_posts('posts_per_page=1&post_type=post');
		define('WP_USE_THEMES', true);
		require_once(ABSPATH.WPINC.'/template-loader.php');
		exit();
	}
}
add_action('init', 'my_init', 1);

Why and how this works?

The function my_init() runs every time when WP runs itself. It checks if my custom page is need at this moment, or do nothing, WP runs his way. Note that my_init() must run as early as possible, thus there in add_action() stay the privilege parameter "1".

If the custom page is need, my function creates 3 global variables (to send need info to other hooks) and fills them. Those are page title, content and comment status. I not need comments there, so set it "closed". Also I not need the original permalink, as some themes allow to click the post title, so I set it to the site's main URL. The custom page serves security problems, so both these "locks" are good in my case. You may need something different, so change it accordingly. For security reasons, both the title and the post content had to be created during the init stage, so I placed the code there. I then added hooks that insert the custom information into the virtual page when the theme renders it.

Now the mistery begins. I have prepared the need page content already, but WP have no page prepared yet. Do we need to run the Mail WP Loop, and I do that with query_posts() function. I need only a single post. Every WP installation have at least one active post, so with these conditions I ask the first active post to be loaded. Now, we have our custom content, have a post prepared to be shown, have the hooks ready to change the content. So we need to run the theme, to show the post. With define('WP_USE_THEMES', true) row we say to the WP "We need to use the active theme". With next row we say "Run the active theme".

What happens next? WP runs the theme. Theme runs the need template. Template shows our content, but with post's ID and other post-specific info. And this the way I "borrow" a post to show my custom content.

Code is poetry!:-)

Share this

This entry was posted in Blog, Hacks and tagged , , , , , , . Bookmark the permalink.

Leave a Reply