Recently I had to to publish an article in a way that common site visitors aren't aware of it's existence. Basically this article had to be excluded from all WordPress loops and visible only when accessed directly. General idea of solution presented in this article is to use pre_get_posts hook to alter WP_Query. Goal is excluding hidden post on frontend, area that isn't single post and when area is single post other than hidden post it self. Now allow me to share code snippet that can be used for this purpose.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | <?php /** Plugin Name: Hidden Posts Plugin URI: http://www.techytalk.info/ Description: Allow post to be visible only when accessed directly Version: 1.0 Author: Marko Martinović Author URI: http://www.techytalk.info/ Copyright 2013. Marko Martinović (email : marko AT techytalk.info) */ class HiddenPosts{ /* post_id => 'post_slug' */ protected $exclude = array( 1 => 'hello-world' ); public function __construct() { add_action('pre_get_posts', array($this, 'pre_get_posts')); } public function pre_get_posts($query) { if( !$query->is_admin && ( !$query->is_single || !in_array($query->query_vars['name'], array_values($this->exclude)) )) { $query->set('post__not_in', array_keys($this->exclude)); } } } $hidden_posts = new HiddenPosts(); |
Excluded posts are contained in $exclude class property, but you could easily use separate table and add WP_List_Table interface to manage excluded posts. Reason for having to include both post ID and post slug, is that pre_get_posts is called very early and post ID isn't yet available trough WP_Query. Did I mention you need to have permalinks enabled in WordPress admin (mod_rewrite) for this code to work?