From 1f2d590321d447a043c77a46bb190a503695a333 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20M=C3=A4chler?= Date: Mon, 12 Mar 2018 16:46:29 +0100 Subject: [PATCH] [BUGFIX] Fixes errors that occur when the same form is used multiple times on the same page --- Classes/Controller/FormController.php | 62 ++++++++++++++++++- .../Misc/PrefillFieldViewHelper.php | 35 ++++++++++- .../Misc/PrefillMultiFieldViewHelper.php | 35 ++++++++++- .../EnableParsleyAndAjaxViewHelper.php | 2 + .../Private/JavaScripts/Powermail/Form.js | 6 +- .../Private/Templates/Form/Confirmation.html | 3 +- Resources/Private/Templates/Form/Create.html | 2 +- Resources/Private/Templates/Form/Form.html | 3 +- 8 files changed, 136 insertions(+), 12 deletions(-) diff --git a/Classes/Controller/FormController.php b/Classes/Controller/FormController.php index a54da5588..67ef27c50 100644 --- a/Classes/Controller/FormController.php +++ b/Classes/Controller/FormController.php @@ -49,7 +49,7 @@ public function formAction() $this->view->assignMultiple( [ 'form' => $form, - 'ttContentData' => $this->contentObject->data, + 'ttContentData' => $this->getCurrentContentObjectData(), 'messageClass' => $this->messageClass, 'action' => ($this->settings['main']['confirmation'] ? 'confirmation' : 'create') ] @@ -63,6 +63,7 @@ public function formAction() */ public function initializeCreateAction() { + $this->forwardIfTtContentUidDoesNotMatch(); $this->forwardIfFormParamsDoNotMatch(); $this->forwardIfMailParamEmpty(); $this->reformatParamsForAction(); @@ -134,6 +135,7 @@ public function createAction(Mail $mail, string $hash = null) */ public function initializeConfirmationAction() { + $this->forwardIfTtContentUidDoesNotMatch(); $this->forwardIfFormParamsDoNotMatch(); $this->forwardIfMailParamEmpty(); $this->reformatParamsForAction(); @@ -216,7 +218,7 @@ protected function prepareOutput(Mail $mail) 'mail' => $mail, 'marketingInfos' => SessionUtility::getMarketingInfos(), 'messageClass' => $this->messageClass, - 'ttContentData' => $this->contentObject->data, + 'ttContentData' => $this->getCurrentContentObjectData(), 'uploadService' => $this->uploadService, 'powermail_rte' => $this->settings['thx']['body'], 'powermail_all' => TemplateUtility::powermailAll($mail, 'web', $this->settings, $this->actionMethodName) @@ -313,6 +315,8 @@ public function initializeAction() { parent::initializeAction(); + $this->storeCurrentContentObjectData(); + // @codeCoverageIgnoreStart if (!isset($this->settings['staticTemplate'])) { $this->controllerContext = $this->buildControllerContext(); @@ -320,6 +324,24 @@ public function initializeAction() } } + /** + * Forward to formAction if content element uids do not match + * used for createAction() and confirmationAction() + * + * @return void + */ + protected function forwardIfTtContentUidDoesNotMatch() + { + $arguments = $this->request->getArguments(); + $currentContentObjectData = $this->getCurrentContentObjectData(); + + if (isset($arguments['field']['__ttcontentuid']) && isset($currentContentObjectData['uid']) + && (int) $arguments['field']['__ttcontentuid'] !== (int) $currentContentObjectData['uid'] + ) { + $this->forward('form'); + } + } + /** * Forward to formAction if wrong form in plugin variables given * used for createAction() and confirmationAction() @@ -452,4 +474,40 @@ public function injectPersistenceManager(PersistenceManager $persistenceManager) { $this->persistenceManager = $persistenceManager; } + + /** + * Storing the current content object data to a global variable. That is necessary + * because content object data gets lost after a request is being forwarded to its + * referring request after an errorAction + * + * @return void + */ + protected function storeCurrentContentObjectData() + { + if (!empty($this->contentObject->data)) { + $tsfe = ObjectUtility::getTyposcriptFrontendController(); + + if (!is_array($tsfe->applicationData['tx_powermail'])) { + $tsfe->applicationData['tx_powermail'] = []; + } + + $tsfe->applicationData['tx_powermail']['currentContentObjectData'] = $this->contentObject->data; + } + } + + /** + * Retrieving data of content object that is currently being rendered + * + * @return array + */ + protected function getCurrentContentObjectData(): array + { + $tsfe = ObjectUtility::getTyposcriptFrontendController(); + + if (isset($tsfe->applicationData['tx_powermail']['currentContentObjectData'])) { + return $tsfe->applicationData['tx_powermail']['currentContentObjectData']; + } + + return []; + } } diff --git a/Classes/ViewHelpers/Misc/PrefillFieldViewHelper.php b/Classes/ViewHelpers/Misc/PrefillFieldViewHelper.php index 056167d88..3bfbff1c9 100644 --- a/Classes/ViewHelpers/Misc/PrefillFieldViewHelper.php +++ b/Classes/ViewHelpers/Misc/PrefillFieldViewHelper.php @@ -141,7 +141,7 @@ protected function getFromMail($value) */ protected function getFromMarker($value) { - if (empty($value) && isset($this->piVars['field'][$this->getMarker()])) { + if (empty($value) && isset($this->piVars['field'][$this->getMarker()]) && $this->isSameContentElement()) { $value = $this->piVars['field'][$this->getMarker()]; } return $value; @@ -155,7 +155,7 @@ protected function getFromMarker($value) */ protected function getFromRawMarker($value) { - if (empty($value) && isset($this->piVars[$this->getMarker()])) { + if (empty($value) && isset($this->piVars[$this->getMarker()]) && $this->isSameContentElement()) { $value = $this->piVars[$this->getMarker()]; } return $value; @@ -365,4 +365,35 @@ public function initialize() $configurationService = ObjectUtility::getObjectManager()->get(ConfigurationService::class); $this->configuration = $configurationService->getTypoScriptConfiguration(); } + + /** + * Check whether GET / POST values may be used by this form, + * because they are from the same content element as the form was submitted + */ + protected function isSameContentElement(): bool + { + $currentContentObjectData = $this->getCurrentContentObjectData(); + + if (isset($currentContentObjectData['uid']) && isset($this->piVars['field']['__ttcontentuid'])) { + return (int) $currentContentObjectData['uid'] === (int) $this->piVars['field']['__ttcontentuid']; + } + + return true; + } + + /** + * Retrieving data of content object that is currently being rendered + * + * @return array + */ + protected function getCurrentContentObjectData(): array + { + $tsfe = ObjectUtility::getTyposcriptFrontendController(); + + if (isset($tsfe->applicationData['tx_powermail']['currentContentObjectData'])) { + return $tsfe->applicationData['tx_powermail']['currentContentObjectData']; + } + + return []; + } } diff --git a/Classes/ViewHelpers/Misc/PrefillMultiFieldViewHelper.php b/Classes/ViewHelpers/Misc/PrefillMultiFieldViewHelper.php index d37a3cded..5aca5e7ce 100644 --- a/Classes/ViewHelpers/Misc/PrefillMultiFieldViewHelper.php +++ b/Classes/ViewHelpers/Misc/PrefillMultiFieldViewHelper.php @@ -184,7 +184,7 @@ protected function getFromMail() protected function getFromMarker() { $selected = false; - if (isset($this->variables['field'][$this->getMarker()])) { + if (isset($this->variables['field'][$this->getMarker()]) && $this->isSameContentElement()) { if (is_array($this->variables['field'][$this->getMarker()])) { foreach (array_keys($this->variables['field'][$this->getMarker()]) as $key) { if ($this->variables['field'][$this->getMarker()][$key] === $this->options[$this->index]['value'] || @@ -215,7 +215,7 @@ protected function getFromMarker() protected function getFromRawMarker() { $selected = false; - if (isset($this->variables[$this->getMarker()])) { + if (isset($this->variables[$this->getMarker()]) && $this->isSameContentElement()) { if (is_array($this->variables[$this->getMarker()])) { foreach (array_keys($this->variables[$this->getMarker()]) as $key) { if ($this->variables[$this->getMarker()][$key] === $this->options[$this->index]['value'] || @@ -530,4 +530,35 @@ public function initialize() $configurationService = ObjectUtility::getObjectManager()->get(ConfigurationService::class); $this->configuration = $configurationService->getTypoScriptConfiguration(); } + + /** + * Check whether GET / POST values may be used by this form, + * because they are from the same content element as the form was submitted + */ + protected function isSameContentElement(): bool + { + $currentContentObjectData = $this->getCurrentContentObjectData(); + + if (isset($currentContentObjectData['uid']) && isset($this->piVars['field']['__ttcontentuid'])) { + return (int) $currentContentObjectData['uid'] === (int) $this->piVars['field']['__ttcontentuid']; + } + + return true; + } + + /** + * Retrieving data of content object that is currently being rendered + * + * @return array + */ + protected function getCurrentContentObjectData(): array + { + $tsfe = ObjectUtility::getTyposcriptFrontendController(); + + if (isset($tsfe->applicationData['tx_powermail']['currentContentObjectData'])) { + return $tsfe->applicationData['tx_powermail']['currentContentObjectData']; + } + + return []; + } } diff --git a/Classes/ViewHelpers/Validation/EnableParsleyAndAjaxViewHelper.php b/Classes/ViewHelpers/Validation/EnableParsleyAndAjaxViewHelper.php index 12f1897d6..b38efac5b 100644 --- a/Classes/ViewHelpers/Validation/EnableParsleyAndAjaxViewHelper.php +++ b/Classes/ViewHelpers/Validation/EnableParsleyAndAjaxViewHelper.php @@ -27,6 +27,7 @@ public function initializeArguments() parent::initializeArguments(); $this->registerArgument('form', Form::class, 'Form', true); $this->registerArgument('additionalAttributes', 'array', 'additionalAttributes', false, []); + $this->registerArgument('ttContentData', 'array', 'ttContentData', false, []); } /** @@ -50,6 +51,7 @@ public function render(): array if ($this->settings['misc']['ajaxSubmit'] === '1') { $additionalAttributes['data-powermail-ajax'] = 'true'; $additionalAttributes['data-powermail-form'] = $form->getUid(); + $additionalAttributes['data-powermail-ttcontentuid'] = $this->arguments['ttContentData']['uid']; if ($this->addRedirectUri) { /** @var RedirectUriService $redirectService */ diff --git a/Resources/Private/JavaScripts/Powermail/Form.js b/Resources/Private/JavaScripts/Powermail/Form.js index 439936c56..0c6055f56 100644 --- a/Resources/Private/JavaScripts/Powermail/Form.js +++ b/Resources/Private/JavaScripts/Powermail/Form.js @@ -189,7 +189,7 @@ function PowermailForm($) { if ($this.data('powermail-ajax-uri')) { redirectUri = $this.data('powermail-ajax-uri'); } - var formUid = $this.data('powermail-form'); + var ttContentUid = $this.data('powermail-ttcontentuid'); if (!regularSubmitOnAjax) { $.ajax({ @@ -207,9 +207,9 @@ function PowermailForm($) { fireAjaxCompleteEvent($txPowermail); }, success: function(data) { - var html = $('*[data-powermail-form="' + formUid + '"]:first', data); + var html = $('*[data-powermail-ttcontentuid="' + ttContentUid + '"]:first', data); if (html.length) { - $('*[data-powermail-form="' + formUid + '"]:first').closest('.tx-powermail').html(html); + $('*[data-powermail-ttcontentuid="' + ttContentUid + '"]:first').closest('.tx-powermail').html(html); // fire tabs and parsley again if ($.fn.powermailTabs) { $('.powermail_morestep').powermailTabs(); diff --git a/Resources/Private/Templates/Form/Confirmation.html b/Resources/Private/Templates/Form/Confirmation.html index 190119a59..f63f4094a 100644 --- a/Resources/Private/Templates/Form/Confirmation.html +++ b/Resources/Private/Templates/Form/Confirmation.html @@ -46,7 +46,7 @@

enctype="multipart/form-data" class="visible-xs-inline-block visible-sm-inline-block visible-md-inline-block visible-lg-inline-block" addQueryString="{settings.misc.addQueryString}" - additionalAttributes="{vh:Validation.EnableParsleyAndAjax(form: mail.form)}"> + additionalAttributes="{vh:Validation.EnableParsleyAndAjax(form: mail.form, ttContentData: ttContentData)}"> + diff --git a/Resources/Private/Templates/Form/Create.html b/Resources/Private/Templates/Form/Create.html index e4c65c4e6..75d629575 100644 --- a/Resources/Private/Templates/Form/Create.html +++ b/Resources/Private/Templates/Form/Create.html @@ -19,7 +19,7 @@ -
+
diff --git a/Resources/Private/Templates/Form/Form.html b/Resources/Private/Templates/Form/Form.html index 1cbea69a2..870d0388a 100644 --- a/Resources/Private/Templates/Form/Form.html +++ b/Resources/Private/Templates/Form/Form.html @@ -20,7 +20,7 @@ section="c{ttContentData.uid}" name="field" enctype="multipart/form-data" - additionalAttributes="{vh:Validation.EnableParsleyAndAjax(form:form)}" + additionalAttributes="{vh:Validation.EnableParsleyAndAjax(form:form,ttContentData:ttContentData)}" addQueryString="{settings.misc.addQueryString}" class="powermail_form powermail_form_{form.uid} {form.css} {settings.styles.framework.formClasses} {vh:Misc.MorestepClass(activate:settings.main.moresteps)}"> @@ -33,6 +33,7 @@

{form.title}

+