Skip to content

Commit 55ab3de

Browse files
committed
[BUGFIX] Add FormEngine transformation for dbType=datetime in flexforms
The database-to-backend-from transformation for dbType=datetime fields (which are supposed to be stored in native databse DATETIME fields, but are stored as datetime strings in flexforms) were not configured. As a consequence the raw value (not an ISO8601 string, but Date + Time separated by a space-char) was passed into formengine and incorrectly interpreted as timestamp, because it failed to be parsed as a ISO8601 date. Add this configuration and remove the previously erroneously used timestamp parsing which is no longer needed since #104309 and was only implicitly used to transform the datetime, which hid this bug by resolving into an incorrectly created date. For this invalid case we'll now throw an error instead of hiding this case with an invalid transformation. Note that this cleanup is related to #104309, but the issue has been present before. Prior to #104309 the field was rendered as "Invalid DateTime", while the switch to ISO8601 in #104309 resulted in an invalid date to be generated: A flexform value like "1960-01-01 05:42:23" was interpreted as 1960 seconds (unix timestamp) after 1970 which results in a fake-date to be calculated: 1970-01-01T00:32:40Z (32:40 because 1960s = 32 * 60 + 40). Releases: main, 13.4, 12.4 Resolves: #105550 Related: #104309 Change-Id: Ibbf4b4e709358247d6eb8d006bedb05818f1d9c2 Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/86912 Reviewed-by: Benjamin Franzke <ben@bnf.dev> Tested-by: Benni Mack <benni@typo3.org> Reviewed-by: Benni Mack <benni@typo3.org> Reviewed-by: Andreas Kienast <akienast@scripting-base.de> Tested-by: Andreas Kienast <akienast@scripting-base.de> Tested-by: Benjamin Franzke <ben@bnf.dev> Tested-by: core-ci <typo3@b13.com>
1 parent 3e3381a commit 55ab3de

File tree

5 files changed

+98
-63
lines changed

5 files changed

+98
-63
lines changed

Build/Sources/TypeScript/backend/form-engine-validation.ts

