diff --git a/src/Forms/Form.php b/src/Forms/Form.php index 96b9d1ee454..b31a10f6941 100644 --- a/src/Forms/Form.php +++ b/src/Forms/Form.php @@ -494,7 +494,8 @@ public function loadMessagesFrom($result) $owner = $this; } - $owner->setMessage($message['message'], $message['messageType'], $message['messageCast']); + $owner->appendMessage($message['message'], $message['messageType'], $message['messageCast']); + } return $this; } diff --git a/src/Forms/FormMessage.php b/src/Forms/FormMessage.php index 3fd5c56e242..756a31228af 100644 --- a/src/Forms/FormMessage.php +++ b/src/Forms/FormMessage.php @@ -31,7 +31,6 @@ trait FormMessage */ protected $messageCast = null; - /** * Returns the field message, used by form validation. * @@ -92,6 +91,30 @@ public function setMessage( return $this; } + /** + * Appends a message to the existing message if the types match, overrides if not + */ + public function appendMessage( + string $message, + string $messageType = ValidationResult::TYPE_ERROR, + string $messageCast = ValidationResult::CAST_TEXT, + ): static { + if (!empty($this->message)) { + $canBeMerged = ($messageType === $this->getMessageType() && $messageCast === $this->getMessageCast()); + // Checks that the exact message string is not already contained before appending + if ($canBeMerged && strpos($this->message, $message) === false) { + $message = sprintf( + '%s%s%s', + $this->message, + $messageType === ValidationResult::CAST_HTML ? '
' : PHP_EOL, + $message + ); + } + } + + return $this->setMessage($message, $messageType, $messageCast); + } + /** * Get casting helper for message cast, or null if not known * diff --git a/tests/php/Forms/FormTest.php b/tests/php/Forms/FormTest.php index eab888d68be..99351980136 100644 --- a/tests/php/Forms/FormTest.php +++ b/tests/php/Forms/FormTest.php @@ -1030,6 +1030,41 @@ public function testFieldMessageEscapeHtml() ); } + public function testFieldMessageAppend() + { + $form = $this->getStubForm(); + $form->appendMessage('Just a string'); + $parser = new CSSContentParser($form->forTemplate()); + $messageEls = $parser->getBySelector('#Form_Form_key1_Holder .message'); + $this->assertStringContainsString('Just a string', $messageEls[0]->asXML()); + + $form->appendMessage('Certainly different'); + $parser = new CSSContentParser($form->forTemplate()); + $messageEls = $parser->getBySelector('#Form_Form_key1_Holder .message'); + $this->assertStringContainsString('Just a string' . PHP_EOL . 'Certainly different', $messageEls[0]->asXML()); + + $form->appendMessage('Just a string'); + $parser = new CSSContentParser($form->forTemplate()); + $messageEls = $parser->getBySelector('#Form_Form_key1_Holder .message'); + $this->assertStringContainsString('Just a string' . PHP_EOL . 'Certainly different', $messageEls[0]->asXML()); + $this->assertEquals(1, substr_count($messageEls[0]->asXML(), 'Just a string'), 'Should not append if already present'); + + $form->appendMessage('This is a good message', ValidationResult::TYPE_GOOD); + $parser = new CSSContentParser($form->forTemplate()); + $messageEls = $parser->getBySelector('#Form_Form_key1_Holder .message'); + $this->assertStringContainsString('This is a good message', $messageEls[0]->asXML()); + $this->assertStringNotContainsString('Just a string', $messageEls[0]->asXML()); + $this->assertStringNotContainsString('Certainly different', $messageEls[0]->asXML()); + + $form->appendMessage('HTML is the future of the web', ValidationResult::TYPE_GOOD, ValidationResult::CAST_HTML); + $parser = new CSSContentParser($form->forTemplate()); + $messageEls = $parser->getBySelector('#Form_Form_key1_Holder .message'); + $this->assertStringContainsString('HTML is the future of the web', $messageEls[0]->asXML()); + $this->assertStringNotContainsString('This is a good message', $messageEls[0]->asXML()); + $this->assertStringNotContainsString('Just a string', $messageEls[0]->asXML()); + $this->assertStringNotContainsString('Certainly different', $messageEls[0]->asXML()); + } + public function testGetExtraFields() { $form = new FormTest\ExtraFieldsForm(