Showing comments only to same custom user role
-
19-04-2021 - |
Question
Is there a way I could show only the comments by a particular user role to his same user role?
For example: The logged in user belongs to the "Advertisers" user role, he should only see the comments made by him and all users under his role.
Thank you.
Solution
Yes you can,
Frontend only
you would need to check each post comment author for it's role. If the role of that comment author is not adverstisers then remove it from the array of comments attached to that post.
Then you would have to return only the comments if the current logged in user is also from the advertisers role.
using the comments_array
filter we can go over each comments attached to a post. But this filter is applied in comments_template so it won't affect the access comments in backend.
Here's how you can do it
add_filter( 'comments_array' , 'wpse_filter_by_role_frontend' , 10, 2 );
function wpse_filter_by_role_frontend( $comments, $post_id ){
$current_user = wp_get_current_user(); // retrieve the currently logged in user
// go over each comments for the current post
foreach( $comments as $key => $comment ){
$comment_author = new WP_User( $comment->user_id ); // for each comment get the author user object
// here we say unset the current comment if the role of the comment author is not the same as the role of the logged in user
if( $comment_author->roles[0] != $current_user->roles[0] ){
unset( $comments[$key] );
}
}
// Return the filtered $comments array
return $comments;
}
Frontend and backend
add_action( 'pre_get_comments' , 'wpse_hide_for_backend' );
function wpse_hide_for_backend( $comments_query ){
// Hide all for non logged in users
if( !is_user_logged_in() ){
return $comments_query->query_vars['comment__in'] = array(0);
}
$current_user = wp_get_current_user();
// if you don't want to apply restrictions to admins
if( $current_user->roles[0] == 'administrator' ){
return $comments_query;
}
$user_ids = get_users( array(
'role__in' => $current_user->roles,
'fields' => 'ID'
) );
$comments_query->query_vars['author__in'] = $user_ids;
}
EDIT
I modified the second function.
Seeing @birgire's answer I realized there was an author_in
query arg and using get_users
with query arg role__in
we can achieve the desired effect on both front and back end.
So thanks to @birgire for the inspiration :)
EDIT
To allow more than just the role of the current user in the fetching of comments (like adding comments made by administrators) simply append the array in role__in
with the desired roles
so the function would become
add_action( 'pre_get_comments' , 'wpse_hide_for_backend' );
function wpse_hide_for_backend( $comments_query ){
// Hide all for non logged in users
if( !is_user_logged_in() ){
return $comments_query->query_vars['comment__in'] = array(0);
}
$current_user = wp_get_current_user();
// if you don't want to apply restrictions to admins
if( $current_user->roles[0] == 'administrator' ){
return $comments_query;
}
$user_ids = get_users( array(
'role__in' => array(
'administrator',
$current_user->roles[0],
),
'fields' => 'ID'
) );
$comments_query->query_vars['author__in'] = $user_ids;
}
or (for readability on this forum)
$permitted_roles = array(
'administrator',
$current_user->roles[0],
);
$user_ids = get_users( array(
'role__in' => $permitted_roles,
'fields' => 'ID'
) );
OTHER TIPS
Here's one way (untested) to display comments from users in the same role as the current user:
add_filter( 'comments_template_query_args', function( array $args )
{
// Nothing to do for visitors
if( ! is_user_logged_in() )
return $args;
// Nothing to do for threaded comments
if( isset( $args['hierarchical'] ) && 'threaded' === $args['hierarchical'] )
return $args;
// Get current user
$u = wp_get_current_user();
// Nothing to do for users without any roles
if( ! isset( $u->roles ) ||empty( $u->roles ) )
return $args;
// Fetch user ids with the same role
$user_ids = get_users( [ 'role__in' => (array) $u->roles, 'fields' => 'ID' ] );
// Restrict comment authors
if( ! empty( $user_ids ) )
$args['author__in'] = (array) $user_ids;
return $args;
} );
Here we assume the user base is not huge and we use the comments_template_query_args
filter to target the main comments query in the comments_template()
part in the theme.