Lines changed: 5 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,6 @@ export default class FormEngineValidation {
137137
* Format field value
138138
*/
139139
public static formatValue(type: string, value: string|number): string {
140-
let theString = '';
141140
switch (type) {
142141
case 'date':
143142
case 'datetime':
@@ -147,27 +146,16 @@ export default class FormEngineValidation {
147146
if (value === '' || value === '0') {
148147
return '';
149148
}
150-
151149
const isoDt = DateTime.fromISO(String(value), { zone: 'utc' });
152-
if (isoDt.isValid) {
153-
return isoDt.toISO({ suppressMilliseconds: true });
154-
}
155-
156-
const parsedInt = typeof value === 'number' ? value : parseInt(value, 10);
157-
if (isNaN(parsedInt)) {
158-
theString = '';
159-
} else {
160-
const dt = DateTime.fromSeconds(parsedInt, { zone: 'utc' });
161-
theString = dt.toISO({ suppressMilliseconds: true });
150+
if (!isoDt.isValid) {
151+
throw new Error('Invalid ISO8601 DateTime string: ' + value);
162152
}
163-
break;
153+
return isoDt.toISO({ suppressMilliseconds: true });
164154
case 'password':
165-
theString = (value) ? FormEngineValidation.passwordDummy : '';
166-
break;
155+
return (value) ? FormEngineValidation.passwordDummy : '';
167156
default:
168-
theString = value.toString();
157+
return value.toString();
169158
}
170-
return theString;
171159
}
172160

173161
/**

Build/Sources/TypeScript/backend/tests/form-engine-validation-test.ts

Lines changed: 84 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,16 @@ interface FormEngineConfig {
99
interface FormatValueData {
1010
description: string,
1111
type: string,
12-
value: number|string,
12+
value: string,
1313
result: string
1414
}
1515

16+
interface FormatInvalidValueData {
17+
description: string,
18+
type: string,
19+
value: number|string,
20+
}
21+
1622
interface ProcessValueData {
1723
description: string,
1824
command: string,
@@ -59,24 +65,6 @@ function using(values: (() => Values)|Values, func: (...args: unknown[]) => void
5965

6066
describe('TYPO3/CMS/Backend/FormEngineValidationTest:', () => {
6167
const formatValueDataProvider: Array<FormatValueData> = [
62-
{
63-
'description': 'returns empty string with string 0',
64-
'type': 'date',
65-
'value': '0',
66-
'result': ''
67-
},
68-
{
69-
'description': 'returns date with int 0',
70-
'type': 'date',
71-
'value': 0,
72-
'result': '1970-01-01T00:00:00Z'
73-
},
74-
{
75-
'description': 'works for type date with timestamp',
76-
'type': 'date',
77-
'value': 10000000,
78-
'result': '1970-04-26T17:46:40Z'
79-
},
8068
{
8169
'description': 'works for type date with iso date',
8270
'type': 'date',
@@ -90,23 +78,17 @@ describe('TYPO3/CMS/Backend/FormEngineValidationTest:', () => {
9078
'result': '2016-12-02T11:16:06Z'
9179
},
9280
{
93-
'description': 'returns empty string with non-iso date',
81+
'description': 'works for type date with empty value',
9482
'type': 'date',
95-
'value': 'foo',
83+
'value': '',
9684
'result': ''
9785
},
9886
{
99-
'description': 'works for type datetime',
100-
'type': 'datetime',
87+
'description': 'works for type date with 0 value',
88+
'type': 'date',
10189
'value': '0',
10290
'result': ''
10391
},
104-
{
105-
'description': 'works for type datetime with timestamp',
106-
'type': 'datetime',
107-
'value': 10000000,
108-
'result': '1970-04-26T17:46:40Z'
109-
},
11092
{
11193
'description': 'works for type datetime with iso date',
11294
'type': 'datetime',
@@ -120,35 +102,53 @@ describe('TYPO3/CMS/Backend/FormEngineValidationTest:', () => {
120102
'result': '2016-12-02T11:16:06Z'
121103
},
122104
{
123-
'description': 'resolves to empty result for zero value',
105+
'description': 'works for type datetime with empty value',
124106
'type': 'datetime',
125-
'value': '0',
107+
'value': '',
126108
'result': ''
127109
},
128110
{
129-
'description': 'resolves to empty result for invalid value',
111+
'description': 'works for type datetime with 0 value',
130112
'type': 'datetime',
131-
'value': 'invalid',
113+
'value': '0',
132114
'result': ''
133115
},
134116
{
135-
'description': 'works for type time',
117+
'description': 'works for type time with iso date',
136118
'type': 'time',
137-
'value': 0,
138-
'result': '1970-01-01T00:00:00Z'
119+
'value': '2016-12-02T11:16:06Z',
120+
'result': '2016-12-02T11:16:06Z'
139121
},
140122
{
141-
'description': 'works for type time with timestamp',
123+
'description': 'works for type time with empty value',
142124
'type': 'time',
143-
'value': 10000000,
144-
'result': '1970-04-26T17:46:40Z'
125+
'value': '',
126+
'result': ''
145127
},
146128
{
147-
'description': 'works for type time with iso date',
129+
'description': 'works for type time with 0 value',
148130
'type': 'time',
149-
'value': '2016-12-02T11:16:06.000Z',
131+
'value': '0',
132+
'result': ''
133+
},
134+
{
135+
'description': 'works for type timesec with iso date',
136+
'type': 'timesec',
137+
'value': '2016-12-02T11:16:06Z',
150138
'result': '2016-12-02T11:16:06Z'
151-
}
139+
},
140+
{
141+
'description': 'works for type timesec with empty value',
142+
'type': 'timesec',
143+
'value': '',
144+
'result': ''
145+
},
146+
{
147+
'description': 'works for type timesec with 0 value',
148+
'type': 'timesec',
149+
'value': '0',
150+
'result': ''
151+
},
152152
];
153153

154154
describe('tests for formatValue', () => {
@@ -161,6 +161,48 @@ describe('TYPO3/CMS/Backend/FormEngineValidationTest:', () => {
161161
});
162162
});
163163

164+
const formatInvalidValueDataProvider: Array<FormatInvalidValueData> = [
165+
{
166+
'description': 'throws error with int 0',
167+
'type': 'date',
168+
'value': 0,
169+
},
170+
{
171+
'description': 'throws error for type date with timestamp',
172+
'type': 'date',
173+
'value': 10000000,
174+
},
175+
{
176+
'description': 'throws error with non-iso date',
177+
'type': 'date',
178+
'value': 'foo',
179+
},
180+
{
181+
'description': 'throws error for type datetime with timestamp',
182+
'type': 'datetime',
183+
'value': 10000000,
184+
},
185+
{
186+
'description': 'throws error for invalid value',
187+
'type': 'datetime',
188+
'value': 'invalid',
189+
},
190+
{
191+
'description': 'throws error for type time with timestamp',
192+
'type': 'time',
193+
'value': 10000000,
194+
},
195+
];
196+
197+
describe('tests for invalid value to formatValue', () => {
198+
using(formatInvalidValueDataProvider, function(testCase: FormatInvalidValueData) {
199+
it(testCase.description, () => {
200+
FormEngineValidation.initialize(document.createElement('form'));
201+
expect(() => FormEngineValidation.formatValue(testCase.type, testCase.value)).to.throw();
202+
});
203+
});
204+
});
205+
164206
const processValueDataProvider: Array<ProcessValueData> = [
165207
{
166208
'description': 'works for command alpha with numeric value',

0 commit comments

Comments
 (0)