You are here

fapi_validation.module in Form API Validation 6

File

fapi_validation.module
View source
<?php

/**
 * Implementation of hook_form_alter
 */
function fapi_validation_form_alter(&$form, $form_state, $form_id) {
  if (!isset($form['#validate']) || !is_array($form['#validate'])) {
    $form['#validate'] = array();
  }
  $form['#validate'] = array_merge(array(
    'fapi_validation_form_validate',
  ), $form['#validate']);
}

/**
 * Validate the form searching for #rules and #filters params.
 */
function fapi_validation_form_validate(&$form, &$form_state) {

  // Initializing register
  fapi_validation_register($form, NULL, $form_state);

  // Starting validation process
  _fapi_validation_element_validate($form, $form_state);

  // Updating $form_state
  $form_state = fapi_validation_register($form);
}
function _fapi_validation_element_validate(&$elements, $child = FALSE) {
  if (isset($elements['#filters'])) {
    fapi_validation_filters_execute($elements);
  }
  if (isset($elements['#rules'])) {
    fapi_validation_rules_execute($elements);
  }
  $values = array();
  foreach (element_children($elements) as $key) {
    _fapi_validation_element_validate($elements[$key], TRUE);
  }
  return $values;
}
function fapi_validation_register(&$element = NULL, $value = NULL, $form_state = NULL) {
  static $fs;
  if (!is_null($form_state)) {
    $fs = $form_state;
  }
  if (!is_null($element) && !is_null($value)) {
    form_set_value($element, $value, $fs);
    $element['#value'] = $value;
  }
  else {
    return $fs;
  }
}
function fapi_validation_filters_execute(&$element) {
  $data = _fapi_validation_data('filters');
  if (!isset($element['#value'])) {
    return;
  }
  $value = $element['#value'];
  foreach ($element['#filters'] as $filter) {
    if (!isset($data[$filter])) {
      continue;
    }
    $value = $data[$filter]['callback']($value);
  }
  fapi_validation_register($element, $value);
}
function fapi_validation_rules_execute(&$element) {
  $data = _fapi_validation_data('rules');

  // If element is empty and not required, by pass rule validation.
  if (!$element['#required'] && empty($element['#value'])) {
    return;
  }
  foreach ($element['#rules'] as $rule) {
    $params = array(
      $element['#value'],
    );
    $error_message = NULL;

    // If $rule is an array, use error message if is setted.
    if (is_array($rule)) {
      if (isset($rule['error'])) {
        $error_message = $rule['error'];
      }
      if (!isset($rule['rule'])) {
        drupal_set_message(t('Rule array with wrong structure on %field.', array(
          '%field' => $element['#name'],
        )), 'error');
        continue;
      }
      $rule = $rule['rule'];
    }
    preg_match('/^(.*?)(\\[(.*)\\])?$/', $rule, $rs);
    $rule = $rs[1];
    if (!isset($data[$rule])) {
      drupal_set_message(t('Rule %rule not found!', array(
        '%rule' => $rule,
      )), 'error');
      continue;
    }

    // Parsing parameters.
    if (isset($rs[3])) {
      if ($rule == 'regexp') {
        $params[] = array(
          $rs[3],
        );
      }
      else {
        $params[] = preg_split('/ *, */', $rs[3]);
      }
    }
    $ret = call_user_func_array($data[$rule]['callback'], $params);
    if (!$ret) {
      $error = is_null($error_message) ? $data[$rule]['error_msg'] : $error_message;
      form_set_error(implode("][", $element['#parents']), t($error, array(
        '%field' => $element['#title'],
      )));
    }
  }
}
function _fapi_validation_data($type, $refresh = NULL) {
  static $data = array();
  if (!count($data[$type]) || $refresh) {
    foreach (module_implements('fapi_validation_' . $type) as $module) {
      $validations = module_invoke($module, 'fapi_validation_' . $type);
      if (isset($validations) && is_array($validations)) {
        foreach ($validations as $name => $info) {
          $data[$type][$name] = $info;
        }
      }
    }
  }
  return $data[$type];
}

/**
 * Implementation of hook_fapi_validation_rules
 */
