You are here

value_is.module in Value is 7

All the element validators for #element_validate.

File

value_is.module
View source
<?php

/**
 * @file
 * All the element validators for #element_validate.
 */

/**
 * Implements hook_element_info_alter().
 */
function value_is_element_info_alter(&$info) {

  // Required file.
  if (isset($info['file'])) {
    if (!isset($info['file']['#validate'])) {
      $info['file']['#validate'] = array();
    }
    array_unshift($info['file']['#validate'], '_value_is_file_element_validate');
    $info['file']['#process'][] = '_value_is_file_element_process';
  }

  // Disabled checkboxes.
  if (isset($info['checkboxes'])) {
    $info['checkboxes']['#process'][] = '_value_is_disabled_options_process';
    $info['checkboxes']['#value_callback'] = '_value_is_disabled_options_value_callback';
  }
}

/**
 * Process callback for file input elements.
 */
function _value_is_file_element_process($element, &$form_state, $form) {
  $file = _value_is_get_file($element);
  $error = _value_is_get_file_error($file);
  if (!$error) {
    $element['#value'] = $file;
    form_set_value($element, $file, $form_state);
  }
  return $element;
}

/**
 * Helper to get a file's error code. This requires logic, because a file can be a list of files.
 */
function _value_is_get_file_error($file) {
  if (isset($file[0])) {
    return isset($file[0]['error']) ? $file[0]['error'] : -1;
  }
  return isset($file['error']) ? $file['error'] : -1;
}

/**
 * Helper to get a file from $_FILES.
 */
function _value_is_get_file($element) {
  $input_name = trim(str_replace(array(
    '[',
    ']',
  ), ' ', str_replace('[]', '', $element['#name'])));
  $input_name_path = preg_split('/\\s+/', $input_name);

  // Traverse $_FILES recursively to find the actual file. This is not pretty, but
  // the only (?) way.
  $properties = array(
    'name',
    'type',
    'tmp_name',
    'error',
    'size',
  );
  $input_name_part = array_shift($input_name_path);
  foreach ($properties as $prop) {
    $source[$prop] = @$_FILES[$input_name_part][$prop];
    if ($source[$prop] === NULL) {
      return;
    }
  }
  while ($input_name_part = array_shift($input_name_path)) {
    foreach ($properties as $prop) {
      $source[$prop] = @$source[$prop][$input_name_part];
      if ($source[$prop] === NULL) {
        return;
      }
    }
  }

  // Flip array 2d for arrayed/multiple files.
  if ($source && is_array($source['error'])) {
    $source = _value_is_flip_array_2d($source);
  }
  return $source;
}

/**
 * Process callback for checkboxes elements.
 */
function _value_is_disabled_options_process($element, &$form_state, &$full_form) {
  $state = _value_is_disabled_options_state($element);
  return $element;
}

/**
 * Helper to determine if there's nothing to do in this element. Depends on:
 * - #value_callback must be mine
 * - element must NOT already be (fully) #disabled
 * - some #disabled_options or #hidden_options must exist
 */
function _value_is_disabled_options_passthrough($element) {
  $good_value_callback = $element['#value_callback'] == '_value_is_disabled_options_value_callback';
  $disabled = !empty($element['#disabled']);
  $no_config = empty($element['#disabled_options']) && empty($element['#hidden_options']);
  return !($good_value_callback && !$disabled && !$no_config);
}

/**
 * Helper to save unchangeable checkboxes state and alter $element.
 */
function _value_is_disabled_options_state(&$element) {
  $passthrough = _value_is_disabled_options_passthrough($element);
  if ($passthrough) {
    return array();
  }
  $state = array();
  foreach ($element['#options'] as $key => $label) {
    if (isset($element['#disabled_options']) && in_array($key, $element['#disabled_options'])) {
      $element[$key]['#disabled'] = TRUE;
      $value = in_array($key, $element['#default_value']) ? $key : 0;
      $state[$key] = $value;
    }
    if (isset($element['#hidden_options']) && in_array($key, $element['#hidden_options'])) {
      $element[$key]['#access'] = FALSE;
      $value = in_array($key, $element['#default_value']) ? $key : 0;
      $state[$key] = $value;
    }
  }
  return $state;
}

/**
 * Value callback for checkboxes elements.
 */
function _value_is_disabled_options_value_callback($element, $input = FALSE, $form_state = array()) {
  $passthrough = _value_is_disabled_options_passthrough($element);
  $default = isset($element['#value']) ? $element['#value'] : (isset($element['#default_value']) ? $element['#default_value'] : array());
  if ($passthrough && !empty($element['#disabled'])) {
    return drupal_map_assoc($default);
  }
  $state = _value_is_disabled_options_state($element);
  $access = !isset($element['#access']) || $element['#access'];
  $submitted = $access && $input !== FALSE;
  if ($submitted) {
    $input_data = is_array($input) ? $input : array();
    return drupal_map_assoc(array_filter($state + $input_data));
  }
  return drupal_map_assoc($default);
}

/**
 * Helper to flip a 2D array.
 */
function _value_is_flip_array_2d($array) {
  $out = array();
  foreach ($array as $a => $children) {
    foreach ($children as $b => $value) {
      $out[$b][$a] = $value;
    }
  }
  return $out;
}

