You are here

user_readonly.module in User Read-Only 5

Same filename and directory in other branches
  1. 6 user_readonly.module
  2. 7 user_readonly.module

This module provides restrictions on user account/profile fields.

File

user_readonly.module
View source
<?php

/**
 * @file
 *
 * This module provides restrictions on user account/profile fields.
 */

/**
 * Gets the default restrictions set by user_readonly_admin_settings()
 * and if none are set, sets up some empty array elements.
 *
 * @return array
 */
function _user_readonly_get() {
  $a = variable_get('user_readonly', '');
  if (empty($a)) {
    $a = array(
      0 => array(
        'mode' => 'deny',
        'roles' => array(),
        'action' => 'disable',
      ),
    );
  }
  return $a;
}

/**
 * Implementation of hook_perm().
 */
function user_readonly_perm() {
  return array(
    'administer user read-only settings',
  );
}

/**
 * Implementation of hook_menu().
 *
 * @return array
 */
function user_readonly_menu($may_cache) {
  $items = array();
  if ($may_cache) {
    $items[] = array(
      'path' => 'admin/user/user_readonly',
      'description' => t('User ReadOnly settings.'),
      'title' => t('User ReadOnly'),
      'callback' => 'drupal_get_form',
      'callback arguments' => array(
        'user_readonly_admin_settings',
      ),
      'access' => user_access('administer user read-only settings'),
    );
  }
  return $items;
}

/**
 * Implementation of hook_help().
 */
function user_readonly_help($section) {
  switch ($section) {
    case 'admin/user/user_readonly':
      global $user;
      return t('Here you can define modification restrictions for user/profile editing.  The options below the fieldsets correspond to the appropriate fields which are visible in <a href="@account_url">account settings form</a>.  Note that password-type and date-type fields cannot be disabled; they must be deleted.', array(
        '@account_url' => url("user/{$user->uid}/edit"),
      ));
      break;
  }
}

/**
 * Configuration form for setting default restrictions.
 *
 * @return array
 */
function user_readonly_admin_settings() {

  // important: tell Drupal to keep the tree structure of the form
  $form = array(
    '#tree' => TRUE,
  );
  $settings = _user_readonly_get();

  // build the list of fields that we can configure
  $fields = array();

  // drupal_retrieve_form() call changes the page title... so we workaround this
  $title = drupal_get_title();
  $user_edit = drupal_retrieve_form('user_edit');
  drupal_set_title($title);
  foreach ($user_edit as $k => $v) {
    if ($k[0] != '_' && !element_property($k) && is_array($v)) {
      foreach ($v as $key => $value) {
        if (!element_property($key) && is_array($v[$key])) {
          $fields[$key] = check_plain($v['#title']) . (empty($v['#title']) ? '' : ' &raquo; ') . check_plain($key == 'pass' ? t('Password') : $value['#title']);
        }
      }
    }
  }
  if (module_exists('profile')) {
    $result = db_query('SELECT * FROM {profile_fields} ORDER BY category, weight, title');
    while ($obj = db_fetch_object($result)) {
      $fields[$obj->name] = $obj->title;
    }
  }
  $roles = user_roles(TRUE);
  $modes = array(
    0 => t('Use the default role settings.'),
    'deny' => t('Only <strong>DENY</strong> changes to users with these roles.'),
    'allow' => t('Only <strong>ALLOW</strong> changes to users with these roles.'),
  );

  // create the part of the form all the fields use for every field options
  $partialf = array(
    '#type' => 'fieldset',
    '#collapsible' => TRUE,
    '#collapsed' => TRUE,
  );
  $partialf['mode'] = array(
    '#type' => 'radios',
    '#title' => t('Restrictions mode'),
    '#default_value' => $settings[0]['mode'],
    '#options' => $modes,
    '#description' => t('Define the restriction rules. To deny all changes, choose ALLOW, but do not select any fields below.'),
  );
  $partialf['roles'] = array(
    '#type' => 'checkboxes',
    '#title' => t('Roles'),
    '#default_value' => $settings[0]['roles'],
    '#options' => $roles,
  );
  $partialf['action'] = array(
    '#type' => 'radios',
    '#title' => t('When restrictions apply'),
    '#default_value' => $settings[0]['action'],
    '#options' => array(
      0 => t('Use the default settings.'),
      'disable' => t('Disable the fields.'),
      'delete' => t('Delete the fields.'),
    ),
    '#description' => t('Disabling fields greys them out but users can still see the fields.  Deleting fields hides them.  This option is independent from the above restriction rule setting.'),
  );

  // create the default settings form
  $defaultf = $partialf;
  $defaultf['#collapsed'] = FALSE;
  $defaultf['#title'] = t('Default settings for all fields');
  unset($defaultf['mode']['#options'][0]);
  unset($defaultf['action']['#options'][0]);
  $form[0] = $defaultf;

  // create the form for all fields
  foreach ($fields as $fid => $fname) {
    $partialf['#title'] = $fname;
    $defaults = $settings[$fid];
    if (empty($defaults)) {
      $defaults = array(
        'mode' => 0,
        'roles' => array(),
        'action' => 0,
      );
    }
    $partialf['mode']['#default_value'] = $defaults['mode'];
    $partialf['roles']['#default_value'] = $defaults['roles'];
    $partialf['action']['#default_value'] = $defaults['action'];
    $form[$fid] = $partialf;
    if (!empty($defaults['mode']) || !empty($defaults['action'])) {
      $form[$fid]['#collapsed'] = FALSE;
    }
  }
  $form['submit'] = array(
    '#type' => 'submit',
    '#value' => t('Save configuration'),
  );
  $form['reset'] = array(
    '#type' => 'submit',
    '#value' => t('Reset to defaults'),
  );

  // doesn't use standard system_settings_form() because the config is stored as an array of role settings
  return $form;
}

