From 4a54033d1eefc74e01024859fe22a2de1f7c6fc3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C2=A0Ja=CC=81n=20Mikla=CC=81s=CC=8C?= Date: Wed, 7 Aug 2024 10:52:35 +0200 Subject: [PATCH] Correctly show error message next to the field when the same form is rendered multiple times Every form block now has unique ID (even the same block in two different form has different ID) used for rendering error messages. Before this, when the same form was rendered on a page multiple times, error messages of custom fields were always shown on the last rendered form, even if the first one was submitted. [MAILPOET-6182] --- .../lib/Form/Block/BlockRendererHelper.php | 24 +++++++++++++++---- mailpoet/lib/Form/Block/Checkbox.php | 2 +- mailpoet/lib/Form/Block/Date.php | 2 +- mailpoet/lib/Form/Block/Radio.php | 2 +- mailpoet/lib/Form/Block/Segment.php | 2 +- mailpoet/lib/Form/Block/Select.php | 4 +++- mailpoet/lib/Form/Block/Text.php | 4 +++- mailpoet/lib/Form/Block/Textarea.php | 4 +++- mailpoet/lib/Form/BlocksRenderer.php | 10 +++++--- 9 files changed, 39 insertions(+), 15 deletions(-) diff --git a/mailpoet/lib/Form/Block/BlockRendererHelper.php b/mailpoet/lib/Form/Block/BlockRendererHelper.php index 14d608b9e6..0ec509ecee 100644 --- a/mailpoet/lib/Form/Block/BlockRendererHelper.php +++ b/mailpoet/lib/Form/Block/BlockRendererHelper.php @@ -27,7 +27,9 @@ class BlockRendererHelper { } public function getInputValidation(array $block, array $extraRules = [], ?int $formId = null): string { - $rules = []; + $rules = [ + 'errors-container' => '.' . $this->getErrorsContainerClass($block, $formId), + ]; $blockId = $this->wp->escAttr($block['id']); if ($blockId === 'email') { @@ -52,13 +54,11 @@ class BlockRendererHelper { $rules['required'] = true; $rules['mincheck'] = 1; $rules['group'] = $blockId; - $rules['errors-container'] = '.mailpoet_error_' . $blockId . '_' . $formId; $rules['required-message'] = __('Please select a list.', 'mailpoet'); } if (!empty($block['params']['required'])) { $rules['required'] = true; - $rules['errors-container'] = '.mailpoet_error_' . $blockId . '_' . $formId; $rules['required-message'] = __('This field is required.', 'mailpoet'); } @@ -74,13 +74,11 @@ class BlockRendererHelper { if (in_array($block['type'], ['radio', 'checkbox'])) { $rules['group'] = 'custom_field_' . $blockId; - $rules['errors-container'] = '.mailpoet_error_' . $blockId . ($formId ? '_' . $formId : ''); $rules['required-message'] = __('This field is required.', 'mailpoet'); } if ($block['type'] === 'date') { $rules['group'] = 'custom_field_' . $blockId; - $rules['errors-container'] = '.mailpoet_error_' . $blockId . ($formId ? '_' . $formId : ''); } $validation = []; @@ -267,6 +265,22 @@ class BlockRendererHelper { }, $value); } + public function renderErrorsContainer(array $block = [], ?int $formId = null): string { + $errorContainerClass = $this->getErrorsContainerClass($block, $formId); + return ''; + } + + private function getErrorsContainerClass(array $block = [], ?int $formId = null): string { + $validationId = $block['validation_id'] ?? null; + if (!$validationId) { + $validationId = $this->wp->escAttr($block['id']); + if ($formId) { + $validationId .= '_' . $formId; + } + } + return 'mailpoet_error_' . $validationId; + } + private function translateValidationErrorMessage(string $validate): string { switch ($validate) { case 'email': diff --git a/mailpoet/lib/Form/Block/Checkbox.php b/mailpoet/lib/Form/Block/Checkbox.php index 7e9764983c..25dd3fd290 100644 --- a/mailpoet/lib/Form/Block/Checkbox.php +++ b/mailpoet/lib/Form/Block/Checkbox.php @@ -74,7 +74,7 @@ class Checkbox { $html .= ''; - $html .= ''; + $html .= $this->rendererHelper->renderErrorsContainer($block, $formId); return $this->wrapper->render($block, $html); } diff --git a/mailpoet/lib/Form/Block/Date.php b/mailpoet/lib/Form/Block/Date.php index 2c0a09aada..a8119603e3 100644 --- a/mailpoet/lib/Form/Block/Date.php +++ b/mailpoet/lib/Form/Block/Date.php @@ -92,7 +92,7 @@ class Date { } } - $html .= ''; + $html .= $this->rendererHelper->renderErrorsContainer($block, $formId); return $html; } diff --git a/mailpoet/lib/Form/Block/Radio.php b/mailpoet/lib/Form/Block/Radio.php index 768afb6920..dc96619398 100644 --- a/mailpoet/lib/Form/Block/Radio.php +++ b/mailpoet/lib/Form/Block/Radio.php @@ -76,7 +76,7 @@ class Radio { $html .= ''; - $html .= ''; + $html .= $this->rendererHelper->renderErrorsContainer($block, $formId); return $this->wrapper->render($block, $html); } diff --git a/mailpoet/lib/Form/Block/Segment.php b/mailpoet/lib/Form/Block/Segment.php index e0aa18f73f..dc76648710 100644 --- a/mailpoet/lib/Form/Block/Segment.php +++ b/mailpoet/lib/Form/Block/Segment.php @@ -69,7 +69,7 @@ class Segment { $html .= ''; } - $html .= ''; + $html .= $this->rendererHelper->renderErrorsContainer($block, $formId); // End fieldset around checkboxes $html .= ''; diff --git a/mailpoet/lib/Form/Block/Select.php b/mailpoet/lib/Form/Block/Select.php index e7539900f7..8c06a25218 100644 --- a/mailpoet/lib/Form/Block/Select.php +++ b/mailpoet/lib/Form/Block/Select.php @@ -32,7 +32,7 @@ class Select { $this->blockStylesRenderer = $blockStylesRenderer; } - public function render(array $block, array $formSettings): string { + public function render(array $block, array $formSettings, ?int $formId = null): string { $html = ''; $fieldName = 'data[' . $this->rendererHelper->getFieldName($block) . ']'; @@ -94,6 +94,8 @@ class Select { } $html .= ''; + $html .= $this->rendererHelper->renderErrorsContainer($block, $formId); + return $this->wrapper->render($block, $html); } } diff --git a/mailpoet/lib/Form/Block/Text.php b/mailpoet/lib/Form/Block/Text.php index 2bdf5092e3..1b1528acec 100644 --- a/mailpoet/lib/Form/Block/Text.php +++ b/mailpoet/lib/Form/Block/Text.php @@ -31,7 +31,7 @@ class Text { $this->wp = $wp; } - public function render(array $block, array $formSettings): string { + public function render(array $block, array $formSettings, ?int $formId = null): string { $type = 'text'; $automationId = ' '; $id = ''; @@ -86,6 +86,8 @@ class Text { $html .= '/>'; + $html .= $this->rendererHelper->renderErrorsContainer($block, $formId); + return $this->wrapper->render($block, $html); } } diff --git a/mailpoet/lib/Form/Block/Textarea.php b/mailpoet/lib/Form/Block/Textarea.php index c8be5205ef..2b4c7ccddc 100644 --- a/mailpoet/lib/Form/Block/Textarea.php +++ b/mailpoet/lib/Form/Block/Textarea.php @@ -31,7 +31,7 @@ class Textarea { $this->wp = $wp; } - public function render(array $block, array $formSettings): string { + public function render(array $block, array $formSettings, ?int $formId = null): string { $html = ''; $name = $this->rendererHelper->getFieldName($block); $styles = $this->inputStylesRenderer->renderForTextInput($block['styles'] ?? [], $formSettings); @@ -57,6 +57,8 @@ class Textarea { $html .= '>' . $this->rendererHelper->escapeShortCodes($this->rendererHelper->getFieldValue($block)) . ''; + $html .= $this->rendererHelper->renderErrorsContainer($block, $formId); + return $this->wrapper->render($block, $html); } } diff --git a/mailpoet/lib/Form/BlocksRenderer.php b/mailpoet/lib/Form/BlocksRenderer.php index b3603b045e..ad32084ae7 100644 --- a/mailpoet/lib/Form/BlocksRenderer.php +++ b/mailpoet/lib/Form/BlocksRenderer.php @@ -18,6 +18,7 @@ use MailPoet\Form\Block\Select; use MailPoet\Form\Block\Submit; use MailPoet\Form\Block\Text; use MailPoet\Form\Block\Textarea; +use MailPoet\Util\Security; class BlocksRenderer { /** @var Checkbox */ @@ -104,6 +105,9 @@ class BlocksRenderer { if ($formId) { $formSettings['id'] = $formId; } + // This is used to properly show validation message when + // the same form is rendered on a page multiple times + $block['validation_id'] = Security::generateRandomString(); switch ($block['type']) { case FormEntity::HTML_BLOCK_TYPE: $html .= $this->html->render($block, $formSettings); @@ -142,15 +146,15 @@ class BlocksRenderer { break; case FormEntity::SELECT_BLOCK_TYPE: - $html .= $this->select->render($block, $formSettings); + $html .= $this->select->render($block, $formSettings, $formId); break; case FormEntity::TEXT_BLOCK_TYPE: - $html .= $this->text->render($block, $formSettings); + $html .= $this->text->render($block, $formSettings, $formId); break; case FormEntity::TEXTAREA_BLOCK_TYPE: - $html .= $this->textarea->render($block, $formSettings); + $html .= $this->textarea->render($block, $formSettings, $formId); break; case FormEntity::SUBMIT_BLOCK_TYPE: