Projet

Général

Profil

Paste
Télécharger (40,5 ko) Statistiques
| Branche: | Révision:

root / drupal7 / sites / all / modules / webform_validation / webform_validation.validators.inc @ 65389548

1 85ad3d82 Assos Assos
<?php
2
3
/**
4
 * @file
5 81b16cc2 Assos Assos
 * Provides validation functionality and hooks.
6 85ad3d82 Assos Assos
 */
7
8
/**
9
 * Implements hook_webform_validation_validators().
10
 *
11 76bdcd04 Assos Assos
 * This function returns an array of validators, in the validator key => options
12
 * array form. Possible options:
13
 * - name (required): name of the validator.
14
 * - component_types (required): defines which component types can be validated
15
 *   by this validator. Specify 'all' to allow all types.
16
 * - negatable (optional): define whether the rule can be negated, meaning it
17
 *   will validate the inverse of the rule.
18
 * - custom_error (optional): define whether a user can specify a custom error
19
 *   message upon creating the validation rule.
20
 * - custom_data (optional): define whether custom data can be added to the
21
 *   validation rule.
22
 * - min_components (optional): define the minimum number of components to be
23
 *   selected for creating a validation rule.
24
 * - max_components (optional): define the maximum number of components to be
25
 *   selected for creating a validation rule.
26
 * - description (optional): provide a descriptive explanation about the
27
 *   validator.
28 85ad3d82 Assos Assos
 */
