$ev->add_property('description', clean_param($event->description, PARAM_NOTAGS)); $ev->add_property('class', 'PUBLIC'); // PUBLIC / PRIVATE / CONFIDENTIAL $ev->add_property('last-modified', Bennu::timestamp_to_datetime($event->timemodified)); $ev->add_property('dtstamp', Bennu::timestamp_to_datetime()); // now if ($event->timeduration > 0) { //dtend is better than duration, because it works in Microsoft Outlook and works better in Korganizer $ev->add_property('dtstart', Bennu::timestamp_to_datetime($event->timestart)); // when event starts. $ev->add_property('dtend', Bennu::timestamp_to_datetime($event->timestart + $event->timeduration)); } else { // When no duration is present, ie an all day event, VALUE should be date instead of time and dtend = dtstart + 1 day. $ev->add_property('dtstart', Bennu::timestamp_to_date($event->timestart), array('value' => 'DATE')); // All day event. $ev->add_property('dtend', Bennu::timestamp_to_date($event->timestart + DAYSECS), array('value' => 'DATE')); // All day event. } if ($event->courseid != 0) { $coursecontext = context_course::instance($event->courseid); $ev->add_property('categories', format_string($courses[$event->courseid]->shortname, true, array('context' => $coursecontext))); } $ical->add_component($ev); } $serialized = $ical->serialize(); if (empty($serialized)) { // TODO die('bad serialization'); } $filename = 'icalexport.ics'; header('Last-Modified: ' . gmdate('D, d M Y H:i:s', time()) . ' GMT');