diff --git a/core/lib/Drupal/Core/Form/ConfigFormBase.php b/core/lib/Drupal/Core/Form/ConfigFormBase.php index b9af2323fc6..7a200baf86d 100644 --- a/core/lib/Drupal/Core/Form/ConfigFormBase.php +++ b/core/lib/Drupal/Core/Form/ConfigFormBase.php @@ -137,7 +137,6 @@ abstract class ConfigFormBase extends FormBase { if (is_string($target)) { $target = ConfigTarget::fromString($target); } - $target->elementName = $element['#name']; $target->elementParents = $element['#parents']; $map[$target->configName . ':' . $target->propertyPath] = $target; $form_state->set(static::CONFIG_KEY_TO_FORM_ELEMENT_MAP, $map); @@ -192,7 +191,20 @@ abstract class ConfigFormBase extends FormBase { // will not have the sequence index in it. $property_path = rtrim($property_path, '0123456789.'); } - $form_element_name = $map["$config_name:$property_path"]->elementName; + + if ($property_path === '') { + // There is a map to a non-existing config key. Try to work backwards. + $property_path = $violation->getParameters()['@key'] ?? ''; + } + + if (isset($map["$config_name:$property_path"])) { + $form_element_name = implode('][', $map["$config_name:$property_path"]->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; } diff --git a/core/lib/Drupal/Core/Form/ConfigTarget.php b/core/lib/Drupal/Core/Form/ConfigTarget.php index 45eee5799df..ddf7bc50007 100644 --- a/core/lib/Drupal/Core/Form/ConfigTarget.php +++ b/core/lib/Drupal/Core/Form/ConfigTarget.php @@ -9,18 +9,6 @@ namespace Drupal\Core\Form; */ final class ConfigTarget { - /** - * The name of the form element which maps to this config property. - * - * @var string - * - * @see \Drupal\Core\Form\ConfigFormBase::storeConfigKeyToFormElementMap() - * - * @internal - * This property is for internal use only. - */ - public string $elementName; - /** * The parents of the form element which maps to this config property. * diff --git a/core/modules/system/tests/modules/form_test/config/schema/form_test.schema.yml b/core/modules/system/tests/modules/form_test/config/schema/form_test.schema.yml index 9af17cdd860..dccdc5bc936 100644 --- a/core/modules/system/tests/modules/form_test/config/schema/form_test.schema.yml +++ b/core/modules/system/tests/modules/form_test/config/schema/form_test.schema.yml @@ -5,3 +5,9 @@ form_test.object: bananas: type: string label: 'Bananas' + favorite_vegetable: + type: required_label + label: 'Favorite vegetable' + nemesis_vegetable: + type: required_label + label: 'Nemesis vegetable' diff --git a/core/modules/system/tests/modules/form_test/form_test.routing.yml b/core/modules/system/tests/modules/form_test/form_test.routing.yml index 9c971a727e1..fd4db9da386 100644 --- a/core/modules/system/tests/modules/form_test/form_test.routing.yml +++ b/core/modules/system/tests/modules/form_test/form_test.routing.yml @@ -528,3 +528,17 @@ form_test.javascript_states_form: _form: '\Drupal\form_test\Form\JavascriptStatesForm' requirements: _access: 'TRUE' + +form_test.tree_config_target: + path: '/form-test/tree-config-target' + defaults: + _form: '\Drupal\form_test\Form\TreeConfigTargetForm' + requirements: + _access: 'TRUE' + +form_test.incorrect_config_target: + path: '/form-test/incorrect-config-target' + defaults: + _form: '\Drupal\form_test\Form\IncorrectConfigTargetForm' + requirements: + _access: 'TRUE' diff --git a/core/modules/system/tests/modules/form_test/src/Form/IncorrectConfigTargetForm.php b/core/modules/system/tests/modules/form_test/src/Form/IncorrectConfigTargetForm.php new file mode 100644 index 00000000000..5296edb9cb8 --- /dev/null +++ b/core/modules/system/tests/modules/form_test/src/Form/IncorrectConfigTargetForm.php @@ -0,0 +1,36 @@ + 'textfield', + '#title' => t('Missing key'), + '#config_target' => 'form_test.object:does_not_exist', + ]; + return parent::buildForm($form, $form_state); + } + +} diff --git a/core/modules/system/tests/modules/form_test/src/Form/TreeConfigTargetForm.php b/core/modules/system/tests/modules/form_test/src/Form/TreeConfigTargetForm.php new file mode 100644 index 00000000000..502fbd8f713 --- /dev/null +++ b/core/modules/system/tests/modules/form_test/src/Form/TreeConfigTargetForm.php @@ -0,0 +1,49 @@ + 'details', + '#tree' => TRUE, + '#input' => TRUE, + '#title' => t('Vegetable preferences'), + ]; + $form['vegetables']['favorite'] = [ + '#type' => 'textfield', + '#title' => t('Favorite'), + '#default_value' => 'Potato', + '#config_target' => 'form_test.object:favorite_vegetable', + ]; + $form['vegetables']['nemesis'] = [ + '#type' => 'textfield', + '#title' => t('Nemesis'), + '#default_value' => 'Broccoli', + '#config_target' => 'form_test.object:nemesis_vegetable', + ]; + return parent::buildForm($form, $form_state); + } + +} diff --git a/core/modules/system/tests/src/Functional/Form/ConfigTargetTest.php b/core/modules/system/tests/src/Functional/Form/ConfigTargetTest.php new file mode 100644 index 00000000000..5ab7a735956 --- /dev/null +++ b/core/modules/system/tests/src/Functional/Form/ConfigTargetTest.php @@ -0,0 +1,50 @@ +drupalGet('/form-test/tree-config-target'); + $page = $this->getSession()->getPage(); + $page->fillField('Favorite', ''); + $page->pressButton('Save configuration'); + $assert_session = $this->assertSession(); + $assert_session->statusMessageContains('This value should not be blank.', 'error'); + $assert_session->elementAttributeExists('named', ['field', 'Favorite'], 'aria-invalid'); + $assert_session->elementAttributeNotExists('named', ['field', 'Nemesis'], 'aria-invalid'); + } + + /** + * Tests #config_target with an incorrect key. + */ + public function testIncorrectKey(): void { + $this->drupalGet('/form-test/incorrect-config-target'); + $page = $this->getSession()->getPage(); + $page->pressButton('Save configuration'); + $assert_session = $this->assertSession(); + $assert_session->statusMessageContains('\'does_not_exist\' is not a supported key.', 'error'); + $assert_session->elementAttributeExists('named', ['field', 'Missing key'], 'aria-invalid'); + } + +}