You are here

site_disclaimer.module in Site Disclaimer 7

Same filename and directory in other branches
  1. 6 site_disclaimer.module

This module adds Site Disclaimer to the registration page.

File

site_disclaimer.module
View source
<?php

/**
 * @file
 * This module adds Site Disclaimer to the registration page.
 *
 */

/**
 * @todo: cancel/logout button on the "accept new terms of use" page
 * @todo: remove breadcrumbs on the "accept new terms of use" page
 *
 */
define('SITE_DISCLAIMER_SETTINGS_PATH', 'admin/config/people/site_disclaimer');
define('SITE_DISCLAIMER_ACCEPT_PATH', '_legal/accept_new');
define('SITE_DISCLAIMER_DEFAULT_TITLE', t('Terms of Use'));
define('SITE_DISCLAIMER_DEFAULT_CHECKBOX_LABEL', t('I agree with these terms'));

/**
 * Implements hook_help().
 */
function site_disclaimer_help($path, $arg) {
  switch ($path) {
    case 'admin/help#site_disclaimer':
      return '<p>' . t('Site Disclaimer form (which includes a Site Disclaimer statement and an [x] checkbox) is displayed on the registration page, and the visitor is required to accept it by checking the [x] checkbox in order to register. If Site Disclaimer statement is revised later, Site Disclaimer form will be displayed after registered user logs in and the user will be required to accept the new version of the terms by checking the [x] checkbox in order to proceed using the website.') . '</p>';
      break;
    case SITE_DISCLAIMER_SETTINGS_PATH:
      return '<p>' . t('Site Disclaimer form (which includes a Site Disclaimer statement and an [x] checkbox) is displayed on the registration page, and the visitor is required to accept it by checking the [x] checkbox in order to register. If Site Disclaimer statement is revised later, Site Disclaimer form will be displayed after registered user logs in and the user will be required to accept the new version of the terms by checking the [x] checkbox in order to proceed using the website.') . '</p>';
      break;
  }
}

/**
 * Implements hook_menu().
 */
function site_disclaimer_menu() {
  $items = array();
  $items[SITE_DISCLAIMER_SETTINGS_PATH] = array(
    'description' => 'Add Site Disclaimer to the registration page.',
    'title' => 'Site Disclaimer',
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'site_disclaimer_admin_settings',
    ),
    'access arguments' => array(
      'administer site disclaimer',
    ),
    'file' => 'site_disclaimer.admin.inc',
  );
  $items['site_disclaimer/autocomplete'] = array(
    'title' => 'Autocomplete node title',
    'page callback' => 'site_disclaimer_autocomplete',
    'access arguments' => array(
      'access content',
    ),
    'type' => MENU_CALLBACK,
    'file' => 'site_disclaimer.admin.inc',
  );
  $items[SITE_DISCLAIMER_ACCEPT_PATH] = array(
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'site_disclaimer_confirm',
    ),
    'access callback' => TRUE,
    'type' => MENU_CALLBACK,
    'file' => 'site_disclaimer.pages.inc',
  );
  return $items;
}

/**
 * Implements hook_permission().
 */
function site_disclaimer_permission() {
  return array(
    'administer site disclaimer' => array(
      'title' => t('Administer site disclaimer'),
      'description' => t('Perform administration tasks for site disclaimer.'),
    ),
    'bypass site disclaimer' => array(
      'title' => t('Bypass site disclaimer'),
      'description' => t('Bypass the site disclaimer upon logging in.'),
    ),
  );
}

/**
 * Implements hook_form_form_id_alter().
 */