29
function webform_validation_webform_validation_validators() {
30
  $validators = array(
31
    'numeric' => array(
32
      'name' => t('Numeric values'),
33
      'component_types' => array(
34 5c451ca3 Assos Assos
        'hidden',
35 85ad3d82 Assos Assos
        'number',
36
        'textfield',
37
      ),
38
      'custom_data' => array(
39 65389548 Assos Assos
        'label' => t('Numeric validation range'),
40
        'description' => t('Optionally specify the minimum-maximum range to validate the user-entered numeric value against. Usage:') . theme('table', array(
41
          'header' => array(t('Value'), t('Meaning')),
42
          'rows' => array(
43
            array(t('(empty)'), t('No value validation')),
44
            array('100', t('Greater than or equal to 100')),
45
            array('|100', t('Less than or equal to 100 (including negative numbers)')),
46
            array('0|100', t('Greater than or equal to 0 &amp; less than or equal to 100')),
47
            array('10|100', t('Greater than or equal to 10 &amp; less than or equal to 100')),
48
            array('-100|-10', t('Greater than or equal to -100 &amp; less than or equal to -10')),
49
          ),
50
        )),
51
        'validate_regex' => '/^((-?[\d.]+)?\|)?(-?[\d.]+)$/',
52 85ad3d82 Assos Assos
        'required' => FALSE,
53
      ),
54
      'description' => t('Verifies that user-entered values are numeric, with the option to specify min and / or max values.'),
55
    ),
56
    'min_length' => array(
57
      'name' => t('Minimum length'),
58
      'component_types' => array(
59
        'email',
60
        'hidden',
61 5c451ca3 Assos Assos
        'number',
62
        'textarea',
63
        'textfield',
64 85ad3d82 Assos Assos
      ),
65
      'custom_data' => array(
66
        'label' => t('Minimum number of characters'),
67
        'description' => t('Specify the minimum number of characters that have to be entered to pass validation.'),
68 65389548 Assos Assos
        'validate_regex' => '/^\d+$/',
69 85ad3d82 Assos Assos
      ),
70 a2baadd1 Assos Assos
      'description' => t('Verifies that a user-entered value contains at least the specified number of characters.'),
71 85ad3d82 Assos Assos
    ),
72
    'max_length' => array(
73
      'name' => t('Maximum length'),
74
      'component_types' => array(
75
        'email',
76
        'hidden',
77 5c451ca3 Assos Assos
        'number',
78
        'textarea',
79
        'textfield',
80 85ad3d82 Assos Assos
      ),
81
      'custom_data' => array(
82
        'label' => t('Maximum number of characters'),
83
        'description' => t('Specify the maximum number of characters that can be entered to pass validation.'),
84 65389548 Assos Assos
        'validate_regex' => '/^\d+$/',
85 85ad3d82 Assos Assos
      ),
86 a2baadd1 Assos Assos
      'description' => t('Verifies that a user-entered value contains at most the specified number of characters.'),
87 85ad3d82 Assos Assos
    ),
88
    'min_words' => array(
89
      'name' => t('Minimum number of words'),
90
      'component_types' => array(
91
        'hidden',
92
        'html_textarea',
93 5c451ca3 Assos Assos
        'textarea',
94
        'textfield',
95 85ad3d82 Assos Assos
      ),
96
      'custom_data' => array(
97
        'label' => t('Minimum number of words'),
98 9df8b457 Assos Assos
        'description' => t('Specify the minimum number of words that have to be entered to pass validation. Words are defined as strings of letters separated by spaces.'),
99 65389548 Assos Assos
        'validate_regex' => '/^\d+$/',
100 85ad3d82 Assos Assos
      ),
101
      'description' => t('Verifies that a user-entered value contains at least the specified number of words.'),
102
    ),
103
    'max_words' => array(
104
      'name' => t('Maximum number of words'),
105
      'component_types' => array(
106
        'hidden',
107
        'html_textarea',
108 5c451ca3 Assos Assos
        'textarea',
109
        'textfield',
110 85ad3d82 Assos Assos
      ),
111
      'custom_data' => array(
112
        'label' => t('Maximum number of words'),
113 9df8b457 Assos Assos
        'description' => t('Specify the maximum number of words that have to be entered to pass validation. Words are defined as strings of letters separated by spaces.'),
114 65389548 Assos Assos
        'validate_regex' => '/^\d+$/',
115 85ad3d82 Assos Assos
      ),
116
      'description' => t('Verifies that a user-entered value contains at most the specified number of words.'),
117
    ),
118 bb746689 Assos Assos
    // Only available in Webform 4; removed below if not.
119 5c451ca3 Assos Assos
    'sum' => array(
120
      'name' => t('Adds up to'),
121
      'component_types' => array(
122
        'number',
123
      ),
124
      'custom_data' => array(
125
        'label' => t('Number the fields add up to'),
126 81b16cc2 Assos Assos
        'description' => t('Specify the number and the type of comparison. For example:') . theme('item_list', array(
127
          'items' => array(
128
            t('Enter "=3" if the components must add up to exactly 3.'),
129
            t('Enter ">10" if the components must add up to greater than 10.'),
130
            t('Enter ">=10" if the components must add up to greater than or equal to 10.'),
131
            t('Enter "<20" if the components must add up to less than 20.'),
132
            t('Enter "<=20" if the components must add up to less than or equal to 20.'),
133
          ),
134
        )),
135 65389548 Assos Assos
        'validate_regex' => '/^(=|>|>=|<|<=)(-?[\d.]+)$/',
136 5c451ca3 Assos Assos
      ),
137
      'description' => t('Require the values of the selected fields to add up to exactly, greater than or equal to, or less than or equal to a specified number.'),
138
    ),
139 85ad3d82 Assos Assos
    'equal' => array(
140
      'name' => t('Equal values'),
141
      'component_types' => array(
142 5c451ca3 Assos Assos
        'date',
143 85ad3d82 Assos Assos
        'email',
144
        'hidden',
145 5c451ca3 Assos Assos
        'number',
146
        'select',
147
        'textarea',
148
        'textfield',
149
        'time',
150 9df8b457 Assos Assos
        'boolean',
151 85ad3d82 Assos Assos
      ),
152
      'min_components' => 2,
153 5c451ca3 Assos Assos
      'description' => t('Verifies that all specified components contain equal values. If all components are of type email, they will get case-insensitive comparison.'),
154 85ad3d82 Assos Assos
    ),
155
    'comparison' => array(
156
      'name' => t('Compare two values'),
157
      'component_types' => array(
158
        'date',
159
        'email',
160
        'hidden',
161
        'number',
162
        'select',
163 5c451ca3 Assos Assos
        'textarea',
164
        'textfield',
165 85ad3d82 Assos Assos
        'time',
166
      ),
167
      'custom_error' => TRUE,
168
      'custom_data' => array(
169
        'label' => t('Comparison operator'),
170 5c451ca3 Assos Assos
        'description' => t('Specify the comparison operator you want to use. Must be one of: >, >=, <, <=. The validator will compare the first component with the second using this operator. If the components are of type email, they will get case-insensitive comparison.'),
171 65389548 Assos Assos
        'validate_regex' => '/^(>|>=|<|<=)$/',
172 85ad3d82 Assos Assos
      ),
173
      'min_components' => 2,
174
      'max_components' => 2,
175 e4c061ad Assos Assos
      'description' => t('Compare two values for greater than (>), less than (<), greater than or equal to (>=), or less than or equal to (<=).'),
176 85ad3d82 Assos Assos
    ),
177
    'unique' => array(
178
      'name' => t('Unique values'),
179
      'component_types' => array(
180 5c451ca3 Assos Assos
        'date',
181 85ad3d82 Assos Assos
        'email',
182
        'hidden',
183 5c451ca3 Assos Assos
        'number',
184
        'select',
185
        'textarea',
186
        'textfield',
187
        'time',
188 9df8b457 Assos Assos
        'boolean',
189 85ad3d82 Assos Assos
      ),
190
      'min_components' => 2,
191 5c451ca3 Assos Assos
      'description' => t('Verifies that none of the specified components contain the same value as another selected component in this submission. (To check that values are unique between submissions, use the unique validation option on the "Edit component" page for that component.) If all components are of type email, they will get case-insensitive comparison.'),
192 85ad3d82 Assos Assos
    ),
193
    'specific_value' => array(
194
      'name' => t('Specific value(s)'),
195
      'negatable' => TRUE,
196
      'component_types' => array(
197 5c451ca3 Assos Assos
        'email',
198
        'hidden',
199 85ad3d82 Assos Assos
        'number',
200
        'select',
201
        'textarea',
202 5c451ca3 Assos Assos
        'textfield',
203 9df8b457 Assos Assos
        'boolean',
204 85ad3d82 Assos Assos
      ),
205
      'custom_error' => TRUE,
206
      'custom_data' => array(
207
        'label' => t('(Key) value'),
208
        'description' => t('Specify the specific value(s) you want the component to contain. Separate multiple options by a comma. For components that have keys, use the key value instead.'),
209
      ),
210
      'description' => t('Verifies that the value of the specified component is from a list of allowed values.'),
211
    ),
212
    'default_value' => array(
213
      'name' => t('Default value'),
214
      'negatable' => TRUE,
215
      'component_types' => array(
216
        'email',
217
        'hidden',
218 5c451ca3 Assos Assos
        'number',
219
        'select',
220
        'textarea',
221
        'textfield',
222 9df8b457 Assos Assos
        'boolean',
223 85ad3d82 Assos Assos
      ),
224
      'custom_error' => TRUE,
225
      'description' => t('Verifies that the user-entered value is the default value for that component. Negate if you want not the default value.'),
226
    ),
227 a2baadd1 Assos Assos
    'someofseveral' => array(
228 5c451ca3 Assos Assos
      'name' => t('Some of several'),
229 85ad3d82 Assos Assos
      'component_types' => array(
230 5c451ca3 Assos Assos
        'date',
231 85ad3d82 Assos Assos
        'email',
232 5c451ca3 Assos Assos
        'file',
233
        'number',
234 85ad3d82 Assos Assos
        'select',
235 5c451ca3 Assos Assos
        'textarea',
236
        'textfield',
237 9df8b457 Assos Assos
        'time',
238
        'boolean',
239 85ad3d82 Assos Assos
      ),
240 a2baadd1 Assos Assos
      'custom_data' => array(
241 5c451ca3 Assos Assos
        'label' => t('Number to be completed'),
242 81b16cc2 Assos Assos
        'description' => t('Specify the number that must be completed and the type of comparison. For example:') . theme('item_list', array(
243
          'items' => array(
244
            t('Enter ">=1" if the user must complete <b>at least</b> 1 of the selected components.'),
245
            t('Enter "=3" if the user must complete <b>exactly</b> 3 of the selected components.'),
246
            t('Enter "<=2" if the user must complete <b>at most</b> 2 of the selected components.'),
247
          ),
248
        )),
249 65389548 Assos Assos
        'validate_regex' => '/^[><]?=\d+$/',
250 85ad3d82 Assos Assos
      ),
251
      'min_components' => 2,
252 5c451ca3 Assos Assos
      'description' => t('Requires the user to complete some number of components out of a group of components. For example, complete at least 2 out of 3, complete at most 4 out of 6, or complete exactly 3 our of 4.'),
253 85ad3d82 Assos Assos
    ),
254
    'select_min' => array(
255
      'name' => t('Minimum number of selections required'),
256
      'component_types' => array(
257
        'select',
258
      ),
259
      'custom_data' => array(
260
        'label' => t('Minimum number of selections'),
261
        'description' => t('Specify the minimum number of options a user should select.'),
262 65389548 Assos Assos
        'validate_regex' => '/^\d+$/',
263 85ad3d82 Assos Assos
      ),
264
      'description' => t('Forces the user to select at least a defined number of options from the specified webform components.'),
265
    ),
266
    'select_max' => array(
267
      'name' => t('Maximum number of selections allowed'),
268
      'component_types' => array(
269
        'select',
270
      ),
271
      'custom_data' => array(
272
        'label' => t('Maximum number of selections'),
273
        'description' => t('Specify the maximum number of options a user can select.'),
274 65389548 Assos Assos
        'validate_regex' => '/^\d+$/',
275 85ad3d82 Assos Assos
      ),
276
      'description' => t('Forces the user to select at most a defined number of options from the specified webform components.'),
277
    ),
278
    'select_exact' => array(
279
      'name' => t('Exact number of selections required'),
280
      'negatable' => TRUE,
281
      'component_types' => array(
282
        'select',
283
      ),
284
      'custom_data' => array(
285
        'label' => t('Number of selections'),
286
        'description' => t('Specify how many options a user can select.'),
287 65389548 Assos Assos
        'validate_regex' => '/^\d+$/',
288 85ad3d82 Assos Assos
      ),
289
      'description' => t('Forces the user to select exactly the defined number of options from the specified webform components.'),
290
    ),
291
    'plain_text' => array(
292
      'name' => t('Plain text (disallow tags)'),
293
      'negatable' => TRUE,
294
      'component_types' => array(
295
        'email',
296
        'hidden',
297 5c451ca3 Assos Assos
        'textarea',
298
        'textfield',
299 85ad3d82 Assos Assos
      ),
300 81b16cc2 Assos Assos
      'description' => t("Verifies that user-entered data doesn't contain HTML tags."),
301 85ad3d82 Assos Assos
    ),
302
    'starts_with' => array(
303
      'name' => t('Starts with'),
304
      'negatable' => TRUE,
305
      'component_types' => array(
306
        'email',
307
        'hidden',
308 5c451ca3 Assos Assos
        'number',
309
        'textarea',
310
        'textfield',
311 85ad3d82 Assos Assos
      ),
312
      'custom_data' => array(
313
        'label' => t('Starts with'),
314
        'description' => t('Enter the text that this field must start with.'),
315
      ),
316
      'description' => t('Verifies that user-entered data starts with a given string.'),
317
    ),
318
    'ends_with' => array(
319
      'name' => t('Ends with'),
320
      'negatable' => TRUE,
321
      'component_types' => array(
322
        'email',
323
        'hidden',
324 5c451ca3 Assos Assos
        'number',
325
        'textarea',
326
        'textfield',
327 85ad3d82 Assos Assos
      ),
328
      'custom_data' => array(
329
        'label' => t('Ends with'),
330
        'description' => t('Enter the text that this field must end with.'),
331
      ),
332
      'description' => t('Verifies that user-entered data ends with a given string.'),
333
    ),
334
    'pattern' => array(
335 5c451ca3 Assos Assos
      'name' => t('Pattern'),
336 85ad3d82 Assos Assos
      'component_types' => array(
337
        'hidden',
338 5c451ca3 Assos Assos
        'textarea',
339
        'textfield',
340 85ad3d82 Assos Assos
      ),
341
      'custom_error' => TRUE,
342
      'custom_data' => array(
343
        'label' => t('Pattern'),
344 81b16cc2 Assos Assos
        'description' => t('Specify a pattern where:') . theme('item_list', array('items' => array(t('@ = any letter A-Z'), t('# = any numeral 0-9'), t('| = separates two or more acceptable patterns'), t('Any other character must appear in its exact position')))) . t('Examples') . theme('item_list', array('items' => array(t('North American phone number: (###) ###-####'), t('D-2500 series model numbers: D-25##'), t('UK Postal Code: @# #@@|@## #@@|@@# #@@|@@## #@@|@#@ #@@|@@#@ #@@|GIR0AA')))),
345 85ad3d82 Assos Assos
      ),
346
      'description' => t('Verifies that a user-entered value follows to a specified pattern.'),
347
    ),
348
    'regex' => array(
349
      'name' => t('Regular expression, case-sensitive'),
350
      'negatable' => TRUE,
351
      'component_types' => array(
352
        'email',
353
        'hidden',
354 5c451ca3 Assos Assos
        'number',
355
        'textarea',
356
        'textfield',
357 85ad3d82 Assos Assos
      ),
358
      'custom_error' => TRUE,
359
      'custom_data' => array(
360 4f315dab Assos Assos
        'label' => t('Regex code (case-sensitive)'),
361
        'description' => t('Specify regex code to validate the user input against. Do not include delimiters such as /.'),
362 85ad3d82 Assos Assos
      ),
363 4f315dab Assos Assos
      'description' => t('Validates user-entered text against a case-sensitive regular expression.'),
364 85ad3d82 Assos Assos
    ),
365
    'regexi' => array(
366
      'name' => t('Regular expression, case-insensitive'),
367
      'negatable' => TRUE,
368
      'component_types' => array(
369
        'email',
370
        'hidden',
371 5c451ca3 Assos Assos
        'number',
372
        'textarea',
373
        'textfield',
374 85ad3d82 Assos Assos
      ),
375
      'custom_error' => TRUE,
376
      'custom_data' => array(
377 4f315dab Assos Assos
        'label' => t('Regex code (case-insensitive)'),
378
        'description' => t('Specify regex code to validate the user input against. Do not include delimiters such as /.'),
379 85ad3d82 Assos Assos
      ),
380 4f315dab Assos Assos
      'description' => t('Validates user-entered text against a case-insensitive regular expression.'),
381 85ad3d82 Assos Assos
    ),
382
    'must_be_empty' => array(
383
      'name' => t('Must be empty'),
384
      'component_types' => array(
385 5c451ca3 Assos Assos
        'hidden',
386 85ad3d82 Assos Assos
        'number',
387 5c451ca3 Assos Assos
        'textarea',
388 85ad3d82 Assos Assos
        'textfield',
389
      ),
390
      'description' => t('Verifies that a specified textfield remains empty. Recommended use case: used as an anti-spam measure by hiding the element with CSS.'),
391
    ),
392
    'blacklist' => array(
393
      'name' => t('Words blacklist'),
394
      'negatable' => TRUE,
395
      'component_types' => array(
396
        'email',
397
        'hidden',
398 5c451ca3 Assos Assos
        'textarea',
399
        'textfield',
400 85ad3d82 Assos Assos
      ),
401
      'custom_error' => TRUE,
402
      'custom_data' => array(
403
        'label' => t('Blacklisted words'),
404
        'description' => t('Specify illegal words, seperated by commas.'),
405
      ),
406 81b16cc2 Assos Assos
      'description' => t("Validates that user-entered data doesn't contain any of the specified illegal words."),
407 85ad3d82 Assos Assos
    ),
408 9df8b457 Assos Assos
    'username' => array(
409 85ad3d82 Assos Assos
      'name' => t('Must match a username'),
410
      'negatable' => TRUE,
411
      'component_types' => array(
412
        'hidden',
413 5c451ca3 Assos Assos
        'textfield',
414 85ad3d82 Assos Assos
      ),
415
      'description' => t('Validates that user-entered data matches a username.'),
416
    ),
417
    'valid_url' => array(
418 5c451ca3 Assos Assos
      'name' => t('Valid URL'),
419 85ad3d82 Assos Assos
      'negatable' => TRUE,
420
      'component_types' => array(
421
        'hidden',
422 5c451ca3 Assos Assos
        'textfield',
423 85ad3d82 Assos Assos
      ),
424
      'description' => t('Validates that the user-entered data is a valid URL.'),
425
    ),
426
  );
427
428 bb746689 Assos Assos
  // Only available in Webform 4.
429
  module_load_include('inc', 'webform', 'components/number');
430
  if (!function_exists('webform_compare_floats')) {
431
    unset($validators['sum']);
432
  }
433
434 85ad3d82 Assos Assos
  if (module_exists('email_verify')) {
435
    $validators['email_verify'] = array(
436 5c451ca3 Assos Assos
      'name' => t('Email Verify'),
437 85ad3d82 Assos Assos
      'component_types' => array(
438
        'email',
439
      ),
440
      'description' => t('Verifies that an email address actually exists using the <a href="https://drupal.org/project/email_verify">Email Verification module</a>.'),
441
    );
442
  }
443
444
  return $validators;
445
}
446
447
/**
448
 * Implements hook_webform_validation_validate().
449
 */
