6

I want to restrict users in wordpress to view their own post and media items only. Following the steps given in the below link I have developed the plugin to restrict users to view the own posts and media items only.

https://wordpress.stackexchange.com/a/34858/12615

// Show only posts and media related to logged in 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 );
        add_filter('views_edit-post', 'fix_post_counts');
        add_filter('views_upload', 'fix_media_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="%1$s"%2$s>%4$s <span class="count">(%3$d)</span></a>',
            admin_url('edit.php?post_type=post'),
            $class,
            $result->found_posts,
            __('All')
        );
        elseif( $type['status'] == 'publish' ):
            $class = ($wp_query->query_vars['post_status'] == 'publish') ? ' class="current"' : '';
            $views['publish'] = sprintf(
            '<a href="%1$s"%2$s>%4$s <span class="count">(%3$d)</span></a>',
            admin_url('edit.php?post_type=post'),
            $class,
            $result->found_posts,
            __('Publish')
        );
        elseif( $type['status'] == 'draft' ):
            $class = ($wp_query->query_vars['post_status'] == 'draft') ? ' class="current"' : '';
            $views['draft'] = sprintf(
            '<a href="%1$s"%2$s>%4$s <span class="count">(%3$d)</span></a>',
            admin_url('edit.php?post_type=post'),
            $class,
            $result->found_posts,
            __('Draft')
        );
        elseif( $type['status'] == 'pending' ):
            $class = ($wp_query->query_vars['post_status'] == 'pending') ? ' class="current"' : '';
            $views['pending'] = sprintf(
            '<a href="%1$s"%2$s>%4$s <span class="count">(%3$d)</span></a>',
            admin_url('edit.php?post_type=post'),
            $class,
            $result->found_posts,
            __('Pending')
        );
        elseif( $type['status'] == 'trash' ):
            $class = ($wp_query->query_vars['post_status'] == 'trash') ? ' class="current"' : '';
            $views['trash'] = sprintf(
            '<a href="%1$s"%2$s>%4$s <span class="count">(%3$d)</span></a>',
            admin_url('edit.php?post_type=post'),
            $class,
            $result->found_posts,
            __('Trash')
        );
        endif;
    }
    return $views;
}

