Skip to content
Snippets Groups Projects
Commit 0f24df96 authored by Benjamin Franzke's avatar Benjamin Franzke
Browse files

[BUGFIX] Fix workspace stage-change mail recipient selection

Stage-change notification mails have only been delivered to the last
recipient off the list of possible recipients, because
Utility.convertFormToObject failed to detect checkbox elements
from (other) frames.
In this case the to-be-converted form elements are created on the top
frame (modal contents are placed outside list frame on the top frame).

Due to JavaScript being prototype based, instanceof checks do
only operate per-frame. Prototypes are bound to the current window.
`foo instanceof HTMLInputElement` is basically a shortcut
and equivalent to `foo instanceof window.HTMLInputElement`
while `window != top.window`.

Instead of `instanceof` checks, we switch to a `tagName` comparision
which is usable for cross-frame HTMLElement type detection.

Resolves: #99784
Releases: main, 12.4, 11.5
Change-Id: If9bfd7be1e46d8c04619be3563d3bdba9d9de549
Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/79953


Tested-by: default avatarBenjamin Franzke <ben@bnf.dev>
Tested-by: default avatarcore-ci <typo3@b13.com>
Reviewed-by: default avatarBenjamin Franzke <ben@bnf.dev>
parent 69849b3f
Branches
Tags
No related merge requests found
...@@ -129,11 +129,12 @@ class Utility { ...@@ -129,11 +129,12 @@ class Utility {
const value = element.value; const value = element.value;
if (name) { if (name) {
if (element instanceof HTMLInputElement && element.type == 'checkbox') { if (element.tagName.toLowerCase() === 'input' && element.type == 'checkbox') {
const checkbox = element as HTMLInputElement;
if (obj[name] === undefined) { if (obj[name] === undefined) {
obj[name] = []; obj[name] = [];
} }
if (element.checked){ if (checkbox.checked){
obj[name].push(value); obj[name].push(value);
} }
......
...@@ -10,4 +10,4 @@ ...@@ -10,4 +10,4 @@
* *
* The TYPO3 project - inspiring people to share! * The TYPO3 project - inspiring people to share!
*/ */
class Utility{static trimExplode(t,e){return e.split(t).map((t=>t.trim())).filter((t=>""!==t))}static trimItems(t){return t.map((t=>t instanceof String?t.trim():t))}static intExplode(t,e,r=!1){return e.split(t).map((t=>parseInt(t,10))).filter((t=>!isNaN(t)||r&&0===t))}static isNumber(t){return!isNaN(parseFloat(t.toString()))&&isFinite(t)}static getParameterFromUrl(t,e){if(console.warn("The function `getParameterFromUrl()` of `@typo3/backend/utility` has been marked as deprecated and will be removed in TYPO3 v13. Use `new URL(url, window.location.origin).searchParams.get(parameter)` instead."),"function"!=typeof t.split)return"";const r=t.split("?");let i="";if(r.length>=2){const t=r.join("?"),n=encodeURIComponent(e)+"=",a=t.split(/[&;]/g);for(let t=a.length;t-- >0;)if(-1!==a[t].lastIndexOf(n,0)){i=a[t].split("=")[1];break}}return i}static updateQueryStringParameter(t,e,r){const i=new RegExp("([?&])"+e+"=.*?(&|$)","i"),n=t.includes("?")?"&":"?";return t.match(i)?t.replace(i,"$1"+e+"="+r+"$2"):t+n+e+"="+r}static convertFormToObject(t){const e={};return t.querySelectorAll("input, select, textarea").forEach((t=>{const r=t.name,i=t.value;r&&(t instanceof HTMLInputElement&&"checkbox"==t.type?(void 0===e[r]&&(e[r]=[]),t.checked&&e[r].push(i)):e[r]=i)})),e}static mergeDeep(...t){const e=t=>t&&"object"==typeof t;return t.reduce(((t,r)=>(Object.keys(r).forEach((i=>{const n=t[i],a=r[i];Array.isArray(n)&&Array.isArray(a)?t[i]=n.concat(...a):e(n)&&e(a)?t[i]=Utility.mergeDeep(n,a):t[i]=a})),t)),{})}static urlsPointToSameServerSideResource(t,e){if(!t||!e)return!1;const r=window.location.origin;try{const i=new URL(t,Utility.isValidUrl(t)?void 0:r),n=new URL(e,Utility.isValidUrl(e)?void 0:r),a=i.origin+i.pathname+i.search;return a===n.origin+n.pathname+n.search}catch(t){return!1}}static isValidUrl(t){try{return new URL(t),!0}catch(t){return!1}}}export default Utility; class Utility{static trimExplode(t,e){return e.split(t).map((t=>t.trim())).filter((t=>""!==t))}static trimItems(t){return t.map((t=>t instanceof String?t.trim():t))}static intExplode(t,e,r=!1){return e.split(t).map((t=>parseInt(t,10))).filter((t=>!isNaN(t)||r&&0===t))}static isNumber(t){return!isNaN(parseFloat(t.toString()))&&isFinite(t)}static getParameterFromUrl(t,e){if(console.warn("The function `getParameterFromUrl()` of `@typo3/backend/utility` has been marked as deprecated and will be removed in TYPO3 v13. Use `new URL(url, window.location.origin).searchParams.get(parameter)` instead."),"function"!=typeof t.split)return"";const r=t.split("?");let i="";if(r.length>=2){const t=r.join("?"),a=encodeURIComponent(e)+"=",n=t.split(/[&;]/g);for(let t=n.length;t-- >0;)if(-1!==n[t].lastIndexOf(a,0)){i=n[t].split("=")[1];break}}return i}static updateQueryStringParameter(t,e,r){const i=new RegExp("([?&])"+e+"=.*?(&|$)","i"),a=t.includes("?")?"&":"?";return t.match(i)?t.replace(i,"$1"+e+"="+r+"$2"):t+a+e+"="+r}static convertFormToObject(t){const e={};return t.querySelectorAll("input, select, textarea").forEach((t=>{const r=t.name,i=t.value;if(r)if("input"===t.tagName.toLowerCase()&&"checkbox"==t.type){const a=t;void 0===e[r]&&(e[r]=[]),a.checked&&e[r].push(i)}else e[r]=i})),e}static mergeDeep(...t){const e=t=>t&&"object"==typeof t;return t.reduce(((t,r)=>(Object.keys(r).forEach((i=>{const a=t[i],n=r[i];Array.isArray(a)&&Array.isArray(n)?t[i]=a.concat(...n):e(a)&&e(n)?t[i]=Utility.mergeDeep(a,n):t[i]=n})),t)),{})}static urlsPointToSameServerSideResource(t,e){if(!t||!e)return!1;const r=window.location.origin;try{const i=new URL(t,Utility.isValidUrl(t)?void 0:r),a=new URL(e,Utility.isValidUrl(e)?void 0:r),n=i.origin+i.pathname+i.search;return n===a.origin+a.pathname+a.search}catch(t){return!1}}static isValidUrl(t){try{return new URL(t),!0}catch(t){return!1}}}export default Utility;
\ No newline at end of file \ No newline at end of file
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