/**
 * Automatic handler for the submission from user_readonly_admin_settings()
 */
function user_readonly_admin_settings_submit($form_id, $form_values) {
  if ($form_values['op'] == t('Save configuration')) {
    variable_set('user_readonly', $form_values);
    drupal_set_message(t('The configuration options have been saved.'));
  }
  else {
    if ($form_values['op'] == t('Reset to defaults')) {
      variable_del('user_readonly');
      drupal_set_message(t('The configuration options have been reset to their default values.'));
    }
  }
  drupal_goto('admin/user/user_readonly');
}

/**
 * Prevent the user from attempting to edit the field,
 * thus preventing confusion.
 * insert a hidden field w/ the appropriate value, since
 * disabled fields do not get posted.
 */
function user_readonly_form_alter($form_id, &$form) {
  if ($form_id != 'user_edit') {
    return;
  }
  $settings = _user_readonly_get();
  global $user;
  $user_roles = $user->roles;
  foreach ($form as $group => $data) {
    if (!is_array($data) || preg_match("/^#/", $group)) {
      continue;
    }
    foreach (element_children($data) as $key => $value) {

      // only restrict access to fields controlled by this module.
      if (empty($settings[$value]) || !is_array($data[$value])) {
        continue;
      }

      //use the default values if the setting tells so
      $settings_used = empty($settings[$value]['mode']) ? $settings[0] : $settings[$value];

      // check whether this user is allowed to make changes to this field
      // first, check if any of this user's roles are ticked in the settings
      $ticked = FALSE;
      foreach ($user_roles as $role_rid => $role_name) {
        if (!empty($settings_used['roles'][$role_rid])) {

          //this means that in the settings, this user qualifies as 'ticked'.  That can mean 'allow' or 'deny', depending on the mode.
          $ticked = TRUE;
          break;
        }
      }
      if (!user_access('administer user read-only settings') && ($ticked == TRUE && $settings_used['mode'] == 'deny' || $ticked == FALSE && $settings_used['mode'] == 'allow')) {
        $action = empty($settings_used['action']) ? $settings[0]['action'] : $settings_used['action'];
        switch ($form[$group][$value]['#type']) {
          case 'date':
            $form[$group]['user_readonly'][$value] = $form[$group][$key];
            $form[$group]['user_readonly'][$value]['#type'] = 'item';
            $form[$group]['user_readonly'][$value]['#description'] = '';
            $form[$group]['user_readonly'][$value]['#title'] = '';
            $form[$group][$value]['#disabled'] = TRUE;
            break;
          case 'password_confirm':

            // due to the complex nature of these fields, we simply delete them from the form.
            unset($form[$group][$value]);
            break;
          default:
            if ($action == 'delete') {
              $form[$group][$value]['#type'] = 'hidden';
            }
            else {

              /*if ($action == 'disable')*/

              // fields must have a hidden field w/ proper value as disabled fields are not submitted.
              $form[$group]['user_readonly'][$value] = $form[$group][$value];
              $form[$group]['user_readonly'][$value]['#type'] = 'hidden';

              // new in Drupal 5: #disabled property
              $form[$group][$value]['#disabled'] = TRUE;
            }
        }
      }
    }
  }
}

Functions

Namesort descending Description
user_readonly_admin_settings Configuration form for setting default restrictions.
user_readonly_admin_settings_submit Automatic handler for the submission from user_readonly_admin_settings()
user_readonly_form_alter Prevent the user from attempting to edit the field, thus preventing confusion. insert a hidden field w/ the appropriate value, since disabled fields do not get posted.
user_readonly_help Implementation of hook_help().
user_readonly_menu Implementation of hook_menu().
user_readonly_perm Implementation of hook_perm().
_user_readonly_get Gets the default restrictions set by user_readonly_admin_settings() and if none are set, sets up some empty array elements.