New Users are saved with no role selected

This ended up being a pretty significant problem with the function I hooked into editable_roles.

The Goal:

  • Allow Plugin Operators to add new Managers and New Employees
  • Allow Plugin Managers to add new Employees

The Problem:

  • New users added by an Operator and/or a Manager were being saved with no role
  • Operators/Managers could not modify the role of existing users

Test Results:

When the same user management capabilities were given to the WP default Editor role, Editors were able to successfully add/edit users’ roles.

Since the issue was exclusive to my custom roles, I temporarily disabled the filter to see what would happen, and once I was no longer restricting editable roles, Operators and Managers were able to add new users without issue. At this point, I knew the issue was tied to my filter function.

I did a var_dump() of the editable roles for the Administrator (which would not be filtered), and a var_dump() of the editable roles for the Operator (which would be filtered).

Long story short, the structure of the two dumped arrays did not match, and that is what was ultimately causing the issue.


Solution

Here is the original function:

function wf_limitAvailableRoles( $roles ){
    $user = wp_get_current_user();
    if (in_array( 'wf_operator', $user->roles)) {
        $roles = array(
            array(
                "name" => "wf_manager",
                "capabilities" => wf_getManagerCaps(),
            ),
            array(
                "name" => "wf_employee",
                "capabilities" => wf_getEmployeeCaps(),
            ),
        );
    }

    return $roles;
}
add_filter( 'editable_roles', 'wf_limitAvailableRoles' );

The issue is my $roles argument. According to the Codex, this array has a very specific formatting requirement, which I was not adhering to.

I had formatted my array as:

array(
    array(
        "name' => [role name]
        "capabilities" => [capabilities]
    ),

    array(
        "name' => [role name]
        "capabilities" => [capabilities]
    )
);

What I really want to use is this:

array(
    [role_slug] => array(
        "name' => [role name]
        "capabilities" => [capabilities]
    ),

    [role_slug] => array(
        "name' => [role name]
        "capabilities" => [capabilities]
    ),
);