Mein Ziel war es Termine auf einer Webseite anzuzeigen und diese am Besten komfortabel von unterwegs zu ändern bzw. zu ergänzen. Daraus entstand die Idee, einen Google-Kalender als Grundlage zu nehmen, da sich so ein Kalender einfach auf dem Smartphone sowie am PC im Browser verwalten lässt.
Da die Termine des Kalenders, den man dazu nutzt, ja öffentlich sichtbar sein sollen, muss man den Kalender im Google-Konto unter den Kalendereinstellungen öffentlich machen. Anschließend kann man über die Kalenderadresse (ebenfalls in den Kalendereinstellungen zu finden) auf die ICS-Datei zu greifen.
BEGIN:VEVENT DTSTART:20161222T180000Z DTEND:20161222T190000Z DTSTAMP:20170113T194254Z UID:08vrhqa8n51g1nlejngf4bl02k@google.com CREATED:20170104T193610Z DESCRIPTION: LAST-MODIFIED:20170104T193610Z LOCATION: SEQUENCE:0 STATUS:CONFIRMED SUMMARY:Testtermin TRANSP:TRANSPARENT BEGIN:VALARM ACTION:DISPLAY DESCRIPTION:This is an event reminder TRIGGER:-P0DT0H10M0S END:VALARM END:VEVENT
Hinweis: In der ICS-Datei sind alle Termine enthalten, die jemals in den Kalender eingetragen wurden, d.h. die Dateigröße wächst stetig.
Folgendes Script wandelt die ICS-Datei in ein Array um:
function get_event_array($source) { $handle = fopen($source,"r"); $event = false; $multipleLines = false; $multipleLinesKey = ''; unset($events); $events = array(); if($handle) { while(($line = fgets($handle, 4096)) !== false) { if (trim($line) == "BEGIN:VEVENT") { $obj = null; $event = true; $line = fgets($handle, 4096); $multipleLines = false; } if (startsWith($line, "DESCRIPTION:")) { $multipleLines = true; $parts = explode(":", $line); $key = $parts[0]; $multipleLinesKey = $key; unset($parts[0]); $obj[$multipleLinesKey] = trim(implode(":", $parts)); } elseif (startsWith($line, "ATTACH;")) { $multipleLines = true; $parts = explode(";", $line); $key = $parts[0]; $multipleLinesKey = $key; $parts2 = explode(":", $parts[1]); unset($parts2[0]); $obj[$multipleLinesKey] = implode(":", $parts); } elseif (startsWith($line, "DTSTART;VALUE=DATE:") ) { $parts = explode(";", $line); $key = $parts[0]; $parts2 = explode(":", $parts[1]); unset($parts2[0]); $obj[$key] = implode(":", $parts2); $multipleLines = false; } elseif (startsWith($line, "DTSTART") && !startsWith($line, "DTSTART;TZID=")) { $parts = explode(":", $line); $key = $parts[0]; unset($parts[0]); $obj[$key] = implode(":", $parts); $multipleLines = false; } elseif (startsWith($line, ' ')) { if ($multipleLines) $obj[$multipleLinesKey] .= trim($line); } else { $parts = explode(":", $line); $key = $parts[0]; unset($parts[0]); $obj[$key] = implode(":", $parts); $multipleLines = false; } if (trim($line) == "END:VEVENT" && $event == true) { $event = false; $events[] = $obj; $multipleLines = false; } } fclose($handle); return $events; } }
Der Teil vor dem Doppelpunkt einer jeden Zeile ist der Schlüssel des assoziativen Arrays.
Dieses Array lässt sich mit folgenden Zeilen nach dem Startdatum sortieren:
$sortArray = array(); foreach($eventsdata as $key => $array) { $sortArray[$key] = $array['DTSTART']; } array_multisort($sortArray, SORT_ASC, SORT_NUMERIC, $eventsdata);
Da hier die Verarbeitung der Daten doch relativ aufwändig ist, nutze ich hier einen Cronjob, der das Script zyklisch automatisch ausführt und die Termine in eine MySQL-Datenbank speichert.
Bei der Verwendung der Termine ist zu beachten, dass bei den Zeitangaben in der ICS-Datei keine Zeitzoneninformationen mitgegeben werden. Deswegen prüfe ich auf Sommer/Winterzeit und passe die Uhrzeit manuell an:
if (date('I', $event_date) == 1) { $event_time = strtotime(substr($event['DTSTART'],9,2).":".substr($event['DTSTART'],11,2).":".substr($event['DTSTART'],13,2)) + 7200; } else { $event_time = strtotime(substr($event['DTSTART'],9,2).":".substr($event['DTSTART'],11,2).":".substr($event['DTSTART'],13,2)) + 3600; }
Thanks, great article.