agreement.module in Agreement 7.2
Same filename and directory in other branches
Agreement module code - agreement.module.
Module allows the administrator to force a user role to accept an agreement before accessing any site content.
File
agreement.moduleView source
<?php
/**
* @file
* Agreement module code - agreement.module.
*
* Module allows the administrator to force a user role to accept an agreement
* before accessing any site content.
*/
/**
* Implements hook_permission().
*/
function agreement_permission() {
return array(
'administer agreements' => array(
'title' => t('Administer agreements'),
),
'bypass agreement' => array(
'title' => t('Bypass agreement'),
),
'revoke own agreement' => array(
'title' => t('Revoke own agreement'),
),
);
}
/**
* Implements hook_init().
*/
function agreement_init() {
// If the user hasn't already agreed, redirect them to the agreement page.
global $user;
// Users with the bypass agreement permission are always excluded from any
// agreement.
if (!user_access('bypass agreement')) {
$path = strtolower(drupal_get_path_alias(current_path()));
$info = agreement_type_get_best_match($user, $path);
if ($info) {
// Save intended destination.
if (!isset($_SESSION['agreement_destination'])) {
if (preg_match('/^user\\/reset/i', current_path())) {
$_SESSION['agreement_destination'] = 'change password';
}
else {
$_SESSION['agreement_destination'] = current_path();
}
}
drupal_goto(check_plain($info['path']));
exit;
}
}
}
/**
* Implements hook_menu().
*/
function agreement_menu() {
$items = array();
$items['admin/config/people/agreement'] = array(
'access arguments' => array(
'administer agreements',
),
'description' => 'Configure settings for the Agreement module.',
'file' => 'agreement.admin.inc',
'page callback' => 'agreement_type_overview',
'page arguments' => array(),
'title' => 'Agreement settings',
'type' => MENU_NORMAL_ITEM,
);
$items['admin/config/people/agreement/manage'] = array(
'access arguments' => array(
'administer agreements',
),
'title' => 'Manage',
'type' => MENU_DEFAULT_LOCAL_TASK,
);
$items['admin/config/people/agreement/manage/%agreement_type'] = array(
'access arguments' => array(
'administer agreements',
),
'file' => 'agreement.admin.inc',
'page callback' => 'drupal_get_form',
'page arguments' => array(
'agreement_settings_form',
5,
),
'title' => 'Manage Agreement: %agreement_type',
'title arguments' => array(
5,
),
'title callback' => 'agreement_type_edit_title',
'type' => MENU_NORMAL_ITEM,
);
$items['admin/config/people/agreement/manage/%agreement_type/edit'] = array(
'access arguments' => array(
'administer agreements',
),
'title' => 'Modify',
'type' => MENU_DEFAULT_LOCAL_TASK,
);
$items['admin/config/people/agreement/add'] = array(
'access arguments' => array(
'administer agreements',
),
'file' => 'agreement.admin.inc',
'page callback' => 'drupal_get_form',
'page arguments' => array(
'agreement_settings_form',
NULL,
),
'title' => 'Add agreement',
'type' => MENU_LOCAL_ACTION,
);
$items['admin/config/people/agreement/manage/%agreement_type/reset'] = array(
'access arguments' => array(
'administer agreements',
),
'file' => 'agreement.admin.inc',
'page callback' => 'drupal_get_form',
'page arguments' => array(
'agreement_type_reset_form',
5,
),
'title' => 'Reset',
'type' => MENU_LOCAL_TASK,
'weight' => 1,
);
$items['admin/config/people/agreement/manage/%agreement_type/delete'] = array(
'access arguments' => array(
'administer agreements',
),
'file' => 'agreement.admin.inc',
'page callback' => 'drupal_get_form',
'page arguments' => array(
'agreement_type_delete_form',
5,
),
'title' => 'Remove',
'type' => MENU_LOCAL_TASK,
'weight' => 2,
);
$types = agreement_type_load(NULL, FALSE);
foreach ($types as $name => $type) {
$page = check_plain($type['path']);
if (!isset($items[$page])) {
$items[$page] = array(
'access arguments' => array(
'access content',
),
'description' => 'The ' . $type['type'] . ' agreement page.',
'file' => 'agreement.pages.inc',
'page callback' => 'agreement_page',
'page arguments' => array(
$name,
),
'title' => $type['settings']['title'],
'type' => MENU_CALLBACK,
);
}
}
return $items;
}
/**
* Implements hook_user_update().
*/
function agreement_user_update(&$edit, &$account, $category = NULL) {
global $user;
$types = agreement_type_load();
foreach ($types as $name => $info) {
// Do not require user to re-accept agreement if they've just changed their
// password.
if ($info['settings']['frequency'] === 0 && !empty($edit['pass']) && $account->uid === $user->uid) {
agreement_agree($account, $name, 2);
}
}
}
/**
* Implements hook_theme().
*/
function agreement_theme($existing, $type, $theme, $path) {
return array(
'agreement_page' => array(
'render element' => 'form',
),
);
}
/**
* Implements hook_mail().
*/
function agreement_mail($key, &$message, $params) {
switch ($key) {
case 'notice':
$variables = array(
'!site-name' => variable_get('site_name', 'Drupal'),
'!username' => format_username($params['account']),
);
$message['subject'] = t('!site-name: !username accepted agreement', $variables, array(
'langcode' => $message['language']->language,
));
$message['body'][] = t('The user has accepted the agreement.');
break;
case 'revoked':
$variables = array(
'!site-name' => variable_get('site_name', 'Drupal'),
'!username' => format_username($params['account']),
);
$message['subject'] = t('!site-name: !username revoked acceptance of agreement', $variables, array(
'langcode' => $message['language']->language,
));
$message['body'][] = t('The user has revoked their acceptance of the agreement.');
break;
}
}
/**
* Implements hook_views_api().
*/
function agreement_views_api() {
return array(
'api' => 3,
'path' => drupal_get_path('module', 'agreement'),
);
}
/**
* Format the agreement page.
*
* @ingroup themeable
*/
function theme_agreement_page(&$variables) {
return $variables['form'];
}
/**
* Load agreement types.
*
* @param string $name
* (Optional) An agreement type machine name to load.
* @param bool $use_cache
* (Optional) Whether or not to load from cache or not.
*
* @return array
* An associative array of agreement types keyed by the agreement type ID, or
* a single agreement type.
*/
function agreement_type_load($name = NULL, $use_cache = TRUE) {
$agreement_types =& drupal_static(__FUNCTION__);
if (!$use_cache || !isset($agreement_types) || !is_array($agreement_types)) {
$types = array();
$query = db_select('agreement_type');
$query
->fields('agreement_type')
->orderBy('name');
$result = $query
->execute();
if (!empty($result)) {
$types = $result
->fetchAllAssoc('name', PDO::FETCH_ASSOC);
// Unserialize the type settings.
foreach ($types as $type_name => $type) {
$types[$type_name]['settings'] = unserialize($types[$type_name]['settings']);
}
}
// Set the type(s) into static cache.
$agreement_types = $types;
}
else {
$types = $agreement_types;
}
return !empty($types) && isset($name) && isset($types[$name]) ? $types[$name] : $types;
}
/**
* Save an agreement type.
*
* @param array $info
* The agreement type info.
* @param bool $rebuild_menu
* (Optional) Rebuilds the menu cache.
*
* @return array
* The agreement type that was saved after setting static cache.
*/
function agreement_type_save($info, $rebuild_menu = FALSE) {
$new = (object) $info;
$new->settings = serialize($new->settings);
if (isset($new->id)) {
drupal_write_record('agreement_type', $new, array(
'id',
));
}
else {
drupal_write_record('agreement_type', $new);
}
// When a user changes the URL of the page the menu will need to be rebuilt.
// Submitting the form lands the user right back here. This will also reset
// the static cache as built in hook_menu().
if ($rebuild_menu) {
menu_rebuild();
}
// Prevent multiple static cache reset when menu is rebuilt, but do reset the
// cache when menu is not rebuilt.
return agreement_type_load($new->name, !$rebuild_menu);
}
/**
* Retrieve the label for the agreement type to display as the page title.
*
* @param array $info
* The agreement type info array.
*
* @return string
* The page title.
*/
function agreement_type_edit_title($info) {
$type = '';
if (isset($info['type'])) {
$type = $info['type'];
}
return t('Manage Agreement: @type', array(
'@type' => $type,
));
}
/**
* Whether or not an agreement type exists by name.
*
* @param string $name
* The agreement type machine name.
*
* @return bool
* TRUE if the agreement type exists.
*/
function agreement_type_name_exists($name) {
$result = db_select('agreement_type')
->condition('name', $name)
->fields('agreement_type', array(
'name',
))
->execute()
->fetchField();
return $result && $result === $name;
}
/**
* Has the user account agreed to the agreement yet?
*
* @param object $account
* The user account.
* @param array $info
* The agreement type..
*
* @return bool
* TRUE if the user has agreed.
*/
function agreement_has_agreed($account, $info) {
$type = $info['name'];
// Check the user account data for the agreement.
if (isset($account->data['agreement']) && isset($account->data['agreement'][$type])) {
return $info['settings']['frequency'] ? session_id() === $account->data['agreement'] : TRUE;
}
$query = db_select('agreement');
$query
->fields('agreement', array(
'agreed',
))
->condition('type', $type)
->condition('uid', $account->uid)
->range(0, 1);
if ($info['settings']['frequency'] == 0) {
// Must agree on every login.
$query
->condition('sid', session_id());
}
else {
// Must agree when frequency is set greater than zero (number of days).
if ($info['settings']['frequency'] > 0) {
$frequency_timestamp = time() - $info['settings']['frequency'] * 24 * 60 * 60;
}
else {
$frequency_timestamp = 0;
}
$reset_date = isset($info['settings']['reset_date']) ? $info['settings']['reset_date'] : 0;
$timestamp = max($reset_date, $frequency_timestamp);
if ($timestamp > 0) {
$query
->condition('agreed_date', $timestamp, '>=');
}
}
return $query
->execute()
->fetchField();
}
/**
* Agrees the user account to the agreement.
*
* @param object $account
* The user account object.
* @param string $type
* The agreement type name.
* @param int $agreed
* (Optional) Set the agreed value.
*/
function agreement_agree($account, $type, $agreed = 1) {
db_delete('agreement')
->condition('uid', $account->uid)
->condition('type', $type)
->execute();
$edit = (object) array(
'uid' => $account->uid,
'type' => $type,
'agreed' => $agreed,
'sid' => session_id(),
'agreed_date' => REQUEST_TIME,
);
drupal_write_record('agreement', $edit);
}
/**
* Get the best match agreement type for a user and path.
*
* @param object $account
* The user account to check.
* @param string $path
* The path alias to check based on current path.
*
* @return bool|array
* The agreement type or FALSE if none found that matched the criteria.
*/
function agreement_type_get_best_match($account, $path) {
$types = agreement_type_load();
$default_exceptions = array(
'user/logout',
'admin/config/people/agreement',
'admin/config/people/agreement/*',
'admin/config/people/agreement/manage/*',
);
// Get a list of pages to never display agreement on.
$exceptions = array_reduce($types, function (&$result, $item) {
$result[] = $item['path'];
return $result;
}, $default_exceptions);
$exception_string = implode("\n", $exceptions);
if (drupal_match_path($path, $exception_string)) {
return FALSE;
}
// Reduce the agreement types based on the agreement restricted roles.
$account_roles = array_keys($account->roles);
$role_types = array_reduce($types, function (&$result, $item) use ($account) {
if (_agreement_user_has_role($account, $item['settings']['role'])) {
$result[$item['name']] = $item;
}
return $result;
}, array());
// Try to find an agreement type that matches the path.
$info = array_reduce($role_types, function (&$result, $item) use ($path, $account) {
if ($result) {
return $result;
}
$pattern = html_entity_decode(strtolower($item['settings']['visibility_pages']));
$has_match = drupal_match_path($path, $pattern);
$has_agreed = agreement_has_agreed($account, $item);
if (0 === (int) $item['settings']['visibility_settings'] && FALSE === $has_match && !$has_agreed) {
// An agreement type exists that matches any page.
$result = $item;
}
elseif (1 === (int) $item['settings']['visibility_settings'] && $has_match && !$has_agreed) {
// An agreement type exists that matches the current path.
$result = $item;
}
return $result;
}, FALSE);
return $info;
}
/**
* Internal function to get the user's "agreement status".
*
* @param object $uid
* (Optional) UID for which the status should be checked. Defaults to current
* user.
* @param int $frequency
* (Optional) Frequency. This is here for legacy purposes.
* @param int $reset
* (Optional) Whether a "reset" has occurred on the agreement.
*
* @return bool
* if agreement found in db.
*
* @deprecated See agreement_has_agreed().
*
* @internal
*/
function _agreement_status($uid = NULL, $frequency = 0, $reset = 0) {
// If the UID is not specified, use the current user.
if (empty($uid)) {
global $user;
$uid = $user->uid;
}
// Make sure we weren't passed some garbage as $uid.
$uid = (int) $uid;
$query = db_select('agreement', 'a');
$query
->fields('a', array(
'agreed',
))
->condition('a.uid', $uid, '=')
->condition('a.name', 'default', '=')
->range(0, 1);
// Must agree on every login.
if ($frequency == 0) {
$query
->condition('a.sid', session_id(), '=');
}
else {
// Must agree when frequency is set greater than zero (number of days).
if ($frequency > 0) {
$frequency_timestamp = time() - $frequency * 24 * 60 * 60;
}
else {
$frequency_timestamp = 0;
}
$timestamp = max($reset, $frequency_timestamp);
if ($timestamp > 0) {
$query
->condition('agreed_date', $timestamp, '>=');
}
}
return $query
->execute()
->fetchField();
}
/**
* Agreement settings form submit callback.
*
* Rebuilds the menu system when an user changes the URL or page title of the
* page.
*
* @param array $form
* The form array.
* @param array $form_state
* The form state array.
*
* @deprecated See agreement.pages.inc
*/
function _agreement_admin_form_submit($form, &$form_state) {
if ($form_state['values']['agreement_page_url'] !== $form['agreement_page_url']['#default_value'] || $form_state['values']['agreement_page_title'] !== $form['agreement_page_title']['#default_value']) {
menu_rebuild();
}
// If they selected to force re-acceptance of the agreement for every user.
if (!empty($form_state['values']['agreement_clear'])) {
variable_set('agreement_reset', time());
}
}
/**
* Get agreement translated string constants.
*
* @param string $name
* The constant name to retrieve as a string.
*
* @return string
* Get the translated string for the agreement "constant".
*/
function agreement_get_translated_message($name) {
$messages = _agreement_get_translated_messages();
if ($name && isset($messages[$name])) {
return $messages[$name];
}
return '';
}
/**
* Get all translated string constants.
*
* @return array
* An array keyed by the "constant" name and value as the translated string.
*/
function _agreement_get_translated_messages() {
$agreement_constants =& drupal_static(__FUNCTION__);
if (!isset($agreement_constants)) {
$agreement_constants = array(
'AGREEMENT_PAGE_URL' => 'agreement',
'AGREEMENT_PAGE_TITLE' => t('Our Agreement'),
'AGREEMENT_MESSAGE_SUCCESS' => t('Thank you for accepting our agreement.'),
'AGREEMENT_MESSAGE_FAILURE' => t('You must accept our agreement to continue.'),
'AGREEMENT_MESSAGE_REVOKED' => t('You successfully revoked your acceptance of our agreement.'),
'AGREEMENT_CHECKBOX_TEXT' => t('I agree.'),
'AGREEMENT_SUBMIT_TEXT' => t('Submit'),
'AGREEMENT_FORMAT' => filter_default_format(),
);
}
return $agreement_constants;
}
/**
* Checks if user has agreement roles.
*
* @param object $account
* The user account.
* @param array $role_ids
* The role ids to check.
*
* @return bool
* TRUE if the user's roles intersect with the provided role ids.
*/
function _agreement_user_has_role($account, $role_ids) {
$account_roles = array_keys($account->roles);
return !empty(array_intersect($role_ids, $account_roles));
}
Functions
Name![]() |
Description |
---|---|
agreement_agree | Agrees the user account to the agreement. |
agreement_get_translated_message | Get agreement translated string constants. |
agreement_has_agreed | Has the user account agreed to the agreement yet? |
agreement_init | Implements hook_init(). |
agreement_mail | Implements hook_mail(). |
agreement_menu | Implements hook_menu(). |
agreement_permission | Implements hook_permission(). |
agreement_theme | Implements hook_theme(). |
agreement_type_edit_title | Retrieve the label for the agreement type to display as the page title. |
agreement_type_get_best_match | Get the best match agreement type for a user and path. |
agreement_type_load | Load agreement types. |
agreement_type_name_exists | Whether or not an agreement type exists by name. |
agreement_type_save | Save an agreement type. |
agreement_user_update | Implements hook_user_update(). |
agreement_views_api | Implements hook_views_api(). |
theme_agreement_page | Format the agreement page. |
_agreement_admin_form_submit Deprecated | Agreement settings form submit callback. |
_agreement_get_translated_messages | Get all translated string constants. |
_agreement_status Deprecated | Internal function to get the user's "agreement status". |
_agreement_user_has_role | Checks if user has agreement roles. |