You are here

webform_tokens.module in Webform Tokens 7

Same filename and directory in other branches
  1. 6 webform_tokens.module
  2. 7.4 webform_tokens.module

The Webform Tokens module.

File

webform_tokens.module
View source
<?php

/**
 * @file
 * The Webform Tokens module.
 */

/**
 * Implements hook_token_info().
 */
function webform_tokens_token_info() {
  $types['webform-tokens'] = array(
    'name' => t('Webform Tokens-provided data'),
    'description' => t('Tokens for Webform submitted data and metadata. The old [webform:] style will work if Webform Rules is not enabled.'),
    'needs-data' => 'webform-submission',
  );
  $tokens = array();
  $tokens['meta-label-(Field_Key)'] = array(
    'name' => t('Meta: Label of given component'),
    'description' => t('The label for the specified component. The easiest way to use this is to insert the <code>val</code> token for the component you want, then change <code>val</code> to <code>meta-label</code>.'),
  );
  $tokens['meta-nid'] = array(
    'name' => t('Meta: Parent webform node ID'),
    'description' => t('The Node ID (nid) of the parent webform.'),
    'type' => 'node',
  );
  $tokens['meta-sid'] = array(
    'name' => t('Meta: Submission ID'),
    'description' => t('The submission\'s ID.'),
  );
  $tokens['meta-uid'] = array(
    'name' => t('Meta: Submitting user\'s ID'),
    'description' => t('The submitting user\'s ID.'),
    'type' => 'user',
  );
  $tokens['meta-remote_addr'] = array(
    'name' => t('Meta: Submitting user\'s IP address'),
    'description' => t('The submitting user\'s IP address.'),
  );
  $tokens['meta-submitted'] = array(
    'name' => t('Meta: Submission date'),
    'description' => t('The date the webform was submitted.'),
    'type' => 'date',
  );
  $q = db_select('webform_component');
  $q
    ->join('node', 'node', 'webform_component.nid = node.nid');
  $q = $q
    ->fields('webform_component')
    ->fields('node', array(
    'title',
  ))
    ->condition('webform_component.type', array(
    'markup',
    'pagebreak',
    'fieldset',
  ), 'NOT IN')
    ->execute();
  while ($component = $q
    ->fetchAssoc()) {
    $component_extra = !empty($component['extra']) ? unserialize($component['extra']) : array();
    if (!is_array($component_extra)) {
      $component_extra = array(
        $component_extra,
      );
    }

    // Create token if it does not exists; add this nid if it already exists.
    $title = '"' . $component['title'] . '" (' . $component['nid'] . ')';
    if (isset($tokens['val-' . $component['form_key']])) {
      $tokens['val-' . $component['form_key']]['description'] .= ', ' . $title;
    }
    else {
      $tokens['val-' . $component['form_key']] = array(
        'name' => t('Value:') . ' ' . $component['name'],
        'description' => t('Available in Webform') . ' ' . $title,
      );
    }

    // Render select options components as chained arrays.
    if (!empty($component_extra['items'])) {
      $tokens['val-' . $component['form_key']]['type'] = 'array';
    }
    elseif ($component['type'] === 'date') {
      $tokens['val-' . $component['form_key']]['type'] = 'date';
    }
  }
  $type_tokens = array(
    'webform-tokens' => $tokens,
  );
  return array(
    'types' => $types,
    'tokens' => $type_tokens,
  );
}

/**
 * Implements hook_tokens().
 *
 * The first "_tokens" is part of the module name.
 */
