data = $array; $this->setDefaults(); } public function preCompile() { return $this->prepareEventData(); } protected function prepareEventData() { $this->setDateTime(); $this->setCategories(); $this->setAttendees(); $this->setOrganizer(); $this->setAlarm(); $this->setRecurrence(); $this->setAttachments(); } protected function setDefaults() { if (!isset($this->data['uid'])) { $currentDateTime = $this->getCurrentDateTime(); $this->data['created'] = $currentDateTime; $this->data['dtstamp'] = $currentDateTime; $this->data['last-modified'] = $currentDateTime; $this->data['uid'] = md5(__NAMESPACE__) . '-' . wp_generate_uuid4(); } } protected function getCurrentDateTime() { return ( new DateTime('now', new DateTimeZone('UTC')) )->format($this->dateTimeFormat); } protected function setDateTime() { $dates = [ 'dtstart' => $this->getDtStart(), 'dtend' => $this->getDtEnd() ]; foreach ($dates as $key => $value) { $dateTime = $value; if (is_string($value)) { $dateTime = new DateTime($value, new DateTimeZone('UTC')); } if ($dateTime instanceof DateTime) { $this->data[$key] = $dateTime->format($this->dateTimeFormat); } else { throw new Exception("Invalid value: {$value} for {$key}."); } } } protected function getDtStart() { if (!isset($this->data['dtstart'])) { if (!isset($this->data['DTSTART'])) { throw new Exception('The Event needs an dtstart/DTSTART property.'); } else { $dtStart = $this->data['DTSTART']; } } else { $dtStart = $this->data['dtstart']; } return $dtStart; } protected function getDtEnd() { if (!isset($this->data['dtend'])) { if (!isset($this->data['DTEND'])) { throw new Exception('The Event needs an dtend/DTEND property.'); } else { $dtEnd = $this->data['DTEND']; } } else { $dtEnd = $this->data['dtend']; } return $dtEnd; } protected function setCategories() { if (!isset($this->data['categories'])) { return; } $categories = $this->data['categories']; if (is_array($categories)) { $categories = implode(',', $categories); } $categories = str_replace(', ', ',', $categories); $this->data['categories'] = $categories; } protected function setAttendees() { if (!isset($this->data['attendees'])) { return; } foreach ($this->data['attendees'] as &$attendee) { if (!isset($attendee['email'])) { throw new Exception('An attendee must have an email.'); } if (!isset($attendee['name'])) { $attendee['name'] = $attendee['email']; } $str = ''; foreach ($attendee as $key => $value) { $key = strtolower($key); if ($key == 'name') { $str .= "CN={$value};"; } elseif ($key == 'role') { $value = strtoupper($value); $str .= "ROLE={$value};"; } elseif ($key == 'rsvp') { if (is_bool($value)) { $value = $value === true ? 'TRUE' : 'FALSE'; } $value = strtoupper($value); $str .= "RSVP={$value};"; } elseif ($key == 'partstat') { $value = strtoupper($value); $str .= "PARTSTAT={$value};"; } } $str = rtrim($str, ';'); $str .= ":mailto:{$attendee['email']}"; $attendee['str'] = $str; } } protected function setOrganizer() { if (!isset($this->data['organizer'])) { return; } $organizer = &$this->data['organizer']; if (!isset($organizer['email'])) { throw new \Exception('An organizer must have an email.'); } if (!isset($organizer['name'])) { $organizer['name'] = $organizer['email']; } $str = ''; foreach ($organizer as $key => $value) { $key = strtolower($key); if ($key == 'name') { $str .= "CN={$value};"; } elseif ($key == 'language') { $str .= "LANGUAGE={$value};"; } } if (isset($organizer['sent_by'])) { $str .= "SENT-BY=mailto:{$organizer['sent_by']}"; } $str = rtrim($str, ';'); $str .= ":mailto:{$organizer['email']}"; $organizer['str'] = $str; } protected function setAlarm() { if (!isset($this->data['alarm'])) { return; } $alarm = &$this->data['alarm']; $action = strtoupper($alarm['action']); $alarm['action'] = $action; if (isset($alarm['trigger'])) { // For exact time of the event if ($alarm['trigger'] === true) { $alarm['trigger_str'] = "RELATED=START:PT0S"; return; } if (!isset($alarm['trigger']['after'])) { if (isset($alarm['trigger']['before'])) { $isBefore = $alarm['trigger']['before'] === true; } else { $isBefore = true; } } else { $isBefore = $alarm['trigger']['after'] === false; } $period = $isBefore ? '-P' : 'P'; $time = ''; foreach ($alarm['trigger'] as $key => $value) { if ($key == 'years' && is_numeric($value) && $value) { $period = $period . $value . 'Y'; } elseif ($key == 'months' && is_numeric($value) && $value) { $period = $period . $value . 'M'; } elseif ($key == 'days' && is_numeric($value) && $value) { $period = $period . $value . 'D'; } elseif ($key == 'hours' && is_numeric($value) && $value) { $time = $time . $value . 'H'; } elseif ($key == 'minutes' && is_numeric($value) && $value) { $time = $time . $value . 'M'; } elseif ($key == 'seconds' && is_numeric($value) && $value) { $time = $time . $value . 'S'; } } } if ($time) { $period = $period . 'T' . $time; } $alarm['trigger_str'] = "RELATED=START:{$period}"; } protected function setRecurrence() { if (!isset($this->data['repeat'])) { return; } $str = ''; $recurrence = &$this->data['repeat']; foreach ($recurrence as $key => $value) { $value = is_array($value) ? implode(',', $value) : $value; $str .= strtoupper($key) . '=' . strtoupper($value) . ';'; } $str = rtrim($str, ';'); $recurrence['str'] = $str; } public function setAttachments() { if (!isset($this->data['attachments'])) { return; } $attachments = &$this->data['attachments']; foreach ($this->data['attachments'] as $attachment) { if (!isset($attachment['url'], $attachment['name'])) { throw new Exception('An attachment requires a name and url key.'); } $url = $attachment['url']; $filename = $attachment['name']; $attachments['list'][] = 'ATTACH;FILENAME=' . $filename . ':' . $url; } } public function compile() { $this->preCompile(); if (!isset($this->data['sequence'])) { $this->data['sequence'] = 0; } else { $this->data['sequence'] += 1; } $this->data['last-modified'] = $this->getCurrentDateTime(); $appNS = strtolower(explode('\\', __NAMESPACE__)[0]); $calendar[] = "BEGIN:VCALENDAR"; $calendar[] = "VERSION:2.0"; $calendar[] = "CALSCALE:GREGORIAN"; $calendar[] = "PRODID:-//authlab.{$appNS}//CalDAV Client//EN"; $calendar[] = "BEGIN:VEVENT"; $calendar[] = "CREATED:{$this->data['created']}"; $calendar[] = "DTSTAMP:{$this->data['dtstamp']}"; $calendar[] = "LAST-MODIFIED:{$this->data['last-modified']}"; $calendar[] = "SEQUENCE:{$this->data['sequence']}"; $calendar[] = "UID:{$this->data['uid']}"; $calendar[] = "DTSTART:{$this->data['dtstart']}"; $calendar[] = "DTEND:{$this->data['dtend']}"; if (isset($this->data['transp'])) { $calendar[] = "TRANSP:{$this->data['transp']}"; } else { $calendar[] = "TRANSP:TRANSPARENT"; } if (isset($this->data['status'])) { $eventStatus = strtoupper($this->data['status']); $calendar[] = "STATUS:{$eventStatus}"; } if (isset($this->data['summary'])) { $calendar[] = "SUMMARY:{$this->data['summary']}"; } if (isset($this->data['description'])) { $eventDescription = str_replace("\n", " ", $this->data['description']); $calendar[] = "DESCRIPTION:{$eventDescription}"; } if (isset($this->data['location'])) { $calendar[] = "LOCATION:{$this->data['location']}"; } if (isset($this->data['categories'])) { $calendar[] = "CATEGORIES:{$this->data['categories']}"; } if (isset($this->data['repeat'])) { $calendar[] = "RRULE:{$this->data['repeat']['str']}"; } if (isset($this->data['attendees'])) { foreach ($this->data['attendees'] as $attendee) { $calendar[] = "ATTENDEE;{$attendee['str']}"; } } if (isset($this->data['organizer'])) { $calendar[] = "ORGANIZER;{$this->data['organizer']['str']}"; } if (isset($this->data['attachments'])) { $calendar[] = implode("\n", $this->data['attachments']['list']); } if (isset($this->data['alarm'])) { $calendar[] = "BEGIN:VALARM"; if (isset($this->data['alarm']['action'])) { $calendar[] = "ACTION:{$this->data['alarm']['action']}"; } if (isset($this->data['alarm']['description'])) { $alarmDescription = str_replace( "\n", " ", $this->data['alarm']['description'] ); $calendar[] = "DESCRIPTION:{$alarmDescription}"; } if (isset($this->data['alarm']['trigger'])) { $calendar[] = "TRIGGER;{$this->data['alarm']['trigger_str']}"; } $calendar[] = "END:VALARM"; } $calendar[] = "END:VEVENT"; $calendar[] = "END:VCALENDAR"; $this->generatedEventData = implode("\n", $calendar); return $this->generatedEventData; } public function getUid() { return $this->data['uid']; } public function __get($key) { return $this->data[$key]; } public function __set($key, $value) { $this->data[$key] = $value; } #[\ReturnTypeWillChange] public function jsonSerialize() { return $this->data; } }