function fapi_validation_fapi_validation_rules() {
  return array(
    'numeric' => array(
      'callback' => 'fapi_validation_rule_numeric',
      'error_msg' => t('Use only numbers at %field.'),
    ),
    'alpha' => array(
      'callback' => 'fapi_validation_rule_alpha',
      'error_msg' => t('Use only alpha characters at %field.'),
    ),
    'alpha_numeric' => array(
      'callback' => 'fapi_validation_rule_alpha_numeric',
      'error_msg' => t('Use only alpha numerics characters at %field.'),
    ),
    'email' => array(
      'callback' => 'fapi_validation_rule_email',
      'error_msg' => t('%field not is a valid email.'),
    ),
    'length' => array(
      'callback' => 'fapi_validation_rule_length',
      'error_msg' => t('Invalid size of %field value.'),
    ),
    'chars' => array(
      'callback' => 'fapi_validation_rule_chars',
      'error_msg' => t('Invalid characters on %field value.'),
    ),
    'url' => array(
      'callback' => 'fapi_validation_rule_url',
      'error_msg' => t('Invalid format of %field.'),
    ),
    'ipv4' => array(
      'callback' => 'fapi_validation_rule_ipv4',
      'error_msg' => t('Invalid format of %field.'),
    ),
    'alpha_dash' => array(
      'callback' => 'fapi_validation_rule_alpha_dash',
      'error_msg' => t('Use only alpha numerics, hyphen and underscore at %field.'),
    ),
    'digit' => array(
      'callback' => 'fapi_validation_rule_digit',
      'error_msg' => t('Use only digits on %field.'),
    ),
    'decimal' => array(
      'callback' => 'fapi_validation_rule_decimal',
      'error_msg' => t('Use only decimal on %field.'),
    ),
    'regexp' => array(
      'callback' => 'fapi_validation_rule_regexp',
      'error_msg' => t('%field value does not match rule.'),
    ),
  );
}

/**
 * Implementation of hook_fapi_validation_filters
 */
function fapi_validation_fapi_validation_filters() {
  return array(
    'numeric' => array(
      'callback' => 'fapi_validation_filter_numeric',
    ),
    'trim' => array(
      'callback' => 'fapi_validation_filter_trim',
    ),
    'uppercase' => array(
      'callback' => 'fapi_validation_filter_uppercase',
    ),
    'lowercase' => array(
      'callback' => 'fapi_validation_filter_lowercase',
    ),
  );
}

/**
 * Rules
 */
function fapi_validation_rule_numeric($value) {
  return is_numeric($value);
}
function fapi_validation_rule_alpha($value) {
  return (bool) preg_match('/^[\\pL]++$/uD', (string) $value);
}
function fapi_validation_rule_alpha_numeric($value) {
  return (bool) preg_match('/^[\\pL\\pN]++$/uD', (string) $value);
}
function fapi_validation_rule_email($value) {
  return valid_email_address($value);
}
function fapi_validation_rule_length($value, $params) {
  $size = mb_strlen($value);
  if (count($params) == 1) {
    return $size == (int) $params[0];
  }
  else {
    if (count($params) == 2) {
      return $size >= (int) $params[0] && $size <= (int) $params[1];
    }
  }
}
function fapi_validation_rule_url($value, $params = array()) {
  return valid_url($value, !empty($params) && $params[0] == 'absolute');
}
function fapi_validation_rule_ipv4($value) {
  $pattern = '/^([1-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])' . '(\\.([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])){3}$/';
  return (bool) preg_match($pattern, $value);
}
function fapi_validation_rule_alpha_dash($value) {
  return (bool) preg_match('/^[-\\pL\\pN_]+$/uD', (string) $value);
}
function fapi_validation_rule_digit($value) {
  return (bool) preg_match('/^\\d+$/', $value);
}
function fapi_validation_rule_chars($value, $params) {
  for ($i = 0; $i < mb_strlen($value); $i++) {
    $current = substr($value, $i, 1);
    if (!in_array($current, $params)) {
      return FALSE;
    }
  }
  return TRUE;
}
function fapi_validation_rule_decimal($value, $params) {
  if (count($params) == 2) {
    $pattern = '/^[0-9]{' . $params[0] . '}\\.[0-9]{' . $params[1] . '}$/';
    return (bool) preg_match($pattern, (string) $value);
  }
  else {
    return (bool) preg_match('/\\d+\\.\\d+/', $value);
  }
  return FALSE;
}
function fapi_validation_rule_regexp($value, $params) {
  return (bool) preg_match($params[0], (string) $value);
}

/**
 * Filters
 */
function fapi_validation_filter_numeric($value) {
  return preg_replace('/[^0-9]+/', '', $value);
}
function fapi_validation_filter_trim($value) {
  return trim($value);
}
function fapi_validation_filter_uppercase($value) {
  return mb_strtoupper($value);
}
function fapi_validation_filter_lowercase($value) {
  return mb_strtolower($value);
}