From b7540532dcbf5988ad69525fad64f5a5f8aae60f Mon Sep 17 00:00:00 2001 From: Alex Pott <alex.a.pott@googlemail.com> Date: Tue, 14 Nov 2023 22:46:13 +0000 Subject: [PATCH] Issue #3401186 by Wim Leers, alexpott: Follow-up for #3382510: Throw \LogicException when >1 #config_target in the same form targets the same property path --- core/lib/Drupal/Core/Form/ConfigFormBase.php | 8 ++++ .../Tests/Core/Form/ConfigTargetTest.php | 44 +++++++++++++++++++ 2 files changed, 52 insertions(+) diff --git a/core/lib/Drupal/Core/Form/ConfigFormBase.php b/core/lib/Drupal/Core/Form/ConfigFormBase.php index 0383bfe443a9..daf6f409b20a 100644 --- a/core/lib/Drupal/Core/Form/ConfigFormBase.php +++ b/core/lib/Drupal/Core/Form/ConfigFormBase.php @@ -136,6 +136,14 @@ public function storeConfigKeyToFormElementMap(array $element, FormStateInterfac $target = ConfigTarget::fromString($target); } foreach ($target->propertyPaths as $property_path) { + if (isset($map[$target->configName][$property_path])) { + throw new \LogicException(sprintf('Two #config_targets both target "%s" in the "%s" config: `%s` and `%s`.', + $property_path, + $target->configName, + '$form[\'' . implode("']['", $map[$target->configName][$property_path]) . '\']', + '$form[\'' . implode("']['", $element['#array_parents']) . '\']', + )); + } $map[$target->configName][$property_path] = $element['#array_parents']; } $form_state->set(static::CONFIG_KEY_TO_FORM_ELEMENT_MAP, $map); diff --git a/core/tests/Drupal/Tests/Core/Form/ConfigTargetTest.php b/core/tests/Drupal/Tests/Core/Form/ConfigTargetTest.php index 01de877eff6d..3932d14552a0 100644 --- a/core/tests/Drupal/Tests/Core/Form/ConfigTargetTest.php +++ b/core/tests/Drupal/Tests/Core/Form/ConfigTargetTest.php @@ -3,9 +3,14 @@ namespace Drupal\Tests\Core\Form; use Drupal\Core\Config\Config; +use Drupal\Core\Config\ConfigFactoryInterface; +use Drupal\Core\Config\TypedConfigManagerInterface; +use Drupal\Core\Form\ConfigFormBase; use Drupal\Core\Form\ConfigTarget; use Drupal\Core\Form\ToConfig; use Drupal\Core\Form\FormStateInterface; +use Drupal\Core\Form\FormState; +use Drupal\Core\Form\RedundantEditableConfigNamesTrait; use Drupal\Tests\UnitTestCase; use Prophecy\Argument; @@ -15,6 +20,45 @@ */ class ConfigTargetTest extends UnitTestCase { + /** + * @covers \Drupal\Core\Form\ConfigFormBase::storeConfigKeyToFormElementMap + */ + public function testDuplicateTargetsNotAllowed(): void { + $form = [ + 'test' => [ + '#type' => 'text', + '#default_value' => 'A test', + '#config_target' => new ConfigTarget('system.site', 'admin_compact_mode', 'intval', 'boolval'), + '#name' => 'test', + '#array_parents' => ['test'], + ], + 'duplicate' => [ + '#type' => 'text', + '#config_target' => new ConfigTarget('system.site', 'admin_compact_mode', 'intval', 'boolval'), + '#name' => 'duplicate', + '#array_parents' => ['duplicate'], + ], + ]; + + $test_form = new class( + $this->prophesize(ConfigFactoryInterface::class)->reveal(), + $this->prophesize(TypedConfigManagerInterface::class)->reveal(), + ) extends ConfigFormBase { + use RedundantEditableConfigNamesTrait; + + public function getFormId() { + return 'test'; + } + + }; + $form_state = new FormState(); + $test_form->storeConfigKeyToFormElementMap($form['test'], $form_state); + + $this->expectException(\LogicException::class); + $this->expectExceptionMessage('Two #config_targets both target "admin_compact_mode" in the "system.site" config: `$form[\'test\']` and `$form[\'duplicate\']`.'); + $test_form->storeConfigKeyToFormElementMap($form['duplicate'], $form_state); + } + /** * @covers ::fromForm * @covers ::fromString -- GitLab