This repository has been archived on 2024-02-15. You can view files and clone it, but cannot push or open issues or pull requests.
webseite-krautspace/src/getEvents.php
+++ 2048026c27 neue ordnerstruktur, php-code hinzugefügt
die ordner public und src hinzugefügt,
zapcallib.php für iCalendar files hinzugefügt,
getContent.php und getEvent.php hinzugefügt
2022-02-18 11:59:12 +01:00

488 lines
12 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
/**
* Datei: getEvents.php
* Autor: bernd@nr18.space
* Letze Änderung: 08.07.2020
* Kurzbeschreibung:
* Enthält Funktionen zum Parsen und Ausgeben einer iCalendar Kalenderdatei.
* Die Bibliothek zum Parsen des iCalendarfiles stammt von ZContent.
* Der Quelltext liegt auf https://github.com/zcontent/icalendar. Da sie
* auf calendar.org verlinkt war, dachte ich eigentlich, daß sie gut wäre.
*/
require_once("../src/lib/zapcallib.php");
function printEventList(): bool
{
/**
* Die Startfuktion für die Ausgabe der Termine als Liste in index.php.
* Nach erfolgreicher initialisierung läuft die Funktion durch das Array
* der Events (ZCalNode´s vom Typ 'VEVENT') ruft für jedes Element erst
* die Funktion zur Umwandlung in ein assoziatives Array und dann die
* Ausgabefunktion auf. Gibt einen Boolean zurück.
*/
$events = initEvents();
$helper = new ZDateHelper();
date_default_timezone_set("UTC");
/**
* Startdatum für wiederkehrende Termine aktualisieren
*
* @var ZCiCalNode $event
*/
foreach ($events as $event)
{
/**
* @var ZCiCalDataNode $eventDTStart
*/
$eventDTStart = $event->data['DTSTART'];
/** @var string[] $eventDTStartValues */
$eventDTStartValues = $eventDTStart->value;
$event_start = $eventDTStartValues[0] ?? '';
$unix_start = $helper->fromiCaltoUnixDateTime($event_start);
$rrule = $event->data['RRULE']->value[0];
//todo rrule always set
if (EventIsPast($unix_start) === true AND isset ($rrule))
{
$new_unix = calculateNextStart($unix_start, $rrule);
$date = date('Ymd', $new_unix);
$time = date('His', $new_unix);
$connector = 'T';
$new_start = "{$date}{$connector}{$time}";
$event->data['DTSTART']->value[0] = $new_start;
}
}
/**
* Eventliste nach Startdatum sortieren
*/
usort($events, 'compareEventStart');
/**
* Termine ausgeben
*/
foreach ($events as $event)
{
printListItem($event);
}
return true;
}
function printListItem(ZCiCalNode $event): bool
/**
* Die Ausgabefunktion für die Ausgabe der Termine als Liste. Hier wird die
* Zeitangabe des iCal-Formates in Datum, Uhrzeit und Wochentag umgewandelt.
* Anschließend erfolgt die Ausgabe der einzelnen Teile.
*/
{
date_default_timezone_set("UTC");
$helper = new ZDateHelper();
$hyph = " - ";
$uhr = " Uhr";
$komma = ", ";
$event_start = $event->data['DTSTART']->value[0];
$event_url = lowerURL($event->data['URL']->parameter['value']);
$event_title = $event->data['SUMMARY']->value[0];
$event_location = trim($event->data['LOCATION']->value[0], '"');
$event_descr = trim($event->data['DESCRIPTION']->value[0], '"');
$unix = $helper->fromiCaltoUnixDateTime($event_start);
$event_date = date('d.m.Y', $unix);
$event_time = date('H:i', $unix);
$event_day = toGerman(date('l', $unix));
$dateline = "{$event_day}{$komma}{$event_date}{$hyph}{$event_time}{$uhr}";
displayHeadline($dateline, $event_title);
displayLocation($event_location);
displayDescription($event_descr);
displayURL($event_url);
return true;
}
function displayHeadline(string $dateline, $event_title): bool
{
echo "\n<section class='termin'>\n";
echo "<p class='headline'>" . $dateline . ": " . $event_title . "</p>\n";
return true;
}
function displayLocation(string $location): bool
{
echo "<ul class='events'>\n";
echo "<li>$location</li>\n";
return true;
}
function displayDescription(string $description): bool
{
echo "<li>$description</li>\n";
return true;
}
function displayURL(string $url): bool
{
$stripped = trim($url, '"');
echo "<li><a href=" . $url . ">" . $stripped . "</a></li>\n";
echo "</ul>\n";
echo "</section>\n";
return true;
}
/**
* Die Startfuktion für die Ausgabe der Termine als Tabelle in termine.php
*/
function printEventTable(): bool
{
$events = initEvents();
printTableHead();
foreach ($events as $event)
{
$event_array = getEventArray($event);
printTableItem($event_array);
}
echo "\t</tbody>\n";
echo "</table>\n";
return true;
}
function printTableHead()
{
echo "\n\r<table class='w3-table w3-bordered'>\n";
echo "\t<thead>\n";
echo "\t<tr>\n";
echo "\t\t<th>Datum</th>\n";
echo "\t\t<th>Wochentag</th>\n";
echo "\t\t<th>Zeit</th>\n";
echo "\t\t<th>Ort</th>\n";
echo "\t\t<th>Titel</th>\n";
echo "\t\t<th>Beschreibung</th>\n";
echo "\t</tr>\n";
echo "\t</thead>\n";
echo "\t<tbody>\n";
}
function printTableItem($event_array): bool
{
date_default_timezone_set("UTC");
$time = $event_array['DTSTART'];
$helper = new ZDateHelper();
$unix = $helper->fromiCaltoUnixDateTime($time);
$event_date = date('d.m.Y', $unix);
$event_time = date('H:i', $unix);
$event_day = toGerman(date('l', $unix));
$event_uid = $event_array['UID'];
$event_url = lowerURL($event_array['URL']);
$event_title = trim($event_array['SUMMARY'], '"');
$event_descr = trim($event_array['DESCRIPTION'], '"');
$event_location = trim($event_array['LOCATION'], '"');
echo "\t<tr id='" . $event_uid . "'>\n";
echo "\t\t<td>" . $event_date . "</td>\n";
echo "\t\t<td>" . $event_day . "</td>\n";
echo "\t\t<td>" . $event_time . " Uhr</td>\n";
echo "\t\t<td>" . $event_location . "</td>\n";
echo "\t\t<td>" . $event_title . "</td>\n";
echo "\t\t<td>" . $event_descr;
printURL($event_url);
echo "\t</tr>\n";
return true;
}
function printURL(string $url): bool
{
$stripped = trim($url, '"');
if ($url != '')
{
echo "</br><a class='event' href=" . $url . ">" . $stripped . "</a></td>\n";
}
else
{
echo "</td>\n";
}
return true;
}
/**
* Funktionen, die von beiden Ausgaben benutzt werden.
*/
/**
* @return ZCiCalNode[]|null
*/
function initEvents(): ?array
/**
* Allgemeingültige Funktion zur Initialisierung. Enthält die Schritte, die
* von beiden Ausgaben gleichermaßen gebraucht werden.
* - Erstellen des iCalendar Objekts (initCalendar).
* - Schaut, ob der Kalender überhaupt Events enthält (printEventCount).
* - Sammel alle Events in einer Liste (grabEvents).
* Gibt zweidimmensionales assoziatives Array oder Null zurück.
*/
{
$iCalObj = initCalendar();
if (!isset ($iCalObj))
{
printError("Fehler beim Initialisieren des Kalenders");
return null;
}
$count = printEventCount($iCalObj);
if ($count == 0 or $count == false)
{
return null;
}
$events = grabEvents($iCalObj);
return $events;
}
function initCalendar(): ?ZCiCal
/**
* Erstellt das Kalenderobjekt vom Typ ZCiCal.
* Gibt das Kalenderobjekt oder Null zurück.
*/
{
$iCalFile = '../public/krautspace.ics';
$iCalString = file_get_contents($iCalFile);
if ($iCalString == false)
{
printError("Kann Kalenderdatei nicht lesen");
return null;
}
$iCalObj = new ZCiCal($iCalString);
return $iCalObj;
}
function printEventCount(ZCiCal $iCalObj): ?int
/**
* Gibt die Anzahl der Events zurück, die das übergebene
* Kalenderobjekt enthält. Im Fehlerfall wird Null zurück
* gegeben.
*/
{
$eventCount = $iCalObj->countEvents();
if (!isset ($eventCount))
{
printError("Fehler beim Parsen des Kalenders");
return null;
}
// echo "<p>$eventCount anstehende Events</p>";
return $eventCount;
}
function grabEvents(ZCiCal $iCalObj): ?array
{
/**
* Läuft durch das iCalendar objekt und sammelt alle Nodes vom Typ
* 'VEVENT' ein. Gibt ein Array mit Objekten vom Typ 'ZCiCalNode' zurück.
* Im Fehlerfall wird Null zurück gegeben.
*/
$events = [];
if (isset ($iCalObj->tree->child))
{
foreach ($iCalObj->tree->child as $node)
{
if ($node->getName() == "VEVENT")
{
$events[] = $node;
}
}
}
else
{
printError("Cant find nodes");
return null;
}
return $events;
}
function getEventArray(ZCiCalNode $node): array
{
/**
* Bekommt eine Event Node vom Typ 'ZiCalNode' übergeben und extrahiert
* daraus die gewünschten Elemente. Bildet daraus ein zweidimmensionales
* assoziatives Array. Gibt dieses Array zurück.
* Wird derzeit nur von der tabellarischen Ausgabe referenziert, welche
+ momentan nicht genutzt wird.
*/
/**
* @var ZCiCalNode $node
* @var ZCiCalDataNode $event
*/
$event = $node->data;
$event_array = [];
$keys = array('DTSTART', 'SUMMARY', 'DESCRIPTION', 'URL', 'LOCATION');
foreach ($keys as $key)
{
$event_array[$key] = $event[$key]->value[0];
if ($key === 'DTSTART')
{
if (isset ($event[$key]->parameter['tzid']))
{
$event_array['TZ'] = $event[$key]->parameter['tzid'];
}
}
else if ($key === 'URL')
{
$event_array[$key] = $event[$key]->parameter['value'];
}
}
return $event_array;
}
function printError($errMsg)
{
echo "\n\r<p>$errMsg</p>\n\r";
return true;
}
function toGerman(string $day): string
{
switch ($day)
{
case 'Monday':
return 'Montag';
case 'Tuesday':
return 'Dienstag';
case 'Wednesday':
return 'Mittwoch';
case 'Thursday':
return 'Donnerstag';
case 'Friday':
return 'Freitag';
case 'Saturday':
return 'Samstag';
case 'Sunday':
return 'Sonntag';
default:
return '?';
}
}
function lowerURL(string $url): string
{
$old = array('HTTPS', 'HTTP', 'FTP', 'WWW', 'SSH');
$new = array('https', 'http', 'ftp', 'www', 'ssh');
$new_url = str_replace($old, $new, $url);
return $new_url;
}
function calculateNextStart(int $unix_start, string $rrule): int
/**
* Berechnet für wiederkehrende Termine den aktuell nächsten Termin.
* dabei werden zur Zeit nur der der Zeitraum zwischen zwei Terminen
* und eine mögliche Anzahl der Termine berücksichtigt. Gibt den neuen
* Termin als Unix-Zeitstempel zurück.
*/
{
$counter = 0;
$rule_array = getRuleArray($rrule);
if (isset ($rule_array['COUNT']))
{
$count = $rule_array['COUNT'];
}
if (isset ($rule_array['FREQ']))
{
$frequency = $rule_array['FREQ'];
}
if (isset ($rule_array['INTERVAL']))
{
$interval = $rule_array['INTERVAL'];
}
if (isset ($rule_array['UNTIL']))
{
//todo implement
$until_string = $rule_array['UNTIL'];
}
$freq_offset = getOffset($frequency);
if (isset ($interval))
{
$offset = $freq_offset * $interval;
}
else
{
$offset = $freq_offset;
}
while ($unix_start <= time())
{
if (isset ($count))
{
if ($counter >= $count)
{
break;
}
}
$unix_start = $unix_start + $offset;
$counter = $counter + 1;
}
return $unix_start;
}
function getOffset(string $frequence): int
{
switch ($frequence)
{
case 'HOURLY':
return 3600;
case 'DAILY':
return 86400;
case 'WEEKLY':
return 604800;
default:
return 1;
}
}
function getRuleArray(string $rrule): array
/**
* Zerlegt den String einer RRULE und gibt die einzelnen Elemente als
* assoziatives Array zurück.
*/
{
$rule_array = [];
$rule_strings = explode(';', $rrule);
foreach ($rule_strings as $r_string)
{
$rule = explode('=', $r_string);
$rule_array[$rule[0]] = $rule[1];
}
return $rule_array;
}
function EventIsPast(int $unix_start): bool
/**
* Prüft, ob die übergebenen Unixzeit älter als der aktuelle Tag ist. Gibt
* Wahr oder Falsch zurück.
*/
{
$event_date = date('d.m.Y', $unix_start);
$day_end = strtotime($event_date) + 86400;
$actual_date = time();
if ($day_end < $actual_date)
{
return true;
}
return false;
}
/**
* Bekommt zwei Eventnodes übergeben und vergleicht deren Startdatum. Die
* Funktion wird intern von ausort() benutzt, um das Array mit den Eventnodes
* nach Datum zu sortieren.
*
* @param ZCiCalNode $event_a
* @param ZCiCalNode $event_b
* @return int
*/
function compareEventStart(ZCiCalNode $event_a, ZCiCalNode $event_b): int
{
$a = $event_a->data['DTSTART']->value[0];
$b = $event_b->data['DTSTART']->value[0];
return $a <=> $b;
}