450
function webform_validation_webform_validation_validate($validator_name, $items, $components, $rule) {
451 5c451ca3 Assos Assos
  if (!$items) {
452
    return NULL;
453
  }
454
455 65389548 Assos Assos
  // Allow translation for all components item names if available.
456
  if (module_exists('webform_localization')) {
457
    foreach ($components as &$component) {
458
      $dummy_element = array(
459
        '#title' => '',
460
      );
461
      _webform_localization_translate_component($dummy_element, $component);
462
      if (isset($dummy_element['#title']) && (string) $dummy_element['#title']) {
463
        $component['name'] = $dummy_element['#title'];
464
      }
465
    }
466
  }
467
468 5c451ca3 Assos Assos
  // For certain validators, if all components to be compared are email
469
  // components, make the values lower-case to avoid case-sensitive comparison.
470
  if (in_array($validator_name, array('equal', 'comparison', 'unique'))) {
471
    $all_email = TRUE;
472
    foreach ($rule['components'] as $component) {
473
      if ($component['type'] !== 'email') {
474
        $all_email = FALSE;
475
        break;
476 a2baadd1 Assos Assos
      }
477
    }
478 5c451ca3 Assos Assos
    if ($all_email) {
479
      $items = array_map('strtolower', $items);
480
    }
481
  }
482 a2baadd1 Assos Assos
483 76bdcd04 Assos Assos
  // Some components, such as multiple select, send their values as arrays,
484
  // others don't. Convert all to arrays and write the rules to handle them that
485
  // way. Remove empty values.
486 5c451ca3 Assos Assos
  foreach ($items as $key => $val) {
487
    $new_values = array();
488
    foreach ((array) $val as $val_key => $val_val) {
489
      if ((string) $val_val !== '') {
490
        $new_values[$val_key] = $val_val;
491
      }
492
    }
493
    $items[$key] = $new_values;
494
  }
495 e4c061ad Assos Assos
  // Ensure later calls to key() get the first item.
496
  reset($items);
497 85ad3d82 Assos Assos
498 5c451ca3 Assos Assos
  $errors = array();
499
  switch ($validator_name) {
500
    case 'numeric':
501
      $num_range = _webform_numeric_check_data($rule['data']);
502
      foreach ($items as $key => $val) {
503
        foreach ($val as $subval) {
504 81b16cc2 Assos Assos
          // First check if the value is numeric.
505 5c451ca3 Assos Assos
          if (is_numeric($subval)) {
506
            $subval = (float) $subval;
507
          }
508
          else {
509
            $errors[$key] = t('%item is not numeric.', array('%item' => $components[$key]['name']));
510
            continue;
511
          }
512
513 76bdcd04 Assos Assos
          // Now validate the entered numeric value against the validator range
514
          // settings, if appropriate.
515 81b16cc2 Assos Assos
          // a. validate min & max.
516 5c451ca3 Assos Assos
          if (isset($num_range['min']) && isset($num_range['max'])) {
517 81b16cc2 Assos Assos
            // Validate the min - max range.
518 5c451ca3 Assos Assos
            if ($subval < $num_range['min'] || $subval > $num_range['max']) {
519 81b16cc2 Assos Assos
              $errors[$key] = t('%item is not within the allowed range %range.', array('%item' => $components[$key]['name'], '%range' => str_replace('|', ' - ', $rule['data'])));
520 85ad3d82 Assos Assos
            }
521 5c451ca3 Assos Assos
          }
522
          else {
523 81b16cc2 Assos Assos
            // b. validate min.
524 5c451ca3 Assos Assos
            if (isset($num_range['min'])) {
525
              if ($subval < $num_range['min']) {
526
                $errors[$key] = t('%item should be greater than or equal to %val.', array('%item' => $components[$key]['name'], '%val' => $num_range['min']));
527 85ad3d82 Assos Assos
              }
528 5c451ca3 Assos Assos
            }
529 81b16cc2 Assos Assos
            // c. validate max.
530 5c451ca3 Assos Assos
            if (isset($num_range['max'])) {
531
              if ($subval > $num_range['max']) {
532
                $errors[$key] = t('%item should be less than or equal to %val.', array('%item' => $components[$key]['name'], '%val' => $num_range['max']));
533 85ad3d82 Assos Assos
              }
534
            }
535
          }
536
        }
537 5c451ca3 Assos Assos
      }
538
      return $errors;
539 81b16cc2 Assos Assos
540 5c451ca3 Assos Assos
    case 'min_length':
541
      $min_length = $rule['data'];
542
      foreach ($items as $key => $val) {
543
        foreach ($val as $subval) {
544
          if (drupal_strlen($subval) < $min_length) {
545
            $errors[$key] = t('%item should be at least %num characters long.', array('%item' => $components[$key]['name'], '%num' => $min_length));
546 85ad3d82 Assos Assos
          }
547
        }
548 5c451ca3 Assos Assos
      }
549
      return $errors;
550 81b16cc2 Assos Assos
551 5c451ca3 Assos Assos
    case 'max_length':
552
      $max_length = $rule['data'];
553
      foreach ($items as $key => $val) {
554
        foreach ($val as $subval) {
555
          if (drupal_strlen($subval) > $max_length) {
556
            $errors[$key] = t('%item should be at most %num characters long.', array('%item' => $components[$key]['name'], '%num' => $max_length));
557 85ad3d82 Assos Assos
          }
558
        }
559 5c451ca3 Assos Assos
      }
560
      return $errors;
561 81b16cc2 Assos Assos
562 5c451ca3 Assos Assos
    case 'min_words':
563
      $min_words = $rule['data'];
564
      foreach ($items as $key => $val) {
565
        foreach ($val as $subval) {
566
          if (_webform_validation_count_words($subval) < $min_words) {
567
            $error = format_plural($min_words, '%item should be at least 1 word long.', '%item should be at least @count words long.', array('%item' => $components[$key]['name']));
568
            $errors[$key] = $error;
569 85ad3d82 Assos Assos
          }
570
        }
571 5c451ca3 Assos Assos
      }
572
      return $errors;
573 81b16cc2 Assos Assos
574 5c451ca3 Assos Assos
    case 'max_words':
575
      $max_words = $rule['data'];
576
      foreach ($items as $key => $val) {
577
        foreach ($val as $subval) {
578
          if (_webform_validation_count_words($subval) > $max_words) {
579
            $error = format_plural($max_words, '%item should be at most 1 word long.', '%item should be at most @count words long.', array('%item' => $components[$key]['name']));
580
            $errors[$key] = $error;
581 85ad3d82 Assos Assos
          }
582
        }
583 5c451ca3 Assos Assos
      }
584
      return $errors;
585 81b16cc2 Assos Assos
586 5c451ca3 Assos Assos
    case 'sum':
587
      // Get the numbers to sum.
588
      $sum = array();
589
      foreach ($items as $item) {
590
        if (isset($item[0])) {
591
          $sum[] = $item[0];
592
        }
593
      }
594
      // If none of the components are completed, don't run this validator.
595
      if (!count($sum)) {
596
        return array();
597
      }
598
      $sum = array_sum($sum);
599
600
      // Number being compared with.
601
      $compare_number = (float) preg_replace('/^[^0-9]+/', '', $rule['data']);
602
603
      // Parse the comparision operator and do comparison.
604 bb746689 Assos Assos
      module_load_include('inc', 'webform', 'components/number');
605 5c451ca3 Assos Assos
      $error = FALSE;
606
      if (substr($rule['data'], 0, 2) === '<=') {
607 bb746689 Assos Assos
        if (!(webform_compare_floats($sum, $compare_number) <= 0)) {
608 5c451ca3 Assos Assos
          $error = t('less than or equal to');
609
        }
610
      }
611
      elseif (substr($rule['data'], 0, 1) === '<') {
612 bb746689 Assos Assos
        if (!(webform_compare_floats($sum, $compare_number) < 0)) {
613 5c451ca3 Assos Assos
          $error = t('less than');
614
        }
615
      }
616
      elseif (substr($rule['data'], 0, 2) === '>=') {
617 bb746689 Assos Assos
        if (!(webform_compare_floats($sum, $compare_number) >= 0)) {
618 5c451ca3 Assos Assos
          $error = t('greater than or equal to');
619
        }
620
      }
621
      elseif (substr($rule['data'], 0, 1) === '>') {
622 bb746689 Assos Assos
        if (!(webform_compare_floats($sum, $compare_number) > 0)) {
623 5c451ca3 Assos Assos
          $error = t('greater than');
624
        }
625
      }
626
      else {
627 bb746689 Assos Assos
        if (!(webform_compare_floats($sum, $compare_number) === 0)) {
628 5c451ca3 Assos Assos
          $error = t('exactly');
629
        }
630
      }
631
      // Set error if needed.
632
      if ($error) {
633
        $keys = array_keys($items);
634
        $errors[$keys[0]] = t('These items must add up to %verb %compare_number:', array('%verb' => $error, '%compare_number' => $compare_number)) . theme('item_list', array('items' => _webform_validation_get_names_of_rule_components($rule)));
635
      }
636
      return $errors;
637 81b16cc2 Assos Assos
638 5c451ca3 Assos Assos
    case 'equal':
639
      $first_entry_key = key($items);
640
      $first_entry = array_shift($items);
641
      foreach ($items as $key => $val) {
642
        if ($val !== $first_entry) {
643
          $errors[$key] = t('%item_checked does not match %item_first.', array('%item_checked' => $components[$key]['name'], '%item_first' => $components[$first_entry_key]['name']));
644
        }
645
      }
646
      return $errors;
647 81b16cc2 Assos Assos
648 5c451ca3 Assos Assos
    case 'comparison':
649
      foreach (array(1, 2) as $count) {
650
        $entry[$count]['key'] = key($items);
651
        $value = array_shift($items);
652
        if ($components[$entry[$count]['key']]['type'] === 'date') {
653 1f623f01 Assos Assos
          if (!empty($value) && checkdate((int) $value['month'], (int) $value['day'], (int) $value['year'])) {
654 5c451ca3 Assos Assos
            $entry[$count]['value'] = date('Y-m-d', mktime(0, 0, 0, (int) $value['month'], (int) $value['day'], (int) $value['year']));
655
          }
656
          else {
657
            $entry[$count]['value'] = NULL;
658 85ad3d82 Assos Assos
          }
659
        }
660 5c451ca3 Assos Assos
        elseif ($components[$entry[$count]['key']]['type'] === 'time') {
661 65389548 Assos Assos
          if (isset($value['hour']) && isset($value['minute'])) {
662
            $time = $value['hour'] . ':' . str_pad($value['minute'], 2, '0', STR_PAD_LEFT);
663
            if (!empty($value['ampm'])) {
664
              $time .= ' ' . $value['ampm'];
665
            }
666
            $time = strtotime($time);
667
          }
668
          else {
669
            $time = NULL;
670 85ad3d82 Assos Assos
          }
671 5c451ca3 Assos Assos
          if ($time) {
672
            $entry[$count]['value'] = date('H:i', $time);
673 85ad3d82 Assos Assos
          }
674
          else {
675 5c451ca3 Assos Assos
            $entry[$count]['value'] = NULL;
676 85ad3d82 Assos Assos
          }
677
        }
678 5c451ca3 Assos Assos
        else {
679
          $entry[$count]['value'] = _webform_validation_flatten_array($value);
680 85ad3d82 Assos Assos
        }
681 5c451ca3 Assos Assos
      }
682 85ad3d82 Assos Assos
683 5c451ca3 Assos Assos
      // Don't validate if either are empty.
684
      if ((string) $entry[1]['value'] === '' || (string) $entry[2]['value'] === '') {
685
        return array();
686
      }
687 85ad3d82 Assos Assos
688 5c451ca3 Assos Assos
      $error = FALSE;
689
      switch ($rule['data']) {
690
        case '>':
691
          if (!($entry[1]['value'] > $entry[2]['value'])) {
692
            $error = TRUE;
693 85ad3d82 Assos Assos
          }
694 5c451ca3 Assos Assos
          break;
695 81b16cc2 Assos Assos
696 5c451ca3 Assos Assos
        case '>=':
697
          if (!($entry[1]['value'] >= $entry[2]['value'])) {
698
            $error = TRUE;
699
          }
700
          break;
701 81b16cc2 Assos Assos
702 5c451ca3 Assos Assos
        case '<':
703
          if (!($entry[1]['value'] < $entry[2]['value'])) {
704
            $error = TRUE;
705
          }
706
          break;
707 81b16cc2 Assos Assos
708 5c451ca3 Assos Assos
        case '<=':
709
          if (!($entry[1]['value'] <= $entry[2]['value'])) {
710
            $error = TRUE;
711
          }
712
          break;
713
      }
714
715
      if ($error) {
716
        $errors[$entry[2]['key']] = _webform_validation_i18n_error_message($rule);
717
      }
718
      return $errors;
719 81b16cc2 Assos Assos
720 5c451ca3 Assos Assos
    case 'unique':
721
      foreach ($items as $key => $val) {
722
        $items[$key] = _webform_validation_flatten_array($val);
723
      }
724 76bdcd04 Assos Assos
      // Now we count how many times each value appears, and find out which
725
      // values appear more than once.
726 5c451ca3 Assos Assos
      $items_count = array_count_values(array_map('drupal_strtolower', array_map('trim', $items)));
727 76bdcd04 Assos Assos
      $doubles = array_filter($items_count, function ($x) {
728
        return $x > 1;
729
      });
730 5c451ca3 Assos Assos
      foreach ($items as $key => $val) {
731
        if (in_array(drupal_strtolower($val), array_keys($doubles))) {
732
          $errors[$key] = t('The value of %item is not unique.', array('%item' => $components[$key]['name']));
733 85ad3d82 Assos Assos
        }
734 5c451ca3 Assos Assos
      }
735
      return $errors;
736 81b16cc2 Assos Assos
737 5c451ca3 Assos Assos
    case 'specific_value':
738
      $specific_values = explode(',', $rule['data']);
739
      $specific_values = array_map('trim', $specific_values);
740
      foreach ($items as $key => $val) {
741 76bdcd04 Assos Assos
        // Selects: Fail if at least one checked and at least one not in the
742
        // allowed values.
743 5c451ca3 Assos Assos
        $val = array_filter($val);
744
        $test = count($val) && count(array_diff($val, $specific_values));
745
        _webform_validation_test($errors, $key, $rule, $test);
746
      }
747
      return $errors;
748 81b16cc2 Assos Assos
749 5c451ca3 Assos Assos
    case 'default_value':
750
      foreach ($items as $key => $val) {
751
        $val = _webform_validation_flatten_array($val);
752
        $test = $val != $components[$key]['value'];
753
        _webform_validation_test($errors, $key, $rule, $test);
754
      }
755
      return $errors;
756 81b16cc2 Assos Assos
757 5c451ca3 Assos Assos
    case 'someofseveral':
758
      // Determine the number of components completed.
759
      foreach ($items as $key => $val) {
760
        $items[$key] = _webform_validation_flatten_array($val);
761
        $items[$key] = (bool) strlen($items[$key]);
762
      }
763
      $number_completed = count(array_filter($items));
764
765
      // Number being compared with.
766
      $compare_number = (int) preg_replace('/[^0-9]+/', '', $rule['data']);
767
      if ($compare_number < 1) {
768
        $compare_number = 1;
769
      }
770
      elseif ($compare_number > count($rule['components'])) {
771
        $compare_number = count($rule['components']);
772
      }
773
774
      // Parse the comparision operator and do comparison.
775
      $error = FALSE;
776
      if (substr($rule['data'], 0, 1) === '=') {
777
        if (!($number_completed === $compare_number)) {
778
          $error = t('exactly');
779 85ad3d82 Assos Assos
        }
780 5c451ca3 Assos Assos
      }
781
      elseif (substr($rule['data'], 0, 2) === '<=') {
782
        if (!($number_completed <= $compare_number)) {
783
          $error = t('at most');
784 85ad3d82 Assos Assos
        }
785 5c451ca3 Assos Assos
      }
786
      else {
787
        if (!($number_completed >= $compare_number)) {
788
          $error = t('at least');
789 85ad3d82 Assos Assos
        }
790 5c451ca3 Assos Assos
      }
791
792
      // Set error if needed.
793
      if ($error) {
794
        $keys = array_keys($items);
795
        $errors[$keys[0]] = t('You must complete %verb %compare_number of these items:', array('%verb' => $error, '%compare_number' => $compare_number)) . theme('item_list', array('items' => _webform_validation_get_names_of_rule_components($rule)));
796
      }
797
      return $errors;
798 81b16cc2 Assos Assos
799 5c451ca3 Assos Assos
    case 'select_min':
800
      $min_selections = $rule['data'];
801
      foreach ($items as $key => $val) {
802
        if (count(array_filter($val, '_webform_validation_check_false')) < $min_selections) {
803
          $errors[$key] = t('Please select at least %num options for %item.', array('%num' => $min_selections, '%item' => $components[$key]['name']));
804 85ad3d82 Assos Assos
        }
805 5c451ca3 Assos Assos
      }
806
      return $errors;
807 81b16cc2 Assos Assos
808 5c451ca3 Assos Assos
    case 'select_max':
809
      $max_selections = $rule['data'];
810
      foreach ($items as $key => $val) {
811
        if (count(array_filter($val, '_webform_validation_check_false')) > $max_selections) {
812
          $errors[$key] = t('Please select maximum %num options for %item.', array('%num' => $max_selections, '%item' => $components[$key]['name']));
813 85ad3d82 Assos Assos
        }
814 5c451ca3 Assos Assos
      }
815
      return $errors;
816 81b16cc2 Assos Assos
817 5c451ca3 Assos Assos
    case 'select_exact':
818
      $allowed_selections = $rule['data'];
819
      foreach ($items as $key => $val) {
820
        $error_strings = array(
821
          'regular' => 'Please select %num options for %item.',
822
          'negated' => 'Please do not select %num options for %item.',
823
        );
824
        $error_vars = array('%num' => $allowed_selections, '%item' => $components[$key]['name']);
825
        $test = count(array_filter($val, '_webform_validation_check_false')) != $allowed_selections;
826
        _webform_validation_test($errors, $key, $rule, $test, $error_strings, $error_vars);
827
      }
828
      return $errors;
829 81b16cc2 Assos Assos
830 5c451ca3 Assos Assos
    case 'plain_text':
831
      foreach ($items as $key => $val) {
832
        $error_strings = array(
833
          'regular' => '%item only allows the use of plain text.',
834
          'negated' => '%item must contain HTML tags.',
835
        );
836
        $error_vars = array('%item' => $components[$key]['name']);
837
        foreach ($val as $subval) {
838
          $test = strcmp($subval, strip_tags($subval));
839 85ad3d82 Assos Assos
          _webform_validation_test($errors, $key, $rule, $test, $error_strings, $error_vars);
840
        }
841 5c451ca3 Assos Assos
      }
842
      return $errors;
843 81b16cc2 Assos Assos
844 5c451ca3 Assos Assos
    case 'starts_with':
845
    case 'ends_with':
846
      $pattern = preg_quote($rule['data'], '/');
847
      if ($validator_name === 'starts_with') {
848
        $pattern = '^' . $pattern;
849
        $verb = t('start');
850
      }
851
      else {
852
        $pattern .= '$';
853
        $verb = t('end');
854
      }
855
      $pattern = '/' . $pattern . '/';
856
857
      foreach ($items as $key => $val) {
858
        $error_strings = array(
859
          'regular' => '%item must %verb with "%string".',
860
          'negated' => '%item must not %verb with "%string".',
861
        );
862
        $error_vars = array('%item' => $components[$key]['name'], '%verb' => $verb, '%string' => $rule['data']);
863
        foreach ($val as $subval) {
864
          $test = !preg_match($pattern, $subval);
865
          _webform_validation_test($errors, $key, $rule, $test, $error_strings, $error_vars);
866 85ad3d82 Assos Assos
        }
867 5c451ca3 Assos Assos
      }
868
      return $errors;
869 81b16cc2 Assos Assos
870 5c451ca3 Assos Assos
    case 'pattern':
871
      $pattern = preg_quote($rule['data'], '/');
872
      $pattern = str_replace('@', '[a-zA-Z]', $pattern);
873
      $pattern = str_replace('#', '[0-9]', $pattern);
874
      $pattern = '(' . $pattern . ')';
875
      // Un-escape "|" operator.
876
      $pattern = preg_replace('/(\\s*)(\\\\)(\\|)(\\s*)/', ')|(', $pattern);
877
      foreach ($items as $key => $val) {
878
        foreach ($val as $subval) {
879
          $test = !preg_match('/^(' . $pattern . ')$/', $subval);
880
          _webform_validation_test($errors, $key, $rule, $test);
881 85ad3d82 Assos Assos
        }
882 5c451ca3 Assos Assos
      }
883
      return $errors;
884 81b16cc2 Assos Assos
885 5c451ca3 Assos Assos
    case 'regex':
886
    case 'regexi':
887
      mb_regex_encoding('UTF-8');
888
      $regex = $rule['data'];
889
      foreach ($items as $key => $val) {
890
        foreach ($val as $subval) {
891
          if ($validator_name === 'regexi') {
892
            $match = (bool) mb_eregi($regex, $subval);
893 a2baadd1 Assos Assos
          }
894 5c451ca3 Assos Assos
          else {
895
            $match = (bool) mb_ereg($regex, $subval);
896 a2baadd1 Assos Assos
          }
897 5c451ca3 Assos Assos
          $test = !$match;
898
          _webform_validation_test($errors, $key, $rule, $test);
899 85ad3d82 Assos Assos
        }
900 5c451ca3 Assos Assos
      }
901
      return $errors;
902 81b16cc2 Assos Assos
903 5c451ca3 Assos Assos
    case 'must_be_empty':
904
      foreach ($items as $key => $val) {
905
        if (count($val) !== 0) {
906
          $errors[$key] = t('%item does not contain the correct data.', array('%item' => $components[$key]['name']));
907 85ad3d82 Assos Assos
        }
908 5c451ca3 Assos Assos
      }
909
      return $errors;
910 81b16cc2 Assos Assos
911 5c451ca3 Assos Assos
    case 'blacklist':
912
      $blacklist = preg_quote($rule['data'], '/');
913
      $blacklist = explode(',', $blacklist);
914
      $blacklist = array_map('trim', $blacklist);
915
      $blacklist = '/\b(' . implode('|', $blacklist) . ')\b/i';
916
      foreach ($items as $key => $val) {
917
        foreach ($val as $subval) {
918
          $test = preg_match($blacklist, $subval);
919
          _webform_validation_test($errors, $key, $rule, $test);
920 85ad3d82 Assos Assos
        }
921 5c451ca3 Assos Assos
      }
922
      return $errors;
923 81b16cc2 Assos Assos
924 5c451ca3 Assos Assos
    case 'username':
925
      foreach ($items as $key => $val) {
926
        $error_strings = array(
927
          'regular' => 'The %item field does not match an active username.',
928
          'negated' => 'The %item field matches an active username.',
929
        );
930
        $error_vars = array('%item' => $components[$key]['name']);
931
        foreach ($val as $subval) {
932
          $test = !db_query_range('SELECT 1 FROM {users} WHERE name = :username AND status = 1', 0, 1, array(':username' => $subval))->fetchField();
933
          _webform_validation_test($errors, $key, $rule, $test, $error_strings, $error_vars);
934 85ad3d82 Assos Assos
        }
935 5c451ca3 Assos Assos
      }
936
      return $errors;
937 81b16cc2 Assos Assos
938 5c451ca3 Assos Assos
    case 'valid_url':
939
      foreach ($items as $key => $val) {
940
        $error_strings = array(
941
          'regular' => '%item does not appear to be a valid URL.',
942
          'negated' => '%item must not be a valid URL.',
943
        );
944
        $error_vars = array('%item' => $components[$key]['name']);
945
        foreach ($val as $subval) {
946
          $test = !valid_url($subval, TRUE);
947
          _webform_validation_test($errors, $key, $rule, $test, $error_strings, $error_vars);
948 85ad3d82 Assos Assos
        }
949 5c451ca3 Assos Assos
      }
950
      return $errors;
951 81b16cc2 Assos Assos
952 5c451ca3 Assos Assos
    case 'email_verify':
953
      if (module_exists('email_verify')) {
954 85ad3d82 Assos Assos
        foreach ($items as $key => $val) {
955 a2baadd1 Assos Assos
          foreach ($val as $subval) {
956 5c451ca3 Assos Assos
            $error = email_verify_check($subval);
957
            if ($error) {
958
              $errors[$key] = $error;
959 85ad3d82 Assos Assos
            }
960
          }
961
        }
962 5c451ca3 Assos Assos
      }
963
      return $errors;
964 85ad3d82 Assos Assos
  }
965
}
966
967 5c451ca3 Assos Assos
/**
968
 * Return an array of the names of the components in a validation rule.
969
 *
970 81b16cc2 Assos Assos
 * @param array $rule
971 5c451ca3 Assos Assos
 *   Array of information about a validation rule.
972
 *
973
 * @return array
974
 *   Array of the filtered names of the components in $rule.
975
 */
