I have several unpublished posts in my WordPress website and I am trying to make it accessible for normal users (who are not logged in) using the normal post slugs (site.com/post-here
). I understand it may not be the best practice but for my special purpose, this needs to be done.
I have tried adding the following code snippet into my functions.php
file:
function enable_view_drafts() {
$role = get_role( 'subscriber' );
$role->add_cap( 'read_private_posts' );
$role->add_cap( 'edit_posts' );
}
add_action( 'after_setup_theme', 'enable_view_drafts');
I’ve also tried init
hook instead of after_setup_theme
. No luck.
My understanding is that changes to roles are saved to the database so only need to be done once. That is why I’m using after_setup_theme
hook to call the function.
But when I try to access the page as a normal user, I’m being shown a 404 page instead of showing the post content. I’ve also tried loading the preview URL (site.com/?p=212&preview=true
) but that didn’t work either.
These are my guesses:
- the normal user doesn’t have enough
caps
to read the drafts post. - testing and viewing draft posts on the front-end is not possible for any users (including administrators).
What changes do I have to make in order to accomplish what I’m trying to do? If it’s not possible, what alternative solutions do you suggest?
Note: I’m not looking for plugin-based solutions.
You cannot assign capabilities to unknown users. If you want to make a post visible for everyone, create a separate URL for these posts and add a control element to the post editor to enable the preview on selected posts only.
When such an URL is called, check if a preview is allowed for the post and if the post hasnât been published already. Also make sure search engines ignore this URL.
For the URL I would use an endpoint:
Now you can create URLs like â¦
⦠where
123
ist the post ID.Then use a callback handler to inspect the post ID, check if it is valid and overwrite the main query. This is probably the only acceptable use case for
query_posts()
. 🙂Letâs say the endpoint is a class
T5_Endpoint
(a model), and the output handler is a classT5_Render_Endpoint
(a view) which gets the model passed earlier. Then there is probably a methodrender()
called ontemplate_redirect
:$this->meta
is another model (classT5_Post_Meta
) for the post meta value that controls if a preview is allowed. The control is set into the Publish box (actionpost_submitbox_misc_actions
), rendered by another view that gets the same meta class.So
T5_Post_Meta
knows where and when to store the meta value, the views do something with it.Also, hook into
transition_post_status
to delete the post meta field when the post is published. We donât want to waste resources, right?This is just an outline. There are many details to cover ⦠I have written a small plugin that shows how to implement this: T5 Public Preview.
I solved this problem in what I thought was a simpler way than @toscho’s answer above.
My use case is I’m using the same database for an internal intranet staging site and a public-facing site, and the workflow is that authors write drafts and share it with other users who view those drafts on the intranet site, before publishing. I specifically didn’t want to require reviewers to log in to see drafts, so I’m just depending on a constant,
ENV_PRODUCTION
which is set in the wp-config file based on the hostname in$_SERVER['SERVER_NAME']
. Thats what the checks forENV_PRODUCTION
here are doing; just shorting out all of these filters if the production site is being viewed.This is a little weird, because you have to hook in after WP_Query removes all of the posts from the $wp_query->posts array, but it seems stable and secure to me.
There’s two separate parts to the filters.
I think the “User Role Editor” plugin available at WordPress.org’s website might be what you’re looking for. By the way, why do you want to give access to your drafts to everybody? I personally can’t think of an instance where this would be required.
I think G.M.’s comment is the best one here.
I assume you are trying to do the following:
Is that correct?
Unfortunately, I can’t think of any simple way to do this. You could post it as a private post so that they need to enter a password to view it but you need to be logged in for this.
You could also password protect it, but then it will still appear in your feed and list of recent posts, etc.
Could you not create a guest user account and give them the username/password when you give them the URL?
Read here for more info: http://codex.wordpress.org/Content_Visibility
Alternatively, there is a plugin that might suit your needs: http://wordpress.org/extend/plugins/shareadraft/
I had a quick look at the code and it appears the developer is modifying the value returned by get_post_status so you might be able to play around with that:
http://codex.wordpress.org/Function_Reference/get_post_status
HTH
You could just change the visibility on the page/post to “Private” which is only visible to Editors and Administrators and not public visitors, search engines, rss feeds, etc.