function FormValidator::doValidateForm

Same name and namespace in other branches
  1. 9 core/lib/Drupal/Core/Form/FormValidator.php \Drupal\Core\Form\FormValidator::doValidateForm()
  2. 8.9.x core/lib/Drupal/Core/Form/FormValidator.php \Drupal\Core\Form\FormValidator::doValidateForm()
  3. 10 core/lib/Drupal/Core/Form/FormValidator.php \Drupal\Core\Form\FormValidator::doValidateForm()

Performs validation on form elements.

First ensures required fields are completed, #maxlength is not exceeded, and selected options were in the list of options given to the user. Then calls user-defined validators.

Parameters

$elements: An associative array containing the structure of the form.

\Drupal\Core\Form\FormStateInterface $form_state: The current state of the form. The current user-submitted data is stored in $form_state->getValues(), though form validation functions are passed an explicit copy of the values for the sake of simplicity. Validation handlers can also $form_state to pass information on to submit handlers. For example: $form_state->set('data_for_submission', $data); This technique is useful when validation requires file parsing, web service requests, or other expensive requests that should not be repeated in the submission step.

$form_id: A unique string identifying the form for validation, submission, theming, and hook_form_alter functions. Is only present on the initial call to the method, which receives the entire form array as the $element, and not on recursive calls.

1 call to FormValidator::doValidateForm()
FormValidator::validateForm in core/lib/Drupal/Core/Form/FormValidator.php
Validates user-submitted form data in the $form_state.

File

core/lib/Drupal/Core/Form/FormValidator.php, line 230

Class

FormValidator
Provides validation of form submissions.

Namespace

Drupal\Core\Form

Code

protected function doValidateForm(&$elements, FormStateInterface &$form_state, $form_id = NULL) {
    // Recurse through all children, sorting the elements so that the order of
    // error messages displayed to the user matches the order of elements in
    // the form. Use a copy of $elements so that it is not modified by the
    // sorting itself.
    $elements_sorted = $elements;
    foreach (Element::children($elements_sorted, TRUE) as $key) {
        if (isset($elements[$key]) && $elements[$key]) {
            $this->doValidateForm($elements[$key], $form_state);
        }
    }
    // Validate the current input.
    if (!isset($elements['#validated']) || !$elements['#validated']) {
        // The following errors are always shown.
        if (isset($elements['#needs_validation'])) {
            $this->performRequiredValidation($elements, $form_state);
        }
        // Set up the limited validation for errors.
        $form_state->setLimitValidationErrors($this->determineLimitValidationErrors($form_state));
        // Make sure a value is passed when the field is required.
        if (isset($elements['#needs_validation']) && $elements['#required']) {
            // A simple call to empty() will not cut it here as some fields, like
            // checkboxes, can return a valid value of '0'. Instead, check the
            // length if it's a string, and the item count if it's an array.
            // An unchecked checkbox has a #value of integer 0, different than
            // string '0', which could be a valid value.
            $is_empty_multiple = is_countable($elements['#value']) && count($elements['#value']) == 0;
            $is_empty_string = is_string($elements['#value']) && mb_strlen(trim($elements['#value'])) == 0;
            $is_empty_value = $elements['#value'] === 0;
            $is_empty_null = is_null($elements['#value']);
            if ($is_empty_multiple || $is_empty_string || $is_empty_value || $is_empty_null) {
                // Flag this element as #required_but_empty to allow #element_validate
                // handlers to set a custom required error message, but without having
                // to re-implement the complex logic to figure out whether the field
                // value is empty.
                $elements['#required_but_empty'] = TRUE;
            }
        }
        // Call user-defined form level validators.
        if (isset($form_id)) {
            $this->executeValidateHandlers($elements, $form_state);
        }
        elseif (isset($elements['#element_validate'])) {
            foreach ($elements['#element_validate'] as $callback) {
                $complete_form =& $form_state->getCompleteForm();
                call_user_func_array($form_state->prepareCallback($callback), [
                    &$elements,
                    &$form_state,
                    &$complete_form,
                ]);
            }
        }
        // Ensure that a #required form error is thrown, regardless of whether
        // #element_validate handlers changed any properties. If $is_empty_value
        // is defined, then above #required validation code ran, so the other
        // variables are also known to be defined and we can test them again.
        if (isset($is_empty_value) && ($is_empty_multiple || $is_empty_string || $is_empty_value || $is_empty_null)) {
            if (isset($elements['#required_error'])) {
                $form_state->setError($elements, $elements['#required_error']);
            }
            elseif (isset($elements['#title'])) {
                $form_state->setError($elements, $this->t('@name field is required.', [
                    '@name' => $elements['#title'],
                ]));
            }
            else {
                $form_state->setError($elements);
            }
        }
        $elements['#validated'] = TRUE;
    }
    // Done validating this element, so turn off error suppression.
    // self::doValidateForm() turns it on again when starting on the next
    // element, if it's still appropriate to do so.
    $form_state->setLimitValidationErrors(NULL);
}

Buggy or inaccurate documentation? Please file an issue. Need support? Need help programming? Connect with the Drupal community.