I've created some custom profile fields that iare set to visibility = "Hidden profile field, only accessible by administrators, modules and themes." But they show up to the member when s/he views their edit profile page.

i'm running 4.6, and the profile module is "profile.module,v 1.94 2005/04/21 18:49:06 dries Exp $".

I see these lines in the profile module:

function profile_view_profile($user) {

  profile_load_profile($user);

  // Show private fields to administrators and people viewing their own account.
  if (user_access('administer users') || $GLOBALS['user']->uid == $user->uid) {
    $result = db_query('SELECT * FROM {profile_fields} WHERE visibility != %d ORDER BY category, weight', PROFILE_HIDDEN);
  }

<!-- begin look at me -->
  else {
    $result = db_query('SELECT * FROM {profile_fields} WHERE visibility != %d AND visibility != %d ORDER BY category, weight', PROFILE_PRIVATE, PROFILE_HIDDEN);
  }
<!-- end look at me -->

  while ($field = db_fetch_object($result)) {
    if ($value = profile_view_field($user, $field)) {
      $description = ($field->visibility == PROFILE_PRIVATE) ? t('The content of this field is private and only visible to yourself.') : '';
      $title = ($field->type != 'checkbox') ? check_plain($field->title) : '';
      $fields[$field->category] .= form_item($title, $value, $description);
    }
  }

  return $fields;
}

so i think that "visibility != %d" means that the value is not an integer, which i'm not understanding because visbility is, well, an integer. And i'm not following the repetition of this phrase.

Perhaps sleep deprivation and allergies are rendering me insensible, but much searching has not delivered up an answer to me.

thanks,
--derek

Comments

philosophe’s picture

just a bump for visibility ;)

--derek

Steven’s picture

There: http://drupaldocs.org/db_query .

Whoever inventing bumping should be shot. It is the single most annoying and useless practice on forums.

--
If you have a problem, please search before posting a question.

philosophe’s picture

funny, i had found a partial answer and then found Steven's left-handed pointer.

traveling from pointless searches on drupal, to better searches via google, to my o'reilly books and back, i proved that the "%d" was the integer type specifier for printf(), as i thought. then looking at the db_query() function i see that this can take user-supplied parameters, and those are what are getting subbed by the %ds.

as an aside, why not state the syntax to include the possibility of parameters? why not db_query($query [,parameter(s)])? Seeing that would have clued me in days ago.

but this doesn't explain the repeated phrase, and doesn't explain why my hidden fields are showing up.

-- derek

philosophe’s picture

%d used twice for two user-supplied parameters. duh.

-- derek

philosophe’s picture

trial and error led to this ugly hack of profile.module in order to keep PROFILE_HIDDEN fields off the edit profile fields page for the user.

The goal was to display hidden fields ONLY to administrators, which i thought the module was supposed to do anyway.

the original code was

