user_save does not save data if a user changes his email address, I want him to lose a specific role (if he had that role in the first place). To make matters more complicated, we have the "email confirm" module enabled and this bitchy little module uses user_presave() in a way that leaves no traces of an email change when it is called during the edit of a profile. So I wrote a module and gave it weight -1 to make sure it gets a chance to compare $edit->mail to the users current mail before "email confirm" begins to work.

My code looks like this (version with a lot of debug statements that will be removed in the live environment):

function xyz_user_presave(&amp;$edit, $account, $category) {
  if (!empty($edit['mail']) &amp;&amp; (!empty($account-&gt;mail) &amp;&amp; $account-&gt;mail != $edit['mail']) &amp;&amp; !user_access('administer users') &amp;&amp; !drupal_installation_attempted()) {
    // remove xyz role if the users changes his email address
    $user = user_load_by_mail($account-&gt;mail);
    $role = user_role_load_by_name('xyz');
    if (array_key_exists($role-&gt;rid, $user-&gt;roles)){
      drupal_set_message('In if-clause.');
      $return1 = print_r($user-&gt;roles, TRUE);
      drupal_set_message($return1);
      $user2 = user_save($user, array('roles' =&gt; array_filter($user-&gt;roles, function($item) use ($role) {return $item != $role-&gt;name;})));
      $user3 = user_load_by_mail($account-&gt;mail);
      $return2 = print_r($user3-&gt;roles, TRUE);
      drupal_set_message($return2);
      if (!$user2){
        drupal_set_message('User_save() failed.');      
      }
    }
  } 
}


If I log in with a test user that has role xyz and change his email address at the "edit profile" site, i receive these status messages:


In if-clause. 
Array ( [2] => authenticated user [5] => abc [8]
=> xyz ) 
Array ( [2] => authenticated user [5] => abc )


The debug messages tell me that:


It has been found out, that the user has the role xy and therefor the if-clause was entered.
Before the call to user_save(), the user had the role xyz
After the call to user_save(), the user was freshly loaded and he did not have the role xyz anymore


Yet despite all this, the user does not lose the role, no matter how often I change the email address or flush the cache.

My question now is: What the hell?

Using user_save() in the user_presave() function seems to be odd, but when I put the $roles array in $edit without the xyz-role, I receive pdo exception that states, that the roles are already set for this user.
This did the trick.

function xyz_user_presave(&amp;$edit, $account, $category) {
  if (!empty($edit['mail']) &amp;&amp; (!empty($account-&gt;mail) &amp;&amp; $account-&gt;mail != $edit['mail']) &amp;&amp; !user_access('administer users') &amp;&amp; !drupal_installation_attempted()) {
    $role_position = array_search('xyz', $account-&gt;roles);
    // Use !== or === here since $role_position may be zero or FALSE
    if ($role_position !== FALSE) {
      unset($account-&gt;roles[$role_position]);
      $edit['roles'] = $account-&gt;roles;
    }
  }
}


I still do not know what's wrong with the code in the initial post, but whatever...