function site_disclaimer_form_user_register_form_alter(&$form, $form_state, $form_id = NULL, $langcode = NULL, $preview = FALSE) {

  // Administrative users can skip site_disclaimer on admin/user/user/create page.
  if ((user_access('administer users') || user_access('administer site disclaimer') || user_access('bypass site disclaimer')) && !$preview && $form_id == 'user_register_form') {
    return;
  }
  $height = variable_get('site_disclaimer_node_height', '');
  if ($height) {
    $css = '#site-disclaimer { height:' . check_plain($height) . '; overflow:auto; }';

    // Revert the styling so print shows the full text.
    $css2 = '#site-disclaimer { height:auto; overflow:visible; }';
    $form['#attached']['css'] = array(
      $css => array(
        'type' => 'inline',
      ),
      $css2 => array(
        'type' => 'inline',
        'media' => 'print',
      ),
    );

    //    drupal_add_css('' . $css . '', array('type' => 'inline'));
    //    drupal_add_html_head('<style type="text/css" media="print">' . $css2 . '</style>', $key = NULL /* TODO Set this variable. */);
  }

  // Getting the node that contains the Site Disclaimer.
  $nid = _site_disclaimer_nid_translated(variable_get('site_disclaimer_node_id', ''), $langcode);
  $node = NULL;
  if (!empty($nid)) {
    $node = node_load($nid);
    if (empty($node)) {
      watchdog('Site Disclaimer', 'The Site Disclaimer node !nid could not be loaded. Please check the settings and the node.', array(
        '!nid' => $nid,
      ), WATCHDOG_ALERT, l(t('Administer Site Disclaimer'), SITE_DISCLAIMER_SETTINGS_PATH));
    }
  }

  // Will we show the full text of the Terms or only provide a link to the Terms.
  // Reading the checkbox label to find out.
  $checkbox_label = filter_xss_admin(_site_disclaimer_variable_get_translated('site_disclaimer_checkbox_label', SITE_DISCLAIMER_DEFAULT_CHECKBOX_LABEL, $langcode));
  $use_link = strpos($checkbox_label, '@link') !== FALSE;
  $use_named_links = strpos($checkbox_label, '@&quot;') !== FALSE;
  $show_node = $node && !$use_link && !$use_named_links;

  // If there is no node to show and no links in the $checkbox_label, we don't show the terms form.
  // Same logic as in _site_disclaimer_enabled()
  if (!$use_link && !$use_named_links && !$node) {
    return;
  }
  $checkbox_label = theme('site_disclaimer_checkbox_label', array(
    'checkbox_label' => $checkbox_label,
    'node' => $node,
  ));
  $fieldset_en = variable_get('site_disclaimer_fieldset', 1);
  if ($fieldset_en) {

    // Adding the fieldset.
    $form['site_disclaimer'] = array(
      '#type' => 'fieldset',
      '#title' => check_plain(_site_disclaimer_variable_get_translated('site_disclaimer_title', SITE_DISCLAIMER_DEFAULT_TITLE, $langcode)),
      '#weight' => 10,
    );
    $fieldset =& $form['site_disclaimer'];
  }
  else {
    $fieldset =& $form;
  }

  // Adding the Site Disclaimer to the fieldset.
  if ($show_node) {

    //D6    $terms = node_prepare($node);
    $build = node_view($node, 'full');
    if ($build) {
      $build['#site_disclaimer'] = TRUE;
      $build['#site_disclaimer_theme'] = isset($build['#theme']) ? $build['#theme'] : '';
      $build['#theme'] = 'site_disclaimer_node';
      $fieldset['site_disclaimer_text'] = array(
        'node' => $build,
        '#weight' => 9,
      );
    }
    else {
      watchdog('Site Disclaimer', 'The output of Site Disclaimer node !nid is empty. Please check the the node content.', array(
        '!nid' => $nid,
      ), WATCHDOG_ALERT, l(t('Administer Site Disclaimer'), SITE_DISCLAIMER_SETTINGS_PATH));
    }
  }

  // Adding the checkbox to the fieldset.
  $fieldset['I_agree'] = array(
    '#type' => 'checkbox',
    '#title' => $checkbox_label,
    '#required' => TRUE,
    // The following adds "required" validation to the checkbox (patches core missing functionality as of D6.16)
    '#element_validate' => array(
      '_site_disclaimer_validate_checkbox',
    ),
    '#return_value' => variable_get('site_disclaimer_version', 1),
    '#weight' => 10,
  );
  return $form;
}

/**
 * Implements hook_user_presave().
 */
function site_disclaimer_user_presave(&$edit, $account, $category) {
  if (isset($edit['I_agree'])) {
    $edit['data']['site_disclaimer'] = $edit['I_agree'];
    unset($edit['I_agree']);
  }
}

/**
 * Implements hook_init().
 */
function site_disclaimer_init() {
  global $user;
  if (user_is_logged_in() && !user_access('bypass site disclaimer') && !user_access('administer site disclaimer')) {
    $site_disclaimer_enabled = _site_disclaimer_enabled();
    $site_disclaimer_version = variable_get('site_disclaimer_version', 1);
    if ($site_disclaimer_enabled && (!isset($user->data['site_disclaimer']) || $user->data['site_disclaimer'] < $site_disclaimer_version)) {
      $allow_nodes = variable_get('site_disclaimer_allow_nodes', array());

      // Allowed paths, array path components mean logical or (any of)
      $allow_paths = array(
        explode('/', SITE_DISCLAIMER_ACCEPT_PATH),
        array(
          'user',
          'logout',
        ),
        array(
          'js',
        ),
      );

      // Any links in the Site Disclaimer node or in the checkbox should also be allowed.
      if (!empty($allow_nodes)) {
        $allow_paths[] = array(
          'node',
          $allow_nodes,
        );

        // Special case for print.module - allow the user to also print the allowed nodes.
        $allow_paths[] = array(
          'print',
          'node',
          $allow_nodes,
        );
        $allow_paths[] = array(
          'printpdf',
          'node',
          $allow_nodes,
        );
      }

      // @todo: implement hook_site_disclaimer_allowed_paths_alter() here, so paths like print, printpdf can belong to print module
      // Check if the path is in the allowed list
      foreach ($allow_paths as $allow_path) {

        // This while loop ends in "return" if the path matches.
        // If the path does not match, break 2 will loop to the next allowed path
        while (1) {
          $i = 0;

          // Array path components mean logical or (any of)
          foreach ($allow_path as $part) {
            if (is_array($part) && !in_array(arg($i), $part)) {
              break 2;
            }
            if (!is_array($part) && arg($i) != $part) {
              break 2;
            }
            $i++;
          }

          // The arg() path matches the one in the $allow_path
          return;
        }
      }
      drupal_goto(SITE_DISCLAIMER_ACCEPT_PATH, array(
        'query' => drupal_get_destination(),
      ));
    }
  }
}

/**
 * Implements hook_theme().
 */
function site_disclaimer_theme() {
  return array(
    'site_disclaimer_node' => array(
      'render element' => 'element',
    ),
    'site_disclaimer_checkbox_label' => array(
      'variables' => array(
        'checkbox_label' => '',
        'node' => NULL,
      ),
    ),
  );
}

/**
 * Implements MODULE_preprocess().
 */
function site_disclaimer_preprocess(&$variables, $hook) {

  //drupal_set_message(iprintr($variables,'variables',0));
  if (isset($variables['elements']['#site_disclaimer']) && isset($variables['elements']['#site_disclaimer_theme']) && $hook == $variables['elements']['#site_disclaimer_theme']) {
    $variables['display_submitted'] = FALSE;

    // Hide author info
    $variables['title'] = '';

    // Hide node title
  }
}

/**
 * Theme the Site Disclaimer section.
 *
 * @param $variables
 *  Array with 'element' - the Site Disclaimer build array.
 * @return
 *  HTML output.
 * @ingroup themeable
 */
function theme_site_disclaimer_node($variables) {
  $element = $variables['element'];

  //drupal_set_message(iprintr($element,'element',0));
  $theme = isset($element['#site_disclaimer_theme']) ? $element['#site_disclaimer_theme'] : 'node';

  // Hide node tags, links
  unset($element['field_tags'], $element['links']);

  // id to match our css (#site-disclaimer) for setting Site Disclaimer form height
  $output = '<div id="site-disclaimer" class="content clear-block">';
  $output .= theme($theme, $element);
  $output .= '</div>';
  return $output;
}

/**
 * Theme the Site Disclaimer checkbox label.
 *
 * @param $checkbox_label
 *  The label from the admin form saved in the DB.
 * @param $node
 *  The Site Disclaimer $node.
 * @return
 *  HTML output.
 * @ingroup themeable
 */
function theme_site_disclaimer_checkbox_label($variables) {
  $checkbox_label = $variables['checkbox_label'];
  $node = $variables['node'];
  if (!drupal_strlen($checkbox_label)) {
    return '';
  }
  $output = $checkbox_label;
  if (!empty($node)) {

    //We are linking to the terms instead, replace the link.
    $output = str_replace('@link', l($node->title, 'node/' . $node->nid), $output);
  }
  $output = _site_disclaimer_checkbox_label_substitute_links($output);
  return $output;
}

/**
 * Implements hook_node_insert().
 */
