summaryrefslogtreecommitdiff
path: root/ical-feed.php
diff options
context:
space:
mode:
Diffstat (limited to 'ical-feed.php')
-rw-r--r--ical-feed.php138
1 files changed, 138 insertions, 0 deletions
diff --git a/ical-feed.php b/ical-feed.php
new file mode 100644
index 0000000..ee1eeba
--- /dev/null
+++ b/ical-feed.php
@@ -0,0 +1,138 @@
+<?php
+/* DISPLAY - iCal export
+ *
+ */
+
+function communievents_escape_ical_text($text) {
+ return strtr($text, array(
+ "\\" => "\\\\",
+ ',' => '\,',
+ ';' => '\;',
+ "\r\n" => "\\n", // spec says line breaks need to be \n only
+ "\n" => "\\n"
+ ));
+}
+
+// FIXME! this assumes valid utf-8
+function communievents_fold_ical_line_helper($text, $index, $maxlength) {
+ $length = 0;
+ $i = $index;
+
+ while ($i < strlen($text) && $length < $maxlength) {
+ $c = ord($text[$i]);
+ if ($c < 128) {
+ $clen = 1;
+ } else if ($c < 224) {
+ $clen = 2;
+ } else if ($c < 240) {
+ $clen = 3;
+ } else {
+ $clen = 4;
+ }
+
+ if ($length + $clen > $maxlength)
+ break;
+
+ $i += $clen;
+ $length += $clen;
+ }
+
+ return substr($text, $index, $length);
+}
+
+function communievents_fold_ical_text($text) {
+ //XXX: the iCal spec wants the lines to be at most 75 octets,
+ // but we must not split UTF-8 because some readers (notably
+ // thunderbird) choke on it, even though the RFC says you
+ // should handle it gracefully :-(
+
+ if (strlen($text) <= 75) {
+ return $text;
+ } else {
+ $text_arr = array();
+ $text_arr[0] = communievents_fold_ical_line_helper($text, 0, 75);
+ $i = strlen($text_arr[0]);
+ while ($i < strlen($text)) {
+ $s = communievents_fold_ical_line_helper($text, $i, 74);
+ $i += strlen($s);
+ $text_arr[] = $s;
+ }
+
+ return join("\r\n ", $text_arr);
+ }
+}
+
+function communievents_write_ical_line($field, $text) {
+ echo communievents_fold_ical_text("$field:" . communievents_escape_ical_text($text)) . "\r\n";
+}
+
+function communievents_print_ical_feed() {
+ global $wpdb;
+
+ $tz = new DateTimeZone(CommuniApi::TIMEZONE);
+ $tz_utc = new DateTimeZone('UTC');
+ $now_utc = new DateTime('now', $tz_utc);
+ $dtstamp = $now_utc->format('Ymd\THis\Z');
+
+ header('Content-Type: text/calendar');
+ header('Content-Disposition: attachment; filename="communievents.ics"');
+
+ communievents_write_ical_line('BEGIN', 'VCALENDAR');
+ communievents_write_ical_line('VERSION', '2.0');
+ communievents_write_ical_line('PRODID', '-//' . get_bloginfo('name') . '//NONSGML Events//EN');
+ communievents_write_ical_line('CALSCALE', 'GREGORIAN');
+ communievents_write_ical_line('X-WR-TIMEZONE', CommuniApi::TIMEZONE);
+
+ $table_name = $wpdb->prefix . 'communievents_events';
+
+ $list = $wpdb->get_results("SELECT * FROM $table_name WHERE official=1 ORDER BY start");
+
+ if ($list) {
+ foreach ($list as $event) {
+ $start_dt = new DateTime($event->start, $tz);
+ $end_dt = new DateTime($event->end, $tz);
+
+ communievents_write_ical_line('BEGIN', 'VEVENT');
+
+ communievents_write_ical_line('UID', 'communi-event-' . $event->id . '-' . $start_dt->format('U'));
+ communievents_write_ical_line('STATUS', 'CONFIRMED');
+ communievents_write_ical_line('DTSTAMP', $dtstamp);
+ if ($event->allday) {
+ communievents_write_ical_line('DTSTART;VALUE=DATE', $start_dt->format('Ymd'));
+ if ($end_dt->format('Ymd') != $start_dt->format('Ymd')) {
+ // end is non-inclusive! move it into the next day
+ $end_dt->modify('+1 minute');
+ communievents_write_ical_line('DTEND;VALUE=DATE', $end_dt->format('Ymd'));
+ }
+ } else {
+ communievents_write_ical_line('DTSTART', $start_dt->format('Ymd\THis'));
+ if ($event->end != $event->start) {
+ communievents_write_ical_line('DTEND', $end_dt->format('Ymd\THis'));
+ }
+ }
+
+ communievents_write_ical_line('SUMMARY', $event->title);
+
+ if (!empty($event->description)) {
+ communievents_write_ical_line('DESCRIPTION', html_entity_decode(strip_tags($event->description), ENT_QUOTES|ENT_SUBSTITUTE|ENT_HTML5, 'UTF-8'));
+ communievents_write_ical_line('X-ALT-DESC;FMTTYPE=text/html', $event->description);
+ }
+
+ if (!empty($event->location)) {
+ communievents_write_ical_line('LOCATION', $event->location);
+ }
+
+ communievents_write_ical_line('URL;VALUE=URI', $event->url);
+
+ communievents_write_ical_line('END', 'VEVENT');
+ }
+ }
+
+ communievents_write_ical_line('END', 'VCALENDAR');
+}
+
+function communievents_setup_ical_feed() {
+ add_feed('communievents-ics', 'communievents_print_ical_feed');
+ // FIXME: emklahr.de compat HACK
+ add_feed('eo-events', 'communievents_print_ical_feed');
+}