Hack: Allow Future Posts To Be Viewed

Suppose you want to publish a post in the near future, but allow people to view it now. Why would you want to do that? Well, suppose you have a regular publishing schedule like I do. But then someone asks a question and you create a post that answers that question. You already have the next few days’ worth of posts scheduled, so this new one is set for next week. But you want to be able to let that person see the post now. So you want the post to appear on your front page, feeds, and category lists as scheduled. But if someone knows the URL, then they can view the post instead of seeing a Not Found error.

Turns out it was rather tricky to do this. The pre_get_posts hook is the right one to use. But you don’t know much about the requested page at that point. I don’t want people to be able to view just any future post, but ones I mark as ok to view in advance. So I added a custom field previewok and only want this to work if a yes is in that field.

Well, you can’t get custom fields or any meta data at the early stage of pre_get_posts. So you need to do your own temporary WP_Query call to take the name in the URL, convert it to a post ID, and then grab that custom field.

You also want to check for some other conditions. is_main_query means this will only work on the primary page content. is_single means it will only work if this is the actual post page, not the front page, feed, or some other list.

Then you need to alter the query to allow future post statuses, as well as the normal publish ones. Here is the find bit of code, suitable for a functions.php or custom plugin.

add_action('pre_get_posts', 'wpaction_allow_view_future_posts');
function wpaction_allow_view_future_posts($query) {
	if ($query->is_main_query()) {
		if (is_single()) {
			$temp = new WP_Query(array('name'=>$query->query['name'], 'post_status'=>'future', 'fields'=>'ids'));
			if (count($temp->posts) > 0) {
				$id = $temp->posts[0];
				if (get_post_meta($id, 'previewok', true) == 'yes') {
					$query->set('post_status', array( 'future', 'publish'));
				}
			}
		}
	}
}

Leave a Reply

Your email address will not be published. Required fields are marked *