You are here

webform_anonymous.module in Webform Anonymous 7

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

This module enables a webform setting to anonymize the webform's results from everyone.

@author Daniel Imhoff

File

webform_anonymous.module
View source
<?php

/**
 * @file
 * This module enables a webform setting to anonymize the webform's results from
 * everyone.
 *
 * @author Daniel Imhoff
 */

/**
 * Implements hook_permission().
 */
function webform_anonymous_permission() {
  return array(
    'anonymize webform results' => array(
      'title' => t('Edit anonymize results setting'),
      'description' => t('Change the webform setting that anonymizes users who have submitted a webform.'),
    ),
  );
}

/**
 * Implements hook_form_FORM_ID_alter() for webform_configure_form().
 */
function webform_anonymous_form_webform_configure_form_alter(&$form, &$form_state) {
  if (user_access('anonymize webform results')) {
    $anonymous_setting = _webform_anonymous_webform_anonymous_information($form['#node']->nid);
    if (!empty($anonymous_setting)) {
      $locker = user_load($anonymous_setting['locked_uid']);
      $locker_uri = entity_uri('user', $locker);
    }

    // Add a custom submit handler.
    $form['#submit'][] = 'webform_anonymous_form_webform_configure_form_submit';

    // Add a Yes or No question to make the results of this webform anonymous
    // or not.
    $form['submission']['anonymous'] = array(
      '#type' => 'radios',
      '#title' => t('Anonymize results'),
      '#description' => t('Make the results of this webform anonymous to everyone.'),
      '#options' => array(
        1 => t('Yes'),
        0 => t('No'),
      ),
      '#default_value' => !empty($anonymous_setting) && $anonymous_setting['anonymous'] ? 1 : 0,
      '#disabled' => !empty($anonymous_setting) && $anonymous_setting['locked'] ? 1 : 0,
    );
    if (empty($anonymous_setting) || !$anonymous_setting['locked']) {
      $description = t('Warning: Once locked, the results of this webform will be irreversibly anonymous.');
    }
    else {
      $description = t('The results of this webform have been locked in an anonymous state by !user.', array(
        '!user' => l(format_username($locker), $locker_uri['path']),
      ));
    }

    // A checkbox in case the webform creator wants to lock the results in an
    // anonymous state.
    $form['submission']['anonymous_locked'] = array(
      '#type' => 'checkbox',
      '#title' => t('Lock anonymity'),
      '#description' => $description,
      '#default_value' => !empty($anonymous_setting) && $anonymous_setting['locked'] ? 1 : 0,
      '#states' => array(
        'visible' => array(
          ':input[name="anonymous"]' => array(
            'value' => 1,
          ),
        ),
      ),
      '#disabled' => !empty($anonymous_setting) && $anonymous_setting['locked'] ? 1 : 0,
    );
  }
}

/**
 * Additional submit handler for saving webform anonymous settings.
 */
function webform_anonymous_form_webform_configure_form_submit(&$form, &$form_state) {

  // Fetch the anonymous setting of this webform.
  $anonymous_setting = _webform_anonymous_webform_anonymous_information($form['#node']->nid);

  // No need to do all this work if it wasn't changed.
  if (empty($anonymous_setting) || $form_state['values']['anonymous'] !== $anonymous_setting['anonymous'] || (string) $form_state['values']['anonymous_locked'] !== $anonymous_setting['locked']) {
    global $user;
    if (!$form_state['values']['anonymous']) {
      $form_state['values']['anonymous_locked'] = 0;
    }
    $record = array(
      'nid' => $form['#node']->nid,
      'anonymous' => $form_state['values']['anonymous'],
      'locked' => $form_state['values']['anonymous_locked'],
      'locked_uid' => !empty($anonymous_setting) && $form_state['values']['anonymous_locked'] !== $anonymous_setting['locked'] ? $user->uid : 0,
    );

    // Insert or update the anonymous status of this webform.
    drupal_write_record('webform_anonymous', $record, empty($anonymous_setting) ? array() : 'nid');
  }
}

/**
 * Implements hook_form_FORM_ID_alter() for webform_client_form().
 */
