So I am building a system with 3 different custom roles - Admins, Providers, and Users.
Providers have access to users.php, or the list users page. However, they should not be able to see/edit/access Admins, or other Providers. They should be able to see/edit themselves obviously, and see/edit all Users.
My question is how can I prevent Providers from seeing the "ALL" or "Admins" tab/link on this page? How can I ensure they only see themselves and Users?
Image included for clarity of what I am trying to accomplish:
I have tried a few methods in the pre_user_query
hook. Here is a simplified version of my code.
Read the comments!
// alter what shows on the list users page by role
function abc_pre_user_query($user_search) {
// first off, I can't even get users because 'get_users' causes this error:
// Fatal error: Allowed memory size of 134217728 bytes exhausted (tried to allocate 262144 bytes)
/*
$args = array(
'role' => 'abc_admin',
'fields' => 'all',
);
$users = get_users( $args );
*/
// So for testing, I just manually create a list of user IDs to exclude
// this would be IDs of all abc_admins and providers (besides the current provider)
$users = array('18', '19', '38');
/************************
METHOD 1 - SQL
************************/
$user_search->query_where = str_replace('WHERE 1=1',
"WHERE 1=1 AND
(wp_usermeta.meta_key = 'wp_capabilities' AND wp_usermeta.meta_value NOT LIKE '%abc_admin%') AND
((wp_usermeta.meta_key = 'wp_capabilities' AND wp_usermeta.meta_value NOT LIKE '%provider%') OR wp_users.ID = " . $current_uid . ")",
$user_search->query_where);
// This works! But when the user is on "ALL", it shows zero users and shows this error:
// [Unknown column 'wp_usermeta.meta_key' in 'where clause']
// So I was thinking of forcing user.php to redirect to users.php?role=provider, but this seems hacky
// maybe I am on the right path here and am missing something?
/************************
METHOD 2 - Query vars
************************/
// Here I try various ways to alter the $user_search WP User Query Object
// Either change 'exclude' to my $users array, or change 'role' to only grab the user role
// ... to no avail
//$user_search::set('exclude', $users); // Deprecated: Non-static method WP_User_Query::set() should not be called statically
//$user_search::set('role', 'user'); // Deprecated: Non-static method WP_User_Query::set() should not be called statically
//$user_search->query_vars['exclude'] = $users; // does nothing
//$user_search->query_vars['role'] = 'user'; // does nothing
// I can print $user_search here, and can confirm the lines that say "does nothing"
// actually change in query_vars, but on the users page NOTHING CHANGES
// Maybe using ::set is the correct way and I am calling it incorrectly?
}
add_action('pre_user_query', 'abc_pre_user_query');
So as you can see, I tried 2 main methods to get this to work. I can't imagine this is the first time somebody has had to do something like this.
I am using User Role Editor by the way. However there is no ultra specific capability like list_abc_admins
or list_other_providers
or anything. There is only list_users
, which the provider has, so that role can view ALL accounts on the site, which is exactly my problem.
Maybe the preferred approach has something to do with creating more highly specific capabilities and implementing them somehow? I feel like altering the user query is way more efficient, but I guess I could be wrong.
I can post the $user_search
variable or whatever else if needed.
Thanks in advance!