startime/endtime are forced to "today" after saving
Since v10.4.18 we face a regression when using @'range' on a date/time field.
How to reproduce¶
Take any TCA definition and put some
lower constraint on the range of
endtime. Here is an example of such a problematic definition (which originates back from many versions of TYPO3):
'endtime' => [ 'exclude' => 1, 'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.endtime', 'config' => [ 'type' => 'input', 'size' => 13, 'eval' => 'datetime', 'checkbox' => 0, 'default' => 0, 'range' => [ 'lower' => mktime(0, 0, 0, date('m'), date('d'), date('Y')) ], 'behaviour' => [ 'allowLanguageSynchronization' => true, ], 'renderType' => 'inputDateTime', ], ],
Even if that definition not really makes sense anymore since TCA is cached since TYPO3 v9, this was never a problem but is suddenly breaking (typically) custom records:
- Create a (or update an existing) record having those
- Upon saving the (empty) start/end fields are now populated with the date on midnight (+ GMT/timezone offset) of the day you last cleared the whole cache
- You CANNOT clear that field again
This is highly breaking because typically for the
endtime field, this has impact on records you create/edit and can be particularly weird in relation with IRRE where you don't always see that such a visibility restriction has been enforced.
Thanks to Benni, it looks like that the culprit commit is https://git.typo3.org/Packages/TYPO3.CMS.git/blobdiff/ae55eef595bdd4d0676d3b9d96cfc08a4f327527..adce6dbe8b305c71c447929bc14e5c87b4ad6954:/typo3/sysext/core/Classes/DataHandling/DataHandler.php
and particularly (for me, by reading) to this part:
+ && ( + !isset($tcaFieldConf['default']) + || floor($res['value']) !== (int)$tcaFieldConf['default'] + || ceil($res['value']) !== (int)$tcaFieldConf['default'] + )
Indeed, there's the use of
floor() with a strict comparison with an
int-cast of the default value. having "0" as value in the field (if empty), leads to
ceil() to return a double which is strictly compared to an int and can logically never be true.
Again, by reading only, not tested so far:
+ && ( + !isset($tcaFieldConf['default']) + || (int)floor($res['value']) !== (int)$tcaFieldConf['default'] + || (int)ceil($res['value']) !== (int)$tcaFieldConf['default'] + )