Commit ce36139d authored by Elias Häußler's avatar Elias Häußler 🐛 Committed by Georg Ringer
Browse files

[BUGFIX] Allow slug recreation if postModifiers are defined

Slug fields currently only support slug recreation if the given
generator fields are directly visible in the backend. However, this
makes it impossible to recreate slugs even if some postModifiers are
defined who can take care of successful slug generation.

This commit allows slug recreation if at least one postModifier is
defined, even if the defined generator fields are not usable for
slug generation.

Therefore also EditDocumentController was adjusted to not
automatically add slug fields to columnsOnly in case postModifiers
are defined for this record.

Resolves: #89187
Releases: master, 10.4
Change-Id: Ifd50ec106b5b302cea23d37e470eafae840c8993
Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/61716

Tested-by: default avatarTYPO3com <noreply@typo3.com>
Tested-by: Oliver Bartsch's avatarOliver Bartsch <bo@cedev.de>
Tested-by: Anja Leichsenring's avatarAnja Leichsenring <aleichsenring@ab-softlab.de>
Tested-by: Georg Ringer's avatarGeorg Ringer <georg.ringer@gmail.com>
Reviewed-by: Oliver Bartsch's avatarOliver Bartsch <bo@cedev.de>
Reviewed-by: Anja Leichsenring's avatarAnja Leichsenring <aleichsenring@ab-softlab.de>
Reviewed-by: Georg Ringer's avatarGeorg Ringer <georg.ringer@gmail.com>
parent 605b3e51
......@@ -101,8 +101,10 @@ class SlugElement {
}
}).delegateTo(document, fieldsToListenOnList.join(','));
}
}
// Clicking the recreate button makes new slug proposal created from 'title' field
// Clicking the recreate button makes new slug proposal created from 'title' field or any defined postModifiers
if (fieldsToListenOnList.length > 0 || this.hasPostModifiersDefined()) {
new RegularEvent('click', (e: Event): void => {
e.preventDefault();
if (this.readOnlyField.classList.contains('hidden')) {
......@@ -222,6 +224,15 @@ class SlugElement {
return availableFields;
}
/**
* Check whether the slug element has post modifiers defined for slug generation
*
* @return boolean
*/
private hasPostModifiersDefined(): boolean {
return Array.isArray(this.options.config.generatorOptions.postModifiers) && this.options.config.generatorOptions.postModifiers.length > 0;
}
}
export = SlugElement;
......@@ -495,8 +495,12 @@ class EditDocumentController
if ($this->columnsOnly && $table !== false && isset($GLOBALS['TCA'][$table])) {
$fields = GeneralUtility::trimExplode(',', $this->columnsOnly, true);
foreach ($fields as $field) {
if (isset($GLOBALS['TCA'][$table]['columns'][$field]) && $GLOBALS['TCA'][$table]['columns'][$field]['config']['type'] === 'slug') {
foreach ($GLOBALS['TCA'][$table]['columns'][$field]['config']['generatorOptions']['fields'] as $fields) {
$postModifiers = $GLOBALS['TCA'][$table]['columns'][$field]['config']['generatorOptions']['postModifiers'] ?? [];
if (isset($GLOBALS['TCA'][$table]['columns'][$field])
&& $GLOBALS['TCA'][$table]['columns'][$field]['config']['type'] === 'slug'
&& (!is_array($postModifiers) || $postModifiers === [])
) {
foreach ($GLOBALS['TCA'][$table]['columns'][$field]['config']['generatorOptions']['fields'] ?? [] as $fields) {
$this->columnsOnly .= ',' . (is_array($fields) ? implode(',', $fields) : $fields);
}
}
......
......@@ -10,4 +10,4 @@
*
* The TYPO3 project - inspiring people to share!
*/
define(["require","exports","TYPO3/CMS/Core/Ajax/AjaxRequest","TYPO3/CMS/Core/DocumentService","TYPO3/CMS/Core/Event/DebounceEvent","TYPO3/CMS/Core/Event/RegularEvent"],(function(e,t,i,l,s,n){"use strict";var o,a;!function(e){e.toggleButton=".t3js-form-field-slug-toggle",e.recreateButton=".t3js-form-field-slug-recreate",e.inputField=".t3js-form-field-slug-input",e.readOnlyField=".t3js-form-field-slug-readonly",e.hiddenField=".t3js-form-field-slug-hidden"}(o||(o={})),function(e){e.AUTO="auto",e.RECREATE="recreate",e.MANUAL="manual"}(a||(a={}));return class{constructor(e,t){this.options=null,this.fullElement=null,this.manuallyChanged=!1,this.readOnlyField=null,this.inputField=null,this.hiddenField=null,this.request=null,this.fieldsToListenOn={},this.options=t,this.fieldsToListenOn=this.options.listenerFieldNames||{},l.ready().then(t=>{this.fullElement=t.querySelector(e),this.inputField=this.fullElement.querySelector(o.inputField),this.readOnlyField=this.fullElement.querySelector(o.readOnlyField),this.hiddenField=this.fullElement.querySelector(o.hiddenField),this.registerEvents()})}registerEvents(){const e=Object.values(this.getAvailableFieldsForProposalGeneration()).map(e=>`[data-formengine-input-name="${e}"]`),t=this.fullElement.querySelector(o.recreateButton);e.length>0?("new"===this.options.command&&new s("input",()=>{this.manuallyChanged||this.sendSlugProposal(a.AUTO)}).delegateTo(document,e.join(",")),new n("click",e=>{e.preventDefault(),this.readOnlyField.classList.contains("hidden")&&(this.readOnlyField.classList.toggle("hidden",!1),this.inputField.classList.toggle("hidden",!0)),this.sendSlugProposal(a.RECREATE)}).bindTo(t)):(t.classList.add("disabled"),t.disabled=!0),new s("input",()=>{this.manuallyChanged=!0,this.sendSlugProposal(a.MANUAL)}).bindTo(this.inputField);const i=this.fullElement.querySelector(o.toggleButton);new n("click",e=>{e.preventDefault();const t=this.readOnlyField.classList.contains("hidden");this.readOnlyField.classList.toggle("hidden",!t),this.inputField.classList.toggle("hidden",t),t?(this.inputField.value!==this.readOnlyField.value?this.readOnlyField.value=this.inputField.value:(this.manuallyChanged=!1,this.fullElement.querySelector(".t3js-form-proposal-accepted").classList.add("hidden"),this.fullElement.querySelector(".t3js-form-proposal-different").classList.add("hidden")),this.hiddenField.value=this.readOnlyField.value):this.hiddenField.value=this.inputField.value}).bindTo(i)}sendSlugProposal(e){const t={};if(e===a.AUTO||e===a.RECREATE){for(const[e,i]of Object.entries(this.getAvailableFieldsForProposalGeneration()))t[e]=document.querySelector('[data-formengine-input-name="'+i+'"]').value;!0===this.options.includeUidInValues&&(t.uid=this.options.recordId.toString())}else t.manual=this.inputField.value;this.request instanceof i&&this.request.abort(),this.request=new i(TYPO3.settings.ajaxUrls.record_slug_suggest),this.request.post({values:t,mode:e,tableName:this.options.tableName,pageId:this.options.pageId,parentPageId:this.options.parentPageId,recordId:this.options.recordId,language:this.options.language,fieldName:this.options.fieldName,command:this.options.command,signature:this.options.signature}).then(async t=>{const i=await t.resolve(),l="/"+i.proposal.replace(/^\//,""),s=this.fullElement.querySelector(".t3js-form-proposal-accepted"),n=this.fullElement.querySelector(".t3js-form-proposal-different");s.classList.toggle("hidden",i.hasConflicts),n.classList.toggle("hidden",!i.hasConflicts),(i.hasConflicts?n:s).querySelector("span").innerText=l;this.hiddenField.value!==i.proposal&&this.fullElement.querySelector("input").dispatchEvent(new Event("change")),e===a.AUTO||e===a.RECREATE?(this.readOnlyField.value=i.proposal,this.hiddenField.value=i.proposal,this.inputField.value=i.proposal):this.hiddenField.value=i.proposal}).finally(()=>{this.request=null})}getAvailableFieldsForProposalGeneration(){const e={};for(const[t,i]of Object.entries(this.fieldsToListenOn)){null!==document.querySelector('[data-formengine-input-name="'+i+'"]')&&(e[t]=i)}return e}}}));
\ No newline at end of file
define(["require","exports","TYPO3/CMS/Core/Ajax/AjaxRequest","TYPO3/CMS/Core/DocumentService","TYPO3/CMS/Core/Event/DebounceEvent","TYPO3/CMS/Core/Event/RegularEvent"],(function(e,t,i,s,l,n){"use strict";var o,a;!function(e){e.toggleButton=".t3js-form-field-slug-toggle",e.recreateButton=".t3js-form-field-slug-recreate",e.inputField=".t3js-form-field-slug-input",e.readOnlyField=".t3js-form-field-slug-readonly",e.hiddenField=".t3js-form-field-slug-hidden"}(o||(o={})),function(e){e.AUTO="auto",e.RECREATE="recreate",e.MANUAL="manual"}(a||(a={}));return class{constructor(e,t){this.options=null,this.fullElement=null,this.manuallyChanged=!1,this.readOnlyField=null,this.inputField=null,this.hiddenField=null,this.request=null,this.fieldsToListenOn={},this.options=t,this.fieldsToListenOn=this.options.listenerFieldNames||{},s.ready().then(t=>{this.fullElement=t.querySelector(e),this.inputField=this.fullElement.querySelector(o.inputField),this.readOnlyField=this.fullElement.querySelector(o.readOnlyField),this.hiddenField=this.fullElement.querySelector(o.hiddenField),this.registerEvents()})}registerEvents(){const e=Object.values(this.getAvailableFieldsForProposalGeneration()).map(e=>`[data-formengine-input-name="${e}"]`),t=this.fullElement.querySelector(o.recreateButton);e.length>0&&"new"===this.options.command&&new l("input",()=>{this.manuallyChanged||this.sendSlugProposal(a.AUTO)}).delegateTo(document,e.join(",")),e.length>0||this.hasPostModifiersDefined()?new n("click",e=>{e.preventDefault(),this.readOnlyField.classList.contains("hidden")&&(this.readOnlyField.classList.toggle("hidden",!1),this.inputField.classList.toggle("hidden",!0)),this.sendSlugProposal(a.RECREATE)}).bindTo(t):(t.classList.add("disabled"),t.disabled=!0),new l("input",()=>{this.manuallyChanged=!0,this.sendSlugProposal(a.MANUAL)}).bindTo(this.inputField);const i=this.fullElement.querySelector(o.toggleButton);new n("click",e=>{e.preventDefault();const t=this.readOnlyField.classList.contains("hidden");this.readOnlyField.classList.toggle("hidden",!t),this.inputField.classList.toggle("hidden",t),t?(this.inputField.value!==this.readOnlyField.value?this.readOnlyField.value=this.inputField.value:(this.manuallyChanged=!1,this.fullElement.querySelector(".t3js-form-proposal-accepted").classList.add("hidden"),this.fullElement.querySelector(".t3js-form-proposal-different").classList.add("hidden")),this.hiddenField.value=this.readOnlyField.value):this.hiddenField.value=this.inputField.value}).bindTo(i)}sendSlugProposal(e){const t={};if(e===a.AUTO||e===a.RECREATE){for(const[e,i]of Object.entries(this.getAvailableFieldsForProposalGeneration()))t[e]=document.querySelector('[data-formengine-input-name="'+i+'"]').value;!0===this.options.includeUidInValues&&(t.uid=this.options.recordId.toString())}else t.manual=this.inputField.value;this.request instanceof i&&this.request.abort(),this.request=new i(TYPO3.settings.ajaxUrls.record_slug_suggest),this.request.post({values:t,mode:e,tableName:this.options.tableName,pageId:this.options.pageId,parentPageId:this.options.parentPageId,recordId:this.options.recordId,language:this.options.language,fieldName:this.options.fieldName,command:this.options.command,signature:this.options.signature}).then(async t=>{const i=await t.resolve(),s="/"+i.proposal.replace(/^\//,""),l=this.fullElement.querySelector(".t3js-form-proposal-accepted"),n=this.fullElement.querySelector(".t3js-form-proposal-different");l.classList.toggle("hidden",i.hasConflicts),n.classList.toggle("hidden",!i.hasConflicts),(i.hasConflicts?n:l).querySelector("span").innerText=s;this.hiddenField.value!==i.proposal&&this.fullElement.querySelector("input").dispatchEvent(new Event("change")),e===a.AUTO||e===a.RECREATE?(this.readOnlyField.value=i.proposal,this.hiddenField.value=i.proposal,this.inputField.value=i.proposal):this.hiddenField.value=i.proposal}).finally(()=>{this.request=null})}getAvailableFieldsForProposalGeneration(){const e={};for(const[t,i]of Object.entries(this.fieldsToListenOn)){null!==document.querySelector('[data-formengine-input-name="'+i+'"]')&&(e[t]=i)}return e}hasPostModifiersDefined(){return Array.isArray(this.options.config.generatorOptions.postModifiers)&&this.options.config.generatorOptions.postModifiers.length>0}}}));
\ No newline at end of file
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