976
function _webform_validation_get_names_of_rule_components(array $rule) {
977
  $names = array();
978
  foreach ($rule['components'] as $component) {
979
    $names[] = _webform_filter_xss($component['name']);
980
  }
981
  return $names;
982
}
983
984 85ad3d82 Assos Assos
/**
985 76bdcd04 Assos Assos
 * Helper function to negate validation rules as needed.
986
 *
987
 * Creates the correct error message.
988 85ad3d82 Assos Assos
 */
989
function _webform_validation_test(&$errors, $key, $rule, $test, array $error_strings = NULL, array $error_vars = NULL) {
990
  $rule['negate'] = !empty($rule['negate']);
991
  if ($rule['negate']) {
992
    $test = !$test;
993
  }
994
  if ($test) {
995
    if ($error_strings) {
996
      $error = t($error_strings[$rule['negate'] ? 'negated' : 'regular'], $error_vars);
997
    }
998
    else {
999
      $error = _webform_validation_i18n_error_message($rule);
1000
    }
1001
    $errors[$key] = $error;
1002
  }
1003
}
1004
1005
/**
1006
 * Count the number of words in a value.
1007 a2baadd1 Assos Assos
 *
1008
 * Strip HTML first.
1009 1f623f01 Assos Assos
 *
1010
 * @param string|array $val
1011
 *   A string or array of strings in which to count words.
1012
 *
1013
 * @return int
1014
 *   The number of words in the input.
1015 85ad3d82 Assos Assos
 */
1016
function _webform_validation_count_words($val) {
1017 a2baadd1 Assos Assos
  $val = _webform_validation_flatten_array($val);
1018
1019 1f623f01 Assos Assos
  // Strip any HTML tags so they're not counted in the word count.
1020 a2baadd1 Assos Assos
  $val = strip_tags($val);
1021 1f623f01 Assos Assos
  // Convert character entities back to characters. Without this, entities for
1022
  // whitespace characters would not be counted as word boundaries.
1023
  $val = html_entity_decode($val);
1024 a2baadd1 Assos Assos
1025 1f623f01 Assos Assos
  return count(preg_split('/[[:space:]\xC2\xA0]+/', $val));
1026 85ad3d82 Assos Assos
}
1027
1028
/**
1029 81b16cc2 Assos Assos
 * Helper function to deal with submitted values that are arrays.
1030
 *
1031
 * For example, multiple select component. We flatten the array as a
1032
 * comma-separated list to do the comparison.
1033 85ad3d82 Assos Assos
 */
1034
function _webform_validation_flatten_array($val) {
1035
  if (is_array($val)) {
1036
    $arr = array_filter($val, '_webform_validation_check_false');
1037
    return implode(',', $arr);
1038
  }
1039
  return $val;
1040
}
1041
1042
/**
1043 81b16cc2 Assos Assos
 * Get a array of validator definitions.
1044 5c451ca3 Assos Assos
 *
1045 81b16cc2 Assos Assos
 * @return array
1046
 *   Information about validators.
1047 85ad3d82 Assos Assos
 */
1048
function webform_validation_get_validators() {
1049 81b16cc2 Assos Assos
  static $validators;
1050
  if ($validators) {
1051
    return $validators;
1052
  }
1053
1054 85ad3d82 Assos Assos
  $validators = module_invoke_all('webform_validation_validators');
1055 76bdcd04 Assos Assos
  // Let modules use hook_webform_validator_alter($validators) to change
1056
  // validator settings.
1057 85ad3d82 Assos Assos
  drupal_alter('webform_validator', $validators);
1058 5c451ca3 Assos Assos
1059
  // Remove entries for which only partial information exists.
1060
  foreach ($validators as $validator_key => $validator_info) {
1061
    if (!isset($validator_info['name']) || !isset($validator_info['component_types'])) {
1062
      unset($validators[$validator_key]);
1063
    }
1064
  }
1065
1066 85ad3d82 Assos Assos
  return $validators;
1067
}
1068
1069
/**
1070 5c451ca3 Assos Assos
 * Return an array of the names of the validators.
1071
 *
1072
 * @return array
1073
 *   Array of with keys being validator IDs and values validator names.
1074 85ad3d82 Assos Assos
 */
1075
function webform_validation_get_validators_selection() {
1076
  $selection = array();
1077
  $validators = webform_validation_get_validators();
1078
  if ($validators) {
1079
    foreach ($validators as $validator_key => $validator_info) {
1080
      $selection[$validator_key] = $validator_info['name'];
1081
    }
1082
  }
1083
  return $selection;
1084
}
1085
1086
/**
1087 81b16cc2 Assos Assos
 * Get a list of valid component types per validator.
1088
 *
1089
 * These are defined via hook_webform_validation_validators(). If "all" is
1090
 * specified, all available component types will be returned.
1091 85ad3d82 Assos Assos
 */
1092
function webform_validation_valid_component_types($validator) {
1093
  $validators = webform_validation_get_validators();
1094
  if ($info = $validators[$validator]) {
1095
    $allowed_types = $info['component_types'];
1096 5c451ca3 Assos Assos
    if (in_array('all', $allowed_types, TRUE)) {
1097 85ad3d82 Assos Assos
      return array_keys(webform_components());
1098
    }
1099
    return $info['component_types'];
1100
  }
1101
}
1102
1103
/**
1104 5c451ca3 Assos Assos
 * Return information about a specified validator.
1105
 *
1106 81b16cc2 Assos Assos
 * @param string $validator_key
1107 5c451ca3 Assos Assos
 *   The key of the validator to return information about.
1108
 *
1109
 * @return array
1110
 *   Array of information about the validator.
1111 85ad3d82 Assos Assos
 */
1112
function webform_validation_get_validator_info($validator_key) {
1113
  $validators = webform_validation_get_validators();
1114
  return $validators[$validator_key];
1115
}
1116
1117
/**
1118 81b16cc2 Assos Assos
 * Handle translatable error messages, if available.
1119 85ad3d82 Assos Assos
 */
1120
function _webform_validation_i18n_error_message($rule) {
1121
  $rule['error_message'] = filter_xss($rule['error_message']);
1122 a2baadd1 Assos Assos
  if (module_exists('i18n')) {
1123
    return i18n_string('webform_validation:error_message:' . $rule['ruleid'] . ':message', $rule['error_message']);
1124 85ad3d82 Assos Assos
  }
1125
  return $rule['error_message'];
1126
}
1127
1128
/**
1129 4f315dab Assos Assos
 * Helper function used by array_filter() to determine if a value is empty.
1130
 *
1131
 * This is used in place of empty() because string '0' needs to be considered
1132
 * not empty and return FALSE.
1133
 *
1134
 * @param mixed $var
1135
 *   The value to check.
1136
 *
1137
 * @return bool
1138
 *   TRUE if $var is not one of FALSE, int 0, or empty string; FALSE otherwise.
1139
 *
1140
 * @see https://www.drupal.org/node/886458
1141
 * @see https://www.drupal.org/node/2638172
1142 85ad3d82 Assos Assos
 */