function webform_tokens_tokens($type, array $tokens, array $data = array(), array $options = array()) {

  // Support [webform:] tokens if Webform Rules is not enabled.
  if ($type === 'webform' && isset($data['webform']) && module_exists('webform_rules') === FALSE) {
    $type = 'webform-tokens';
    $data['webform-submission'] = $data['webform'];
  }
  if ($type === 'webform-tokens' && isset($data['webform-submission']) && is_object($data['webform-submission'])) {
    $submission = $data['webform-submission'];
    $nid = $submission->nid;
    $sid = $submission->sid;
    $replacements = array();
    $special_tokens = array(
      'meta-nid',
      'webform-meta-nid',
      'meta-submitted',
      'webform-meta-submitted',
    );
    foreach ($tokens as $name => $original) {
      switch ($name) {
        case 'meta-nid':
        case 'webform-meta-nid':
          $replacements[$original] = $submission->nid;
          break;
        case 'meta-sid':
        case 'webform-meta-sid':
          $replacements[$original] = $submission->sid;
          break;
        case 'meta-uid':
        case 'webform-meta-uid':
          $replacements[$original] = $submission->uid;
          break;
        case 'meta-remote_addr':
        case 'webform-meta-remote_addr':
          $replacements[$original] = $submission->remote_addr;
          break;
        case 'meta-submitted':
        case 'webform-meta-submitted':
          $replacements[$original] = $submission->submitted;
          break;
        default:

          // Don't replace if the name will be generated later.
          foreach ($special_tokens as $special_name) {
            if (strpos($name, $special_name) !== FALSE && $name != $special_name) {
              break 2;
            }
          }
          static $components;

          // Initialize components for this webform submission if necessary.
          if (!isset($components[$nid][$sid])) {
            $components = array(
              $nid => array(
                $sid => array(),
              ),
            );
            $q = db_select('webform_component')
              ->fields('webform_component')
              ->condition('type', array(
              'markup',
              'pagebreak',
              'fieldset',
            ), 'NOT IN')
              ->condition('nid', $submission->nid)
              ->execute()
              ->fetchAllAssoc('cid', PDO::FETCH_ASSOC);
            foreach ($q as $this_component) {
              $cid = $this_component['cid'];
              if (isset($submission->data[$cid])) {
                $submission->data[$cid] += $this_component;
              }
              else {
                $submission->data[$cid] = array();
              }

              // Modify the submission.
              $components[$nid][$sid] += array(
                $cid => $submission->data[$cid],
              );
            }
          }
          $cid_found = FALSE;
          foreach ($components as $this_nid => $this_submission) {
            foreach ($this_submission as $this_sid => $this_component) {
              foreach ($this_component as $this_cid => $component_data) {
                if (!empty($component_data)) {

                  // We have to account for chained tokens as well.
                  $prefix_check = token_find_with_prefix($tokens, 'val-' . $component_data['form_key']);
                  if (in_array($name, array(
                    'val-' . $component_data['form_key'],
                    'meta-label-' . $component_data['form_key'],
                  )) || !empty($prefix_check)) {
                    $cid = $this_cid;
                    $cid_found = TRUE;
                    break;
                  }
                  $prefix_check = token_find_with_prefix($tokens, 'webform-val-' . $component_data['form_key']);
                  if (in_array($name, array(
                    'webform-val-' . $component_data['form_key'],
                    'webform-key-' . $component_data['form_key'],
                    'meta-label-' . $component_data['form_key'],
                  )) || !empty($prefix_check)) {
                    $cid = $this_cid;
                    $cid_found = TRUE;
                    break;
                  }
                }
              }
              if ($cid_found) {
                break;
              }
            }
            if ($cid_found) {
              break;
            }
          }
          if ($cid_found && !empty($components[$nid][$sid][$cid])) {
            $replacements += _webform_tokens_add_component_replacement($components[$nid][$sid][$cid], $submission, array(
              'original' => $original,
              'name' => $name,
              'tokens' => $tokens,
              'options' => $options,
            ));
          }
          break;
      }
    }
    if ($webform_meta_node_tokens = token_find_with_prefix($tokens, 'meta-nid')) {
      $webform_meta_node = node_load($submission->nid);
      $replacements += token_generate('node', $webform_meta_node_tokens, array(
        'node' => $webform_meta_node,
      ), $options);
    }
    if ($webform_meta_node_tokens = token_find_with_prefix($tokens, 'webform-meta-nid')) {
      $webform_meta_node = node_load($submission->nid);
      $replacements += token_generate('node', $webform_meta_node_tokens, array(
        'node' => $webform_meta_node,
      ), $options);
    }
    if ($webform_meta_node_tokens = token_find_with_prefix($tokens, 'meta-uid')) {
      $webform_meta_user = user_load($submission->uid);
      $replacements += token_generate('user', $webform_meta_node_tokens, array(
        'user' => $webform_meta_user,
      ), $options);
    }
    if ($webform_meta_node_tokens = token_find_with_prefix($tokens, 'webform-meta-uid')) {
      $webform_meta_user = user_load($submission->uid);
      $replacements += token_generate('user', $webform_meta_node_tokens, array(
        'user' => $webform_meta_user,
      ), $options);
    }
    if ($webform_meta_submitted_tokens = token_find_with_prefix($tokens, 'meta-submitted')) {
      $webform_meta_submitted = $submission->submitted;
      $replacements += token_generate('date', $webform_meta_submitted_tokens, array(
        'date' => $webform_meta_submitted,
      ), $options);
    }
    if ($webform_meta_submitted_tokens = token_find_with_prefix($tokens, 'webform-meta-submitted')) {
      $webform_meta_submitted = $submission->submitted;
      $replacements += token_generate('date', $webform_meta_submitted_tokens, array(
        'date' => $webform_meta_submitted,
      ), $options);
    }
    return $replacements;
  }
}

/**
 * Helper function to find an individual replacement.
 */
