Commit f274f58d authored by Andreas Fernandez's avatar Andreas Fernandez Committed by Frank Nägler
Browse files

[TASK] Move "Refresh required" modal interception into JavaScript land

The "Refresh required" is currently built in PHP and invoked when changing
a field that is explictly configured as "onChange => reload" in TCA. Since
we aren't limited to the technology of our time anymore, the main logic
can get moved into FormEngine.js and only registration is kept in
FormEngine for now.

This commit also removed some superfluous usages of
`TBE_EDITOR_fieldChanged`, as those are already handled by FormEngine.

Resolves: #88665
Releases: master
Change-Id: I255b70fba7af8253c6bc02611029a74a57a2a043
Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/61204

Tested-by: default avatarTYPO3com <noreply@typo3.com>
Tested-by: Frank Nägler's avatarFrank Naegler <frank.naegler@typo3.org>
Tested-by: Anja Leichsenring's avatarAnja Leichsenring <aleichsenring@ab-softlab.de>
Reviewed-by: Frank Nägler's avatarFrank Naegler <frank.naegler@typo3.org>
Reviewed-by: Oliver Hader's avatarOliver Hader <oliver.hader@typo3.org>
Reviewed-by: Anja Leichsenring's avatarAnja Leichsenring <aleichsenring@ab-softlab.de>
parent 87268b67
......@@ -121,16 +121,6 @@ class FormFlexAjaxController extends AbstractFormEngineAjaxController
$formData['parameterArray']['itemFormElName'] = 'data[' . $tableName . '][' . $formData['databaseRow']['uid'] . '][' . $fieldName . ']';
// JavaScript code for event handlers:
// @todo: see if we can get rid of this - used in group elements, and also for the "reload" on type field changes
$formData['parameterArray']['fieldChangeFunc'] = [];
$formData['parameterArray']['fieldChangeFunc']['TBE_EDITOR_fieldChanged'] = 'TBE_EDITOR.fieldChanged('
. GeneralUtility::quoteJSvalue($tableName)
. ',' . GeneralUtility::quoteJSvalue($formData['databaseRow']['uid'])
. ',' . GeneralUtility::quoteJSvalue($fieldName)
. ',' . GeneralUtility::quoteJSvalue($formData['parameterArray']['itemFormElName'])
. ');';
// @todo: check GroupElement for usage of elementBaseName ... maybe kick that thing?
// Feed resulting form data to container structure to render HTML and other result data
......
......@@ -18,6 +18,7 @@ use TYPO3\CMS\Backend\Utility\BackendUtility;
use TYPO3\CMS\Core\Authentication\BackendUserAuthentication;
use TYPO3\CMS\Core\Localization\LanguageService;
use TYPO3\CMS\Core\Type\Bitmask\JsConfirmation;
use TYPO3\CMS\Core\Utility\GeneralUtility;
/**
* The container handles single elements.
......@@ -84,25 +85,6 @@ class FlexFormElementContainer extends AbstractContainer
$fakeParameterArray['fieldConf']['description'] = $flexFormFieldArray['description'];
}
$alertMsgOnChange = '';
if (isset($fakeParameterArray['fieldConf']['onChange']) && $fakeParameterArray['fieldConf']['onChange'] === 'reload') {
if ($this->getBackendUserAuthentication()->jsConfirmation(JsConfirmation::TYPE_CHANGE)) {
$alertMsgOnChange = 'top.TYPO3.Modal.confirm('
. 'TYPO3.lang["FormEngine.refreshRequiredTitle"],'
. ' TYPO3.lang["FormEngine.refreshRequiredContent"]'
. ')'
. '.on('
. '"button.clicked",'
. ' function(e) { if (e.target.name == "ok" && TBE_EDITOR.checkSubmit(-1)) { TBE_EDITOR.submitForm() } top.TYPO3.Modal.dismiss(); }'
. ');';
} else {
$alertMsgOnChange = 'if (TBE_EDITOR.checkSubmit(-1)){ TBE_EDITOR.submitForm();}';
}
}
if ($alertMsgOnChange) {
$fakeParameterArray['fieldChangeFunc']['alert'] = $alertMsgOnChange;
}
$originalFieldName = $parameterArray['itemFormElName'];
$fakeParameterArray['itemFormElName'] = $parameterArray['itemFormElName'] . $flexFormFormPrefix . '[' . $flexFormFieldName . '][vDEF]';
if ($fakeParameterArray['itemFormElName'] !== $originalFieldName) {
......@@ -138,6 +120,14 @@ class FlexFormElementContainer extends AbstractContainer
}
$childResult = $this->nodeFactory->create($options)->render();
// Create a JavaScript code line which will ask the user to save/update the form due to changing the element.
// This is used for eg. "type" fields and others configured with "onChange"
if (isset($fakeParameterArray['fieldConf']['onChange']) && $fakeParameterArray['fieldConf']['onChange'] === 'reload') {
$showConfirmation = $this->getBackendUserAuthentication()->jsConfirmation(JsConfirmation::TYPE_CHANGE) ? 'true' : 'false';
$resultArray['requireJsModules'][] = ['TYPO3/CMS/Backend/FormEngine' => 'function (FormEngine) {FormEngine.requestConfirmationOnFieldChange(' . GeneralUtility::quoteJSvalue($parameterArray['itemFormElName']) . ', ' . $showConfirmation . ');}'];
}
if (!empty($childResult['html'])) {
// Possible line breaks in the label through xml: \n => <br/>, usage of nl2br() not possible, so it's done through str_replace (?!)
$processedTitle = str_replace('\\n', '<br />', htmlspecialchars($fakeParameterArray['fieldConf']['label']));
......
......@@ -110,43 +110,8 @@ class SingleFieldContainer extends AbstractContainer
$parameterArray['itemFormElValue'] = $this->data['defaultLanguageRow'][$fieldName];
}
if (strpos($this->data['processedTca']['ctrl']['type'], ':') === false) {
$typeField = $this->data['processedTca']['ctrl']['type'];
} else {
$typeField = substr($this->data['processedTca']['ctrl']['type'], 0, strpos($this->data['processedTca']['ctrl']['type'], ':'));
}
// Create a JavaScript code line which will ask the user to save/update the form due to changing the element.
// This is used for eg. "type" fields and others configured with "onChange"
if (!empty($this->data['processedTca']['ctrl']['type']) && $fieldName === $typeField
|| isset($parameterArray['fieldConf']['onChange']) && $parameterArray['fieldConf']['onChange'] === 'reload'
) {
if ($backendUser->jsConfirmation(JsConfirmation::TYPE_CHANGE)) {
$alertMsgOnChange = 'top.TYPO3.Modal.confirm('
. 'TYPO3.lang["FormEngine.refreshRequiredTitle"],'
. ' TYPO3.lang["FormEngine.refreshRequiredContent"]'
. ')'
. '.on('
. '"button.clicked",'
. ' function(e) { if (e.target.name == "ok" && TBE_EDITOR.checkSubmit(-1)) { TBE_EDITOR.submitForm() } top.TYPO3.Modal.dismiss(); }'
. ');';
} else {
$alertMsgOnChange = 'if (TBE_EDITOR.checkSubmit(-1)){ TBE_EDITOR.submitForm() };';
}
} else {
$alertMsgOnChange = '';
}
// JavaScript code for event handlers:
$parameterArray['fieldChangeFunc'] = [];
$parameterArray['fieldChangeFunc']['TBE_EDITOR_fieldChanged'] = 'TBE_EDITOR.fieldChanged('
. GeneralUtility::quoteJSvalue($table) . ','
. GeneralUtility::quoteJSvalue($row['uid']) . ','
. GeneralUtility::quoteJSvalue($fieldName) . ','
. GeneralUtility::quoteJSvalue($parameterArray['itemFormElName'])
. ');';
if ($alertMsgOnChange) {
$parameterArray['fieldChangeFunc']['alert'] = $alertMsgOnChange;
}
// Based on the type of the item, call a render function on a child element
$options = $this->data;
......@@ -159,6 +124,25 @@ class SingleFieldContainer extends AbstractContainer
$options['renderType'] = $parameterArray['fieldConf']['config']['type'];
}
$resultArray = $this->nodeFactory->create($options)->render();
if (strpos($this->data['processedTca']['ctrl']['type'], ':') === false) {
$typeField = $this->data['processedTca']['ctrl']['type'];
} else {
$typeField = substr($this->data['processedTca']['ctrl']['type'], 0, strpos($this->data['processedTca']['ctrl']['type'], ':'));
}
// Create a JavaScript code line which will ask the user to save/update the form due to changing the element.
// This is used for eg. "type" fields and others configured with "onChange"
if ((!empty($this->data['processedTca']['ctrl']['type']) && $fieldName === $typeField)
|| (isset($parameterArray['fieldConf']['onChange']) && $parameterArray['fieldConf']['onChange'] === 'reload')
) {
$showConfirmation = $backendUser->jsConfirmation(JsConfirmation::TYPE_CHANGE) ? 'true' : 'false';
$resultArray['requireJsModules'][] = ['TYPO3/CMS/Backend/FormEngine' => 'function (FormEngine) {'
. 'FormEngine.requestConfirmationOnFieldChange(' . GeneralUtility::quoteJSvalue($parameterArray['itemFormElName']) . ', ' . $showConfirmation . ');'
. '}'];
}
return $resultArray;
}
......
......@@ -201,7 +201,10 @@ class FormResultCompiler
$html = implode(LF, $this->hiddenFieldAccum);
$pageRenderer->addJsFile('EXT:backend/Resources/Public/JavaScript/md5.js');
// load the main module for FormEngine with all important JS functions
$this->requireJsModules['TYPO3/CMS/Backend/FormEngine'] = 'function(FormEngine) {
if (!is_array($this->requireJsModules['TYPO3/CMS/Backend/FormEngine'] ?? null)) {
$this->requireJsModules['TYPO3/CMS/Backend/FormEngine'] = [$this->requireJsModules['TYPO3/CMS/Backend/FormEngine']];
}
$this->requireJsModules['TYPO3/CMS/Backend/FormEngine'][] = 'function(FormEngine) {
FormEngine.initialize(
' . GeneralUtility::quoteJSvalue((string)$uriBuilder->buildUriFromRoute('wizard_element_browser')) . ',
' . ($GLOBALS['TYPO3_CONF_VARS']['SYS']['USdateFormat'] ? '1' : '0') . '
......
......@@ -799,9 +799,8 @@ define(['jquery',
callback.call(null, true);
} else if (e.target.name === 'save') {
$('form[name=' + FormEngine.formName + ']').append($elem);
$('input[name=doSave]').val(1);
Modal.dismiss();
document.editform.submit();
FormEngine.saveDocument();
}
});
} else {
......@@ -833,6 +832,28 @@ define(['jquery',
return true;
};
FormEngine.requestConfirmationOnFieldChange = function(fieldName, showConfirmation) {
const $field = FormEngine.getFieldElement(fieldName);
$field.on('change', function() {
if (showConfirmation) {
const $modal = Modal.confirm(
TYPO3.lang['FormEngine.refreshRequiredTitle'],
TYPO3.lang['FormEngine.refreshRequiredContent']
);
$modal.on('button.clicked', function(e) {
if (e.target.name === 'ok') {
FormEngine.saveDocument();
}
Modal.dismiss();
});
} else {
FormEngine.saveDocument();
}
});
};
/**
* Preview action
*
......@@ -877,9 +898,8 @@ define(['jquery',
break;
case 'save':
$('form[name=' + FormEngine.formName + ']').append($actionElement);
$('input[name=doSave]').val(1);
window.open('', 'newTYPO3frontendWindow');
document.editform.submit();
FormEngine.saveDocument();
break;
}
};
......@@ -977,8 +997,7 @@ define(['jquery',
break;
case 'yes':
$form.append($actionElement);
$('input[name=doSave]').val(1);
document.editform.submit();
FormEngine.saveDocument();
break;
}
};
......@@ -1070,8 +1089,7 @@ define(['jquery',
break;
case 'yes':
$form.append($actionElement);
$('input[name=doSave]').val(1);
document.editform.submit();
FormEngine.saveDocument();
break;
}
};
......@@ -1201,6 +1219,11 @@ define(['jquery',
document.editform.submit();
};
FormEngine.saveDocument = function() {
document.editform.doSave.value = 1;
document.editform.submit();
};
/**
* Main init function called from outside
*
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment