Wird eine Zeile gelöscht, die nicht die letzte im Wizard ist, springt beim nächsten Speichern
das Datum jeder danach folgenden Zeile auf 01.01.1970. Andere Felder (Text, E-Mail) bleiben
korrekt – nur Felder mit rgxp => 'date' (bzw. time/datim) sind betroffen.
Schritte zum Nachstellen:
- Eine Tabelle mit einem MCW-Feld, das eine Spalte mit
'eval' => ['rgxp' => 'date', 'datepicker' => true] hat.
- Drei Zeilen anlegen, in jeder ein Datum setzen (per Kalender-Symbol oder Eintippen – beides betroffen), nach jeder Zeile speichern.
- Formular neu laden.
- Die mittlere Zeile löschen (nicht die letzte!) und speichern.
- Ergebnis: Das Datum der (jetzt) letzten Zeile ist 01.01.1970. Bei mehr als einer Folgezeile dürften alle betroffen sein (nicht eigens getestet).
Ursache:
Zwei zusammenwirkende Stellen:
-
src/Resources/public/js/multicolumnwizard_be_src.js, deleteClick(): Es werden
rows = row.getAllNext() und level = row.getAllPrevious().length berechnet – genau wie
in newClick()/copyClick(), wo damit anschließend updateRowAttributes() auf die
Folgezeilen angewendet wird. In deleteClick() fehlt dieser Aufruf jedoch komplett; die
Variablen werden berechnet und nie benutzt. Nachfolgende Zeilen behalten dadurch ihren
alten Index (per DOM-Inspektion bestätigt: nach dem Löschen von Zeile [1] trägt die
letzte Zeile weiterhin name="feld[2][...]", nicht [1]). Das Formular sendet dadurch ein
Array mit Indexlücke (Schlüssel 0 und 2 statt 0 und 1).
-
src/Contao/Widgets/MultiColumnWizard.php, validator(), etwa Zeile 649: Die
Verarbeitungsschleife läuft for ($i = 0; $i < count($varInput); $i++). Bei einer
Indexlücke (Schlüssel 0 und 2, count($varInput) = 2) werden nur $i = 0 und $i = 1
durchlaufen – der tatsächliche Zeileninhalt bei Schlüssel 2 wird von der Schleife nie
besucht und läuft damit auch nie durch die Datum-zu-Zeitstempel-Umwandlung (Zeile ~681,
new Date($varValue, ...)). Der abschließende Rebuild-Schritt
($sortedData[$sortId] = $varInput[$dataId], Zeile ~752) holt diese Zeile zwar wieder an
die richtige Position zurück – aber unverändert, das Datum bleibt als Text
("25.09.2026") statt als Zeitstempel stehen. Andere Feldtypen benötigen diese Umwandlung
nicht und bleiben deshalb unauffällig korrekt.
-
Beim nächsten Laden wird der gespeicherte Wert mit (int) gecastet. PHPs
String-zu-Zahl-Wandlung liest dabei nur die führenden Ziffern:
(int) "25.09.2026" ergibt 25 – 25 Sekunden nach Mitternacht des 01.01.1970. Das erklärt
auch, warum es exakt dieses Datum ist und nicht irgendein anderes.
Vorschlag:
Entweder (1) deleteClick() ergänzen, sodass es wie newClick()/copyClick() die
Folgezeilen per updateRowAttributes() neu durchnummeriert, oder (2) validator()
robuster gegen Indexlücken machen (z. B. über array_keys($varInput) statt über
count($varInput) iterieren). Beides behebt den Fehler unabhängig voneinander.
Umgebung: menatwork/contao-multicolumnwizard-bundle (aktuell über Composer
^3.4/^3.6), Contao 4.13, PHP 8.3, Chrome.
Wird eine Zeile gelöscht, die nicht die letzte im Wizard ist, springt beim nächsten Speichern
das Datum jeder danach folgenden Zeile auf 01.01.1970. Andere Felder (Text, E-Mail) bleiben
korrekt – nur Felder mit
rgxp => 'date'(bzw.time/datim) sind betroffen.Schritte zum Nachstellen:
'eval' => ['rgxp' => 'date', 'datepicker' => true]hat.Ursache:
Zwei zusammenwirkende Stellen:
src/Resources/public/js/multicolumnwizard_be_src.js,deleteClick(): Es werdenrows = row.getAllNext()undlevel = row.getAllPrevious().lengthberechnet – genau wiein
newClick()/copyClick(), wo damit anschließendupdateRowAttributes()auf dieFolgezeilen angewendet wird. In
deleteClick()fehlt dieser Aufruf jedoch komplett; dieVariablen werden berechnet und nie benutzt. Nachfolgende Zeilen behalten dadurch ihren
alten Index (per DOM-Inspektion bestätigt: nach dem Löschen von Zeile
[1]trägt dieletzte Zeile weiterhin
name="feld[2][...]", nicht[1]). Das Formular sendet dadurch einArray mit Indexlücke (Schlüssel 0 und 2 statt 0 und 1).
src/Contao/Widgets/MultiColumnWizard.php,validator(), etwa Zeile 649: DieVerarbeitungsschleife läuft
for ($i = 0; $i < count($varInput); $i++). Bei einerIndexlücke (Schlüssel 0 und 2,
count($varInput)= 2) werden nur$i = 0und$i = 1durchlaufen – der tatsächliche Zeileninhalt bei Schlüssel 2 wird von der Schleife nie
besucht und läuft damit auch nie durch die Datum-zu-Zeitstempel-Umwandlung (Zeile ~681,
new Date($varValue, ...)). Der abschließende Rebuild-Schritt(
$sortedData[$sortId] = $varInput[$dataId], Zeile ~752) holt diese Zeile zwar wieder andie richtige Position zurück – aber unverändert, das Datum bleibt als Text
("25.09.2026") statt als Zeitstempel stehen. Andere Feldtypen benötigen diese Umwandlung
nicht und bleiben deshalb unauffällig korrekt.
Beim nächsten Laden wird der gespeicherte Wert mit
(int)gecastet. PHPsString-zu-Zahl-Wandlung liest dabei nur die führenden Ziffern:
(int) "25.09.2026"ergibt25– 25 Sekunden nach Mitternacht des 01.01.1970. Das erklärtauch, warum es exakt dieses Datum ist und nicht irgendein anderes.
Vorschlag:
Entweder (1)
deleteClick()ergänzen, sodass es wienewClick()/copyClick()dieFolgezeilen per
updateRowAttributes()neu durchnummeriert, oder (2)validator()robuster gegen Indexlücken machen (z. B. über
array_keys($varInput)statt übercount($varInput)iterieren). Beides behebt den Fehler unabhängig voneinander.Umgebung: menatwork/contao-multicolumnwizard-bundle (aktuell über Composer
^3.4/^3.6), Contao 4.13, PHP 8.3, Chrome.