If you've been having trouble getting the Wordpress WP_User method remove_role to work, then you're not alone. After what seemed like forever, I finally decided to stop looking for solutions to my problem and just open the capabilities.php file in the Wordpress core and start poking around.

Eventually I realized that the original code for remove role was not working like it should.

if ( empty( $this->roles[$role] ) || ( count( $this->roles ) <= 1 ) )

The code above from line 579 of the capabilities.php, wasn't correctly checking for the existence of the $role it was being asked to remove.

The problem is that "$this->roles[$role]" or more correctly "$this->role" does not return a multidimensional array, which is what the code above requires to function correctly. It needs a multidimensional array that contains the role names as keys. Since "$this->roles" returns a indexed array, checking for the existence of a named role will never work.

After changing the code a little, I managed to come up with a solution that works fine or me. I created a new Class called "WP_User_fix" which is an extension the original "WP_User" Class. This new Class overrides the "remove_role" method with the new code shown below.

You will noticed I made another change as well, I didn't like how the code restricted me from removing a role when the user in question only had that one role, maybe I should explain.

In the above code you will see "count( $this->roles ) <= 1" which is basically saying, if $this->roles has less than 1 role contained inside it, then don't continue. The change I made still checks to see if this user has only one role before continuing, however, instead of causing your "remove_role" attempt to fail, it will assign your blogs default role to the user and continue on.

This default role (usually Subscriber) can be set in your Wordpress Admin panel under Settings/General.


class WP_User_fix extends WP_User{
	function remove_role( $role ) {
		// removed the empty($this->roles[$role]) as it was not working and added the in_array() which does.
		// Also moved the (count($this->roles) <= 1) into it's own if statement. 
		if (!in_array($role, $this->roles)){
			return;
		}
		
		// If the user has only one role, this code will assign the "default blog role" to the user.
		// This "default blog role" is set in the Admin panel under Settings/General
		if(count( $this->roles ) <= 1){
			$this->set_role(get_option('default_role'));
		}
		unset( $this->caps[$role] );
		update_usermeta( $this->ID, $this->cap_key, $this->caps );
		$this->get_role_caps();
	}
}

For now this seems to work fine, and until Wordpress releases a patch, you can download this plugin I created. The plugin adds the new extended WP_User_fix Class to your blog for you automatically.

This works just as any other plugin, upload it to your plugins folder and activate it.
In order to use it, simply change the name of the class you are instantiating from WP_User to WP_User_fix.
All the original WP_User functionality will remain intact but now the remove_role method will work fine.

Download the Plugin CodeBanter_WP_User_fix.zip