diff --git a/fapi_validation.module b/fapi_validation.module index 838a36dbc1394ee1044fcb8aa8d5cce57df4cd4c..999fde4dde35332de9296686190a08512eb1a5fb 100644 --- a/fapi_validation.module +++ b/fapi_validation.module @@ -4,6 +4,10 @@ * 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']); } @@ -11,18 +15,19 @@ function fapi_validation_form_alter(&$form, $form_state, $form_id) { * 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); - - foreach (fapi_validation_register() as $key => $value) { - form_set_value($form[$key], $value, $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); } @@ -35,37 +40,87 @@ function _fapi_validation_element_validate(&$elements, $child=FALSE) { return $values; } -function fapi_validation_register($key=NULL, $value=NULL) { - static $register = array(); - if (!is_null($key)) { - $register[$key] = $value; +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; } - return $register; } -function fapi_validation_filters_execute($elements) { +function fapi_validation_filters_execute(&$element) { $data = _fapi_validation_data('filters'); - - $value = $elements['#value']; - foreach($elements['#filters'] as $filter) { + + 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($elements['#name'], $value); + fapi_validation_register($element, $value); } -function fapi_validation_rules_execute($elements) { - $data = _fapi_validation_data('rule'); - - foreach($elements['#rules'] as $rule) { +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; } - $ret = $data[$rule]['callback']($elements['#value']); + + // 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) { - form_set_error($elements['#name'], t($data[$rule]['error_msg'], array('%field'=>$elements['#title']))); + $error = is_null($error_message) ? $data[$rule]['error_msg'] : $error_message; + form_set_error($element['#name'], t($error, array('%field' => $element['#title']))); } } } @@ -73,9 +128,9 @@ function fapi_validation_rules_execute($elements) { 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($data[$type]) || !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; @@ -87,27 +142,65 @@ function _fapi_validation_data($type, $refresh=NULL) { 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' => 'Use only numbers at %field.' + 'error_msg' => t('Use only numbers at %field.') ), 'alpha' => array( 'callback' => 'fapi_validation_rule_alpha', - 'error_msg' => 'Use only alpha characters at %field.' + 'error_msg' => t('Use only alpha characters at %field.') ), 'alpha_numeric' => array( 'callback' => 'fapi_validation_rule_alpha_numeric', - 'error_msg' => 'Use only alpha numerics characters at %field.' + 'error_msg' => t('Use only alpha numerics characters at %field.') ), 'email' => array( 'callback' => 'fapi_validation_rule_email', - 'error_msg' => 'The field %field not is a valid 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( @@ -116,6 +209,12 @@ function fapi_validation_fapi_validation_filters() { 'trim' => array( 'callback' => 'fapi_validation_filter_trim', ), + 'uppercase' => array( + 'callback' => 'fapi_validation_filter_uppercase', + ), + 'lowercase' => array( + 'callback' => 'fapi_validation_filter_lowercase', + ), ); } @@ -136,9 +235,63 @@ function fapi_validation_rule_alpha_numeric($value) { } function fapi_validation_rule_email($value) { - return valid_email_addess($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]; + } + elseif (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 */ @@ -149,4 +302,12 @@ function fapi_validation_filter_numeric($value) { function fapi_validation_filter_trim($value) { return trim($value); -} \ No newline at end of file +} + +function fapi_validation_filter_uppercase($value) { + return mb_strtoupper($value); +} + +function fapi_validation_filter_lowercase($value) { + return mb_strtolower($value); +}