WordPress by default shows ALL posts to users who are Authors. I wanted Authors to only be able to see their own posts so I came up with the following code which works well.

Any suggestions to condense/optimize it?

// Only show posts related to current author
add_action('pre_get_posts', 'query_set_only_author' );
function query_set_only_author( $wp_query ) {
    global $current_user;
    if ( is_admin() && !current_user_can('edit_others_posts') ) {
        $wp_query->set( 'author', $current_user->ID );
    }
}

// Check that user is not an Administrator
if (!current_user_can('promote_users')) {
    add_filter('views_edit-post', 'remove_mine');
    add_filter('views_edit-post', 'posts_all');
    add_filter('views_edit-post', 'posts_published');
    add_filter('views_edit-post', 'posts_draft');
    add_filter('views_edit-post', 'posts_pending');
    add_filter('views_edit-post', 'posts_trash');
}

// Remove "Mine" from filter bar
function remove_mine( $views ) {
    unset($views['mine']);
    return $views;
}

// Fix "All" post count to only include posts related to current author
function posts_all($views) {
    global $current_user;   
    $query = array(
        'author'       => $current_user->ID,
        'post_type'    => 'post'
    );
    $result = new WP_Query($query);
    if ( get_query_var('post_status') == NULL ) $class = ' class="current"';
    $link = sprintf(__('<a href="%s"'.$class.'>All <span class="count">(%d)</span></a>', 'all'),
            admin_url('edit.php?post_type=post'),
            $result->found_posts);
    $views['all'] = $link;
    return $views;
}

// Fix "Published" post count to only include posts related to current author
function posts_published($views) {
    global $current_user;   
    $query = array(
        'author'       => $current_user->ID,
        'post_status'  => 'publish',
        'post_type'    => 'post'
    );
    $result = new WP_Query($query);
    if ( get_query_var('post_status') == 'publish' ) $class = ' class="current"';
    $link = sprintf(__('<a href="%s"'.$class.'>Published <span class="count">(%d)</span></a>', 'publish'),
            admin_url('edit.php?post_status=publish&post_type=post'),
            $result->found_posts);
    $views['publish'] = $link;
    return $views;
}

// Fix "Drafts" post count to only include posts related to current author
function posts_draft($views) {
    global $current_user;   
    $query = array(
        'author'       => $current_user->ID,
        'post_status'  => 'draft',
        'post_type'    => 'post'
    );
    $result = new WP_Query($query);
    if ( get_query_var('post_status') == 'draft' ) $class = ' class="current"';
        $link = sprintf(__('<a href="%s"'.$class.'>Draft'.((sizeof($result->posts)>1)?"s":"").' <span class="count">(%d)</span></a>', 'draft'),
            admin_url('edit.php?post_status=draft&post_type=post'),
            $result->found_posts);
    $views['draft'] = $link;
    return $views;
}

// Fix "Pending" post count to only include posts related to current author
function posts_pending($views) {
    global $current_user;   
    $query = array(
        'author'       => $current_user->ID,
        'post_status'  => 'pending',
        'post_type'    => 'post'
    );
    $result = new WP_Query($query);
    if ( get_query_var('post_status') == 'pending' ) $class = ' class="current"';
        $link = sprintf(__('<a href="%s"'.$class.'>Pending <span class="count">(%d)</span></a>', 'pending'),
            admin_url('edit.php?post_status=pending&post_type=post'),
            $result->found_posts);
    $views['pending'] = $link;
    return $views;
}

// Fix "Trash" post count to only include posts related to current author
function posts_trash($views) {
    global $current_user;   
    $query = array(
        'author'       => $current_user->ID,
        'post_status'  => 'trash',
        'post_type'    => 'post'
    );
    $result = new WP_Query($query);
    if ( get_query_var('post_status') == 'trash' ) $class = ' class="current"';
    $link = sprintf(__('<a href="%s"'.$class.'>Trash <span class="count">(%d)</span></a>', 'trash'),
            admin_url('edit.php?post_status=trash&post_type=post'),
            $result->found_posts);
    $views['trash'] = $link;
    return $views;
}
link|improve this question
feedback

2 Answers

up vote 3 down vote accepted

Ok I figured it out. Here's the optimized code:

// Show only posts related to current user
add_action('pre_get_posts', 'query_set_only_author' );
function query_set_only_author( $wp_query ) {
    global $current_user;
    if( is_admin() && !current_user_can('edit_others_posts') ) {
        $wp_query->set( 'author', $current_user->ID );
        add_filter('views_edit-post', 'fix_post_counts');
    }
}

