By design, wordpress does not have a property per post or page that would signal the application to not use the page in queries of the standard controller WP_Query
as you asked for.
However, it\'s not that this scenario is something too far away. Let\'s look what wordpress has to offer instead.
Wordpress Post Statuses
Posts can have some status, or more precisely, they have a status. That is what you might know already. I list them with their string identifier, their naming and context if any. Every post has one of these:
publish
(Published, post)
future
(Scheduled, post)
draft
(Draft, post)
pending
(Pending, post)
private
(Private, post)
trash
(Trash, post)
auto-draft
(auto-draft)
inherit
(inherit)
Next to those, you can register your own post status. The API function to do that is called register_post_status()
(Wordpress Codex) which is an undocumented function. You find it documented into source: register_post_status()
(Wordpress Source). To get a post\'s status, you can use the get_post_status()
(Wordpress Codex) function.
It\'s not very well documented, I assume because the concept of post statuses was not introduced as a fixed feature set but on best try and then having a look. So expect this to be a bit fragile and it\'s unknown if it can be used to actually solve your issue. But I would nevertheless stick to it, because it\'s a built-in feature which is to be expected, like custom-post-types, to be integrated more and more with each release. CPT\'s for example are not introduced since 2.8 IIRC and still not complete. It just takes some time.
This post status registration function is documented as being available since 3.0.0, so it\'s quite new. It was introduced in 12719, related Ticket is #9674.
You can imagine, that the concept is not well integrated so far.
But it\'s worth to take a look at that end, because it looks like it contains all ingredients which are important for your feature request. Post statuses have properties that are used in the controllers and models decisions to fetch content - that\'s basically why you like to control. Let\'s look what\'s in before I continue with what\'s not working / buggy:
- public
TRUE
/FALSE
- Known to be TRUE
for Published posts. So post statuses with the public
-property set to TRUE
are assume to behave like published posts.
- private
TRUE
/FALSE
- Known to be TRUE
for Private posts. Comparable to the public
-property.
- protected
TRUE
/FALSE
- Protected most certainly stands for "password protected".
- internal
TRUE
/FALSE
- Example for internal post statuses are: Trash; auto-draft and inherit.
- publicly_queryable
TRUE
/FALSE
- If not explicitly set, all public statuses are publicly queryable.
- exclude_from_search
TRUE
/FALSE
- Assumed to be like the property name suggests.
- show_in_admin_all_list
TRUE
/FALSE
- Same.
- show_in_admin_status_list
TRUE
/FALSE
- Same.
- single_view_cap
TRUE
/FALSE
- Something special, probably worth to look into for your question.
- _builtin - Optional, internal switch. Can be used to create built-in post statuses.
Those post status properties are not designed to work with each other. The concept more or less is that everyone of those is FALSE
by default and you can set some for them to TRUE
. The data-structure in wordpress is a standard class with some global accessible properties. It is added to the $wp_post_statuses
global variable which acts like a singleton registry in the global namespace per request, ready to be used after init. So if you would like to see, what has been defined, add a hook at the end of init
for debugging purposes:
add_action( \'init\', function() {
var_dump($GLOBALS[\'wp_post_statuses\']);
die();
}, 99999);
With something like that you can see what\'s in for the moment. As those are standard classes with public properties, nothing is guaranteeing data consistency here. So take care as usual with the wordpress API. Some of those most probably interfere with the functionality of others but how and when is only defined by code which is likely to change. Just take a bit care and double check with the source.
Limitations so far
So as it looks good so far to make use of post statuses, let\'s take a look for the expected to be limitations this comes with.
The admin lacks of options to make own post states available in the publish box for example. that means, you need to either patch the existing display routine or create your own UI so far for it. Patching core might be more probable as it allows you to offer code for an existing feature request (Ticket #12567) and an own post edit meta box might be interactively be interfering with the concept of the publish box.
I suggest some lightweight patch to introduce a new filter that allows to change the listing of radios. The lighter your approach is, the more likely you will get this in. I smell that core developers fear a bit to introduce any changes to that part because of it\'s complexitiy. So the less complex your changes are, the better this is.
Additionally, even if my list above suggest that there is some context for post or page, you can not setup a post status for a specific post type AFAIK. So expect that your post status is available to any custom post type as well or at least the behavior needs to be researched for any of those and properly tested on your concrete site.
So to learn about the deficiencies, it\'s always good to peek what\'s reported in trac to learn about limitations upfront. I do this by searching for the function name (and I use google to search trac next to trac search):
I think this will give you an image.
Defining your own Post Status
So one option might be to define your own post status. That would enable you to re-use existing status and their functionality (namely drafting and trashing) while maintaining your own type for your hiding purposes.
I would setup one as public = TRUE;
but with publicly_queryable = FALSE;
. Then I don\'t know your needs regarding URL design, so using a numeric ID might be okay. This could short-circuit all the permalinks hassles this concept might have. Instead, if identified as single request with a numeric ID, you can introduce some code, that sets public_queryable to true on for the single request (single means here, the page-data is requested directly and not for a listing). Some pseudo code:
$postStatusName = \'direct_only_queryable\'; # your custom status
IF is_single_request
AND get_post_status($request_id) == $postStatusName
THEN $GLOBALS[\'wp_post_statuses\'][$postStatusName]->public_queryable = true;
Set within the right place which would be prior to the actual fetching of the models from the database but after you are able to identify the type of request (see Wordpress 3.0 Program Flow (Toolpress PDF) with the need to trace hooks in WP_Query and related), this can work.
It would offer a quite lightweight integration for your feature while making use of core elements to integrate it. Probably some of the plugins listed by Mike are already making use of custom post statuses, so there would already be example code.