<?php
namespace App\Utils\Calendar\ICal; class Writer { protected $calendar = NULL; public function __construct(\App\Utils\Calendar\Calendar $calendar) { $this->calendar = $calendar; } public function generate() { $eventsList = $this->calendar->getEventsList(); if (!$this->calendar->getNumberOfEvents()) { throw new \RuntimeException("Cannot write calendar file with no events. Please add at least one event."); } $output = ''; $output .= "BEGIN:VCALENDAR\n"; $output .= "VERSION:2.0\n"; $output .= "CALSCALE:GREGORIAN\n"; $output .= sprintf("PRODID:-//%s//%s\n", "DCS", __CLASS__); foreach ($eventsList as $eventObject) { $output .= "BEGIN:VEVENT\n"; $eventUid = $eventObject->getUid(); if (!$eventUid) { throw new \RuntimeException("The event id(`uid`) is mandatory."); } $output .= sprintf("UID:%s\n", $eventUid); $eventDtStamp = $eventObject->getDtStamp(); if ($eventDtStamp === NULL or !$eventDtStamp->isValid()) { throw new \RuntimeException('The event date stamp is not valid.'); } $output .= sprintf("DTSTAMP:%sZ\n", $eventDtStamp->format('Ymd\THis')); $output .= sprintf("SUMMARY:%s\n", $this->escapeString($eventObject->getSummary())); $output .= sprintf("DESCRIPTION:%s\n", $this->escapeString($eventObject->getDescription())); $output .= sprintf("X-ALT-DESC;FMTTYPE=text/html:%s\n", $this->escapeString($eventObject->getDescription())); $output .= sprintf("LOCATION:%s\n", $this->escapeString($eventObject->getLocation())); $output .= sprintf("CLASS:%s\n", $eventObject->getClass()); $eventStartDateObject = $eventObject->getDtStart(); if ($eventStartDateObject === NULL or !$eventStartDateObject->isValid()) { throw new \RuntimeException('The event start date is not valid.'); } if (!$eventObject->getAllDay()) { $output .= sprintf("DTSTART:%sZ\n", $eventStartDateObject->setTimeZone(new \DateTimeZone('UTC'))->format('Ymd\THis')); } else { $output .= sprintf("DTSTART;VALUE=DATE:%s\n", $eventStartDateObject->format('Ymd')); } $eventDurationObject = $eventObject->getDuration(); $eventEndDateObject = $eventObject->getDtEnd(); if ($eventDurationObject === NULL and ($eventEndDateObject === NULL or !$eventEndDateObject->isValid())) { throw new \RuntimeException('The event duration or event end date must be set.'); } if ($eventDurationObject) { $output .= sprintf("DURATION:%s\n", $eventDurationObject->formatIso()); } else { if (!$eventObject->getAllDay()) { $output .= sprintf("DTEND:%sZ\n", $eventEndDateObject->setTimeZone(new \DateTimeZone('UTC'))->format('Ymd\THis')); } else { $output .= sprintf("DTEND;VALUE=DATE:%s\n", $eventEndDateObject->format('Ymd')); } } foreach ($eventObject->getRemindersList() as $reminderObject) { $reminderTriggerObject = $reminderObject->getTrigger(); $reminderAction = $reminderObject->getAction(); $reminderDescription = $this->escapeString($reminderObject->getDescription()); if ($reminderTriggerObject === NULL) { throw new \RuntimeException("The reminder trigger is not valid."); } if ($reminderAction == 'DISPLAY' and !$reminderDescription) { throw new \RuntimeException("The reminder description must be set if `ACTION` is set as `DISPLAY`."); } $output .= "BEGIN:VALARM\n"; $output .= sprintf("TRIGGER:-%s\n", $reminderTriggerObject->formatIso()); $output .= sprintf("ACTION:%s\n", $reminderAction); $output .= sprintf("DESCRIPTION:%s\n", $reminderDescription); $output .= "END:VALARM\n"; } $output .= "END:VEVENT\n"; } $output .= 'END:VCALENDAR'; return $output; } private function escapeString($string) { $string = str_replace(["\r\n", "\n", "\r"], "\\n", $string); return preg_replace('/([\,;])/','\\\$1', $string); } } 