Project

General

Profile

Paste
Download (12.9 KB) Statistics
| Branch: | Revision:

root / drupal7 / sites / all / modules / webform / webform.tokens.inc @ 01f36513

1
<?php
2

    
3
/**
4
 * @file
5
 * Builds placeholder replacement tokens for webform-related data.
6
 */
7

    
8
/**
9
 * Implements hook_token_info().
10
 */
11
function webform_token_info() {
12
  // Webform submission tokens.
13
  $info['types']['submission'] = array(
14
    'name' => t('Submission'),
15
    'description' => t('Tokens related to webform submissions.'),
16
    'needs-data' => 'webform-submission',
17
  );
18

    
19
  $info['tokens']['submission']['serial'] = array(
20
    'name' => t('Serial number'),
21
    'description' => t('The serial number of this webform submission.'),
22
  );
23
  $info['tokens']['submission']['sid'] = array(
24
    'name' => t('Submission ID'),
25
    'description' => t('The unique indentifier for the webform submission.'),
26
  );
27
  $info['tokens']['submission']['access-token'] = array(
28
    'name' => t('Access token'),
29
    'description' => t('The security token used to gain access to this webform submission.'),
30
  );
31
  $info['tokens']['submission']['date'] = array(
32
    'name' => t('Date submitted'),
33
    'description' => t('The date the webform was first save as draft or completed.'),
34
    'type' => 'date',
35
  );
36
  $info['tokens']['submission']['completed_date'] = array(
37
    'name' => t('Date completed'),
38
    'description' => t('The date the webform was first completed (not draft).'),
39
    'type' => 'date',
40
  );
41
  $info['tokens']['submission']['modified_date'] = array(
42
    'name' => t('Date modified'),
43
    'description' => t('The date the webform was last saved (draft or completed).'),
44
    'type' => 'date',
45
  );
46
  $info['tokens']['submission']['ip-address'] = array(
47
    'name' => t('IP address'),
48
    'description' => t('The IP address that was used when submitting the webform.'),
49
  );
50
  $info['tokens']['submission']['user'] = array(
51
    'name' => t('Submitter'),
52
    'description' => t('The user that submitted the webform result.'),
53
    'type' => 'user',
54
  );
55
  $info['tokens']['submission']['url'] = array(
56
    'name' => t('URL'),
57
    'description' => t("Webform tokens related to the submission's URL."),
58
    'type' => 'url',
59
  );
60
  $info['tokens']['submission']['edit-url'] = array(
61
    'name' => t('Edit URL'),
62
    'description' => t("Webform tokens related to the submission's Edit URL."),
63
    'type' => 'url',
64
  );
65
  $info['tokens']['submission']['values'] = array(
66
    'name' => t('Webform submission values'),
67
    'description' => '<div>' . t('Webform tokens from submitted data. Replace the "?" with the "form key", including any parent form keys separated by colons. You can append:') . '</div>' .
68
    '<ul>' .
69
    '<li>' . t('the question key for just that one question (grid components).') . '</li>' .
70
    '<li>' . t('the option key for just that one option (grid and select components).') . '</li>' .
71
    '<li>' . t('<code>@token</code> for the value without the label (the default).', array('@token' => ':nolabel')) . '</li>' .
72
    '<li>' . t('<code>@token</code> for just the label.', array('@token' => ':label')) . '</li>' .
73
    '<li>' . t('<code>@token</code> for both the label and value together.', array('@token' => ':withlabel')) . '</li>' .
74
    '<li>' . t('<code>@token</code> for just the key in a key|label pair (grid and select components).', array('@token' => ':key')) . '</li>' .
75
    '</ul>',
76
    'dynamic' => TRUE,
77
  );
78

    
79
  return $info;
80
}
81

    
82
/**
83
 * Implements hook_tokens().
84
 */
