Index: modules/profile.module =================================================================== RCS file: /cvs/drupal/drupal/modules/profile.module,v retrieving revision 1.90.2.2 diff -u -F^f -r1.90.2.2 profile.module --- modules/profile.module 1 Jun 2005 04:30:07 -0000 1.90.2.2 +++ modules/profile.module 10 Jun 2005 07:39:25 -0000 @@ -9,7 +9,8 @@ /** * Flags to define the visibility of a profile field. */ -define('PROFILE_PRIVATE', 1); +// The functionality of PROFILE_PRIVATE is superceded by role based field permissions. +//define('PROFILE_PRIVATE', 1); define('PROFILE_PUBLIC', 2); define('PROFILE_PUBLIC_LISTINGS', 3); @@ -26,6 +27,22 @@ function profile_help($section) { } /** + * Implementation of hook_perm(). + */ +function profile_perm() { + // Compile the permissions for each individual profile field. + $perms = array(); + $result = db_query('SELECT name FROM {profile_fields}'); + while ($record = db_fetch_object($result)) { + $perms[] = 'access ' .$record->name; + $perms[] = 'access own ' .$record->name; + $perms[] = 'edit own ' .$record->name; + } + + return $perms; +} + +/** * Implementation of hook_menu(). */ function profile_menu($may_cache) { @@ -68,8 +85,8 @@ function profile_browse() { $field = db_fetch_object(db_query("SELECT DISTINCT(fid), type, title, page, visibility FROM {profile_fields} WHERE name = '%s'", $name)); if ($name && $field->fid) { - // Do not allow browsing of private fields by non-admins - if (!user_access('administer users') && $field->visibility == PROFILE_PRIVATE) { + // Do not allow browsing of fields by users who can't access the fields content + if (!_profile_perm_access_field($field)) { drupal_access_denied(); return; } @@ -78,7 +95,9 @@ function profile_browse() { $fields = array(); $result = db_query('SELECT name, title, type FROM {profile_fields} WHERE fid != %d AND visibility = %d ORDER BY weight', $field->fid, PROFILE_PUBLIC_LISTINGS); while ($record = db_fetch_object($result)) { - $fields[] = $record; + if (_profile_perm_access_field($record)) { + $fields[] = $record; + } } // Determine what query to use: @@ -125,7 +144,9 @@ function profile_browse() { $fields = array(); $result = db_query('SELECT name, title, type FROM {profile_fields} WHERE visibility = %d', PROFILE_PUBLIC_LISTINGS); while ($record = db_fetch_object($result)) { - $fields[] = $record; + if (_profile_perm_access_field($record)) { + $fields[] = $record; + } } // Extract the affected users: @@ -161,21 +182,23 @@ function profile_save_profile(&$edit, &$ // We use LOWER('%s') instead of PHP's strtolower() to avoid UTF-8 conversion issues. } while ($field = db_fetch_object($result)) { - if (_profile_field_serialize($field->type)) { - $edit[$field->name] = serialize($edit[$field->name]); + if (isset($edit[$field->name])) { + 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; } - 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 profile_view_field($user, $field) { - // Only allow browsing of private fields for admins - $browse = user_access('administer users') || $field->visibility != PROFILE_PRIVATE; + // Only allow browsing of fields by users who can access the fields content for all users + $browse = _profile_perm_access_field($field); - if ($value = $user->{$field->name}) { + if (($value = $user->{$field->name}) && _profile_perm_access_field($field, $user)) { switch ($field->type) { case 'textfield': return check_plain($value); @@ -215,17 +238,11 @@ 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} ORDER BY category, weight'); - } - else { - $result = db_query('SELECT * FROM {profile_fields} WHERE visibility != %d ORDER BY category, weight', PROFILE_PRIVATE); - } + $result = db_query('SELECT * FROM {profile_fields} ORDER BY category, weight'); 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.') : ''; + //$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); } @@ -241,9 +258,10 @@ function _profile_form_explanation($fiel $output .= ' '. t('Put each item on a separate line or separate them by commas. No HTML allowed.'); } - if ($field->visibility == PROFILE_PRIVATE) { - $output .= ' '. t('The content of this field is kept private and will not be shown publicly.'); - } + // We could read the roles with permission to access this field and print them here. + //if ($field->visibility == PROFILE_PRIVATE) { + // $output .= ' '. t('The content of this field is kept private and will not be shown publicly.'); + //} return $output; } @@ -260,35 +278,37 @@ function profile_form_profile($edit, $us $fields = array(); while ($field = db_fetch_object($result)) { - $category = $field->category; - switch ($field->type) { - case 'textfield': - case 'url': - $fields[$category] .= form_textfield(check_plain($field->title), $field->name, $edit[$field->name], 70, 255, _profile_form_explanation($field), NULL, $field->required); - break; - case 'textarea': - $fields[$category] .= form_textarea(check_plain($field->title), $field->name, $edit[$field->name], 70, 5, _profile_form_explanation($field), NULL, $field->required); - break; - case 'list': - $fields[$category] .= form_textarea(check_plain($field->title), $field->name, $edit[$field->name], 70, 5, _profile_form_explanation($field), NULL, $field->required); - break; - case 'checkbox': - $fields[$category] .= form_checkbox(check_plain($field->title), $field->name, 1, $edit[$field->name], _profile_form_explanation($field), NULL, $field->required); - break; - case 'selection': - $options = array('--'); - $lines = split("[,\n\r]", $field->options); - foreach ($lines as $line) { - if ($line = trim($line)) { - $options[$line] = $line; + if (_profile_perm_edit_field($field, $user)) { + $category = $field->category; + switch ($field->type) { + case 'textfield': + case 'url': + $fields[$category] .= form_textfield(check_plain($field->title), $field->name, $edit[$field->name], 70, 255, _profile_form_explanation($field), NULL, $field->required); + break; + case 'textarea': + $fields[$category] .= form_textarea(check_plain($field->title), $field->name, $edit[$field->name], 70, 5, _profile_form_explanation($field), NULL, $field->required); + break; + case 'list': + $fields[$category] .= form_textarea(check_plain($field->title), $field->name, $edit[$field->name], 70, 5, _profile_form_explanation($field), NULL, $field->required); + break; + case 'checkbox': + $fields[$category] .= form_checkbox(check_plain($field->title), $field->name, 1, $edit[$field->name], _profile_form_explanation($field), NULL, $field->required); + break; + case 'selection': + $options = array('--'); + $lines = split("[,\n\r]", $field->options); + foreach ($lines as $line) { + if ($line = trim($line)) { + $options[$line] = $line; + } } - } - $fields[$category] .= form_select(check_plain($field->title), $field->name, $edit[$field->name], $options, _profile_form_explanation($field), 0, 0, $field->required); - break; - case 'date': - $fields[$category] .= _profile_date_field($field, $edit); - break; + $fields[$category] .= form_select(check_plain($field->title), $field->name, $edit[$field->name], $options, _profile_form_explanation($field), 0, 0, $field->required); + break; + case 'date': + $fields[$category] .= _profile_date_field($field, $edit); + break; + } } } @@ -348,7 +368,7 @@ function _profile_map_month($month) { return format_date(gmmktime(0, 0, 0, $month, 2, 1970), 'custom', 'M', 0); } -function profile_validate_profile($edit, $category) { +function profile_validate_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'); @@ -360,13 +380,17 @@ function profile_validate_profile($edit, while ($field = db_fetch_object($result)) { if ($edit[$field->name]) { + if (!_profile_perm_edit_field($field, $user)) { + form_set_error($field->name, t('You do not have permission to edit %field.', array('%field' => theme('placeholder', $field->title)))); + } + if ($field->type == 'url') { if (!valid_url($edit[$field->name], true)) { form_set_error($field->name, t('The value provided for %field is not a valid URL.', array('%field' => theme('placeholder', $field->title)))); } } } - else if ($field->required && !user_access('administer users')) { + else if ($field->required && !user_access('administer users') && _profile_perm_edit_field($field, $user)) { form_set_error($field->name, t('The field %field is required.', array('%field' => theme('placeholder', $field->title)))); } } @@ -399,7 +423,7 @@ function profile_user($type, &$edit, &$u case 'form': return profile_form_profile($edit, $user, $category); case 'validate': - return profile_validate_profile($edit, $category); + return profile_validate_profile($edit, $user, $category); case 'categories': return profile_categories(); } @@ -515,7 +539,7 @@ function _profile_field_form($type, $edi $group .= form_textarea(t('Selection options'), 'options', $edit['options'], 70, 8, t('A list of all options. Put each option on a separate line. Example options are "red", "blue", "green", etc.')); } $group .= form_weight(t('Weight'), 'weight', $edit['weight'], 5, t('The weights define the order in which the form fields are shown. Lighter fields "float up" towards the top of the category.')); - $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.'))); + $group .= form_radios(t('Visibility'), 'visibility', $edit['visibility'], array(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.'))); if ($type == 'selection' || $type == 'list') { $group .= form_textfield(t('Page title'), 'page', $edit['page'], 70, 128, t('The title of the page showing all users with the specified field. The word %value will be substituted with the corresponding value. An example page title is "People whose favorite color is %value". Only applicable if the field is configured to be shown on member list pages.')); } @@ -590,4 +614,17 @@ function _profile_field_serialize($type return $type == 'date'; } +/* + * Returns true if the logged in user has permission to access/view the $field for $user. + */ +function _profile_perm_access_field($field, $user = NULL) { + return user_access('administer users') || user_access('access ' .$field->name) || (($user != NULL) && ($GLOBALS['user']->uid == $user->uid) && user_access('access own ' .$field->name)); +} + +/* + * Returns true if the logged in user has permission to edit the $field for $user. + */ +function _profile_perm_edit_field($field, $user) { + return user_access('administer users') || user_access('edit own ' .$field->name); +} ?>