/**
 * Checks for valid (and optionally existing) user name.
 */
function value_is_username($element, &$form_state, $form) {
  $value = $element['#value'];
  if ('' != $value) {
    $must_exist = !empty($element['#exists']);
    if ($must_exist) {
      $field = isset($element['#field']) ? $element['#field'] : 'name';
      $query = db_select('users', 'u');
      $query
        ->addExpression('COUNT(1)', 'num');
      $query
        ->condition($field, $value);
      $exists = (int) $query
        ->execute()
        ->fetchField();
      if (!$exists) {
        $params = array(
          '%title' => $element['#title'],
        );
        $message = t('%title must contain an existing user name.', $params);
        return form_error($element, $message);
      }
    }
    else {
      $error = user_validate_name($value);
      if ($error) {
        return form_error($element, $error);
      }
    }
  }
}

/**
 * Checks for e-mail address(es) or token(s).
 */
function value_is_email_or_token($element, &$form_state, $form) {
  $element['#allow_tokens'] = TRUE;
  return value_is_email($element, $form_state, $form);
}

/**
 * Checks for e-mail address(es).
 */
function value_is_email($element, &$form_state, $form) {
  $value = $element['#value'];
  if ('' != $value) {
    $allow_tokens = !empty($element['#allow_tokens']);

    // Default is just 1 address.
    $max = isset($element['#max']) ? (int) $element['#max'] : 1;

    // The input will be validated as if it were an array.
    $addresses = explode(',', $value);

    // Too many.
    if ($max < count($addresses)) {
      $params = array(
        '%title' => $element['#title'],
        '@max' => $max,
      );
      $message = t('%title can contain max @max e-mail addresses.', $params);
      return form_error($element, $message);
    }

    // Validate per address.
    foreach ($addresses as $address) {
      if (!valid_email_address(trim($address)) && (!$allow_tokens || !preg_match('#:e?mail\\]#', $address))) {
        $params = array(
          '%title' => $element['#title'],
        );
        $message = 1 < $max ? t('%title must be a comma separated list of valid e-mail addresses.', $params) : t('%title must be a valid e-mail address', $params);
        return form_error($element, $message);
      }
    }
  }
}

/**
 * Helper: integer.
 */
function _value_is_integer($value) {
  return (string) $value === (string) (int) $value;
}

/**
 * Checks for integer (non floating point number).
 */
function value_is_integer($element, &$form_state, $form) {
  $value = $element['#value'];
  if ('' != $value) {

    // Not even close.
    if (!_value_is_integer($value)) {
      return form_error($element, t('Only numbers are allowed in %field.', array(
        '%field' => $element['#title'],
      )));
    }

    // Too low.
    if (isset($element['#min']) && $value < $element['#min']) {
      return form_error($element, t('%name: the value may be no less than %min.', array(
        '%name' => $element['#title'],
        '%min' => $element['#min'],
      )));
    }

    // Too high.
    if (isset($element['#max']) && $value > $element['#max']) {
      return form_error($element, t('%name: the value may be no greater than %max.', array(
        '%name' => $element['#title'],
        '%max' => $element['#max'],
      )));
    }

    // Cast input value to an Int.
    form_set_value($element, (int) $value, $form_state);
  }
}

/**
 * Helper: float.
 */
function _value_is_number(&$value) {
  $value = str_replace(',', '.', $value);
  return is_numeric($value);
}

/**
 * Checks for number (floating point number).
 */
function value_is_number(&$element, &$form_state, $form) {
  $value = $element['#value'];
  if ('' != $value) {

    // Not even close.
    if (!_value_is_number($value)) {
      return form_error($element, t('Only numbers and the decimal separator are allowed in %field.', array(
        '%field' => $element['#title'],
      )));
    }

    // Too low.
    if (isset($element['#min']) && $value < $element['#min']) {
      return form_error($element, t('%name: the value may be no less than %min.', array(
        '%name' => $element['#title'],
        '%min' => $element['#min'],
      )));
    }

    // Too high.
    if (isset($element['#max']) && $value > $element['#max']) {
      return form_error($element, t('%name: the value may be no greater than %max.', array(
        '%name' => $element['#title'],
        '%max' => $element['#max'],
      )));
    }

    // Cast input value to a Float.
    form_set_value($element, (double) $value, $form_state);
  }
}

Functions

Namesort descending Description
value_is_element_info_alter Implements hook_element_info_alter().
value_is_email Checks for e-mail address(es).
value_is_email_or_token Checks for e-mail address(es) or token(s).
value_is_integer Checks for integer (non floating point number).
value_is_number Checks for number (floating point number).
value_is_username Checks for valid (and optionally existing) user name.
_value_is_disabled_options_passthrough Helper to determine if there's nothing to do in this element. Depends on:
_value_is_disabled_options_process Process callback for checkboxes elements.
_value_is_disabled_options_state Helper to save unchangeable checkboxes state and alter $element.
_value_is_disabled_options_value_callback Value callback for checkboxes elements.
_value_is_file_element_process Process callback for file input elements.
_value_is_flip_array_2d Helper to flip a 2D array.
_value_is_get_file Helper to get a file from $_FILES.
_value_is_get_file_error Helper to get a file's error code. This requires logic, because a file can be a list of files.
_value_is_integer Helper: integer.
_value_is_number Helper: float.