user_field_privacy.module in User Field Privacy 7
Provides options for users to override visibility of their own fields.
File
user_field_privacy.moduleView source
<?php
/**
* @file
* Provides options for users to override visibility of their own fields.
*/
/**
* Implements hook_permission().
*/
function user_field_privacy_permission() {
return array(
'access private fields' => array(
'title' => t('Access private fields'),
'description' => t('Allows a user to access private fields of other users.'),
),
);
}
/**
* Implements hook_field_info_alter().
*/
function user_field_privacy_field_info_alter(&$info) {
// Add the 'user_field_privacy' instance setting to all field types.
foreach ($info as $field_type => &$field_type_info) {
$field_type_info += array(
'instance_settings' => array(),
);
$field_type_info['instance_settings'] += array(
'user_field_privacy' => FALSE,
);
}
}
/**
* Implements hook_form_FORM_ID_alter().
*
* Add a checkbox for the 'user_register_form' instance settings on the 'Edit
* field instance' form.
*
* @see user_form_field_ui_field_edit_form_alter()
*/
function user_field_privacy_form_field_ui_field_edit_form_alter(&$form, &$form_state, $form_id) {
$instance = $form['#instance'];
if ($instance['entity_type'] == 'user') {
$form['instance']['settings']['user_field_privacy'] = array(
'#type' => 'checkbox',
'#title' => t('Allow the user to hide this field\'s value by making it private.'),
'#default_value' => $instance['settings']['user_field_privacy'],
// Display just below the 'required' checkbox.
'#weight' => $form['instance']['required']['#weight'] + 0.1,
);
}
}
/**
* Implements hook_field_delete_instance().
*
* Removes a field's privacy settings upon deletion of the field instance.
*/
function user_field_privacy_field_delete_instance($instance) {
db_delete('user_field_privacy_value')
->condition('fid', $instance['field_id'])
->execute();
}
/**
* Returns if a field value should be kept private.
*
* @param $fid
* Field ID.
* @param $uid
* User ID.
* @return bool
* TRUE if the field value should be kept private.
*/
function _user_field_privacy_value($fid, $uid) {
return (bool) db_select('user_field_privacy_value', 'ufpv')
->fields('ufpv', array(
'private',
))
->condition('fid', $fid)
->condition('uid', $uid)
->execute()
->fetchField();
}
/**
* Implements hook_field_attach_form().
*
* Adds the 'private' checkbox to user fields where the field instance's
* settings demand it.
*/
function user_field_privacy_field_attach_form($entity_type, $entity, &$form, &$form_state, $langcode) {
// If we don't know anything about the user (whose field widget is to be
// appended or not with the private checkbox, based on the field instance
// settings), do not do anything.
// The other reason to avoid displaying the private checkbox is that its new
// value wouldn't get stored properly, since those forms most likely would
// NOT contain the mail fields, which would be needed to identify the user.
// So do let's bail out early in case of any disturbances in the force.
// A common use case is to alter users' field values with VBO: one selects a
// bunch of users, then a field (whose widget should be accompanied with the
// private checkbox, based on the field instance settings) - but wait, how
// to decide the #default_value of that checkbox? There's not even one user
// loaded yet, since the update will be done on a bunch of users whose uid
// is not available yet. The solution is to avoid displaying the private
// checkbox when there's no associated user info.
if (!isset($form['#user'])) {
return;
}
if ($entity_type == 'user') {
$user_field_privacy = FALSE;
foreach (field_info_instances('user', 'user') as $instance) {
// Load the field info only for user_field_privacy-enabled fields and
// add the form element only if the $user has access to the field.
if ($instance['settings']['user_field_privacy']) {
$field = field_info_field($instance['field_name']);
if (field_access('edit', $field, 'user')) {
$field_name = $instance['field_name'];
$form[$field_name]['user_field_privacy'] = array(
'#type' => 'checkbox',
'#title' => t('Private'),
'#description' => t('Tick this if you want to hide this value from non-administrators.'),
'#default_value' => _user_field_privacy_value($instance['field_id'], $form['#user']->uid),
);
$form[$field_name]['#user_field_privacy_fid'] = $instance['field_id'];
$form[$field_name]['#attributes']['class'][] = 'user-field-privacy';
$user_field_privacy = TRUE;
}
}
}
// There's a little problem here. The checkbox (form element) needs to be
// added _there_ in the $form array, to have it right after/below the
// field it belongs to. Adding our own submit callback here only if it's
// really needed, ie. when we do have a field that should have a 'private'
// checkbox besides it.
if ($user_field_privacy) {
if (!isset($form['#submit'])) {
$form['#submit'] = array();
}
$form['#submit'][] = 'user_field_privacy_field_attach_form_submit';
}
}
}
/**
* Stores if a user field's value should be kept private.
*
* @see user_field_privacy_field_attach_form
*/
function user_field_privacy_field_attach_form_submit($form, &$form_state) {
// There's another little problem here. This submit callback is executed for
// both the user add and edit forms. When it's executed for the user add
// form, there is NO uid available yet, since the {users} table has NOT been
// written into yet. So we make use of the fact that a user is uniquely
// identifiable not only by her {users}.uid, but her {users}.name as well.
// But wait, our {user_field_privacy_value} does NOT have a 'name' field,
// only a 'uid' one - and that one is not available yet. Don't panic: here
// comes drupal_static() and hook_exit() to the help. Let's store the state
// of all the user's checkboxes into a drupal_static() along with her
// {users}.mail (which we DO have here, too), and write our own precious
// data to the DB in hook_exit(). This array is keyed by the field_id, while
// the values hold the checkbox states.
$user_field_privacy = array();
foreach (element_children($form) as $field_name) {
if (isset($form[$field_name]['#user_field_privacy_fid'])) {
$user_field_privacy[$form[$field_name]['#user_field_privacy_fid']] = $form_state['values'][$field_name]['user_field_privacy'];
unset($form_state['values'][$field_name]['user_field_privacy']);
}
}
if (!empty($user_field_privacy)) {
array_push(drupal_static('user_field_privacy', array()), array(
'mail' => $form_state['values']['mail'],
'fields' => $user_field_privacy,
));
}
}
/**
* Implements hook_exit().
*/
function user_field_privacy_exit() {
foreach (drupal_static('user_field_privacy', array()) as $account) {
$uid = db_select('users', 'u')
->fields('u', array(
'uid',
))
->condition('mail', $account['mail'])
->execute()
->fetchField();
foreach ($account['fields'] as $field_id => $privacy_state) {
db_merge('user_field_privacy_value')
->key(array(
'fid' => $field_id,
'uid' => $uid,
))
->fields(array(
'private' => $privacy_state ? 1 : 0,
))
->execute();
}
}
}
/**
* Implements hook_field_access().
*/
function user_field_privacy_field_access($op, $field, $entity_type, $entity, $account) {
if ($entity_type == 'user') {
switch ($op) {
case 'view':
$instance = field_info_instance('user', $field['field_name'], 'user');
if ($instance['settings']['user_field_privacy']) {
// Grant access if this permission is granted to the viewer.
if (user_access('access private fields')) {
return TRUE;
}
// If the to-be-displayed field's owner have not submitted the user
// add/edit form with the user_field_privacy checkbox on it, then s/he
// will not have any data related to this field, so her/his $entity
// user object is not populated here. In other words, her/his field
// should be available to the public, so grant access.
if (!is_object($entity)) {
return TRUE;
}
// If the field is to be kept private, only grant access if the viewer
// has the same uid as the $user being viewed.
if (_user_field_privacy_value($field['id'], $entity->uid)) {
return (bool) ($entity->uid == $account->uid);
}
// If the field is not to be kept private, grant access.
return TRUE;
}
break;
}
}
}
/**
* Implements hook_field_attach_delete().
*/
function user_field_privacy_field_attach_delete($entity_type, $entity) {
if ($entity_type == 'user') {
db_delete('user_field_privacy_value')
->condition('uid', $entity->uid)
->execute();
}
}
Functions
Name![]() |
Description |
---|---|
user_field_privacy_exit | Implements hook_exit(). |
user_field_privacy_field_access | Implements hook_field_access(). |
user_field_privacy_field_attach_delete | Implements hook_field_attach_delete(). |
user_field_privacy_field_attach_form | Implements hook_field_attach_form(). |
user_field_privacy_field_attach_form_submit | Stores if a user field's value should be kept private. |
user_field_privacy_field_delete_instance | Implements hook_field_delete_instance(). |
user_field_privacy_field_info_alter | Implements hook_field_info_alter(). |
user_field_privacy_form_field_ui_field_edit_form_alter | Implements hook_form_FORM_ID_alter(). |
user_field_privacy_permission | Implements hook_permission(). |
_user_field_privacy_value | Returns if a field value should be kept private. |