// Fix media counts
function fix_media_counts($views) {
    global $wpdb, $current_user, $post_mime_types, $avail_post_mime_types;
    $views = array();
    $count = $wpdb->get_results( "
        SELECT post_mime_type, COUNT( * ) AS num_posts 
        FROM $wpdb->posts 
        WHERE post_type = 'attachment' 
        AND post_author = $current_user->ID 
        AND post_status != 'trash' 
        GROUP BY post_mime_type
    ", ARRAY_A );
    foreach( $count as $row )
        $_num_posts[$row['post_mime_type']] = $row['num_posts'];
    $_total_posts = array_sum($_num_posts);
    $detached = isset( $_REQUEST['detached'] ) || isset( $_REQUEST['find_detached'] );
    if ( !isset( $total_orphans ) )
        $total_orphans = $wpdb->get_var("
            SELECT COUNT( * ) 
            FROM $wpdb->posts 
            WHERE post_type = 'attachment'
            AND post_author = $current_user->ID 
            AND post_status != 'trash' 
            AND post_parent < 1
        ");
    $matches = wp_match_mime_types(array_keys($post_mime_types), array_keys($_num_posts));
    foreach ( $matches as $type => $reals )
        foreach ( $reals as $real )
            $num_posts[$type] = ( isset( $num_posts[$type] ) ) ? $num_posts[$type] + $_num_posts[$real] : $_num_posts[$real];
    $class = ( empty($_GET['post_mime_type']) && !$detached && !isset($_GET['status']) ) ? ' class="current"' : '';
    $views['all'] = "<a href='upload.php'$class>" . sprintf( __('All <span class="count">(%s)</span>', 'uploaded files' ), number_format_i18n( $_total_posts )) . '</a>';
    foreach ( $post_mime_types as $mime_type => $label ) {
        $class = '';
        if ( !wp_match_mime_types($mime_type, $avail_post_mime_types) )
            continue;
        if ( !empty($_GET['post_mime_type']) && wp_match_mime_types($mime_type, $_GET['post_mime_type']) )
            $class = ' class="current"';
        if ( !empty( $num_posts[$mime_type] ) )
            $views[$mime_type] = "<a href='upload.php?post_mime_type=$mime_type'$class>" . sprintf( translate_nooped_plural( $label[2], $num_posts[$mime_type] ), $num_posts[$mime_type] ) . '</a>';
    }
    $views['detached'] = '<a href="upload.php?detached=1"' . ( $detached ? ' class="current"' : '' ) . '>' . sprintf( __( 'Unattached <span class="count">(%s)</span>', 'detached files' ), $total_orphans ) . '</a>';
    return $views;
}

It works well but the post count does not work for custom post type.

i.e All | Published | Drafts | Pending | Trash - counts for custom posts does not work.

For user as admin these are the screenshots for post_type = "post" and post_type= "gallery"

enter image description here

enter image description here

For user as atuhor these are the screenshots for post_type = "post" and post_type= "gallery".

The post count works well for post_type = "post" but when it comes to post_type= "gallery" in second screenshot there is a problem in the

All | Published | Drafts | Pending | Trash | ,part

I applied the above code and got the results as given in image below, the posts count is one but none is displayed as the post is of another user.

What i want to correct is the post count!!!

This is the image in which the post count is 0 for post_type= "posts" which is correct and wanted it to be followed for gallery enter image description here

This is the image in which the post count is 1 for post_type= "gallery" which is wrong as it should be 0 and should be followed same as in the case of posts. enter image description here

  • Please, post the code you are using and the custom post type information. – cybmeta Feb 16 '15 at 8:51
  • Its already there on the link but I have mentioned it now ...@cybmeta – Shahrukh Khan Feb 16 '15 at 10:40
  • You said that you have follow instructions, that doesn't mean that you are using the same exact code. – cybmeta Feb 16 '15 at 10:44
  • I've deleted my answer because, after reading all your comments, it is not clear what you are asking. The title of your question says "restricting to view own posts" but then you say that zero count when other users have posts is wrong. I don't understand. Please, explain what the count should be instead of claiming "What i want to correct is the post count!!!" with no explanation of what it should be. – cybmeta Feb 17 '15 at 13:54
  • @cybmeta i hope i am clear this time.....i have marked red in the photo and want the 4th pictures case to be followed similar to 3rd pictures case – Shahrukh Khan Feb 17 '15 at 15:04
7

You have to change:

'post_type'   => 'post',

To:

'post_type'   => 'your_custom_post_type_name',

And a all the reference to standard post. Also, you should add the filters only for main query or you can end up with issues in secondary queries. Bellow an example code for gallery custom post type. I was trying to debug the code you posted (taken from somewhre) but finally I've decided to post a working code I already use, which is much cleaner (it doesn't include the counter for media (uploads) but, as your question suggest, you have not problems with that).

add_action( 'pre_get_posts', function( $query ) {

    //Note that current_user_can('edit_others_posts') check for
    //capability_type like posts, custom capabilities may be defined for custom posts
    if( is_admin() && ! current_user_can('edit_others_posts') && $query->is_main_query() ) {

        $query->set('author', get_current_user_id());

        //For standard posts
        add_filter('views_edit-post', 'views_filter_for_own_posts' );

        //For gallery post type
        add_filter('views_edit-gallery', 'views_filter_for_own_posts' );

        //You can add more similar filters for more post types with no extra changes
    }

} );

function views_filter_for_own_posts( $views ) {

    $post_type = get_query_var('post_type');
    $author = get_current_user_id();

    unset($views['mine']);

    $new_views = array(
            'all'       => __('All'),
            'publish'   => __('Published'),
            'private'   => __('Private'),
            'pending'   => __('Pending Review'),
            'future'    => __('Scheduled'),
            'draft'     => __('Draft'),
            'trash'     => __('Trash')
            );

    foreach( $new_views as $view => $name ) {

        $query = array(
            'author'      => $author,
            'post_type'   => $post_type
        );

        if($view == 'all') {

            $query['all_posts'] = 1;
            $class = ( get_query_var('all_posts') == 1 || get_query_var('post_status') == '' ) ? ' class="current"' : '';
            $url_query_var = 'all_posts=1';

        } else {

            $query['post_status'] = $view;
            $class = ( get_query_var('post_status') == $view ) ? ' class="current"' : '';
            $url_query_var = 'post_status='.$view;

        }

        $result = new WP_Query($query);

        if($result->found_posts > 0) {

            $views[$view] = sprintf(
                '<a href="%s"'. $class .'>'.__($name).' <span class="count">(%d)</span></a>',
                admin_url('edit.php?'.$url_query_var.'&post_type='.$post_type),
                $result->found_posts
            );

        } else {

            unset($views[$view]);

        }

    }

    return $views;
}
  • i have posted my code and did changes as you told. please check if you understand @cybmeta – Shahrukh Khan Feb 17 '15 at 10:08
  • First, your question was about making the code you posted working for custom post types, and that is what I did in the answer. Second, I've read your comment and you are confused. You have limited the post counters to posts that belongs to current user, so if the user have zero posts, zero is what you get. The "All" counter doesn't mean "post from All users", it means "post from All status". As you can see, the different post counters are for post status: All, draft, published, etc. If you want to modify this you should post another question because it is really different from the original. – cybmeta Feb 17 '15 at 10:29
  • I have updated the content....i hope you can now understand what i mean. The output for posts and gallery are different and i want output of gallery similar as that of posts. – Shahrukh Khan Feb 17 '15 at 13:22
  • Answer updated. – cybmeta Feb 17 '15 at 16:32
  • From the little I could experiment, I see no need for $author, get_current_user_id() or 'author' => $author. If you just remove them all, it will work better because it will work just as well for the current situation plus it will also be good for different pre_get_posts queries. – cregox Oct 9 '15 at 11:10

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.