diff --git a/apps/dav/lib/CalDAV/CalendarImpl.php b/apps/dav/lib/CalDAV/CalendarImpl.php index a4f4fb9835741..1c22625f31639 100644 --- a/apps/dav/lib/CalDAV/CalendarImpl.php +++ b/apps/dav/lib/CalDAV/CalendarImpl.php @@ -28,6 +28,7 @@ use Sabre\VObject\Component\VEvent; use Sabre\VObject\Component\VTimeZone; use Sabre\VObject\ITip\Message; +use Sabre\VObject\Node; use Sabre\VObject\Property; use Sabre\VObject\Reader; use Sabre\VObject\UUIDUtil; @@ -293,18 +294,41 @@ public function export(?CalendarExportRange $range = null): Generator { * @since 31.0.0 * */ - public function import(CalendarImportSettings $settings, VCalendar ...$vObjects): array { + public function import(CalendarImportSettings $settings, callable $generator): array { $calendarId = $this->getKey(); $outcome = []; - foreach ($vObjects as $vObject) { - + foreach ($generator($settings) as $vObject) { + $components = $vObject->getBaseComponents(); + // determine if the object has only one base component type if (count($components) > 1) { - throw new InvalidArgumentException('Import failure: objects can not contain more than one base instance object'); + if ($settings->errors === 1) { + throw new InvalidArgumentException('Error importing calendar object, discovered object with multiple base component types'); + } + $outcome['mbct'] = ['One or more objects discovered with multiple base component types']; + continue; + } + // determine if the object has a uid + if (!isset($components[0]->UID)) { + if ($settings->errors === 1) { + throw new InvalidArgumentException('Error importing calendar object, discovered object without a UID'); + } + $outcome['noid'] = ['One or more objects discovered without a UID']; + continue; } $uid = $components[0]->UID->getValue(); - + // validate object + if ($settings->validate !== 0) { + $issues = $this->validateComponent($vObject, true, 3); + if ($settings->validate === 1 && $issues !== []) { + $outcome[$uid] = $issues; + continue; + } elseif ($settings->validate === 2 && $issues !== []) { + throw new InvalidArgumentException('Error importing calendar object <' . $uid . '>, ' . $issues[0]); + } + } + $objectId = $this->backend->getCalendarObjectByUID($this->calendarInfo['principaluri'], $uid); $objectData = $vObject->serialize(); @@ -316,12 +340,18 @@ public function import(CalendarImportSettings $settings, VCalendar ...$vObjects) $objectId, $objectData ); - } elseif ($objectId !== null && $settings->supersede) { - $this->backend->updateCalendarObject( - $calendarId, - $objectId, - $objectData - ); + $outcome[$uid] = ['Created']; + } elseif ($objectId !== null) { + if ($settings->supersede) { + $this->backend->updateCalendarObject( + $calendarId, + $objectId, + $objectData + ); + $outcome[$uid] = ['Updated']; + } else { + $outcome[$uid] = ['Exists']; + } } } @@ -329,4 +359,22 @@ public function import(CalendarImportSettings $settings, VCalendar ...$vObjects) } + private function validateComponent(VCalendar $vObject, bool $repair, int $level): array { + // validate component(S) + $issues = $vObject->validate(Node::PROFILE_CALDAV); + // attempt to repair + if ($repair && count($issues) > 0) { + $issues = $vObject->validate(Node::REPAIR); + } + // filter out messages based on level + $result = []; + foreach ($issues as $key => $issue) { + if (isset($issue['level']) && $issue['level'] >= $level) { + $result[] = $issue['message']; + } + } + + return $result; + } + } diff --git a/lib/public/Calendar/CalendarImportSettings.php b/lib/public/Calendar/CalendarImportSettings.php index be10a1736d852..a2e707b3e3033 100644 --- a/lib/public/Calendar/CalendarImportSettings.php +++ b/lib/public/Calendar/CalendarImportSettings.php @@ -17,9 +17,8 @@ class CalendarImportSettings { public string $format = 'ical'; public bool $supersede = false; - public bool $emitEvent = false; public bool $emitITip = false; - public int $bulk = 32; - public int $validate = 1; // 0 - no validation, 1 - validate and skip on issue, 2 - validate and fail on issue + public int $errors = 1; // 0 - continue, 1 - fail + public int $validate = 1; // 0 - no validation, 1 - validate and skip on issue, 2 - validate and fail on issue } diff --git a/lib/public/Calendar/ICalendarImport.php b/lib/public/Calendar/ICalendarImport.php index 0f28bb4ad4666..13cc6b76a3e70 100644 --- a/lib/public/Calendar/ICalendarImport.php +++ b/lib/public/Calendar/ICalendarImport.php @@ -23,8 +23,8 @@ interface ICalendarImport { * * @since 31.0.0 * - * @param VCalendar $vObjects + * */ - public function import(CalendarImportSettings $settings, VCalendar ...$vObjects): array; + public function import(CalendarImportSettings $settings, callable $generator): array; }