I want to give a group of user types (Editor + a custom role) the add_users /create_users capability. The only catch is that I wanted to limit that capability to adding 'subscriber' type users only, and nothing above that. Is there a way to do this?
2 Answers
This first step to making this happen is add the capability to create_users
to a given role. You do this be calling get_role
, then using the add_cap
method. This only needs to be done once. Here's an example that does it on plugin activation.
<?php
register_activation_hook( __FILE__, 'wpse42003_activation' );
function wpse42003_activation()
{
foreach( array( 'editor', 'your_custome_role' ) as $r )
{
$role = get_role( $r );
if( $role )
$role->add_cap( 'create_users' );
}
}
If you do that, you probably want to make sure to undo it on plugin deactivation with remove_cap
.
<?php
register_deactivation_hook( __FILE__, 'wpse42003_deactivation' );
function wpse42003_deactivation()
{
foreach( array( 'editor', 'your_custome_role' ) as $r )
{
$role = get_role( $r );
if( $role )
$role->remove_cap( 'create_users' );
}
}
Now the problem of making sure those users can only register subscribers. On the user-new.php
page, the roles drop down get generated by a function called wp_dropdown_roles
, which in turn calls the function get_editable_roles
to fetch the roles the current user can edit/create.
Fortunately for you, there's a filter in there that will allow us to modify this bit. First we'll copy all the $roles
array keys, then loop through and unset any role other than subscriber from $roles
-- only if the current user has the role editor or your custom role.
<?php
add_filter( 'editable_roles', 'wpse42003_filter_roles' );
function wpse42003_filter_roles( $roles )
{
$user = wp_get_current_user();
if( in_array( 'editor', $user->roles ) || in_array( 'your_custom_role', $user->roles ) )
{
$tmp = array_keys( $roles );
foreach( $tmp as $r )
{
if( 'subscriber' == $r ) continue;
unset( $roles[$r] );
}
}
return $roles;
}
The bonus part of this is that get_editable_roles
is called before a user is added or updated -- your editors won't be able to add users by insert extra options in the form with JS or something similar.
note: change your_custom_role
in the examples above to your role's name.
All that as a plugin.
-
I kept looking for a way to filter the user insertion event, hoping to reject the attempt to add users above the desired level, but hadn't thought of simply filtering the dropdown. Thanks so much! Commented Feb 11, 2012 at 23:27
-
With making a few small adjustments to the code to suit my own needs, it still holds up in WP3.9.1 :)– rkeetCommented May 28, 2014 at 13:37
-
FYI, I found that you have to have the following capabilities for this solution to work:
create_users
,edit_users
andlist_users
. See a full explanation in my other comments. I hope that helps. Commented Jul 25, 2014 at 13:33
The answer of @chrisguitarguy is good. I've made a small modification to the code to have it work from a development bureau serving customers on a multi-site install. We were in need to create a 'customer' user role, but of course a customer should not be allowed to add another customer to its domain. Modified from the accepted answer I've come to this:
/**
* Add filter to ensure a Customer type can NOT create another Customer user
*/
add_filter( 'editable_roles', 'limit_create_user' );
function limit_create_user( $roles ){
$user = wp_get_current_user();
if( in_array( 'customer', $user->roles )){
unset( $roles[ 'customer' ]);
}
return $roles;
}
Hoping someone might find some use for this in the future. This was tested and applied in WP3.9.1.
-
I've got similar situation. I've added the following capabilities
create_users
andlist_users
. I've also addededitable_roles
filter, which displays a specific role correctly. However, when I create a new user it's always a 'subscriber' and not a custom role. Has anyone came across this issue? Commented Jul 22, 2014 at 13:00 -
I personally haven't and would like the answer to that ;) Even when going into the database and manually changing
default_role
fromsubscriber
toanything
, after the next refresh of the site, or a specific blog in multi-site, the value has been reset tosubscriber
.– rkeetCommented Jul 22, 2014 at 13:30 -
Ok, I've dug into the WP code for creating a user and figured out why it doesn't work. A user have to have
edit_users
capability to create a user with a role that's been selected from the drop-down menu. Otherwise, withoutedit_users
capability a selected role from the drop-down is ignored and a default role is assigned to the new user (which is usually 'Subscriber' role, unless it was changed to something else). This is for standard non-multisite setup, multisite might need more capabilities for it to work. Commented Jul 25, 2014 at 13:29 -
So, to recap, for this solution to work, a user have to have the following capabilities
create_users
,edit_users
andlist_users
, to be able to create only users of other specific roles - where a role is selected from a drop-down menu on 'Add New User' admin screen. I hope that helps! :) Commented Jul 25, 2014 at 13:29