From 55849506c4c2d62c673caa875d0082ad77eade62 Mon Sep 17 00:00:00 2001 From: Lee Rowlands Date: Fri, 12 Apr 2024 07:51:51 +1000 Subject: [PATCH] Issue #3422872 by kunal.sachdev, Wim Leers: Add validation constraints to contact.settings (cherry picked from commit c41bea2d63080f262f79d5cf993db0558b003453) --- .../Core/Config/Schema/SchemaCheckTrait.php | 7 ++++ .../contact/config/schema/contact.schema.yml | 19 ++++++++-- core/modules/contact/contact.post_update.php | 12 +++++++ .../migrations/d6_contact_settings.yml | 5 +++ .../migrations/d7_contact_settings.yml | 5 +++ .../src/Controller/ContactController.php | 10 ++++-- .../src/Functional/ContactSitewideTest.php | 2 +- .../Functional/Update/NullDefaultFormTest.php | 36 +++++++++++++++++++ 8 files changed, 90 insertions(+), 6 deletions(-) create mode 100644 core/modules/contact/tests/src/Functional/Update/NullDefaultFormTest.php diff --git a/core/lib/Drupal/Core/Config/Schema/SchemaCheckTrait.php b/core/lib/Drupal/Core/Config/Schema/SchemaCheckTrait.php index f2974e3a636..3adb9075ad6 100644 --- a/core/lib/Drupal/Core/Config/Schema/SchemaCheckTrait.php +++ b/core/lib/Drupal/Core/Config/Schema/SchemaCheckTrait.php @@ -52,6 +52,13 @@ trait SchemaCheckTrait { 'This value should not be blank.', ], ], + 'contact.settings' => [ + // @todo Simple config cannot have dependencies on any other config. + // Remove this in https://www.drupal.org/project/drupal/issues/3425992. + 'default_form' => [ + "The 'contact.form.feedback' config does not exist.", + ], + ], 'editor.editor.*' => [ // @todo Fix stream wrappers not being available early enough in // https://www.drupal.org/project/drupal/issues/3416735 diff --git a/core/modules/contact/config/schema/contact.schema.yml b/core/modules/contact/config/schema/contact.schema.yml index 4357a426219..4617e47e760 100644 --- a/core/modules/contact/config/schema/contact.schema.yml +++ b/core/modules/contact/config/schema/contact.schema.yml @@ -37,20 +37,35 @@ contact.form.*: contact.settings: type: config_object label: 'Contact settings' + constraints: + FullyValidatable: ~ mapping: default_form: type: string label: 'Default form identifier' + # It is possible to not configure a default form. + # @see \Drupal\contact\ContactFormEditForm::save() + nullable: true + constraints: + ConfigExists: + prefix: contact.form. flood: + # @see \Drupal\Core\Flood\FloodInterface::isAllowed() type: mapping label: 'Flood control' mapping: limit: type: integer - label: 'Limit' + label: 'Limit (messages per interval)' + constraints: + Range: + min: 1 interval: type: integer - label: 'Interval' + label: 'Interval (seconds)' + constraints: + Range: + min: 1 user_default_enabled: type: boolean label: 'Personal contact form enabled by default' diff --git a/core/modules/contact/contact.post_update.php b/core/modules/contact/contact.post_update.php index fcb12edb46a..ebdc0d7d0f0 100644 --- a/core/modules/contact/contact.post_update.php +++ b/core/modules/contact/contact.post_update.php @@ -13,3 +13,15 @@ function contact_removed_post_updates() { 'contact_post_update_add_message_redirect_field_to_contact_form' => '9.0.0', ]; } + +/** + * Converts empty `default_form` in settings to NULL. + */ +function contact_post_update_set_empty_default_form_to_null(): void { + $config = \Drupal::configFactory()->getEditable('contact.settings'); + // 'default_form' in 'contact.settings' config must be stored as NULL if it + // is empty. + if ($config->get('default_form') === '') { + $config->set('default_form', NULL)->save(); + } +} diff --git a/core/modules/contact/migrations/d6_contact_settings.yml b/core/modules/contact/migrations/d6_contact_settings.yml index a91a9fb1bbd..35e64f5591f 100644 --- a/core/modules/contact/migrations/d6_contact_settings.yml +++ b/core/modules/contact/migrations/d6_contact_settings.yml @@ -11,6 +11,11 @@ source: process: user_default_enabled: contact_default_status 'flood/limit': contact_hourly_threshold + 'flood/interval': + plugin: default_value + # It was defaulted to 3600 in D6. + # @see https://api.drupal.org/api/drupal/includes%21common.inc/function/flood_is_allowed/6.x + default_value: 3600 default_form: plugin: migration_lookup migration: contact_category diff --git a/core/modules/contact/migrations/d7_contact_settings.yml b/core/modules/contact/migrations/d7_contact_settings.yml index 282064630c3..166e9c307a2 100644 --- a/core/modules/contact/migrations/d7_contact_settings.yml +++ b/core/modules/contact/migrations/d7_contact_settings.yml @@ -11,6 +11,11 @@ source: process: user_default_enabled: contact_default_status 'flood/limit': contact_threshold_limit + 'flood/interval': + plugin: default_value + # It was defaulted to 3600 in D7. + # @see https://api.drupal.org/api/drupal/includes%21common.inc/function/flood_is_allowed/7.x + default_value: 3600 default_form: plugin: migration_lookup migration: contact_category diff --git a/core/modules/contact/src/Controller/ContactController.php b/core/modules/contact/src/Controller/ContactController.php index 79ac3f053a0..67b1b98c89b 100644 --- a/core/modules/contact/src/Controller/ContactController.php +++ b/core/modules/contact/src/Controller/ContactController.php @@ -50,9 +50,13 @@ class ContactController extends ControllerBase { // Use the default form if no form has been passed. if (empty($contact_form)) { - $contact_form = $this->entityTypeManager() - ->getStorage('contact_form') - ->load($config->get('default_form')); + $default_form = $config->get('default_form'); + // Load the default form, if configured. + if (!is_null($default_form)) { + $contact_form = $this->entityTypeManager() + ->getStorage('contact_form') + ->load($default_form); + } // If there are no forms, do not display the form. if (empty($contact_form)) { if ($this->currentUser()->hasPermission('administer contact forms')) { diff --git a/core/modules/contact/tests/src/Functional/ContactSitewideTest.php b/core/modules/contact/tests/src/Functional/ContactSitewideTest.php index fa1c94abf21..4b70da6490b 100644 --- a/core/modules/contact/tests/src/Functional/ContactSitewideTest.php +++ b/core/modules/contact/tests/src/Functional/ContactSitewideTest.php @@ -256,7 +256,7 @@ class ContactSitewideTest extends BrowserTestBase { // Test contact form with no default form selected. $this->config('contact.settings') - ->set('default_form', '') + ->set('default_form', NULL) ->save(); $this->drupalGet('contact'); $this->assertSession()->statusCodeEquals(404); diff --git a/core/modules/contact/tests/src/Functional/Update/NullDefaultFormTest.php b/core/modules/contact/tests/src/Functional/Update/NullDefaultFormTest.php new file mode 100644 index 00000000000..4f825d831c2 --- /dev/null +++ b/core/modules/contact/tests/src/Functional/Update/NullDefaultFormTest.php @@ -0,0 +1,36 @@ +databaseDumpFiles = [ + __DIR__ . '/../../../../../system/tests/fixtures/update/drupal-9.4.0.filled.standard.php.gz', + ]; + } + + /** + * Tests the upgrade path for updating empty 'default_form' to NULL. + */ + public function testRunUpdates(): void { + $this->config('contact.settings')->set('default_form', '')->save(); + $this->assertSame('', $this->config('contact.settings')->get('default_form')); + $this->runUpdates(); + $this->assertNull($this->config('contact.settings')->get('default_form')); + } + +}