Hallo zusammen.
Ich habe eine Lösung für mich gefunden, die allerdings etwas häßlich ist. Eigentlich braucht es wohl ein ganz eigenes Modul. Aber ich kenne Contao nicht unter der Haube und konnte deswegen nur die bestehenden Module aufbohren. Ich fasse zusammen.
Das Problem:
Ich möchte einer Gruppe von Frontend-Usern die Möglichkeit geben, in dem bekannten Standard-Kalender selber eine Veranstaltung (Event) eintragen zu können. Derzeit können das nur autorisierte Backend-User. Des Weiteren sollen Frontend-User zu eingetragenen Veranstaltungen (Events) ihre Teilnahme eintragen können.
Bemerkung:
(1) Eigentlich braucht das ein eigenes, neues Modul. Wer sich irgendwann da mal dransetzen möchte, immer her damit. Leider habe ich bislang zu wenig Zeit und Muße, mich so tief in Contao reinzufriemeln.
(2) Ich habe noch folgende Erweiterung installiert, die natürlich nicht nötig ist: simple_event_registration. Im folgenden verwende ich einige Tabellenfelder mit Prefix "ser_". Diese könnt ihr einfach ignorieren, wenn ihr das nicht nutzen wollt.
Meine Lösung:
(a) Event-Formular
Als erstes Dank an Nikolas (Rundinhio) für den Hinweis auf den Formular-Generator. Tatsächlich läßt sich mit der Möglichkeit, eine Tabelle direkt ansprechen zu können, viel erreichen. Ein Bild sagt mehr als tausend Worte. Also:
Als Auswahl-Modul für Datum und Uhrzeit habe ich xdependentcalendarfields bzw. formtimeselection (findet ihr unter der Rubrik "Uhrzeit") benutzt. Danke an Wolfgang (Wolfi) für den Tipp! Achtet bei der Konfiguration des Datums (xdependentcalendarfields) darauf, auf keinen Fall "Heutiges Datum" mit Haken zu aktivieren! Sonst greift ein Bug im Frontend.
Das sind jetzt die sichtbaren Felder, die für meinen Fall schon ausreichen. Es braucht jetzt noch unsichtbare Felder, die ich aus Platzgründen textuell anhänge:
Versteckte Felder und Werte:
pid: 1
published: 1
ser_register: 1
author: 1
ser_email: {{user::email}}
endDate: [kein Wert]
startTime: [kein Wert]
endTime: [kein Wert]
Sachen wie pid oder author brauche ich für meinen simplen Anwendungsfall nicht. Deshalb erlaube ich mir, damit Schindluder zu treiben und setze sie einfach auf "1". Für andere von euch kann das anders sein. Ich habe auch nirgendwo lesen können, was pid genau macht. Also ignorier ich das einfach. Warum ich endDate, startTime und endTime noch brauche, erfahrt ihr unten.
Unter den Eigenschaften des Formulars setze ich als Aktion die Tabelle 'tl_calendar_events':
(b) Datumsformat konvertieren
Jetzt kommt das von Wolfgang beschriebene Riesenproblem mit dem Datumsformat. Im Formular ist das Datum per bequemen Datumswähler einfach ein Text mit folgendem Format: TT-MM-JJJJ (oder Englisch: DD-MM-YYYY). Das versteht die Contao-DB nicht, die fast überall mit Unix-Timestamps arbeitet. Also muß das vor dem Speichern konvertiert werden. Da ich in der Backend-Programmierung so fast Null drinsteck, konvertiere ich das im Frontend mit dem Schmerz, der da Javascript heißt. In Themes/Seitenlayout zu der Seite kommt im Bereich "Zusätzliche <head>-Tags" folgender Code.
Code:
<script language="javascript" type="text/javascript">
function convertTimestamp()
{
var startDateElem = document.getElementsByName("startDate");
var endDateElem = document.getElementsByName("endDate");
var startTimeHElem = document.getElementsByName("time[H]");
var startTimeMElem = document.getElementsByName("time[i]");
var startTimeElem = document.getElementsByName("startTime");
var endTimeElem = document.getElementsByName("endTime");
if (startTimeHElem.length > 0 && startTimeMElem.length > 0 &&
startDateElem.length > 0 && endDateElem.length > 0 &&
startTimeElem.length > 0 && endTimeElem.length > 0)
{
var timeCode = startTimeHElem[0].value + ":" + startTimeMElem[0].value;
var timeStamp = dateToUnixTimestamp(startDateElem[0].value, timeCode);
startDateElem[0].value = timeStamp;
endDateElem[0].value = timeStamp;
startTimeElem[0].value = timeStamp;
endTimeElem[0].value = timeStamp;
}
}
function dateToUnixTimestamp(aDateString, aTimeString)
{
var day = aDateString.substr(0, 2);
var month = aDateString.substr(3, 2) - 1;
var year = aDateString.substr(6, 4);
var hour = aTimeString.substr(0, 2);
var minutes = aTimeString.substr(3, 2);
var dateObject = new Date(Date.UTC(year, month, day, hour, minutes, 0));
var unixTimestamp = (dateObject.getTime() / 1000.0);
return unixTimestamp;
}
</script>
(Vielleicht könnt ihr das auch unter "Eigener JavaScript-Code" ablegen. Ich hatte damit mal Probleme, also hab ich es in <head> gepackt.)
Diese Funktion konvertiert ziemlich billo das Format von den Datums- und Zeit-Feldern in das nötige UNIX-Timestamp-Format und legt es in die Felder startDate, endDate, startTime und endTime ab. Wenn ihr eine ausgefuchstere Verwaltung braucht, zum Beispiel für eine Veranstaltung, die über mehrere Tage gehen kann, muß man diesen Code entsprechend verbessern.
Um dieses ECMA-Script bei einem Submit abzufeuern, mußte ich jetzt leider ganz häßlich in die Code-Erzeugung des Formulars eingreifen. Das geschieht in ./system/modules/frontend/FormSubmit.php.
Code:
public function generate()
{
if ($this->imageSubmit && is_file(TL_ROOT . '/' . $this->singleSRC))
{
return sprintf('<input type="image" src="%s" id="ctrl_%s" onClick="convertTimestamp();submit()" class="submit%s" alt="%s" value="%s"%s />',
$this->singleSRC,
$this->strId,
(strlen($this->strClass) ? ' ' . $this->strClass : ''),
specialchars($this->slabel),
specialchars($this->slabel),
$this->getAttributes());
}
return sprintf('<input type="button" id="ctrl_%s" onClick="convertTimestamp();submit()" class="submit%s" value="%s"%s />',
$this->strId,
(strlen($this->strClass) ? ' ' . $this->strClass : ''),
specialchars($this->slabel),
$this->getAttributes());
}
}
Entscheidend sind die Zeilen 95
return sprintf('<input type="image" src="%s" id="ctrl_%s" onClick="convertTimestamp();submit()" class="submit%s" alt="%s" value="%s"%s />',
bzw. 104
return sprintf('<input type="button" id="ctrl_%s" onClick="convertTimestamp();submit()" class="submit%s" value="%s"%s />',
Ob diese Veränderung einer Contao-Aktualisierung standhält, weiß ich nicht. Außerdem wird jetzt leider bei jedem erzeugten Formular immer die Javascript-Funktion convertTimestamp() aufgerufen. Unschön, aber zumindest wird kein Schaden angerichtet.
Als letztes kommt eine weitere Unschönheit. Der Formulargenerator schreibt alle vorgefundenen Werte stoisch in die angegebene Tabelle 'tl_calendar_events'. Eine Möglichkeit, hier zu filtern, gibt es nicht. Die Konvertierungsfunktion holt sich die Uhrzeit-Daten aus zwei Feldern für Stunde und Minute (time[H] und time[i]), um diese anschließend zu manipulieren und in das für die Tabelle nötige Feld startTime, etc. zu übertragen. Leider versucht der Formulargenerator auch die Daten des Feldes "time" zu speichern. (Einen Haken, um das zu deaktivieren, gibt es leider nicht.) Um mich nicht groß aufzuhalten, habe ich dieses Problem (genervt) mit einem kurzen
Code:
ALTER TABLE `tl_calendar_events` ADD `time` VARCHAR( 20 );
gelöst.
Schöne Feiertage
Lesezeichen