Writing the one for update was easy. The $account contained all the user's profile fields (the ones starting with profile_) and the roles could be assigned based on these (1 for add role, 0 for delete role).
I ran into a problem with insert. The $account contained the keys for the profile fields, but the values were all blank! I still don't really know why this is. The solution, as cumbersome as it might be, is to wait until the new user has a uid, then call user_load() on the user, at which point the profile fields will have their proper values. Then, exactly the same method can be used as in the update case.
As a footnote, we don't actively develop in Drupal 5 any more; all of our development occurs in Drupal 6, but we still support Drupal 5 sites. Here is the finished code in case anyone finds it useful:
/** * Implementation of hook_user(). */ function mymodule_autorole_user($op, &$edit, &$account, $category = NULL) { if ($op == 'insert') { mymodule_autorole_apply_roles($account->uid); } else if ($op == 'update') { mymodule_autorole_apply_roles($account->uid); } } /** * Takes a user account object and uses it to update the user's roles. * * @param $uid * A fully populated user account object such as one returned by user_load(). */ function mymodule_autorole_apply_roles($uid) { $account = user_load(array('uid' => $uid)); // Filter out the profile fields from the account information. $profile_fields = array(); foreach ($account as $fieldname => $field) { // Split up the field name by the underscore character. The field names we // are looking for are named like profile_something, but they could be // profile_something_something, so join back together after the split. $pieces = explode('_', $fieldname); if (array_shift($pieces) == 'profile') { $profile_fields[implode('_', $pieces) . ' club member'] = $field; } } $myaccount = user_load(array('uid' => $account->uid)); $roles = user_roles(); foreach ($profile_fields as $field => $value) { if ($value) { // The checkbox was checked, or the textfield had something in it. Add a // new role corresponding to this, if there is one. foreach ($roles as $key => $role) { if ($role == $field) { $myaccount->roles[$key] = $role; } } } else { // The checkbox was unchecked, or the textfield was empty. Unset the user // role corresponding to this, if there is one. foreach ($roles as $key => $role) { if ($role == $field) { unset($myaccount->roles[$key]); } } } } // Update the user with the new role assignments. db_query("DELETE FROM {users_roles} WHERE uid = %d", $myaccount->uid); foreach ($myaccount->roles as $rid => $role) { db_query("INSERT INTO {users_roles} (uid, rid) VALUES (%d, %d)", $myaccount->uid, $rid); } }
1 comment:
Hi Chris,
I'm facing almost the same problem, but with a little twist. At the moment I'm adding info in a certain profile field, and on a certain date I need to change a user role for all registered users depending on the profile info.
So, I'm not changing the user role when I'm actually changing the profile info. But I'm looking for a solution to do this in a "batch".
How could this be done?
thanks,
Geert
Post a Comment