shouldCreateExampleEvent()) { return; } $exampleEvent = $this->getExampleEvent(); $uid = $exampleEvent->getUid(); $this->calDavBackend->createCalendarObject( $calendarId, "$uid.ics", $exampleEvent->getIcs(), ); } private function getStartDate(): \DateTimeInterface { return $this->time->now() ->add(new \DateInterval('P7D')) ->setTime(10, 00); } private function getEndDate(): \DateTimeInterface { return $this->time->now() ->add(new \DateInterval('P7D')) ->setTime(11, 00); } private function getDefaultEvent(string $uid): VCalendar { $defaultDescription = $this->l10n->t(<< $uid, 'DTSTAMP' => $this->time->now(), 'SUMMARY' => $this->l10n->t('Example event - open me!'), 'DTSTART' => $this->getStartDate(), 'DTEND' => $this->getEndDate(), 'DESCRIPTION' => $defaultDescription, ]; $vCalendar->add('VEVENT', $props); return $vCalendar; } /** * @return string|null The ics of the custom example event or null if no custom event was uploaded. * @throws ExampleEventException If reading the custom ics file fails. */ private function getCustomExampleEvent(): ?string { try { $folder = $this->appData->getFolder(self::FOLDER_NAME); $icsFile = $folder->getFile(self::FILE_NAME); } catch (NotFoundException $e) { return null; } try { return $icsFile->getContent(); } catch (NotFoundException|NotPermittedException $e) { throw new ExampleEventException( 'Failed to read custom example event', 0, $e, ); } } /** * Get the configured example event or the default one. * * @throws ExampleEventException If loading the custom example event fails. */ public function getExampleEvent(): ExampleEvent { $uid = $this->random->generate(32, ISecureRandom::CHAR_ALPHANUMERIC); $customIcs = $this->getCustomExampleEvent(); if ($customIcs === null) { return new ExampleEvent($this->getDefaultEvent($uid), $uid); } [$vCalendar, $vEvent] = $this->parseEvent($customIcs); $vEvent->UID = $uid; $vEvent->DTSTART = $this->getStartDate(); $vEvent->DTEND = $this->getEndDate(); $vEvent->remove('ORGANIZER'); $vEvent->remove('ATTENDEE'); return new ExampleEvent($vCalendar, $uid); } /** * @psalm-return list{VCalendar, VEvent} The VCALENDAR document and its VEVENT child component * @throws ExampleEventException If parsing the event fails or if it is invalid. */ private function parseEvent(string $ics): array { try { $vCalendar = \Sabre\VObject\Reader::read($ics); if (!($vCalendar instanceof VCalendar)) { throw new ExampleEventException('Custom event does not contain a VCALENDAR component'); } /** @var VEvent|null $vEvent */ $vEvent = $vCalendar->getBaseComponent('VEVENT'); if ($vEvent === null) { throw new ExampleEventException('Custom event does not contain a VEVENT component'); } } catch (\Exception $e) { throw new ExampleEventException('Failed to parse custom event: ' . $e->getMessage(), 0, $e); } return [$vCalendar, $vEvent]; } public function saveCustomExampleEvent(string $ics): void { // Parse and validate the event before attempting to save it to prevent run time errors $this->parseEvent($ics); try { $folder = $this->appData->getFolder(self::FOLDER_NAME); } catch (NotFoundException $e) { $folder = $this->appData->newFolder(self::FOLDER_NAME); } try { $existingFile = $folder->getFile(self::FILE_NAME); $existingFile->putContent($ics); } catch (NotFoundException $e) { $folder->newFile(self::FILE_NAME, $ics); } } public function deleteCustomExampleEvent(): void { try { $folder = $this->appData->getFolder(self::FOLDER_NAME); $file = $folder->getFile(self::FILE_NAME); } catch (NotFoundException $e) { return; } $file->delete(); } public function hasCustomExampleEvent(): bool { try { return $this->getCustomExampleEvent() !== null; } catch (ExampleEventException $e) { return false; } } public function setCreateExampleEvent(bool $enable): void { $this->appConfig->setValueBool(Application::APP_ID, self::ENABLE_CONFIG_KEY, $enable); } public function shouldCreateExampleEvent(): bool { return $this->appConfig->getValueBool(Application::APP_ID, self::ENABLE_CONFIG_KEY, true); } }