85
function webform_tokens($type, $tokens, array $data = array(), array $options = array()) {
86
  static $recursion_level = 0;
87

    
88
  // Return early unless submission tokens are needed and there is a submission.
89
  if ($type != 'submission' || empty($data['webform-submission']) || !webform_variable_get('webform_token_access')) {
90
    return array();
91
  }
92

    
93
  // Generate Webform tokens.
94
  $replacements = array();
95

    
96
  // Prepare all the data that we will likely need more than once.
97
  $submission = $data['webform-submission'];
98
  $node = isset($data['node']) ? $data['node'] : node_load($submission->nid);
99
  $email = isset($data['webform-email']) ? $data['webform-email'] : NULL;
100
  $sanitize = !empty($options['sanitize']);
101
  $format = $sanitize ? 'html' : 'text';
102
  $url_options = isset($options['language']) ? $options['language'] : array('absolute' => TRUE);
103
  $language_code = isset($options['language']) ? $options['language']->language : NULL;
104
  $markup_components = array();
105

    
106
  // Markup components may use tokens when displayed. Displaying the tokens
107
  // requires rendering the components. Rendering a markup component can then
108
  // cause infinite recursion. To prevent this, markup components are omitted
109
  // from the rendered submission if recursion has been detected.
110
  if ($recursion_level) {
111
    $markup_components = array_keys(array_filter($node->webform['components'],
112
      function ($component) {
113
        return $component['type'] == 'markup';
114
      }));
115
  }
116

    
117
  $recursion_level++;
118

    
119
  // Replace individual tokens that have an exact replacement.
120
  foreach ($tokens as $name => $original) {
121
    switch ($name) {
122
      case 'serial':
123
        $replacements[$original] = $submission->serial ? $submission->serial : '';
124
        break;
125

    
126
      case 'sid':
127
        $replacements[$original] = $submission->sid ? $submission->sid : '';
128
        break;
129

    
130
      case 'access-token':
131
        $replacements[$original] = webform_get_submission_access_token($submission);
132
        break;
133

    
134
      case 'date':
135
        $replacements[$original] = format_date($submission->submitted, webform_variable_get('webform_date_type'), '', NULL, $language_code);
136
        break;
137

    
138
      case 'completed_date':
139
        if ($submission->completed) {
140
          $replacements[$original] = format_date($submission->completed, webform_variable_get('webform_date_type'), '', NULL, $language_code);
141
        }
142
        break;
143

    
144
      case 'modified_date':
145
        $replacements[$original] = format_date($submission->modified, webform_variable_get('webform_date_type'), '', NULL, $language_code);
146
        break;
147

    
148
      case 'ip-address':
149
        $replacements[$original] = $sanitize ? check_plain($submission->remote_addr) : $submission->remote_addr;
150
        break;
151

    
152
      case 'user':
153
        $account = user_load($submission->uid);
154
        $name = format_username($account);
155
        $replacements[$original] = $sanitize ? check_plain($name) : $name;
156
        break;
157

    
158
      case 'url':
159
        $replacements[$original] = $submission->sid ? url("node/{$node->nid}/submission/{$submission->sid}", $url_options) : '';
160
        break;
161

    
162
      case 'edit-url':
163
        $replacements[$original] = $submission->sid ? url("node/{$node->nid}/submission/{$submission->sid}/edit", $url_options) : '';
164
        break;
165

    
166
      case 'values':
167
        $excluded_components = isset($email['excluded_components']) ? $email['excluded_components'] : array();
168
        $excluded_components = array_merge($excluded_components, $markup_components);
169
        $submission_renderable = webform_submission_render($node, $submission, $email, $format, $excluded_components);
170
        $replacements[$original] = drupal_render($submission_renderable);
171
        break;
172
    }
173
  }
174

    
175
  // Webform submission tokens for individual components.
176
  if ($value_tokens = token_find_with_prefix($tokens, 'values')) {
177
    // Get the full submission renderable without $excluded_components so that
178
    // individually referenced values are available.
179
    $submission_renderable = webform_submission_render($node, $submission, $email, $format, $markup_components);
180
    $available_modifiers = array(
181
      'label',
182
      'withlabel',
183
      'nolabel',
184
      'key',
185
    );
186

    
187
    foreach ($node->webform['components'] as $cid => $component) {
188
      // Build the list of parents for this component.
189
      $parents = ($component['pid'] == 0) ? array($component['form_key']) : webform_component_parent_keys($node, $component);
190
      $parent_token = implode(':', $parents);
191
      foreach ($value_tokens as $name => $original) {
192
        if (strpos($name, $parent_token) !== 0) {
193
          // Token not found as a prefix or exact match for this component.
194
          // Token loop continue.
195
          continue;
196
        }
197
        // Drill down into the renderable to find the element.
198
        $display_element = $submission_renderable;
199
        foreach ($parents as $parent) {
200
          if (!isset($display_element[$parent])) {
201
            // Sometimes an element won't exist in the submission renderable
202
            // due to conditional logic. If not found, skip that element.
203
            // Token loop continue.
204
            continue 2;
205
          }
206
          $display_element = $display_element[$parent];
207
        }
208
        // Individual tokens always have access granted even if they're
209
        // not displayed when printing the whole renderable.
210
        $display_element['#access'] = TRUE;
211

    
212
        // For grid components, see if optional question key is present.
213
        $matched_token = $parent_token;
214
        if ($display_element['#webform_component']['type'] === 'grid') {
215
          list($question_key) = explode(':', substr($name, strlen($matched_token) + 1));
216
          if (strlen($question_key) && isset($display_element[$question_key]['#value'])) {
217
            // Generate a faux select component for this grid question.
218
            $select_component = _webform_defaults_select();
219
            $select_component['type'] = 'select';
220
            $select_component['nid'] = $display_element['#webform_component']['nid'];
221
            $select_component['name'] = $display_element['#grid_questions'][$question_key];
222
            $select_component['extra']['items'] = $display_element['#webform_component']['extra']['options'];
223
            $display_element = _webform_display_select($select_component, $display_element[$question_key]['#value'], $format);
224
            $display_element['#webform_component'] = $select_component;
225
            $matched_token .= ':' . $question_key;
226
          }
227
        }
228

    
229
        // For select components, see if the optional option key is present.
230
        if ($display_element['#webform_component']['type'] === 'select') {
231
          list($option_key) = explode(':', substr($name, strlen($matched_token) + 1));
232
          if (strlen($option_key) && strpos("\n" . $display_element['#webform_component']['extra']['items'], "\n" . $option_key . '|') !== FALSE) {
233
            // Return only this specified option and no other values.
234
            $display_element['#value'] = array_intersect($display_element['#value'], array($option_key));
235
            $matched_token .= ':' . $option_key;
236
          }
237
        }
238

    
239
        // Assume no modifier (implied 'nolabel').
240
        $modifier = NULL;
241
        if (strcmp($name, $matched_token) !== 0) {
242
          // Check if this matches the key plus a modifier.
243
          $modifier = substr($name, strrpos($name, ':') + 1);
244
          // @todo: Allow components to provide additional modifiers per
245
          // type, i.e. key, day, hour, minute, etc.
246
          if (strcmp($name, $matched_token . ':' . $modifier) !== 0 || !in_array($modifier, $available_modifiers)) {
247
            // No match.
248
            // Token loop continue.
249
            continue;
250
          }
251
        }
252

    
253
        if ($modifier === 'label') {
254
          $replacements[$original] = webform_filter_xss($display_element['#title']);
255
        }
256
        elseif ($modifier === 'key' && $display_element['#webform_component']['type'] === 'select') {
257
          $values = array();
258
          foreach ($display_element['#value'] as $value) {
259
            $values[] = webform_filter_xss($value);
260
          }
261
          $replacements[$original] = implode(' ', $values);
262
        }
263
        else {
264
          // Remove theme wrappers for the nolabel modifier.
265
          if ($modifier === 'nolabel' || empty($modifier)) {
266
            $display_element['#theme_wrappers'] = array();
267
          }
268
          $replacements[$original] = render($display_element);
269
        }
270
        // Continue processing tokens in case another modifier is used.
271
      }
272
    }
273

    
274
  }
275

    
276
  // Chained token relationships.
277
  if ($date_tokens = token_find_with_prefix($tokens, 'date')) {
278
    $replacements += token_generate('date', $date_tokens, array('date' => $submission->submitted), $options);
279
  }
280
  if ($submission->completed && ($date_tokens = token_find_with_prefix($tokens, 'completed_date'))) {
281
    $replacements += token_generate('date', $date_tokens, array('date' => $submission->completed), $options);
282
  }
283
  if ($date_tokens = token_find_with_prefix($tokens, 'modified_date')) {
284
    $replacements += token_generate('date', $date_tokens, array('date' => $submission->modified), $options);
285
  }
286
  if (($user_tokens = token_find_with_prefix($tokens, 'user')) && $account = user_load($submission->uid)) {
287
    $replacements += token_generate('user', $user_tokens, array('user' => $account), $options);
288
  }
289
  if ($submission->sid) {
290
    if ($url_tokens = token_find_with_prefix($tokens, 'url')) {
291
      $replacements += token_generate('url', $url_tokens, array('path' => "node/{$node->nid}/submission/{$submission->sid}"), $options);
292
    }
293
    if ($url_tokens = token_find_with_prefix($tokens, 'edit-url')) {
294
      $replacements += token_generate('url', $url_tokens, array('path' => "node/{$node->nid}/submission/{$submission->sid}/edit"), $options);
295
    }
296
  }
297

    
298
  $recursion_level--;
299

    
300
  return $replacements;
301
}