I am working on a multi-user WordPress setup and have made it so a particular type of user can only see and interact with posts, images, pages etc that they have authored. The code to make this happen looks like this:

add_filter('pre_get_posts', 'current_author_posts');

function current_author_posts($query) {

    if ($query->is_admin && current_user_can('artist')) {
        global $user_ID;
        $query->set('author', $user_ID);
    }

    return $query;
}

This works well within the admin interface but leaves all of the post counts displaying incorrectly:

image that shows incorrect post counts within WordPress

Are you aware of any filters or hooks to manipulate these figures and be correct across posts, pages, media and custom post types?

Many thanks.

4 s
4

I got this almost working, but refinements are needed to fit the specifics of the question and to deal with Attachments and Post-Types differently (see comments in code)…


First, I think it’s worth noting how I found the filter:
apply_filters( 'views_' . $screen->id, $views )

  • inspect element
    subsubsub

  • do a global search in /wp-admin and /wp-includes for subsubsub (funny class name, btw)…

  • and here it is: /wp-admin/includes/class-wp-list-table.php

foreach( array( 'edit-post', 'edit-page', 'edit-movie', 'upload' ) as $hook )
    add_filter( "views_$hook" , 'wpse_30331_custom_view_count', 10, 1);

function wpse_30331_custom_view_count( $views ) 
{
    global $current_screen;
    switch( $current_screen->id ) 
    {
        case 'edit-post':
            $views = wpse_30331_manipulate_views( 'post', $views );
            break;
        case 'edit-page':
            $views = wpse_30331_manipulate_views( 'page', $views );
            break;
        case 'edit-movie':
            $views = wpse_30331_manipulate_views( 'movie', $views );
            break;
        case 'upload':
            $views = wpse_30331_manipulate_views( 'attachment', $views );
            break;
    }
    return $views;
}

function wpse_30331_manipulate_views( $what, $views )
{
    global $user_ID, $wpdb;

    /*
     * This is not working for me, 'artist' and 'administrator' are passing this condition (?)
     */
    if ( !current_user_can('artist') ) 
        return $views;

    /*
     * This needs refining, and maybe a better method
     * e.g. Attachments have completely different counts 
     */
    $total = $wpdb->get_var("SELECT COUNT(*) FROM $wpdb->posts WHERE (post_status="publish" OR post_status="draft" OR post_status="pending") AND (post_author="$user_ID"  AND post_type="$what" ) ");
    $publish = $wpdb->get_var("SELECT COUNT(*) FROM $wpdb->posts WHERE post_status="publish" AND post_author="$user_ID" AND post_type="$what" ");
    $draft = $wpdb->get_var("SELECT COUNT(*) FROM $wpdb->posts WHERE post_status="draft" AND post_author="$user_ID" AND post_type="$what" ");
    $pending = $wpdb->get_var("SELECT COUNT(*) FROM $wpdb->posts WHERE post_status="pending" AND post_author="$user_ID" AND post_type="$what" ");

    /*
     * Only tested with Posts/Pages
     * - there are moments where Draft and Pending shouldn't return any value
     */
    $views['all'] = preg_replace( '/\(.+\)/U', '('.$total.')', $views['all'] ); 
    $views['publish'] = preg_replace( '/\(.+\)/U', '('.$publish.')', $views['publish'] ); 
    $views['draft'] = preg_replace( '/\(.+\)/U', '('.$draft.')', $views['draft'] ); 
    $views['pending'] = preg_replace( '/\(.+\)/U', '('.$pending.')', $views['pending'] ); 

    // Debug info
    //echo 'Default counts: <pre>'.print_r($views,true).'</pre>';
    //echo '<hr><hr>';
    //echo 'Query for this screen of this post_type: <b>'.$what.'</b><pre>'.print_r($wp_query,true).'</pre>';

    return $views;
}

Leave a Reply

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