function _webform_tokens_add_component_replacement($component, $submission, $token_data) {
  $replacements = array();
  $nid = $submission->nid;
  $sid = $submission->sid;

  // If this is a request for a label token, no need for all the other stuff.
  if ($token_data['name'] == 'meta-label-' . $component['form_key']) {
    $replacements[$token_data['original']] = $component['name'];
    return $replacements;
  }

  // First, unserialize everything so we can work with them as arrays.
  $fullvalue = FALSE;

  // For components with selectable options (including grids), make an array of options in the form array(safe_key => "Some readable option", ...)
  $options = FALSE;
  if (isset($component['extra']) && is_string($component['extra'])) {
    $component['extra'] = unserialize($component['extra']);

    // Selects use "items".
    if (isset($component['extra']['items']) && is_string($component['extra']['items'])) {
      $component['extra']['options'] = $component['extra']['items'];
    }

    // Grids use "options".
    if (isset($component['extra']['options']) && is_string($component['extra']['options'])) {
      foreach (preg_split('/[\\r\\n]+/', $component['extra']['options']) as $_) {
        if (strpos($_, '|') !== FALSE) {
          $option = explode('|', $_, 2);
          $options[(string) $option[0]] = $option[1];
        }
        else {

          // Make sure the keys are strings.
          $options[(string) $_] = $_;
        }
      }
    }
  }
  if ($options) {
    $component['extra']['options'] = $options;
    foreach ($component['value'] as $chain_value) {
      if (isset($options[$chain_value])) {
        $values[$chain_value] = $options[$chain_value];
      }
    }
    if (!in_array($token_data['name'], array(
      'val-' . $component['form_key'],
      'meta-label-' . $component['form_key'],
    ))) {

      // This token is chained, so call token_generate.
      if ($options_tokens = token_find_with_prefix($token_data['tokens'], 'val-' . $component['form_key'])) {
        return token_generate('array', $options_tokens, array(
          'array' => $values,
        ), $token_data['options']);
      }
    }
    if (!in_array($token_data['name'], array(
      'webform-val-' . $component['form_key'],
      'webform-key-' . $component['form_key'],
    ))) {

      // This token is chained, so call token_generate.
      if ($options_tokens = token_find_with_prefix($token_data['tokens'], 'webform-val-' . $component['form_key'])) {
        return token_generate('array', $options_tokens, array(
          'array' => $values,
        ), $token_data['options']);
      }
    }
    unset($options, $values);
  }
  else {
    $component['extra']['options'] = FALSE;
  }
  if (!empty($component['value']) && is_array($component['value'])) {
    switch ($component['type']) {
      case 'date':

        // Chain tokens.
        if ($found_tokens = token_find_with_prefix($token_data['tokens'], 'val-' . $component['form_key'])) {
          return token_generate('date', $found_tokens, array(
            'date' => strtotime($component['value'][0]),
          ), $token_data['options']);
        }
        if ($found_tokens = token_find_with_prefix($token_data['tokens'], 'webform-val-' . $component['form_key'])) {
          return token_generate('date', $found_tokens, array(
            'date' => strtotime($component['value'][0]),
          ), $token_data['options']);
        }

        // Non-chain token: Format date the same way Webform does.
        $value = webform_date_array($component['value'][0], 'date');
        $value = theme('webform_display_date', array(
          'element' => array(
            '#value' => $value,
          ),
        ));
        break;
      case 'file':
        $file = file_load((int) $component['value'][0]);
        $value = file_create_url($file->uri);
        break;
      case 'select':
      case 'grid':

        // Make key token.
        $fullvalue = array();
        foreach ($component['value'] as $value) {
          if ($token_data['name'] == 'webform-key-' . $component['form_key']) {
            $array_part = 'key';
          }
          else {
            $array_part = 'value';
          }
          if ($array_part === 'value' && isset($component['extra']['options'][$value])) {
            $fullvalue[] = $component['extra']['options'][$value];
          }
          else {
            $fullvalue[] = $value;
          }
        }
        $fullvalue = implode(', ', $fullvalue);

      // Don't break: every field gets a val token.
      default:

        // Usually there is only one value, so implode just removes the array
        // Otherwise, separate the values with a comma.
        // @todo: There should probably be better handling for multiple values
        $value = implode(', ', $component['value']);
    }
  }
  else {
    $value = '';
  }
  if ($fullvalue) {
    $replacements[$token_data['original']] = $fullvalue;
  }
  else {
    $replacements[$token_data['original']] = $value;
  }
  return $replacements;
}

/**
 * Clear the token cache when Webform components are updated.
 */

/**
 * Implements hook_webform_component_insert().
 */
function webform_tokens_webform_component_insert() {
  token_clear_cache();
}

/**
 * Implements hook_webform_component_update().
 */
function webform_tokens_webform_component_update() {
  token_clear_cache();
}

/**
 * Implements hook_webform_component_delete().
 */
function webform_tokens_webform_component_delete() {
  token_clear_cache();
}