fapi_validation.module in Form API Validation 8
Same filename and directory in other branches
Form API validation module
File
fapi_validation.moduleView source
<?php
/**
* @file Form API validation module
*/
use Drupal\Core\Form\FormStateInterface;
// Load filters and validtors
module_load_include('inc', 'fapi_validation', 'src/fapi_filters/fapi_filters');
module_load_include('inc', 'fapi_validation', 'src/fapi_validators/fapi_validators');
/**
* Implements hook_element_info_alter().
*
* PURPOSE: Add fapi validation element processing to all form elements.
*/
function fapi_validation_element_info_alter(array &$info) {
// Loop through all form element types and only hit input variants.
foreach ($info as $type_name => $type_info) {
if (!empty($type_info['#input'])) {
// Processes the form element on form creation.
$info[$type_name]['#process'][] = 'fapi_validation_element_process';
}
}
}
/**
* Process element validators and filters.
*
* Allows both #validators and #filters values. Run on form rendering. Only adds filters and validators on form submission
* if the values have been provided. Saves us from appending a check to every single item on submission.
*/
function fapi_validation_element_process($element, FormStateInterface $form_state) {
if (!empty($element['#filters'])) {
// @TODO: Determine how nescessary this step is. Seems unnescessarily complex given the If below doesn't have it.
// Check if element validate is already empty, and if so make variable for merging in values an empty array.
$element_validate = empty($element['#element_validate']) ? array() : $element['#element_validate'];
$element['#element_validate'] = array_merge(array(
'fapi_validate_element_filter',
), $element_validate);
}
if (!empty($element['#validators'])) {
$element['#element_validate'][] = 'fapi_validate_element_validate';
}
return $element;
}
/**
* Run element filter callbacks.
*/
function fapi_validate_element_filter(&$element, FormStateInterface $form_state) {
fapi_validation_filters_execute($element, $form_state);
}
/**
* Run element validation callbacks.
*/
function fapi_validate_element_validate(&$element, FormStateInterface $form_state) {
fapi_validation_validators_execute($element, $form_state);
}
/**
* Function for executing all filters
*/
function fapi_validation_filters_execute(&$element, FormStateInterface $form_state) {
$available_filters = _fapi_validation_data('filters');
// If the element has no value, there is nothing to filter.
if (!isset($element['#value'])) {
return;
}
// Loop through all passed in filters from form element.
foreach ($element['#filters'] as $element_filter) {
// Make sure filter passed is available as a recognized filter by FAPI validation.
if ($element_filter && !empty($available_filters[$element_filter])) {
// Adjust element value based on calling the appropriate data filter callback.
$element['#value'] = $available_filters[$element_filter]['callback']($element['#value']);
$form_state
->setValue($element['#name'], $element['#value']);
}
else {
drupal_set_message(t('Form item filter array with wrong structure on %field.', array(
'%field' => $element['#name'],
)), 'error');
}
}
}
/**
* Function for executing all validators
*/
function fapi_validation_validators_execute(&$element, FormStateInterface $form_state) {
// If element is empty and not required, by pass rule validation
if (!$element['#required'] && empty($element['#value'])) {
return;
}
//establish errors array
$errors = array();
// Load Validators.
$validators = _fapi_validation_data('validators');
// Loop through all validators on the field
foreach ($element['#validators'] as $validator) {
// Set error message and error callback all to NULL.
$error_message = $error_callback = NULL;
// Some Validators can be an array.
if (is_array($validator)) {
if (!isset($validators['validator'])) {
drupal_set_message(t('Validator array with wrong structure on %field.', array(
'%field' => $element['#name'],
)), 'error');
continue;
}
if (isset($validator['error'])) {
$error_message = $validator['error'];
}
if (isset($validator['error_callback'])) {
$error_callback = $validator['error_callback'];
}
$validator = $validator['validator'];
}
// Break rule into various aspects, incase it's all passed as one string?
preg_match('/^(.*?)(\\[(.*)\\])?$/', $validator, $rs);
$validator = $rs[1];
// Check if rule exists
if (!isset($validators[$validator])) {
drupal_set_message(t('Validator %validator not found!', array(
'%validator' => $validator,
)), 'error');
continue;
}
//Get element value
$params = array(
$element['#value'],
);
// Parsing parameters from validator input
// @TODO: Review that this is the best way to do this... I'd prefer this was passed as an array value.
if (isset($rs[3])) {
if ($validator == 'regexp') {
$params[] = array(
$rs[3],
);
}
else {
$params[] = preg_split('/ *, */', $rs[3]);
}
}
// Call the validator function, pass it the $element and $form_state values.
$validator_success = call_user_func_array($validators[$validator]['callback'], array(
$element['#value'],
$form_state,
));
if (!$validator_success) {
if (!is_null($error_callback)) {
$error_params = array(
$validator,
$params,
$element,
$form_state,
);
$errors[] = call_user_func_array($error_callback, $error_params);
}
else {
$error = is_null($error_message) ? $validators[$validator]['error_msg'] : $error_message;
$error = str_replace('%field', $element['#title'], $error
->render());
$errors[] = t($error, array(
'%field' => $element['#title'],
));
}
}
}
if (!empty($errors)) {
$form_state
->setError($element, implode(' ', $errors));
}
}
/**
* Helper function that finds all invocations of hooks.
*
* @param string $validation_type
* @return mixed
*/
function _fapi_validation_data($validation_type) {
static $data = array();
$fapi_validation_type_hook_implementations = Drupal::moduleHandler()
->invokeAll('fapi_validation_' . $validation_type);
if (isset($fapi_validation_type_hook_implementations) && is_array($fapi_validation_type_hook_implementations)) {
foreach ($fapi_validation_type_hook_implementations as $validation_name => $validation_callback) {
$data[$validation_type][$validation_name] = $validation_callback;
}
}
return $data[$validation_type];
}
Functions
Name | Description |
---|---|
fapi_validate_element_filter | Run element filter callbacks. |
fapi_validate_element_validate | Run element validation callbacks. |
fapi_validation_element_info_alter | Implements hook_element_info_alter(). |
fapi_validation_element_process | Process element validators and filters. |
fapi_validation_filters_execute | Function for executing all filters |
fapi_validation_validators_execute | Function for executing all validators |
_fapi_validation_data | Helper function that finds all invocations of hooks. |