Display only the posts authored by the current WP user on the ‘Posts’ page in the back-end

2 Jan

First, Wish you all a Happy New Year! 🙂
Now lets get down to the nerd stuff!
This is a very commonly faced problem by many WP devs. When logged in as a user with a role that is allowed to create / edit posts such as Author, Editor, Contributor or a custom role with the ‘edit_posts’ capability, the posts list on the ‘Posts’ page in the back-end shows all the published posts, even those by other users. The current user can see and edit his own posts, which is fine, but can see user’s posts which seems to be killing the sense of privacy in a multi-user system and is undesired by many developers. Doesn’t it look more secure and sophisticated when the posts list shows only the current users posts? In fact in a system where users are given accounts and privileges to create / edit posts, this fact is very important that they get to see only their work and not others. Also, it will reduce the posts list!

Unfortunately this is not possible with ‘edit_posts’ capability, as it displays all the published posts, and hence this hack can be used.

We’ll use the very well known action hook, ‘pre_get_posts’ for achieving this. If this sounds strange for you, then I suggest you read more on WP Actions and ‘pre_get_posts’ before reading down.

This is the code that’ll do our job:

add_action('pre_get_posts', 'filter_posts_list');
function filter_posts_list($query)
{
	//$pagenow holds the name of the current page being viewed
	 global $pagenow;

	//$current_user uses the get_currentuserinfo() method to get the currently logged in user's data
	 global $current_user;
	 get_currentuserinfo();
    
    	//Shouldn't happen for the admin, but for any role with the edit_posts capability and only on the posts list page, that is edit.php
    	if(!current_user_can('administrator') && current_user_can('edit_posts') && ('edit.php' == $pagenow))
   	 {
		//global $query's set() method for setting the author as the current user's id
		$query->set('author', $current_user->ID); 
    	}
}

That’s it! The code is pretty simple. We hook into ‘pre_get_posts’ which runs before the query for retrieving the posts list is run. Then we check that the current user is not the Admin but has a role with ‘edit_posts’ capability, and use $pagenow global variable to make sure our code is run only on the ‘Posts’ page in the back-end, which is actually named ‘edit.php’. Variable $query is an object of the WP_Query class, and holds the current query for getting the posts. It has a method ‘set’ that allows you to change the arguments of the query. All the parameters that can be used with WP_Query, are valid over here. Hence we set the current user’s id as the ‘Author’, which means the query will now retrieve only the current user’s posts.

Note: You can filter the posts list with any criteria you want using the same method!

Now, if you log in with the role you did this for (not the Admin!), and view the posts list page, you’ll see that it no more displays all the published posts, but only the current users posts.

There’s one more place that will reveal to the current user that there are other posts in this system as well, that is the 3 links that show the posts counts, ‘All’, ‘Published’ and ‘Mine’. As we’re showing the only the current user’s posts, we are interested in ‘Mine’, hence want to hide the other two.

Let’s do it right away. Edit the above code, and add the following lines to it, right after the line ‘$query->set…’:

$screen = get_current_screen();
 add_filter('views_'.$screen->id, 'remove_post_counts');

We’re using an undocumented filter ‘views_’.{screen_id}, which needs the current screen’s id. Hence we use the ‘get_current_screen()’ method for getting the current screen’s id, and append it to ‘view’. The function ‘remove_post_counts’ is as follows:

function remove_post_counts($posts_count_disp)
{
	//$posts_count_disp contains the 3 links, we keep 'Mine' and remove the other two.
	unset($posts_count_disp['all']);
    	unset($posts_count_disp['publish']);
    
    	return $posts_count_disp;
}

Visit the ‘Posts’ page again, and you should see only the current user’s posts count displayed there.

I assume this tutorial will help you achieve a better level of privacy and thus security, if you’re extensively using custom user roles in your system and allowing unknown users to edit posts. You can use the same trick and filter the posts list in the back-end ‘Posts’ page using any criteria you want!

Doubts, comments, criticism… always welcome!

30 Responses to “Display only the posts authored by the current WP user on the ‘Posts’ page in the back-end”