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
add comment

1 Answer

up vote 2 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
add comment

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.