function site_disclaimer_node_insert($node) {
  _site_disclaimer_nodeapi_work($node, 'insert');
}

/**
 * Implements hook_node_update().
 */
function site_disclaimer_node_update($node) {
  _site_disclaimer_nodeapi_work($node, 'update');
}

/**
 * Implements hook_node_delete().
 */
function site_disclaimer_node_delete($node) {
  _site_disclaimer_nodeapi_work($node, 'delete');
}

/**
 * Implements hook_views_api().
 */
function site_disclaimer_views_api() {
  return array(
    'api' => 2.0,
    'path' => drupal_get_path('module', 'site_disclaimer') . '/views',
  );
}

/**
 * Get selected translation of the variable.
 */
function _site_disclaimer_variable_get_translated($name, $default = '', $langcode = NULL) {
  if (!empty($langcode) && module_exists('i18n_variable')) {
    return i18n_variable_get($name, $langcode, $default);
  }
  else {
    return variable_get($name, $default);
  }
}

/**
 * Get translation of a node for the current language.
 */
function _site_disclaimer_nid_translated($nid, $langcode = NULL) {
  if ($nid != '' && module_exists('translation')) {
    if (empty($langcode)) {
      global $language;
      $langcode = $language->language;
    }

    // translation_node_get_translations() returns empty set for $nid, but works ok ith $node->tnid. Go figure.
    $node = node_load($nid);
    $translations = translation_node_get_translations($node->tnid);
    if (!empty($translations[$langcode])) {
      $nid = $translations[$langcode]->nid;
    }
  }
  return $nid;
}

/**
 * Get an associative array of all node translations (keyed by language code)
 */
function _site_disclaimer_nid_all_translations($nid) {
  global $language;
  $nids = empty($nid) ? array() : array(
    $language->language => $nid,
  );
  if (!empty($nid) && module_exists('translation')) {
    $translations = translation_node_get_translations($nid);
    foreach ($translations as $langcode => $translation) {
      $nids[$langcode] = $translation->nid;
    }
  }
  return $nids;
}

/**
 * Go through the $checkbox_label string, replacing each @"Terms Link" with an actual node link
 *
 * @param $checkbox_label
 *  The label from the admin form saved in the DB.
 * @param $linked_nodes
 *  (Optional) return an array of all linked node nids.
 * @param $linked_errors
 *  (Optional) return an array of all linked node errors.
 * @return
 *  Substituted text output.
 */
function _site_disclaimer_checkbox_label_substitute_links($checkbox_label, &$linked_nodes = NULL, &$linked_errors = NULL) {
  $linked_nodes = array();
  $linked_errors = array();

  // Go through the $output string, replacing @"Terms Link" with an actual node link
  $output = str_replace('&quot;', '"', $checkbox_label);
  $i = 0;
  while ($i < drupal_strlen($output)) {
    if (drupal_substr($output, $i, 2) == '@"') {
      $start = $i + 2;
      $end = strpos($output, '"', $start);
      while (drupal_substr($output, $end - 1, 1) == "\\") {
        $end = strpos($output, '"', $end + 1);
      }
      $title = drupal_substr($output, $start, $end - $start);
      $nodes = node_load_multiple(array(), array(
        'title' => str_replace('\\"', '"', $title),
      ));
      if (empty($nodes)) {
        $linked_errors[$title] = t('No post was found with "!title" title.', array(
          '!title' => $title,
        ));
      }
      else {
        $node = array_shift($nodes);
        $linked_nodes[] = $node->nid;
        $link = l($node->title, 'node/' . $node->nid);
        $output = str_replace('@"' . $title . '"', $link, $output);
        $i += drupal_strlen($link) - 1;
      }
    }
    $i++;
  }
  return $output;
}

/**
 * Validation callback; verify that checkbox is checked.
 */
function _site_disclaimer_validate_checkbox($form, &$form_state) {
  $value = $form_state['values']['I_agree'];
  if ($value != variable_get('site_disclaimer_version', 1)) {
    form_set_error('I_agree', t('You must agree with the !terms to get an account.', array(
      '!terms' => check_plain(variable_get('site_disclaimer_title', SITE_DISCLAIMER_DEFAULT_TITLE)),
    )));
  }
}

/*
 * Worker code for hook_nodeapi().
 */
