4

I'm currently trying to modify my WordPress site so that Authors can not see a specific Admin's posts while editing, but are still able to see each other's posts (as well as the other Admins).

With the following code I can make it so that Authors can only view their own posts, and only their posts are counted within the post count.

How can I modify it so that it only hides a specific Admin's posts and post count?

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;
}
2

Try this - rather than redo all the hard work that WordPress does for the view links, just calculate all the posts for the admin you want to "hide" and subtract from the existing post counts:

function wpse_229427_get_hidden_admin_id() {
    return 3; // You could make this a setting or return a value conditionally
}

function wpse_229427_hide_admin_posts( $wp_query ) {
    if ( is_admin() && ! current_user_can( 'edit_others_posts' ) && ! $wp_query->get( 'author' ) ) {
        $wp_query->set( 'author__not_in', [ wpse_229427_get_hidden_admin_id() ] );
    }
}

add_action( 'pre_get_posts', 'wpse_229427_hide_admin_posts' );

function wpse_229427_adjust_counts( $counts, $type ) {
    if ( $type === 'post' && is_admin() && ! current_user_can( 'edit_others_posts' ) ) {
        global $wpdb;

        $admin_id = wpse_229427_get_hidden_admin_id();
        $items    = $wpdb->get_results(
            $wpdb->prepare(
                "SELECT post_status, COUNT( * ) AS `count` FROM {$wpdb->posts} WHERE post_type = 'post' AND post_author = %d GROUP BY post_status",
                $admin_id
            )
        );

        foreach ( $items as $item ) {
            if ( isset( $counts->{$item->post_status} ) )
                $counts->{$item->post_status} -= $item->count;
        }
    }

    return $counts;
}

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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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