requestSyncReport($url, $username, $sharedSecret, $syncToken); } catch (ClientExceptionInterface $ex) { if ($ex->getCode() === Http::STATUS_UNAUTHORIZED) { // Remote server revoked access to the calendar => remove it $this->federatedCalendarMapper->delete($calendar); $this->logger->error("Authorization failed, remove federated calendar: $url", [ 'app' => 'dav', ]); throw $ex; } $this->logger->error('Client exception:', ['app' => 'dav', 'exception' => $ex]); throw $ex; } // TODO: use multi-get for download $downloadedEvents = 0; foreach ($response['response'] as $resource => $status) { $objectUri = basename($resource); if (isset($status[200])) { $absoluteUrl = $this->prepareUri($url, $resource); $vCard = $this->download($absoluteUrl, $username, $sharedSecret); $this->atomic(function () use ($calendar, $objectUri, $vCard): void { $existingObject = $this->backend->getCalendarObject($calendar->getId(), $objectUri, CalDavBackend::CALENDAR_TYPE_FEDERATED); if (!$existingObject) { $this->backend->createCalendarObject($calendar->getId(), $objectUri, $vCard, CalDavBackend::CALENDAR_TYPE_FEDERATED); } else { $this->backend->updateCalendarObject($calendar->getId(), $objectUri, $vCard, CalDavBackend::CALENDAR_TYPE_FEDERATED); } }, $this->dbConnection); $downloadedEvents++; } else { $this->backend->deleteCalendarObject($calendar->getId(), $objectUri, CalDavBackend::CALENDAR_TYPE_FEDERATED, true); } } return new SyncServiceResult( $response['token'], $downloadedEvents, ); } }