function ConfigFormBase::validateForm

Same name and namespace in other branches
  1. 11.x core/lib/Drupal/Core/Form/ConfigFormBase.php \Drupal\Core\Form\ConfigFormBase::validateForm()

Overrides FormBase::validateForm

6 calls to ConfigFormBase::validateForm()
BookSettingsForm::validateForm in core/modules/book/src/Form/BookSettingsForm.php
Form validation handler.
ImageToolkitForm::validateForm in core/modules/system/src/Form/ImageToolkitForm.php
Form validation handler.
LocaleSettingsForm::validateForm in core/modules/locale/src/Form/LocaleSettingsForm.php
Form validation handler.
NegotiationUrlForm::validateForm in core/modules/language/src/Form/NegotiationUrlForm.php
Form validation handler.
SiteInformationForm::validateForm in core/modules/system/src/Form/SiteInformationForm.php
Form validation handler.

... See full list

13 methods override ConfigFormBase::validateForm()
BookSettingsForm::validateForm in core/modules/book/src/Form/BookSettingsForm.php
Form validation handler.
FormTestArgumentsObject::validateForm in core/modules/system/tests/modules/form_test/src/FormTestArgumentsObject.php
Form validation handler.
FormTestControllerObject::validateForm in core/modules/system/tests/modules/form_test/src/FormTestControllerObject.php
Form validation handler.
FormTestObject::validateForm in core/modules/system/tests/modules/form_test/src/FormTestObject.php
Form validation handler.
FormTestServiceObject::validateForm in core/modules/system/tests/modules/form_test/src/FormTestServiceObject.php
Form validation handler.

... See full list

File

core/lib/Drupal/Core/Form/ConfigFormBase.php, line 203

Class

ConfigFormBase
Base class for implementing system configuration forms.

Namespace

Drupal\Core\Form

Code

public function validateForm(array &$form, FormStateInterface $form_state) {
  $map = $form_state->get(static::CONFIG_KEY_TO_FORM_ELEMENT_MAP) ?? [];
  foreach (array_keys($map) as $config_name) {
    $config = $this->configFactory()
      ->getEditable($config_name);
    static::copyFormValuesToConfig($config, $form_state, $form);
    $typed_config = $this->typedConfigManager()
      ->createFromNameAndData($config_name, $config->getRawData());
    $violations = $typed_config->validate();
    // Rather than immediately applying all violation messages to the
    // corresponding form elements, first collect the messages. The structure
    // of the form may cause a single form element to contain multiple config
    // property paths thanks to `type: sequence`. Common example: a <textarea>
    // with one line per sequence item.
    // @see \Drupal\Core\Config\Schema\Sequence
    // @see \Drupal\Core\Config\Schema\SequenceDataDefinition
    $violations_per_form_element = [];
    /** @var \Symfony\Component\Validator\ConstraintViolationInterface $violation */
    foreach ($violations as $violation) {
      $property_path = $violation->getPropertyPath();
      // Default to index 0.
      $index = 0;
      // Detect if this is a sequence item property path, and if so, attempt
      // to fall back to the containing sequence's property path.
      if (!isset($map[$config_name][$property_path]) && preg_match("/.*\\.(\\d+)\$/", $property_path, $matches) === 1) {
        $index = intval($matches[1]);
        // The property path as known in the config key-to-form element map
        // will not have the sequence index in it.
        $property_path = rtrim($property_path, '0123456789.');
      }
      if (isset($map[$config_name][$property_path])) {
        $config_target = ConfigTarget::fromForm($map[$config_name][$property_path], $form);
        $form_element_name = implode('][', $config_target->elementParents);
      }
      else {
        // We cannot determine where to place the violation. The only option
        // is the entire form.
        $form_element_name = '';
      }
      $violations_per_form_element[$form_element_name][$index] = $violation;
    }
    // Now that we know how many constraint violation messages exist per form
    // element, set them. This is crucial because FormState::setErrorByName()
    // only allows a single validation error message per form element.
    // @see \Drupal\Core\Form\FormState::setErrorByName()
    foreach ($violations_per_form_element as $form_element_name => $violations) {
      // When only a single message exists, just set it.
      if (count($violations) === 1) {
        $form_state->setErrorByName($form_element_name, reset($violations)->getMessage());
        continue;
      }
      // However, if multiple exist, that implies it's a single form element
      // containing a `type: sequence`.
      $form_state->setErrorByName($form_element_name, $this->formatMultipleViolationsMessage($form_element_name, $violations));
    }
  }
}

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