You are here

role_watchdog.module in Role Watchdog 5

Logs changes to user roles.

File

role_watchdog.module
View source
<?php

/**
 * @file
 * Logs changes to user roles.
 */
define('SUPERUSER_RID', -1);
define('IN_ARRAY', TRUE);
define('NOT_IN_ARRAY', FALSE);

/**
 * Implementation of hook_help().
 */
function role_watchdog_help($section) {
  switch ($section) {
    case 'admin/modules#description':
      return t('Logs changes to user roles.');
    case 'admin/settings/role_watchdog':
      return t('Role Watchdog automatically logs all role changes made through the user profile or the User List. Role Watchdog can also monitor one or more roles for user additions or deletions and notify via email whenever a change occurs.');
  }
}

/**
 * Implementation of hook_menu().
 */
function role_watchdog_menu($may_cache) {
  $items = array();
  if ($may_cache) {
    $items[] = array(
      'path' => 'admin/settings/role_watchdog',
      'title' => 'Role watchdog',
      'description' => t('Logs changes to user roles.'),
      'callback' => 'drupal_get_form',
      'callback arguments' => 'role_watchdog_admin_settings',
      'type' => MENU_NORMAL_ITEM,
      'access' => user_access('administer site configuration'),
    );
  }
  return $items;
}

/**
 * Menu callback
 *
 * @return
 *   array of form content.
 */
function role_watchdog_admin_settings() {
  $role_names = array();
  $sql = "SELECT * FROM {role} r WHERE r.rid > 2 ORDER BY name";
  $results = db_query($sql);
  while ($result = db_fetch_object($results)) {
    $role_names[$result->rid] = $result->name;
  }
  $form['role_watchdog_monitor_roles'] = array(
    '#type' => 'select',
    '#title' => t('Monitor for change'),
    '#options' => $role_names,
    '#default_value' => variable_get('role_watchdog_monitor_roles', NULL),
    '#description' => t('Select roles to monitor for change.'),
    '#multiple' => TRUE,
  );
  $form['role_watchdog_notify_roles'] = array(
    '#type' => 'select',
    '#title' => t('Notify on change'),
    '#options' => array(
      SUPERUSER_RID => 'Superuser (uid 1)',
    ) + $role_names,
    '#default_value' => variable_get('role_watchdog_notify_roles', NULL),
    '#description' => t('Select roles to notify on change.'),
    '#multiple' => TRUE,
  );
  return system_settings_form($form);
}

/**
 * Implementation of hook_user().
 *
 * Adds submit hook to monitor role changes.
 */
function role_watchdog_user($type, &$edit, &$account, $category = NULL) {
  if ($type == 'submit' && $category == 'account') {
    if (user_access('administer access control')) {
      return role_watchdog_user_edit_submit(arg(1), $edit, $account);
    }
  }
}

/**
 * Implementation of hook_form_alter()
 *
 * Adds submit hook to monitor role changes.
 *
 * @param $form_id
 *   A unique string identifying the form.
 * @param $form
 *   An associative array containing the structure of the form.
 */
function role_watchdog_form_alter($form_id, &$form) {
  if ($form_id == 'user_admin_account') {
    if (user_access('administer access control')) {
      $form['#submit'] = array(
        'role_watchdog_user_admin_account_submit' => array(),
      ) + (array) $form['#submit'];
    }
  }
}

/**
 * Implementation of hook_form_submit()
 */
function role_watchdog_user_edit_submit($uid, &$form, $account) {
  $old_roles = array_keys($account->roles);
  $new_roles = array_keys($form['roles']);

  //is role added?
  foreach ($new_roles as $rid) {
    $count += _role_watchdog_add_role($rid, $old_roles, $account);
  }

  //is role removed?
  foreach ($old_roles as $rid) {
    $count += _role_watchdog_remove_role($rid, $new_roles, $account, NOT_IN_ARRAY);
  }
  _role_watchdog_set_message($count);
}

/**
 * Implementation of hook_form_submit()
 */
function role_watchdog_user_admin_account_submit($form, &$form_state) {
  list($op, $rid) = explode('-', $form_state['operation']);
  if (!in_array($op, array(
    'add_role',
    'remove_role',
  ))) {
    return;
  }
  if (!$rid) {
    return;
  }
  $accounts = array_filter($form_state['accounts']);
  foreach ($accounts as $uid) {
    $account = user_load(array(
      'uid' => $uid,
    ));
    $old_roles = array_keys($account->roles);
    if ($op == 'add_role') {
      $count += _role_watchdog_add_role($rid, $old_roles, $account);
    }
    else {

      //remove role
      $count += _role_watchdog_remove_role($rid, $old_roles, $account, IN_ARRAY);
    }
  }
  _role_watchdog_set_message($count);
}