function webform_anonymous_form_webform_client_form_alter(&$form, &$form_state) {
  $form['#submit'][] = 'webform_anonymous_webform_client_form_submit';
}

/**
 * Submit handler for webform_client_form().
 *
 * @see webform_client_form_submit()
 * @see webform_anonymous_webform_confirmation_page_access()
 */
function webform_anonymous_webform_client_form_submit($form, &$form_state) {

  // If webform submissions are anonymous, make sure all users get a token
  // added to the URL that will allow them access to the webform confirmation
  // page. (Normally the Webform module only does this for anonymous users and
  // relies on the loaded submission user ID to check access for authenticated
  // users, but that will not be available if the webform submission is
  // anonymous.)
  if (!empty($form_state['values']['details']['nid']) && ($anonymous_info = _webform_anonymous_webform_anonymous_information($form_state['values']['details']['nid'])) && !empty($anonymous_info['anonymous'])) {
    if (is_array($form_state['redirect']) && !empty($form_state['redirect'][1]['query']['sid']) && !isset($form_state['redirect'][1]['query']['token'])) {
      $submission = webform_get_submission($form['#node']->nid, $form_state['redirect'][1]['query']['sid']);
      $form_state['redirect'][1]['query']['token'] = md5($submission->submitted . $submission->sid . drupal_get_private_key());
    }
  }
}

/**
 * Implements hook_menu_alter().
 */
function webform_anonymous_menu_alter(&$items) {
  if ($items['node/%webform_menu/done']['access callback'] == 'webform_confirmation_page_access') {
    $items['node/%webform_menu/done']['access callback'] = 'webform_anonymous_webform_confirmation_page_access';
  }
}

/**
 * Substitute access callback for webform confirmation pages.
 *
 * @see webform_confirmation_page_access()
 * @see webform_anonymous_webform_client_form_submit()
 */
function webform_anonymous_webform_confirmation_page_access($node) {
  global $user;

  // First check the normal access callback.
  if (webform_confirmation_page_access($node)) {
    return TRUE;
  }

  // If the access callback returned FALSE but this is a logged-in user
  // submitting a form with anonymous submissions, check for a token in the URL
  // the same way the normal access callback does for anonymous users.
  if ($user->uid && !empty($node->nid) && ($anonymous_info = _webform_anonymous_webform_anonymous_information($node->nid)) && !empty($anonymous_info['anonymous'])) {
    $sid = !empty($_GET['sid']) && (int) $_GET['sid'] > 0 ? (int) $_GET['sid'] : NULL;
    if ($sid) {
      module_load_include('inc', 'webform', 'includes/webform.submissions');
      if ($submission = webform_get_submission($node->nid, $sid)) {
        $hash_query = !empty($_GET['token']) ? $_GET['token'] : NULL;
        $hash = md5($submission->submitted . $submission->sid . drupal_get_private_key());
        if ($hash_query === $hash) {
          return TRUE;
        }
      }
    }
  }
  return FALSE;
}

/**
 * Implements hook_webform_submission_load().
 */
function webform_anonymous_webform_submission_load(&$submissions) {
  $submission = current($submissions);
  $anonymous_setting = _webform_anonymous_webform_anonymous_information($submission->nid);
  if (!empty($anonymous_setting) && $anonymous_setting['anonymous']) {
    foreach ($submissions as $sid => $submission) {

      // If called for, anonymize uid and ip of submission before display.
      $submission->uid = 0;
      $submission->name = 'Anonymous';
      $submission->remote_addr = '0.0.0.0';
    }
  }
}

/**
 * Fetch the anonymous settings and information of a webform by the node ID.
 *
 * @param int $nid
 *   The node ID that the webform belongs.
 *
 * @return array
 *   A row of information represented as an associative array.
 */
function _webform_anonymous_webform_anonymous_information($nid) {
  return db_select('webform_anonymous', 'w', array(
    'fetch' => PDO::FETCH_ASSOC,
  ))
    ->condition('w.nid', $nid)
    ->fields('w')
    ->execute()
    ->fetchAssoc();
}