From what I can see there is no function provided by the core Drupal 6 module 'profile' that allows coders to set the value of hidden profile fields.

Is this something that should be set via a manual SQL insertion upon registration, and manual SQL delete+insert upon profile updates? (as is done on lines 236-247 of the profile.module)

From the list of unanswered replies on this topic over the last couple of years I'd say this is the case, but just wanted to see if this was commonplace, or 'standard practice'...

Comments

Drave Robber’s picture

It is certainly possible, just somewhat hard to describe generally without knowing what exactly you want to achieve.

The place to look is not profile.module but hook_user().

Upon seeing a more detailed description, I might be willing to take a bet that it can be done in less than 24 hours. :)

sagar ramgade’s picture

Hi,

You need to write a custom module which will contain hook_form_alter function in order to set the value of profile fields. For more info please check this :
http://api.drupal.org/api/drupal/developer--hooks--core.php/function/hoo...

Hope it helps.

Acquia certified Developer, Back end and Front specialist
Need help? Please use my contact form

sydneyshan’s picture

Thanks guys.

I've ended up using hook_user() and the 'update' $op to calculate the value of the hidden field and insert in manually like so:

The profile field ID is hardcoded (7). I should also pop this in the 'insert' $op case but I've got a Rule that applies a user role upon registration (which calls the 'update' $op) so leaving the code here once is fine.


function tio_user_user($op, &$edit, &$account, $category = NULL) {
  switch($op){
    case "update":
      $profile_age = floor( (time() - mktime(0, 0, 0, $account->profile_birthdate['month'], $account->profile_birthdate['day'], $account->profile_birthdate['year']) ) / (60*60*24*365.25) );
      db_query("DELETE FROM {profile_values} WHERE fid = %d AND uid = %d", 7, $account->uid);
      db_query("INSERT INTO {profile_values} (fid, uid, value) VALUES (%d, %d, '%s')", 7, $account->uid, $profile_age);
    break;
  }
}

Drave Robber’s picture

Is there a reason you don't do simply

db_query("UPDATE {profile_values} SET value = '%s' WHERE fid = 7 AND uid = %d",  $profile_age, $account->uid);

..? ^^

Just for readability, not that it's going to be called often enough to affect performance. :)

sydneyshan’s picture

Hi Dave,

In this case I was following the example set by the profile.module. I think the reasoning is that this can be called upon registration OR profile update, therefore the two queries covers this off.

Kind regards,
Shannon

motin’s picture

As far as I understand, we are supposed to use profile_save_profile() to save the fields programmatically.

However, when it comes to a hidden profile field (visibility = 4), this requires that the user running the code has the administer_users permission.

This is due to the following code in profile.module - _profile_get_fields() which profile_save_profile() relies upon:

  if (!user_access('administer users')) {
    $filters[] = 'visibility != %d';
    $args[] = PROFILE_HIDDEN;
  }

Why there is no way to programmatically override this goes beyond my understanding.

As a work-around - copy the relevant functions to your module and modify them slightly so that you can save all profile fields.

Here is an example using profile module v 6.22:

function mymodule_save_profile(&$edit, &$user, $category, $register = FALSE) {
  $result = _mymodule_get_fields($category, $register);
  while ($field = db_fetch_object($result)) {
    if (_profile_field_serialize($field->type)) {
      $edit[$field->name] = serialize($edit[$field->name]);
    }
    db_query("DELETE FROM {profile_values} WHERE fid = %d AND uid = %d", $field->fid, $user->uid);
    db_query("INSERT INTO {profile_values} (fid, uid, value) VALUES (%d, %d, '%s')", $field->fid, $user->uid, $edit[$field->name]);
    // Mark field as handled (prevents saving to user->data).
    $edit[$field->name] = NULL;
  }
}

function _mymodule_get_fields($category, $register = FALSE) {
  $args = array();
  $sql = 'SELECT * FROM {profile_fields} WHERE ';
  $filters = array();
  if ($register) {
    $filters[] = 'register = 1';
  }
  else {
    // Use LOWER('%s') instead of PHP's strtolower() to avoid UTF-8 conversion issues.
    $filters[] = "LOWER(category) = LOWER('%s')";
    $args[] = $category;
  }
  /*if (!user_access('administer users')) {
    $filters[] = 'visibility != %d';
    $args[] = PROFILE_HIDDEN;
  }*/
  $sql .= implode(' AND ', $filters);
  $sql .= ' ORDER BY category, weight';
  return db_query($sql, $args);
}

Now you can use mymodule_save_profile() instead of the stock profile_save_profile() to save your hidden fields regardless of current user permissions.