/**
 * Internal function
 *
 * Handles addition of roles.
 */
function _role_watchdog_add_role($rid, $old_roles, $account) {
  if (!in_array($rid, $old_roles)) {
    global $user;
    $roles = user_roles();
    $message = t('%user added role %role to %account', array(
      '%user' => $user->name,
      '%role' => $roles[$rid],
      '%account' => $account->name,
    ));
    watchdog('user', $message);
    _role_watchdog_notification($rid, $message);
    return 1;
  }
  return 0;
}

/**
 * Internal function
 *
 * Handles removal of roles.
 */
function _role_watchdog_remove_role($rid, $old_roles, $account, $in_array = TRUE) {
  if ($rid > 2 && (in_array($rid, $old_roles) xor !$in_array)) {
    global $user;
    $roles = user_roles();
    $message = t('%user removed role %role from %account', array(
      '%user' => $user->name,
      '%role' => $roles[$rid],
      '%account' => $account->name,
    ));
    watchdog('user', $message);
    _role_watchdog_notification($rid, $message);
    return 1;
  }
  return 0;
}

/**
 * Internal function
 *
 * Handles user message for any changes.
 */
function _role_watchdog_set_message($count) {
  if ($count) {
    drupal_set_message(t('Role !change_has been logged.', array(
      '!change_has' => format_plural($count, 'change has', 'changes have'),
    )));
  }
}

/**
 * Internal function
 *
 * Handles notification of changes in selected roles.
 */
function _role_watchdog_notification($rid, $message) {
  $monitor_roles = variable_get('role_watchdog_monitor_roles', NULL);
  if (in_array($rid, $monitor_roles)) {
    $site_name = variable_get('site_name', 'Drupal');
    $from = "{$site_name} <" . variable_get('site_mail', ini_get('sendmail_from')) . '>';
    $subject = t('Role Watchdog notification on !site_name', array(
      '!site_name' => $site_name,
    ));
    $message = strip_tags($message);
    foreach (_role_watchdog_get_notification_list() as $recipient) {
      if (drupal_mail('role_watchdog_notification', $recipient, $subject, $message, $from)) {
        watchdog('action', t('Sent email to %recipient', array(
          '%recipient' => $recipient,
        )));
      }
      else {
        watchdog('error', t('Unable to send email to %recipient', array(
          '%recipient' => $recipient,
        )));
      }
    }
  }
}

/**
 * Internal function
 *
 * Handles building notification list
 */
function _role_watchdog_get_notification_list() {
  static $role_watchdog_notification_list;
  if (!isset($role_watchdog_notification_list)) {
    $role_watchdog_notification_list = array();
    $notification_roles = variable_get('role_watchdog_notify_roles', NULL);
    $roles = implode(',', $notification_roles);
    $sql = "\n      SELECT DISTINCT u.mail\n        FROM {users} u\n        INNER JOIN {users_roles} r ON u.uid = r.uid\n        WHERE r.rid IN (%s)\n    ";
    $result = db_query($sql, $roles);
    while ($account = db_fetch_object($result)) {
      $role_watchdog_notification_list[] = $account->mail;
    }

    //special case: superuser
    if (in_array(SUPERUSER_RID, $notification_roles)) {
      $sql = "\n        SELECT u.mail\n          FROM {users} u\n          WHERE u.uid = %d\n      ";
      $result = db_result(db_query($sql, 1));
      if (!in_array($result, $role_watchdog_notification_list)) {
        $role_watchdog_notification_list[] = $result;
      }
    }
  }
  return $role_watchdog_notification_list;
}

Functions

Namesort descending Description
role_watchdog_admin_settings Menu callback
role_watchdog_form_alter Implementation of hook_form_alter()
role_watchdog_help Implementation of hook_help().
role_watchdog_menu Implementation of hook_menu().
role_watchdog_user Implementation of hook_user().
role_watchdog_user_admin_account_submit Implementation of hook_form_submit()
role_watchdog_user_edit_submit Implementation of hook_form_submit()
_role_watchdog_add_role Internal function
_role_watchdog_get_notification_list Internal function
_role_watchdog_notification Internal function
_role_watchdog_remove_role Internal function
_role_watchdog_set_message Internal function

Constants

Namesort descending Description
IN_ARRAY
NOT_IN_ARRAY
SUPERUSER_RID @file Logs changes to user roles.