Hide other users posts in the backend

In WordPress you can hide other users posts in the backend for those who should not see them. Authors see every post but are not capable of editing them, which can be really frustrating. Two short snippets help cleaning up the post lists programatically.Read the more up to date and famous one afterwards!
Recent changes with WordPress 4.7
Open in new tab for later

In general the user rights in WordPress are limited and it needs some workarounds like this one. Please leave a comment below with some other user rights that you like to solve but didn’t found it in the core – I will try to find a way.

The edit_others_posts capability show other users content

Capabilities are in WordPress to allow or reject a user access to some areas in the backend. One of them is “edit_others_posts” which is enabled for users like the Administrator. It simply says that you can edit any post you like in the whole webpage. Setting this capability to “false” or removing it will suppress this right.

An user with the author role does not have the edit_others_posts right (see “Roles and Capabilities“). He can open a post and change the text in the editor. Once the Author tries to save his changes WordPress comes up with an error message that he is not allowed to do that. This is late, too late. WordPress allows the Author to see a full list of every post even those he isn’t allowed to change.

This is some bad user experience so I like to stop it very early. In addition it was a requirement recently which I like to share with you. Below you’ll find two snippets that hide other users posts. In that way an Author won’t waste time editing posts and being rejected when it comes to publishing or saving it. Plus it is not that easy to look inside others posts and mess up categories, as this is a complete different capability. So, lets obscure.

Hide other users posts

Lets change the lists in the backend. There is still this one role that has not the rights to edit others posts so all foreign posts shall disappear in his list. This can be done by a simple filter:

/**
 * Show only entries of the current user.
 *
 * @param \WP_Query $query
 */
function show_only_editable( $query ) {
  if ( ! $query->is_admin
       || ! $query->is_main_query()
       || ! $query->get( 'post_type' )
       || current_user_can( 'edit_others_posts' )
  ) {
    // neither query nor cap correct => ignore
    return;
  }

  // Here is a place to be more picky (read on)

  // only show user entries for the current user
  $query->set( 'author', get_current_user_id() );
}

// now register this in WordPress
function hide_others_posts_feature() {
  add_filter( 'pre_get_posts', 'show_only_editable' );
}

add_action( 'admin_init', 'hide_others_posts_feature' );

Only shrink down some post types

Below the picky comment you can place another if-statement to only shrink down lists for a set of post types:

$allowed_post_types = get_option( 'my_cpt', array( 'post', 'page' ) );

if ( ! in_array( $query-get( 'post_type' ), $allowed_post_types ) {
  // found in settings => current post type shall not be filtered
  return;
}

Now there is even an option which can be maintained from any other point in the backend. Every post type that could not be found in the in_array statement will not be filtered in the backend. So only the lists for “post” and “page” will be shrink down to the entries that are made by the current user. Other lists like “attachment” (media) will always show what other users uploaded.

Assure this is done at only some lists

This is almost the same as shrinking down the list for some post types. But it adds one assertion that the current view is really the correct part of the backend:

if ( 'edit-post' != get_current_screen()->id ) {
  // not the edit post list => ignore
  return;
}

Place this in the function under the “lets be picky”-comment. It makes it a bit more stable and you have the possibility to allow the filter in only some lists like “edit-post”, “edit-page” or other.

Correct the counting numbers

A post list with no entries and wrong counters on top.
The post list has wrong counters.

Now we have one last enemy. There will be only posts listed that belong to the current user but the numbers above the list are wrong, as you see in the screenshot. The counters still show the amount of entries a user with the capability “readable” would see. Fortunately there is a filter for that:

/**
 * Calc posts by the "edit_others_posts" capability.
 * 
 * @param int    $counts Number of found posts.
 * @param string $type   Post type.
 *
 * @return object Number of posts for each status.
 */
function recalc_count_posts( $counts, $type ) {
  if ( current_user_can( 'edit_others_posts' ) ) {
    // user is allowed to do so => number count is already correct
    return $counts;
  }

  if ( 'edit-post' == get_current_screen()->id ) {
    // not our location => keep count as it is
    return $counts;
  }

  return wp_count_posts( $type, 'edit_others_posts' );
}

add_filter( 'wp_count_posts', 'no_filter_navigation', 10, 2 );

Again this function early exists when the current user is capable of editing others posts. It needs to exit too, if the current screen is not the list of posts. But if so, then it shall recalculate the amount of posts based on the “edit_others_posts” right. Now the numbers look good:

Completely hide other users posts in the backend with correct numbering.
Completely hide other users posts in the backend with correct numbering.

This user has no posts and so it is correctly shown above the list as “All (0)”.

Conclusion after working with capabilities

First of all: This is one way how it can be done. Another way would be removing the edit link from all posts that are made by the current user. An even simpler solution, if you like it.

WordPress offer a lot of capabilities and filter. You can regulate plenty things with them even for custom post types. This is great once you know some of them and how to use it.

Unfortunately working with those capabilities lead to some weird user experience. Some of my projects have Authors as a role and customers always ask why they see the entries of other users. There are even more obstacles when it comes to very granular user rights like one user vs. one single post. But WordPress does not allow that by default but offers plenty hooks to solve it.

Please write a comment if you have more common scenarios that lead to a suspicious user interface. I like to gather them in a plugin so that the backend of WordPress gets a bit better.

 

Leave a Reply

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