*/ public function readEvents(CalendarSyncConfig $config): array { $response = $this->transport->report( $config->caldavUrl, $config->caldavUsername, $config->caldavPassword, $this->buildCalendarQueryBody(), 1, ['Content-Type' => 'application/xml; charset=utf-8'], ); if (!in_array($response->statusCode, [200, 207], true)) { $this->logger->warning('CalDAV calendar query failed.', [ 'calendarId' => $config->calendarId, 'url' => $config->caldavUrl, 'statusCode' => $response->statusCode, ]); return []; } $parsedItems = $this->xmlParser->parseCalendarMultistatus($response->body); $events = []; foreach ($parsedItems as $item) { $event = $this->icalendarParser->parseEvent( $item['href'], $item['etag'], $item['calendarData'], $config->timezoneOrDefault(), ); if (null !== $event) { $events[] = $event; } } return $events; } public function readEventByHref(CalendarSyncConfig $config, string $href): ?RemoteEvent { $response = $this->transport->get( $this->absoluteUrl($config->caldavUrl, $href), $config->caldavUsername, $config->caldavPassword, ['Accept' => 'text/calendar'], ); if (200 !== $response->statusCode) { $this->logger->warning('CalDAV GET by href failed.', [ 'calendarId' => $config->calendarId, 'url' => $href, 'statusCode' => $response->statusCode, ]); return null; } return $this->icalendarParser->parseEvent( $href, trim((string) $response->header('etag'), '"'), $response->body, $config->timezoneOrDefault(), ); } private function buildCalendarQueryBody(): string { return <<<'XML' XML; } private function absoluteUrl(string $calendarUrl, string $href): string { if (str_starts_with($href, 'http://') || str_starts_with($href, 'https://')) { return $href; } $base = parse_url($calendarUrl); if (!is_array($base) || !isset($base['scheme'], $base['host'])) { return $href; } $prefix = $base['scheme'].'://'.$base['host']; if (isset($base['port'])) { $prefix .= ':'.$base['port']; } return $prefix.$href; } }