8

I have been looking for ways to completely remove the All, Published, and Trash webpages for USERS other than the me, the Administrator.

So the scenario for me is: I have registered users (which I would like to assign with the roles of authors, contributors, etc). Now, when they log in to my website and access the Posts area, I wish for them not to see these three links (All, Published, Trash).

I have tried using the jquery function, which is basically the same as display: none, but I don't think it's the optimal choice. I know there's better ways for me to do this.

I did try using plugins, such as Member and Adminimize, among other things, but I can't find the right one.

I hope there's someone out there who can help me. Thanks in advance.

Remove All, Published, and Trash

3 Answers 3

6

The WP_Posts_List_Table class extends WP_List_Table and within the WP_List_Table::views() method we have the following dynamic views filter:

/**
 * Filter the list of available list table views.
 *
 * The dynamic portion of the hook name, `$this->screen->id`, refers
 * to the ID of the current screen, usually a string.
 *
 * @since 3.5.0
 *
 * @param array $views An array of available list table views.
 */
 $views = apply_filters( "views_{$this->screen->id}", $views );

So we can use the generated views_edit-post filter to adjust the views of the post list table.

Example:

Let's remove the all, publish, future, sticky, draft, pending and trash for non-admins (PHP 5.4+):

/**
 * Remove the 'all', 'publish', 'future', 'sticky', 'draft', 'pending', 'trash' 
 * views for non-admins
 */
add_filter( 'views_edit-post', function( $views )
{
    if( current_user_can( 'manage_options' ) )
        return $views;

    $remove_views = [ 'all','publish','future','sticky','draft','pending','trash' ];

    foreach( (array) $remove_views as $view )
    {
        if( isset( $views[$view] ) )
            unset( $views[$view] );
    }
    return $views;
} );

where you can modify the $remove_views to your needs. Another approach would be to only pick up mine and only return that view.

Then we could try to force the mine view further with:

/**
 * Force the 'mine' view on the 'edit-post' screen
 */
add_action( 'pre_get_posts', function( \WP_Query $q )
{
    if( 
           is_admin() 
        && $q->is_main_query() 
        && 'edit-post' === get_current_screen()->id 
        && ! current_user_can( 'manage_options' )
    )
        $q->set( 'author', get_current_user_id() ); 
} );

Before:

before

After:

after

5
  • You're welcome and hopefully you can adjust it to your needs @chest_nut
    – birgire
    Commented Apr 20, 2016 at 13:36
  • Yes, thank you! I surely will. I'm still learning and it's amazing that you guys are here to help us out. :) @birgire
    – chest_nut
    Commented Apr 20, 2016 at 13:40
  • For custom post types, the filter is views_edit-my_custom_post_type. Refer to the Admin Screen Reference here codex.wordpress.org/Plugin_API/Admin_Screen_Reference
    – Ben
    Commented May 19, 2018 at 18:48
  • I think its better to use wp_count_posts, check the $type that is passed, and unset the desired indexes.
    – Mort 1305
    Commented May 28, 2020 at 6:42
  • 1
    How will that remove the "All" view, as asked by OP? There are also two wp_count_posts() calls in the list table, so one would have to look closer into that to make sure there are no side effects (avoid counting irregularities), as the other instance seems to be affecting the total items count in only some cases. More context is needed than only $type, as the function can be used everywhere. Plugins can also add their own wp_count_posts() calls, e.g. as a bubble count in admin menu that runs on the same page. WooCommerce does this for eg the shop_order post type.
    – birgire
    Commented May 28, 2020 at 11:22
2

Those statuses are turned from get_available_post_statuses(), which in turn gets its values from wp_count_posts().

wp_count_posts() passes it's values through the wp_count_posts filter. So you can tap into that and hijack what gets returned.

Try this:

function _dbdb_wp_count_posts( $counts, $type, $perm ) {
    global $pagenow;

    if( 'edit.php' !== $pagenow ){
        return $counts;
    }

    if( current_user_can( 'manage_options' ) ){
        return $counts;
    }

    $_counts = new stdClass();
    foreach ( $counts as $status => $count ){
        $_counts->$status = '';
    }

    return $_counts;
}
add_filter('wp_count_posts', '_dbdb_wp_count_posts', 99, 3 );

What this does is check if we're on the edit.php page in the Admin,and if not, just return the counts.

Then it checks if the current user can manage site options, which only an Administrator can. If the current user can, all counts are returned.

If you get past this check, it assumes you're not an Administrator, so it resets all counts to 0, effectively removing the status links.

Note: the "all" and "mine" status links are hard-coded in the get_views() method of the WP_Posts_List_Table Class and aren't filterable.

I quickly tested this on my dev server, first signing in as an Admin, and then as an Author. It worked as expected, but be sure to test thoroughly.

4
  • 1
    Thank you for your response. The Published and Trash links are gone. However, I still have the All link, even though its counter is at zero, the link is still active and it brings me to the list of all the posts. Hmm... I'm not sure if that's what's appearing on your end as well?
    – chest_nut
    Commented Apr 19, 2016 at 15:49
  • 1
    Yes. I mentioned that in my answer. The "all" link and the "mine" are hard-coded, not passed through s filter like the others. They can't be removed, only hidden.
    – darrinb
    Commented Apr 19, 2016 at 17:05
  • 1
    I see, thank you @darrinb . Guess I will just hide the All link then. Thanks a lot. I'm still new on WP development I really am wanting to learn as much as I can. Anyway, thanks again, really appreciate it.
    – chest_nut
    Commented Apr 20, 2016 at 0:48
  • 1
    No problem! Glad I could help! If this worked for you, be sure to accept the answer so others know.
    – darrinb
    Commented Apr 20, 2016 at 2:17
0

Return only "Mine" status

add_filter( 'views_edit-{your-cpt}', function( $views ) {           
   if ( current_user_can( 'manage_options' ) ) {
      return $views;
   }
   return array_filter( $views, fn( $i ) => 'mine' === $i, ARRAY_FILTER_USE_KEY );
} );

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.