function _site_disclaimer_nodeapi_work($node, $op) {
  $nid = variable_get('site_disclaimer_node_id', '');
  $nids = $nid != '' ? _site_disclaimer_nid_all_translations($nid) : array();
  $nids += variable_get('site_disclaimer_allow_nodes', array());

  // Figure out translation relationships of the node
  if (!empty($node->tnid)) {
    $node_tnid = $node->tnid;
  }
  elseif (!empty($node->translation_source)) {
    $node_tnid = $node->translation_source->tnid ? $node->translation_source->tnid : $node->translation_source->nid;
  }

  //?  if (!$node_tnid) {

  //    $node_tnid = $_GET['translation'];
  //  }
  if (isset($node->nid) && in_array($node->nid, $nids) || !empty($node_tnid) && in_array($node_tnid, $nids)) {
    module_load_include('inc', 'site_disclaimer', 'site_disclaimer.admin');
    _site_disclaimer_prep_allowed_paths($nid, $op == 'delete' ? $node->nid : NULL);
  }
}

/**
 * Determine if site_disclaimer is enabled.
 */
function _site_disclaimer_enabled($langcode = NULL) {

  // Will we show the full text of the Terms or only provide a link to the Terms.
  // Reading the checkbox label to find out.
  $nid = _site_disclaimer_nid_translated(variable_get('site_disclaimer_node_id', ''), $langcode);
  $checkbox_label = filter_xss_admin(_site_disclaimer_variable_get_translated('site_disclaimer_checkbox_label', SITE_DISCLAIMER_DEFAULT_CHECKBOX_LABEL, $langcode));
  $use_link = strpos($checkbox_label, '@link') !== FALSE;
  $use_named_links = strpos($checkbox_label, '@&quot;') !== FALSE;

  // If there is no node to show and no links in the $checkbox_label, we don't show the terms form.
  $site_disclaimer_enabled = $use_link || $use_named_links || !empty($nid);
  return $site_disclaimer_enabled;
}
function _site_disclaimer_i18n() {
  $variables = array(
    // Rely on node translations.
    //    'site_disclaimer_node_title',
    //    'site_disclaimer_node_id',
    'site_disclaimer_title',
    'site_disclaimer_checkbox_label',
    'site_disclaimer_version_details',
  );
  $i18n_variables = variable_get('i18n_variables', array());
  if (in_array($variables[0], $i18n_variables)) {
    return;
  }
  $i18n_variables = array_merge($i18n_variables, $variables);
  variable_set('i18n_variables', $i18n_variables);
}

Functions

Namesort descending Description
site_disclaimer_form_user_register_form_alter Implements hook_form_form_id_alter().
site_disclaimer_help Implements hook_help().
site_disclaimer_init Implements hook_init().
site_disclaimer_menu Implements hook_menu().
site_disclaimer_node_delete Implements hook_node_delete().
site_disclaimer_node_insert Implements hook_node_insert().
site_disclaimer_node_update Implements hook_node_update().
site_disclaimer_permission Implements hook_permission().
site_disclaimer_preprocess Implements MODULE_preprocess().
site_disclaimer_theme Implements hook_theme().
site_disclaimer_user_presave Implements hook_user_presave().
site_disclaimer_views_api Implements hook_views_api().
theme_site_disclaimer_checkbox_label Theme the Site Disclaimer checkbox label.
theme_site_disclaimer_node Theme the Site Disclaimer section.
_site_disclaimer_checkbox_label_substitute_links Go through the $checkbox_label string, replacing each @"Terms Link" with an actual node link
_site_disclaimer_enabled Determine if site_disclaimer is enabled.
_site_disclaimer_i18n
_site_disclaimer_nid_all_translations Get an associative array of all node translations (keyed by language code)
_site_disclaimer_nid_translated Get translation of a node for the current language.
_site_disclaimer_nodeapi_work
_site_disclaimer_validate_checkbox Validation callback; verify that checkbox is checked.
_site_disclaimer_variable_get_translated Get selected translation of the variable.

Constants

Namesort descending Description
SITE_DISCLAIMER_ACCEPT_PATH
SITE_DISCLAIMER_DEFAULT_CHECKBOX_LABEL
SITE_DISCLAIMER_DEFAULT_TITLE
SITE_DISCLAIMER_SETTINGS_PATH @todo: cancel/logout button on the "accept new terms of use" page @todo: remove breadcrumbs on the "accept new terms of use" page