TransWikia.com

How to restrict subscriber editing other posts but read specific posts in backend

WordPress Development Asked by Juliana Jul on December 15, 2021

I need to allow Subscribers to edit their posts (done) and read (see in backend) posts of specific author or with specific ID (to make copies of it). I found the code, but that’s not enough:

function posts_for_current_author ($query) {
        if( $query->is_admin && 'edit.php' == $GLOBALS['pagenow'] && !current_user_can( 'edit_others_posts' ) ) {
            $query->set('author', $GLOBALS['user_ID'] );
        }
        return $query;
    };
    add_filter('pre_get_posts', 'posts_for_current_author');

One Answer

To query posts with more than one author ID, you can use author__in parameter. This makes posts from chosen authors visible (read only) for the current user.

add_filter('pre_get_posts', 'posts_for_current_author');
function posts_for_current_author($query) {
    if (
        $query->is_admin &&
        'edit.php' === $GLOBALS['pagenow'] &&
        ! current_user_can( 'edit_others_posts' )
    ) {
        $query->set('author__in', array(get_current_user_id(), 1, 2, 3) ); // add 1 or more user IDs
    }
    return $query;
};

One option query posts with multiple author IDs and post IDs is to manipulate the where clause with posts_where filter. I picked idea for this from an old WPSE Q&A. This makes posts from chosen authors and chosen posts visible (read only) to the current user.

With this you can do OR comparison instead of AND, which using both author__in and post__in in pre_get_posts would cause. (At least based on the test I ran locally)

add_filter( 'posts_where', 'wpse_posts_where' );
function wpse_posts_where( $where ) {
    if (
        is_admin() &&
        'edit.php' === $GLOBALS['pagenow'] &&
        ! current_user_can( 'edit_others_posts' )
    ) {
        remove_filter( current_filter(), __FUNCTION__ );
        global $wpdb;

        $current_user_id = get_current_user_id();
        $authors = array(
            $current_user_id,
            1,
            2,
            3,
        );

        $posts = array(
            1,
            2,
            3,
        );

        return str_ireplace(
            "{$wpdb->posts}.post_author in ({$current_user_id})",
            sprintf(
                "({$wpdb->posts}.post_author in (%s) OR {$wpdb->posts}.ID in (%s))",
                implode(',', $authors),
                implode(',', $posts)
            ),
            $where
        );
    } else {
        return $where;
    }
}

Answered by Antti Koskinen on December 15, 2021

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP