function webform_validation_webform_validation_validate in Webform Validation 7
Same name and namespace in other branches
- 6 webform_validation.validators.inc \webform_validation_webform_validation_validate()
Implements hook_webform_validation_validate().
1 call to webform_validation_webform_validation_validate()
- WebformValidationUnitTestCase::test in tests/
WebformValidationUnitTestCase.test - The tests.
File
- ./
webform_validation.validators.inc, line 471 - Provides validation functionality and hooks.
Code
function webform_validation_webform_validation_validate($validator_name, $items, $components, $rule) {
if (!$items) {
return NULL;
}
// For certain validators, if all components to be compared are email
// components, make the values lower-case to avoid case-sensitive comparison.
if (in_array($validator_name, array(
'equal',
'comparison',
'unique',
))) {
$all_email = TRUE;
foreach ($rule['components'] as $component) {
if ($component['type'] !== 'email') {
$all_email = FALSE;
break;
}
}
if ($all_email) {
$items = array_map('strtolower', $items);
}
}
// Some components, such as multiple select, send their values as arrays,
// others don't. Convert all to arrays and write the rules to handle them that
// way. Remove empty values.
foreach ($items as $key => $val) {
$new_values = array();
foreach ((array) $val as $val_key => $val_val) {
if ((string) $val_val !== '') {
$new_values[$val_key] = $val_val;
}
}
$items[$key] = $new_values;
}
// Ensure later calls to key() get the first item.
reset($items);
$errors = array();
switch ($validator_name) {
case 'numeric':
$num_range = _webform_numeric_check_data($rule['data']);
foreach ($items as $key => $val) {
foreach ($val as $subval) {
// First check if the value is numeric.
if (is_numeric($subval)) {
$subval = (double) $subval;
}
else {
$errors[$key] = t('%item is not numeric.', array(
'%item' => $components[$key]['name'],
));
continue;
}
// Now validate the entered numeric value against the validator range
// settings, if appropriate.
// a. validate min & max.
if (isset($num_range['min']) && isset($num_range['max'])) {
// Validate the min - max range.
if ($subval < $num_range['min'] || $subval > $num_range['max']) {
$options = array(
'%item' => $components[$key]['name'],
'%range' => str_replace('|', ' - ', $rule['data']),
);
$errors[$key] = t('%item is not within the allowed range %range.', $options);
}
}
else {
// b. validate min.
if (isset($num_range['min'])) {
if ($subval < $num_range['min']) {
$errors[$key] = t('%item should be greater than or equal to %val.', array(
'%item' => $components[$key]['name'],
'%val' => $num_range['min'],
));
}
}
// c. validate max.
if (isset($num_range['max'])) {
if ($subval > $num_range['max']) {
$errors[$key] = t('%item should be less than or equal to %val.', array(
'%item' => $components[$key]['name'],
'%val' => $num_range['max'],
));
}
}
}
}
}
return $errors;
case 'min_length':
$min_length = $rule['data'];
foreach ($items as $key => $val) {
foreach ($val as $subval) {
if (drupal_strlen($subval) < $min_length) {
$errors[$key] = t('%item should be at least %num characters long.', array(
'%item' => $components[$key]['name'],
'%num' => $min_length,
));
}
}
}
return $errors;
case 'max_length':
$max_length = $rule['data'];
foreach ($items as $key => $val) {
foreach ($val as $subval) {
if (drupal_strlen($subval) > $max_length) {
$errors[$key] = t('%item should be at most %num characters long.', array(
'%item' => $components[$key]['name'],
'%num' => $max_length,
));
}
}
}
return $errors;
case 'min_words':
$min_words = $rule['data'];
foreach ($items as $key => $val) {
foreach ($val as $subval) {
if (_webform_validation_count_words($subval) < $min_words) {
$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'],
));
$errors[$key] = $error;
}
}
}
return $errors;
case 'max_words':
$max_words = $rule['data'];
foreach ($items as $key => $val) {
foreach ($val as $subval) {
if (_webform_validation_count_words($subval) > $max_words) {
$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'],
));
$errors[$key] = $error;
}
}
}
return $errors;
case 'sum':
// Get the numbers to sum.
$sum = array();
foreach ($items as $item) {
if (isset($item[0])) {
$sum[] = $item[0];
}
}
// If none of the components are completed, don't run this validator.
if (!count($sum)) {
return array();
}
$sum = array_sum($sum);
// Number being compared with.
$compare_number = (double) preg_replace('/^[^0-9]+/', '', $rule['data']);
// Parse the comparision operator and do comparison.
module_load_include('inc', 'webform', 'components/number');
$error = FALSE;
if (substr($rule['data'], 0, 2) === '<=') {
if (!(webform_compare_floats($sum, $compare_number) <= 0)) {
$error = t('less than or equal to');
}
}
elseif (substr($rule['data'], 0, 1) === '<') {
if (!(webform_compare_floats($sum, $compare_number) < 0)) {
$error = t('less than');
}
}
elseif (substr($rule['data'], 0, 2) === '>=') {
if (!(webform_compare_floats($sum, $compare_number) >= 0)) {
$error = t('greater than or equal to');
}
}
elseif (substr($rule['data'], 0, 1) === '>') {
if (!(webform_compare_floats($sum, $compare_number) > 0)) {
$error = t('greater than');
}
}
else {
if (!(webform_compare_floats($sum, $compare_number) === 0)) {
$error = t('exactly');
}
}
// Set error if needed.
if ($error) {
$keys = array_keys($items);
$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),
));
}
return $errors;
case 'equal':
$first_entry_key = key($items);
$first_entry = array_shift($items);
foreach ($items as $key => $val) {
if ($val !== $first_entry) {
$errors[$key] = t('%item_checked does not match %item_first.', array(
'%item_checked' => $components[$key]['name'],
'%item_first' => $components[$first_entry_key]['name'],
));
}
}
return $errors;
case 'comparison':
foreach (array(
1,
2,
) as $count) {
$entry[$count]['key'] = key($items);
$value = array_shift($items);
if ($components[$entry[$count]['key']]['type'] === 'date') {
if (!empty($value) && checkdate((int) $value['month'], (int) $value['day'], (int) $value['year'])) {
$entry[$count]['value'] = date('Y-m-d', mktime(0, 0, 0, (int) $value['month'], (int) $value['day'], (int) $value['year']));
}
else {
$entry[$count]['value'] = NULL;
}
}
elseif ($components[$entry[$count]['key']]['type'] === 'time') {
if (isset($value['hour']) && isset($value['minute'])) {
$time = $value['hour'] . ':' . str_pad($value['minute'], 2, '0', STR_PAD_LEFT);
if (!empty($value['ampm'])) {
$time .= ' ' . $value['ampm'];
}
$time = strtotime($time);
}
else {
$time = NULL;
}
if ($time) {
$entry[$count]['value'] = date('H:i', $time);
}
else {
$entry[$count]['value'] = NULL;
}
}
else {
$entry[$count]['value'] = _webform_validation_flatten_array($value);
}
}
// Don't validate if either are empty.
if ((string) $entry[1]['value'] === '' || (string) $entry[2]['value'] === '') {
return array();
}
$error = FALSE;
switch ($rule['data']) {
case '>':
if (!($entry[1]['value'] > $entry[2]['value'])) {
$error = TRUE;
}
break;
case '>=':
if (!($entry[1]['value'] >= $entry[2]['value'])) {
$error = TRUE;
}
break;
case '<':
if (!($entry[1]['value'] < $entry[2]['value'])) {
$error = TRUE;
}
break;
case '<=':
if (!($entry[1]['value'] <= $entry[2]['value'])) {
$error = TRUE;
}
break;
}
if ($error) {
$errors[$entry[2]['key']] = _webform_validation_i18n_error_message($rule);
}
return $errors;
case 'unique':
foreach ($items as $key => $val) {
$items[$key] = _webform_validation_flatten_array($val);
}
// Now we count how many times each value appears, and find out which
// values appear more than once.
$items_count = array_count_values(array_map('drupal_strtolower', array_map('trim', $items)));
$doubles = array_filter($items_count, function ($x) {
return $x > 1;
});
foreach ($items as $key => $val) {
if (in_array(drupal_strtolower($val), array_keys($doubles))) {
$errors[$key] = t('The value of %item is not unique.', array(
'%item' => $components[$key]['name'],
));
}
}
return $errors;
case 'specific_value':
$specific_values = explode(',', $rule['data']);
$specific_values = array_map('trim', $specific_values);
foreach ($items as $key => $val) {
// Selects: Fail if at least one checked and at least one not in the
// allowed values.
$val = array_filter($val);
$test = count($val) && count(array_diff($val, $specific_values));
_webform_validation_test($errors, $key, $rule, $test);
}
return $errors;
case 'default_value':
foreach ($items as $key => $val) {
$val = _webform_validation_flatten_array($val);
$test = $val != $components[$key]['value'];
_webform_validation_test($errors, $key, $rule, $test);
}
return $errors;
case 'someofseveral':
// Determine the number of components completed.
foreach ($items as $key => $val) {
$items[$key] = _webform_validation_flatten_array($val);
$items[$key] = (bool) strlen($items[$key]);
}
$number_completed = count(array_filter($items));
// Number being compared with.
$compare_number = (int) preg_replace('/[^0-9]+/', '', $rule['data']);
if ($compare_number < 1) {
$compare_number = 1;
}
elseif ($compare_number > count($rule['components'])) {
$compare_number = count($rule['components']);
}
// Parse the comparision operator and do comparison.
$error = FALSE;
if (substr($rule['data'], 0, 1) === '=') {
if (!($number_completed === $compare_number)) {
$error = t('exactly');
}
}
elseif (substr($rule['data'], 0, 2) === '<=') {
if (!($number_completed <= $compare_number)) {
$error = t('at most');
}
}
else {
if (!($number_completed >= $compare_number)) {
$error = t('at least');
}
}
// Set error if needed.
if ($error) {
$keys = array_keys($items);
$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),
));
}
return $errors;
case 'select_min':
$min_selections = $rule['data'];
foreach ($items as $key => $val) {
if (count(array_filter($val, '_webform_validation_check_false')) < $min_selections) {
$errors[$key] = t('Please select at least %num options for %item.', array(
'%num' => $min_selections,
'%item' => $components[$key]['name'],
));
}
}
return $errors;
case 'select_max':
$max_selections = $rule['data'];
foreach ($items as $key => $val) {
if (count(array_filter($val, '_webform_validation_check_false')) > $max_selections) {
$errors[$key] = t('Please select maximum %num options for %item.', array(
'%num' => $max_selections,
'%item' => $components[$key]['name'],
));
}
}
return $errors;
case 'select_exact':
$allowed_selections = $rule['data'];
foreach ($items as $key => $val) {
$error_strings = array(
'regular' => 'Please select %num options for %item.',
'negated' => 'Please do not select %num options for %item.',
);
$error_vars = array(
'%num' => $allowed_selections,
'%item' => $components[$key]['name'],
);
$test = count(array_filter($val, '_webform_validation_check_false')) != $allowed_selections;
_webform_validation_test($errors, $key, $rule, $test, $error_strings, $error_vars);
}
return $errors;
case 'plain_text':
foreach ($items as $key => $val) {
$error_strings = array(
'regular' => '%item only allows the use of plain text.',
'negated' => '%item must contain HTML tags.',
);
$error_vars = array(
'%item' => $components[$key]['name'],
);
foreach ($val as $subval) {
$test = strcmp($subval, strip_tags($subval));
_webform_validation_test($errors, $key, $rule, $test, $error_strings, $error_vars);
}
}
return $errors;
case 'starts_with':
case 'ends_with':
$pattern = preg_quote($rule['data'], '/');
if ($validator_name === 'starts_with') {
$pattern = '^' . $pattern;
$verb = t('start');
}
else {
$pattern .= '$';
$verb = t('end');
}
$pattern = '/' . $pattern . '/';
foreach ($items as $key => $val) {
$error_strings = array(
'regular' => '%item must %verb with "%string".',
'negated' => '%item must not %verb with "%string".',
);
$error_vars = array(
'%item' => $components[$key]['name'],
'%verb' => $verb,
'%string' => $rule['data'],
);
foreach ($val as $subval) {
$test = !preg_match($pattern, $subval);
_webform_validation_test($errors, $key, $rule, $test, $error_strings, $error_vars);
}
}
return $errors;
case 'pattern':
$pattern = preg_quote($rule['data'], '/');
$pattern = str_replace('@', '[a-zA-Z]', $pattern);
// Since PHP 7.3, the # character is quoted by preg_quote().
$quoted_hash = version_compare(PHP_VERSION, '7.3.0', '>=') ? '\\#' : '#';
$pattern = str_replace($quoted_hash, '[0-9]', $pattern);
$pattern = '(' . $pattern . ')';
// Un-escape "|" operator.
$pattern = preg_replace('/(\\s*)(\\\\)(\\|)(\\s*)/', ')|(', $pattern);
foreach ($items as $key => $val) {
foreach ($val as $subval) {
$test = !preg_match('/^(' . $pattern . ')$/', $subval);
_webform_validation_test($errors, $key, $rule, $test);
}
}
return $errors;
case 'regex':
case 'regexi':
mb_regex_encoding('UTF-8');
$regex = $rule['data'];
foreach ($items as $key => $val) {
foreach ($val as $subval) {
if ($validator_name === 'regexi') {
$match = (bool) mb_eregi($regex, $subval);
}
else {
$match = (bool) mb_ereg($regex, $subval);
}
$test = !$match;
_webform_validation_test($errors, $key, $rule, $test);
}
}
return $errors;
case 'must_be_empty':
foreach ($items as $key => $val) {
if (count($val) !== 0) {
$errors[$key] = t('%item does not contain the correct data.', array(
'%item' => $components[$key]['name'],
));
}
}
return $errors;
case 'blacklist':
$blacklist = $rule['data'];
$blacklist = token_replace($blacklist);
$blacklist = preg_quote($blacklist, '/');
$blacklist = explode(',', $blacklist);
$blacklist = array_map('trim', $blacklist);
$blacklist = '/\\b(' . implode('|', $blacklist) . ')\\b/i';
foreach ($items as $key => $val) {
foreach ($val as $subval) {
$test = preg_match($blacklist, $subval);
_webform_validation_test($errors, $key, $rule, $test);
}
}
return $errors;
case 'username':
foreach ($items as $key => $val) {
$error_strings = array(
'regular' => 'The %item field does not match an active username.',
'negated' => 'The %item field matches an active username.',
);
$error_vars = array(
'%item' => $components[$key]['name'],
);
foreach ($val as $subval) {
$test = !db_query_range('SELECT 1 FROM {users} WHERE name = :username AND status = 1', 0, 1, array(
':username' => $subval,
))
->fetchField();
_webform_validation_test($errors, $key, $rule, $test, $error_strings, $error_vars);
}
}
return $errors;
case 'valid_url':
foreach ($items as $key => $val) {
$error_strings = array(
'regular' => '%item does not appear to be a valid URL.',
'negated' => '%item must not be a valid URL.',
);
$error_vars = array(
'%item' => $components[$key]['name'],
);
foreach ($val as $subval) {
$test = !valid_url($subval, TRUE);
_webform_validation_test($errors, $key, $rule, $test, $error_strings, $error_vars);
}
}
return $errors;
case 'email_verify':
if (module_exists('email_verify')) {
foreach ($items as $key => $val) {
foreach ($val as $subval) {
$error = email_verify_check($subval);
if ($error) {
$errors[$key] = $error;
}
}
}
}
return $errors;
}
}