// Fix post counts
function fix_post_counts($views) {
    global $current_user, $wp_query;
    unset($views['mine']);
    $types = array(
        array( 'status' =>  NULL ),
        array( 'status' => 'publish' ),
        array( 'status' => 'draft' ),
        array( 'status' => 'pending' ),
        array( 'status' => 'trash' )
    );
    foreach( $types as $type ) {
        $query = array(
            'author'      => $current_user->ID,
            'post_type'   => 'post',
            'post_status' => $type['status']
        );
        $result = new WP_Query($query);
        if( $type['status'] == NULL ):
            $class = ($wp_query->query_vars['post_status'] == NULL) ? ' class="current"' : '';
            $views['all'] = sprintf(__('<a href="%s"'. $class .'>All <span class="count">(%d)</span></a>', 'all'),
                admin_url('edit.php?post_type=post'),
                $result->found_posts);
        elseif( $type['status'] == 'publish' ):
            $class = ($wp_query->query_vars['post_status'] == 'publish') ? ' class="current"' : '';
            $views['publish'] = sprintf(__('<a href="%s"'. $class .'>Published <span class="count">(%d)</span></a>', 'publish'),
                admin_url('edit.php?post_status=publish&post_type=post'),
                $result->found_posts);
        elseif( $type['status'] == 'draft' ):
            $class = ($wp_query->query_vars['post_status'] == 'draft') ? ' class="current"' : '';
            $views['draft'] = sprintf(__('<a href="%s"'. $class .'>Draft'. ((sizeof($result->posts) > 1) ? "s" : "") .' <span class="count">(%d)</span></a>', 'draft'),
                admin_url('edit.php?post_status=draft&post_type=post'),
                $result->found_posts);
        elseif( $type['status'] == 'pending' ):
            $class = ($wp_query->query_vars['post_status'] == 'pending') ? ' class="current"' : '';
            $views['pending'] = sprintf(__('<a href="%s"'. $class .'>Pending <span class="count">(%d)</span></a>', 'pending'),
                admin_url('edit.php?post_status=pending&post_type=post'),
                $result->found_posts);
        elseif( $type['status'] == 'trash' ):
            $class = ($wp_query->query_vars['post_status'] == 'trash') ? ' class="current"' : '';
            $views['trash'] = sprintf(__('<a href="%s"'. $class .'>Trash <span class="count">(%d)</span></a>', 'trash'),
                admin_url('edit.php?post_status=trash&post_type=post'),
                $result->found_posts);
        endif;
    }
    return $views;
}
link|improve this answer
In case anyone is interested, I updated this code to also filter media by author and fix the media count. You can see the complete code here: wordpress.stackexchange.com/questions/1567/… – Paul Nov 27 '11 at 19:56
Paul...have you tried this code without the "views_edit-post" filter? I would think that with you adjusting the query vars at the time of "pre_get_posts", these values would likewise be changed. I'm just curious if it would work without that filter. – tollmanz Nov 28 '11 at 2:24
You'll notice with every other solution available on the web to only show posts related the the current user, it still does not fix the post count. Without this filter, the post count still reflects the number of posts from all users (e.g. All | Published | Drafts | Pending | Trash), even though the posts themselves are filtered. – Paul Nov 28 '11 at 8:43
feedback

First of all Paul thanks for this fantastic code.

But I need some modification and as I am not php guy need little help to fix.

I am having another code to show only author post (not count) but now I want to use that code with this post count code. Can anyone help me to make it works both together.

I have this code and want to use so I can change post visible according to role and will take a second to do by changing role number.

function posts_for_current_author($query) {
    global $user_level;

    if($query->is_admin && $user_level < 8) {
        global $user_ID;
        $query->set('author',  $user_ID);
        unset($user_ID);
    }
    unset($user_level);

    return $query;
}
add_filter('pre_get_posts', 'posts_for_current_author');

and for post count I am using first answer code of Paul of the main question of the post. I want to combine both code together as I said above.... Thank you.

link|improve this answer
Thanks One Trick Pony but getting undefined varialble error. As I mentioned I am not php guy just now started to learn. Can you please help me to get full code? – pixelngrain Dec 15 '11 at 11:54
I found error while debugging Undefined index on below codes $class = ($wp_query->query_vars['post_status'] == NULL) ? ' class="current"' : ''; $class = ($wp_query->query_vars['post_status'] == 'publish') ? ' class="current"' : ''; $class = ($wp_query->query_vars['post_status'] == 'draft') ? ' class="current"' : ''; $class = ($wp_query->query_vars['post_status'] == 'pending') ? ' class="current"' : ''; $class = ($wp_query->query_vars['post_status'] == 'trash') ? ' class="current"' : ''; – pixelngrain Dec 15 '11 at 12:12
Did you try adding: add_filter('views_edit-post', 'fix_post_counts'); to if($query->is_admin && $user_level < 8) {}? – Paul Feb 3 at 2:16
Alright will try and get back to you.. thanks again :) – pixelngrain Feb 6 at 7:35
feedback

Your Answer

 
or
required, but never shown

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