1143
function _webform_validation_check_false($var) {
1144 4f315dab Assos Assos
  return $var !== FALSE && $var !== 0 && $var !== '';
1145 85ad3d82 Assos Assos
}
1146
1147
/**
1148 76bdcd04 Assos Assos
 * Helper function to check numeric data.
1149
 *
1150
 * Process the numeric value validation range that was provided in the numeric
1151
 * validator options.
1152 85ad3d82 Assos Assos
 */
1153
function _webform_numeric_check_data($data) {
1154
  $range = array('min' => NULL, 'max' => NULL);
1155 81b16cc2 Assos Assos
  // If no value was specified, don't validate.
1156 85ad3d82 Assos Assos
  if ($data == '') {
1157
    return $range;
1158
  }
1159
1160 81b16cc2 Assos Assos
  // If only one numeric value was specified, this is the min value.
1161 85ad3d82 Assos Assos
  if (is_numeric($data)) {
1162
    $range['min'] = (float) $data;
1163
  }
1164
1165
  if (strpos($data, '|') !== FALSE) {
1166
    list($min, $max) = explode('|', $data);
1167
    if ($min != '' && is_numeric($min)) {
1168
      $range['min'] = (float) $min;
1169
    }
1170
    if ($max != '' && is_numeric($max)) {
1171
      $range['max'] = (float) $max;
1172
    }
1173
  }
1174
  return $range;
1175
}