function ConfigFormBase::validateForm
Same name in other branches
- 10 core/lib/Drupal/Core/Form/ConfigFormBase.php \Drupal\Core\Form\ConfigFormBase::validateForm()
Overrides FormBase::validateForm
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.
File
-
core/
lib/ Drupal/ Core/ Form/ ConfigFormBase.php, line 201
Class
- ConfigFormBase
- Base class for implementing system configuration forms.
Namespace
Drupal\Core\FormCode
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.