From 6329397b284eef4a007d5c66f0369bffe4163fe6 Mon Sep 17 00:00:00 2001 From: Andrew Paxley Date: Wed, 4 Oct 2023 10:19:35 +1300 Subject: [PATCH] ENH allow stacked messages on FormMessage --- src/Forms/Form.php | 2 +- src/Forms/FormMessage.php | 49 +++++++++++++++++++++++++++++++++- tests/php/Forms/FormTest.php | 51 ++++++++++++++++++++++++++++++++++++ 3 files changed, 100 insertions(+), 2 deletions(-) diff --git a/src/Forms/Form.php b/src/Forms/Form.php index 96b9d1ee454..ffdee56e8a1 100644 --- a/src/Forms/Form.php +++ b/src/Forms/Form.php @@ -494,7 +494,7 @@ public function loadMessagesFrom($result) $owner = $this; } - $owner->setMessage($message['message'], $message['messageType'], $message['messageCast']); + $owner->appendMessage($message['message'], $message['messageType'], $message['messageCast'], true); } return $this; } diff --git a/src/Forms/FormMessage.php b/src/Forms/FormMessage.php index 3fd5c56e242..e9dece3f20b 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,54 @@ public function setMessage( return $this; } + /** + * Appends a message to the existing message if the types match, overrides if not + * + * @param string $message Message string + * @param string $messageType Message type + * @param string $messageCast + * @param bool $force Whether or not to override the existing message if appending is invalid + * @throws InvalidArgumentException + * @return $this + */ + public function appendMessage( + string $message, + string $messageType = ValidationResult::TYPE_ERROR, + string $messageCast = ValidationResult::CAST_TEXT, + bool $force = false, + ): static { + if (empty($this->message)) { + return $this->setMessage($message, $messageType, $messageCast); + } + $canBeMerged = ($messageType === $this->getMessageType() && $messageCast === $this->getMessageCast()); + + if (!$canBeMerged && $force === false) { + throw new InvalidArgumentException( + sprintf( + "Couldn't append message of type %s and cast %s to existing message of type %s and cast %s", + $messageType, $messageCast, $this->getMessageType(), $this->getMessageCast(), + ) + ); + } + + // Checks that the exact message string is not already contained before appending + $messageContainsString = strpos($this->message, $message) !== false; + if ($canBeMerged && $messageContainsString) { + return $this; + } + + if ($canBeMerged) { + $message = sprintf( + '%s%s%s', + $this->message, + $messageCast === 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..5defa0b449a 100644 --- a/tests/php/Forms/FormTest.php +++ b/tests/php/Forms/FormTest.php @@ -1030,6 +1030,57 @@ public function testFieldMessageEscapeHtml() ); } + public function testFieldMessageAppend() + { + $form = $this->getStubForm(); + $form->appendMessage('Just a string'); + $parser = new CSSContentParser($form->forTemplate()); + $messageEls = $parser->getBySelector('.message'); + $this->assertStringContainsString('Just a string', $messageEls[0]->asXML()); + + $form = $this->getStubForm(); + $form->appendMessage('Just a string'); + $form->appendMessage('Certainly different'); + $parser = new CSSContentParser($form->forTemplate()); + $messageEls = $parser->getBySelector('.message'); + $this->assertStringContainsString('Just a string', $messageEls[0]->asXML()); + $this->assertStringContainsString('Certainly different', $messageEls[0]->asXML()); + + $form = $this->getStubForm(); + $form->appendMessage('Just a string'); + $form->appendMessage('Certainly different'); + $form->appendMessage('Just a string'); + $parser = new CSSContentParser($form->forTemplate()); + $messageEls = $parser->getBySelector('.message'); + $this->assertStringContainsString('Just a string', $messageEls[0]->asXML()); + $this->assertStringContainsString('Certainly different', $messageEls[0]->asXML()); + $this->assertEquals(1, substr_count($messageEls[0]->asXML(), 'Just a string'), 'Should not append if already present'); + + } + + public function testFieldMessageAppendExceptions() + { + $form = $this->getStubForm(); + $form->appendMessage('Just a string'); + $this->expectException(\InvalidArgumentException::class); + $this->expectExceptionMessage("Couldn't append message of type good and cast text to existing message of type error and cast text"); + $form->appendMessage('This is a good message', ValidationResult::TYPE_GOOD); + + $form = $this->getStubForm(); + $form->appendMessage('This is a good message', ValidationResult::TYPE_GOOD); + $this->expectException(\InvalidArgumentException::class); + $this->expectExceptionMessage("Couldn't append message of type good and cast html to existing message of type good and cast text"); + $form->appendMessage('HTML is the future of the web', ValidationResult::TYPE_GOOD, ValidationResult::CAST_HTML); + + $form = $this->getStubForm(); + $form->appendMessage('This is a good message', ValidationResult::TYPE_GOOD); + $form->appendMessage('HTML is the future of the web', ValidationResult::TYPE_GOOD, ValidationResult::CAST_HTML, true); + $parser = new CSSContentParser($form->forTemplate()); + $messageEls = $parser->getBySelector('.message'); + $this->assertStringContainsString('HTML is the future of the web', $messageEls[0]->asXML()); + $this->assertStringNotContainsString('This is a good message', $messageEls[0]->asXML()); + } + public function testGetExtraFields() { $form = new FormTest\ExtraFieldsForm(