Take the 2-minute tour ×
WordPress Development Stack Exchange is a question and answer site for WordPress developers and administrators. It's 100% free, no registration required.

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?

share|improve this question

2 Answers 2

up vote 5 down vote accepted

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.

share|improve this answer
    
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! –  tbuteler Feb 11 '12 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 :) –  Nukeface May 28 at 13:37
    
FYI, I found that you have to have the following capabilities for this solution to work: create_users, edit_users and list_users. See a full explanation in my other comments. I hope that helps. –  dashaluna 2 hours ago

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.

share|improve this answer
    
I've got similar situation. I've added the following capabilities create_users and list_users. I've also added editable_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? –  dashaluna Jul 22 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 from subscriber to anything, after the next refresh of the site, or a specific blog in multi-site, the value has been reset to subscriber. –  Nukeface Jul 22 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, without edit_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. –  dashaluna 2 hours ago
    
So, to recap, for this solution to work, a user have to have the following capabilities create_users, edit_users and list_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! :) –  dashaluna 2 hours ago

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.