function profile_form_profile($edit, $user, $category) {

  if (($_GET['q'] == 'user/register') ? 1 : 0) {
    $result = db_query('SELECT * FROM {profile_fields} WHERE register = 1 ORDER BY category, weight');
  }
  else {

     $result = db_query("SELECT * FROM {profile_fields} WHERE LOWER(category) = LOWER('%s') ORDER BY weight", $category);
    // We use LOWER('%s') instead of PHP's strtolower() to avoid UTF-8 conversion issues.
  }

while the new code adds a check for uid of admin, and a check for visibility.

function profile_form_profile($edit, $user, $category) {

  if (($_GET['q'] == 'user/register') ? 1 : 0) {
    $result = db_query('SELECT * FROM {profile_fields} WHERE register = 1 ORDER BY category, weight');
  }
  else {

    if ($user->uid ==1 || $GLOBALS['user']->uid ==1) {
          $result = db_query("SELECT * FROM {profile_fields} WHERE LOWER(category) = LOWER('%s') ORDER BY weight", $category);
    }
    else {
           $result = db_query("SELECT * FROM {profile_fields} WHERE LOWER(category) = LOWER('%s') AND visibility != %d ORDER BY weight", $category, PROFILE_HIDDEN);
    }

    // We use LOWER('%s') instead of PHP's strtolower() to avoid UTF-8 conversion issues.
  }

is there a prettier way of doing this? did i misunderstand how this module was supposed to treat hidden fields?

thanks,
-- derek

sheepy898’s picture

i just posted a "how do i...?" question in the forum related to this (http://drupal.org/node/25183). i also don't understand why drupal displays supposedly hidden fields to the user (although it appears that it's not a bug but rather what the original profile module coders actually wanted to happen).

perhaps they should consider adding a 4th field type ("admin-only", to add to the existing "private" and 2 "public" ones).

rjl’s picture

I am working with an organization that has a big membership/donations/contacts database and they wanted a way to link up drupal user accounts with their database. I wanted to add a field to the drupal profile to store the ID from the database, but I didn't want a non-admin to see this field or to be able to change this field's value. A visiblity option of 'Admin Only' would seem to suffice for my purposes...

There is a similar discussion about this at node/12737 with a patch, but I tried it, and it didn't achieve the effect that I was looking for, so I am not sure what that patch actually does.

Then I found this post, and it seemed that this was a good start, but I needed a little more.

Things you should know...
1. I am new to drupal
2. These code changes are made to the profile module which is a core module, so I was a bit hesitant...
3. Please make a backup copy of the profile module, so you can switch back, in case these changes don't work for you because of some other dependency.
4. I don't know how to create a patch so the changes I made are documented here and you will have to make them yourself manually (if someone wanted to make a patch, that would be great!).
5. You should not have a profile category that displays only admin fields, as the link will show up at the top when a user chooses to Edit his/her profile (no fields will show if the user clicks that category, the field section will be blank)
6. The two options "The user must enter a value." and "Visible in user registration form." should be left un-checked for these admin fields.
7. Applies to 4.6 // $Id: profile.module,v 1.90.2.2 2005/06/01 04:30:07 unconed Exp $

So here are the changes I made...

Near the top (@ line 12) 3 values are defined, define a 4th value for admin only ...
After this section

/**
 * Flags to define the visibility of a profile field.
 */

Add the following 1 line

define('PROFILE_ADMIN', 0);

In the function profile_browse ...
Change this line

if (!user_access('administer users') && $field->visibility != PROFILE_PRIVATE) {

To the following 1 line

if (!user_access('administer users') && $field->visibility <= PROFILE_PRIVATE) {

In the function profile_view_field ...
Change this line

$browse = user_access('administer users') || $field->visibility == PROFILE_PRIVATE;

To the following 1 line

$browse = user_access('administer users') || $field->visibility > PROFILE_PRIVATE;

In the function profile_view_profile ...
Change these 6 lines

if (user_access('administer users') || $GLOBALS['user']->uid == $user->uid) {
  $result = db_query('SELECT * FROM {profile_fields} ORDER BY category, weight');
}
else {
  $result = db_query('SELECT * FROM {profile_fields} WHERE visibility != %d ORDER BY category, weight', PROFILE_PRIVATE);
}

To the following 9 lines

if (user_access('administer users')) {
  $result = db_query('SELECT * FROM {profile_fields} ORDER BY category, weight');
}
elseif ($GLOBALS['user']->uid == $user->uid) {
  $result = db_query('SELECT * FROM {profile_fields} WHERE visibility >= %d ORDER BY category, weight', PROFILE_PRIVATE);
}
else {
  $result = db_query('SELECT * FROM {profile_fields} WHERE visibility > %d ORDER BY category, weight', PROFILE_PRIVATE);
}

In the same function ...
Change this line

$description = ($field->visibility == PROFILE_PRIVATE) ? t('The content of this field is private and only visible to yourself.') : '';

To these 2 lines

$description = ($field->visibility == PROFILE_ADMIN) ? t('The content of this field is visible to administrators only.') : '';
$description = ($field->visibility == PROFILE_PRIVATE) ? t('The content of this field is private and only visible to yourself.') : $description;

In the function _profile_form_explanation ...
After this section

if ($field->visibility == PROFILE_PRIVATE) {
  $output .= ' '. t('The content of this field is kept private and will not be shown publicly.');
}

Add the following 3 lines

if ($field->visibility == PROFILE_ADMIN) {
  $output .= ' '. t('The content of this field is viewable by administatators only.');
}

In the function profile_form_profile ...
Change this line

$result = db_query("SELECT * FROM {profile_fields} WHERE LOWER(category) = LOWER('%s') ORDER BY weight", $category);

To these 6 lines

if (user_access('administer users')) {
    $result = db_query("SELECT * FROM {profile_fields} WHERE LOWER(category) = LOWER('%s') ORDER BY weight", $category);
}
elseif ($GLOBALS['user']->uid == $user->uid) {
    $result = db_query("SELECT * FROM {profile_fields} WHERE LOWER(category) = LOWER('%s') AND visibility >= %d ORDER BY weight", $category, PROFILE_PRIVATE);
}    

In the function _profile_field_form ...
Change this line

$group .= form_radios(t('Visibility'), 'visibility', $edit['visibility'], array(PROFILE_PRIVATE => t('Private field, content only available to privileged users.'), PROFILE_PUBLIC => t('Public field, content shown on profile page but not used on member list pages.'), PROFILE_PUBLIC_LISTINGS => t('Public field, content shown on profile page and on member list pages.')));

To this line

$group .= form_radios(t('Visibility'), 'visibility', $edit['visibility'], array(PROFILE_ADMIN => t('Administrator field, content only available to administrators.'), PROFILE_PRIVATE => t('Private field, content only available to privileged users.'), PROFILE_PUBLIC => t('Public field, content shown on profile page but not used on member list pages.'), PROFILE_PUBLIC_LISTINGS => t('Public field, content shown on profile page and on member list pages.')));
jochenh’s picture

i am on drupal 4.6.5 trying to achieve the same thing but i don't seem to have the same version of profile.module.. for instance trying to make the first code modification in your post, after adding the additional flag, all i see is this line:

    if (!user_access('administer users') && $field->visibility == PROFILE_PRIVATE) {
       drupal_access_denied();
       return;
    }

i dont see that line that you see...

rjl’s picture

Typos, I think I just made a typo there

I tried to paste the entire code but it didn't like that and 'terminated my request' have never seen that before.

Sorry about the typo, let me know if I've made any other idiot mistakes

BTW, while I'm not sure, I think I remember reading about some changes to profile in 4.7, something to keep in mind.