Wednesday, 10 June 2009

Drupal 5: Automatically assign a role on user profile edit

Using Drupal 5, I recently had cause to create a system whereby when a user updates checkboxes in his or her profile, roles would automatically be assigned or unassigned. No problem, I thought, I would just use hook_user() to achieve this. According to the API, I would need the two $ops insert and update.

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);
}
}

4 comments:

Geert said...

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

benslin kard said...

create use of Drupal Development that is responsible for keeping your website up to now and helping you manage the content with comfort.

terri davis said...

Wow great post about Drupal Development. Drupal is best CMS. Hire a Drupal Programmer from us as we hire talents who are capable to think out-of-the-box, with a strong dedication towards constant learning and understanding the fine prints of Drupal in every possible way.

terri davis said...

This is great post about Drupal Development. Drupal is world popular CMS. It is easy to used and easy to manage. Hire Dedicated Drupal web Expert for your Drupal development as per your need.