diff options
Diffstat (limited to 'apps/dav/lib')
-rw-r--r-- | apps/dav/lib/AppInfo/Application.php | 2 | ||||
-rw-r--r-- | apps/dav/lib/CalDAV/Schedule/IMipService.php | 301 | ||||
-rw-r--r-- | apps/dav/lib/CalDAV/Schedule/Plugin.php | 28 | ||||
-rw-r--r-- | apps/dav/lib/Command/FixCalendarSyncCommand.php | 5 | ||||
-rw-r--r-- | apps/dav/lib/Connector/Sabre/FilesPlugin.php | 5 | ||||
-rw-r--r-- | apps/dav/lib/Migration/Version1027Date20230504122946.php | 2 | ||||
-rw-r--r-- | apps/dav/lib/Search/TasksSearchProvider.php | 2 | ||||
-rw-r--r-- | apps/dav/lib/ServerFactory.php | 5 | ||||
-rw-r--r-- | apps/dav/lib/SystemTag/SystemTagList.php | 1 | ||||
-rw-r--r-- | apps/dav/lib/SystemTag/SystemTagPlugin.php | 7 |
10 files changed, 289 insertions, 69 deletions
diff --git a/apps/dav/lib/AppInfo/Application.php b/apps/dav/lib/AppInfo/Application.php index 2325a3c3ba8..ae587c98965 100644 --- a/apps/dav/lib/AppInfo/Application.php +++ b/apps/dav/lib/AppInfo/Application.php @@ -81,6 +81,7 @@ use OCP\Config\BeforePreferenceDeletedEvent; use OCP\Config\BeforePreferenceSetEvent; use OCP\Contacts\IManager as IContactsManager; use OCP\DB\Events\AddMissingIndicesEvent; +use OCP\EventDispatcher\GenericEvent; use OCP\EventDispatcher\IEventDispatcher; use OCP\Federation\Events\TrustedServerRemovedEvent; use OCP\Files\AppData\IAppDataFactory; @@ -91,7 +92,6 @@ use OCP\User\Events\OutOfOfficeClearedEvent; use OCP\User\Events\OutOfOfficeScheduledEvent; use Psr\Container\ContainerInterface; use Psr\Log\LoggerInterface; -use Symfony\Component\EventDispatcher\GenericEvent; use Throwable; use function is_null; diff --git a/apps/dav/lib/CalDAV/Schedule/IMipService.php b/apps/dav/lib/CalDAV/Schedule/IMipService.php index e0d51edc177..69c9e774042 100644 --- a/apps/dav/lib/CalDAV/Schedule/IMipService.php +++ b/apps/dav/lib/CalDAV/Schedule/IMipService.php @@ -45,8 +45,9 @@ class IMipService { private L10NFactory $l10nFactory, private ITimeFactory $timeFactory, ) { - $default = $this->l10nFactory->findGenericLanguage(); - $this->l10n = $this->l10nFactory->get('dav', $default); + $language = $this->l10nFactory->findGenericLanguage(); + $locale = $this->l10nFactory->findLocale($language); + $this->l10n = $this->l10nFactory->get('dav', $language, $locale); } /** @@ -188,6 +189,9 @@ class IMipService { * @return string */ public function generateWhenStringSingular(EventReader $er): string { + // initialize + $startTime = null; + $endTime = null; // calculate time difference from now to start of event $occurring = $this->minimizeInterval($this->timeFactory->getDateTime()->diff($er->recurrenceDate())); // extract start date @@ -202,15 +206,91 @@ class IMipService { // TRANSLATORS // Indicates when a calendar event will happen, shown on invitation emails // Output produced in order: - // In a day/week/month/year on July 1, 2024 for the entire day - // In a day/week/month/year on July 1, 2024 between 8:00 AM - 9:00 AM (America/Toronto) - // In 2 days/weeks/months/years on July 1, 2024 for the entire day - // In 2 days/weeks/months/years on July 1, 2024 between 8:00 AM - 9:00 AM (America/Toronto) - return match ([($occurring[0] > 1), !empty($endTime)]) { - [false, false] => $this->l10n->t('In a %1$s on %2$s for the entire day', [$occurring[1], $startDate]), - [false, true] => $this->l10n->t('In a %1$s on %2$s between %3$s - %4$s', [$occurring[1], $startDate, $startTime, $endTime]), - [true, false] => $this->l10n->t('In %1$s %2$s on %3$s for the entire day', [$occurring[0], $occurring[1], $startDate]), - [true, true] => $this->l10n->t('In %1$s %2$s on %3$s between %4$s - %5$s', [$occurring[0], $occurring[1], $startDate, $startTime, $endTime]), + // In a minute/hour/day/week/month/year on July 1, 2024 for the entire day + // In a minute/hour/day/week/month/year on July 1, 2024 between 8:00 AM - 9:00 AM (America/Toronto) + // In 2 minutes/hours/days/weeks/months/years on July 1, 2024 for the entire day + // In 2 minutes/hours/days/weeks/months/years on July 1, 2024 between 8:00 AM - 9:00 AM (America/Toronto) + return match ([$occurring['scale'], $endTime !== null]) { + ['past', false] => $this->l10n->t( + 'In the past on %1$s for the entire day', + [$startDate] + ), + ['minute', false] => $this->l10n->n( + 'In a minute on %1$s for the entire day', + 'In %n minutes on %1$s for the entire day', + $occurring['interval'], + [$startDate] + ), + ['hour', false] => $this->l10n->n( + 'In a hour on %1$s for the entire day', + 'In %n hours on %1$s for the entire day', + $occurring['interval'], + [$startDate] + ), + ['day', false] => $this->l10n->n( + 'In a day on %1$s for the entire day', + 'In %n days on %1$s for the entire day', + $occurring['interval'], + [$startDate] + ), + ['week', false] => $this->l10n->n( + 'In a week on %1$s for the entire day', + 'In %n weeks on %1$s for the entire day', + $occurring['interval'], + [$startDate] + ), + ['month', false] => $this->l10n->n( + 'In a month on %1$s for the entire day', + 'In %n months on %1$s for the entire day', + $occurring['interval'], + [$startDate] + ), + ['year', false] => $this->l10n->n( + 'In a year on %1$s for the entire day', + 'In %n years on %1$s for the entire day', + $occurring['interval'], + [$startDate] + ), + ['past', true] => $this->l10n->t( + 'In the past on %1$s between %2$s - %3$s', + [$startDate, $startTime, $endTime] + ), + ['minute', true] => $this->l10n->n( + 'In a minute on %1$s between %2$s - %3$s', + 'In %n minutes on %1$s between %2$s - %3$s', + $occurring['interval'], + [$startDate, $startTime, $endTime] + ), + ['hour', true] => $this->l10n->n( + 'In a hour on %1$s between %2$s - %3$s', + 'In %n hours on %1$s between %2$s - %3$s', + $occurring['interval'], + [$startDate, $startTime, $endTime] + ), + ['day', true] => $this->l10n->n( + 'In a day on %1$s between %2$s - %3$s', + 'In %n days on %1$s between %2$s - %3$s', + $occurring['interval'], + [$startDate, $startTime, $endTime] + ), + ['week', true] => $this->l10n->n( + 'In a week on %1$s between %2$s - %3$s', + 'In %n weeks on %1$s between %2$s - %3$s', + $occurring['interval'], + [$startDate, $startTime, $endTime] + ), + ['month', true] => $this->l10n->n( + 'In a month on %1$s between %2$s - %3$s', + 'In %n months on %1$s between %2$s - %3$s', + $occurring['interval'], + [$startDate, $startTime, $endTime] + ), + ['year', true] => $this->l10n->n( + 'In a year on %1$s between %2$s - %3$s', + 'In %n years on %1$s between %2$s - %3$s', + $occurring['interval'], + [$startDate, $startTime, $endTime] + ), default => $this->l10n->t('Could not generate when statement') }; } @@ -247,9 +327,8 @@ class IMipService { // initialize $interval = (int)$er->recurringInterval(); - $startTime = ''; - $endTime = ''; - $conclusion = ''; + $startTime = null; + $conclusion = null; // time of the day if (!$er->entireDay()) { $startTime = $this->l10n->l('time', $er->startDateTime(), ['width' => 'short']); @@ -272,7 +351,7 @@ class IMipService { // Every 3 Days for the entire day until July 13, 2024 // Every 3 Days between 8:00 AM - 9:00 AM (America/Toronto) // Every 3 Days between 8:00 AM - 9:00 AM (America/Toronto) until July 13, 2024 - return match ([($interval > 1), !empty($startTime), !empty($conclusion)]) { + return match ([($interval > 1), $startTime !== null, $conclusion !== null]) { [false, false, false] => $this->l10n->t('Every Day for the entire day'), [false, false, true] => $this->l10n->t('Every Day for the entire day until %1$s', [$conclusion]), [false, true, false] => $this->l10n->t('Every Day between %1$s - %2$s', [$startTime, $endTime]), @@ -299,9 +378,8 @@ class IMipService { // initialize $interval = (int)$er->recurringInterval(); - $startTime = ''; - $endTime = ''; - $conclusion = ''; + $startTime = null; + $conclusion = null; // days of the week $days = implode(', ', array_map(function ($value) { return $this->localizeDayName($value); }, $er->recurringDaysOfWeekNamed())); // time of the day @@ -326,7 +404,7 @@ class IMipService { // Every 2 Weeks on Monday, Wednesday, Friday for the entire day until July 13, 2024 // Every 2 Weeks on Monday, Wednesday, Friday between 8:00 AM - 9:00 AM (America/Toronto) // Every 2 Weeks on Monday, Wednesday, Friday between 8:00 AM - 9:00 AM (America/Toronto) until July 13, 2024 - return match ([($interval > 1), !empty($startTime), !empty($conclusion)]) { + return match ([($interval > 1), $startTime !== null, $conclusion !== null]) { [false, false, false] => $this->l10n->t('Every Week on %1$s for the entire day', [$days]), [false, false, true] => $this->l10n->t('Every Week on %1$s for the entire day until %2$s', [$days, $conclusion]), [false, true, false] => $this->l10n->t('Every Week on %1$s between %2$s - %3$s', [$days, $startTime, $endTime]), @@ -353,9 +431,8 @@ class IMipService { // initialize $interval = (int)$er->recurringInterval(); - $startTime = ''; - $endTime = ''; - $conclusion = ''; + $startTime = null; + $conclusion = null; // days of month if ($er->recurringPattern() === 'R') { $days = implode(', ', array_map(function ($value) { return $this->localizeRelativePositionName($value); }, $er->recurringRelativePositionNamed())) . ' ' . @@ -393,7 +470,7 @@ class IMipService { // Relative: Every 2 Months on the First Sunday, Saturday between 8:00 AM - 9:00 AM (America/Toronto) // Absolute: Every 2 Months on the 1, 8 between 8:00 AM - 9:00 AM (America/Toronto) until December 31, 2024 // Relative: Every 2 Months on the First Sunday, Saturday between 8:00 AM - 9:00 AM (America/Toronto) until December 31, 2024 - return match ([($interval > 1), !empty($startTime), !empty($conclusion)]) { + return match ([($interval > 1), $startTime !== null, $conclusion !== null]) { [false, false, false] => $this->l10n->t('Every Month on the %1$s for the entire day', [$days]), [false, false, true] => $this->l10n->t('Every Month on the %1$s for the entire day until %2$s', [$days, $conclusion]), [false, true, false] => $this->l10n->t('Every Month on the %1$s between %2$s - %3$s', [$days, $startTime, $endTime]), @@ -419,9 +496,8 @@ class IMipService { // initialize $interval = (int)$er->recurringInterval(); - $startTime = ''; - $endTime = ''; - $conclusion = ''; + $startTime = null; + $conclusion = null; // months of year $months = implode(', ', array_map(function ($value) { return $this->localizeMonthName($value); }, $er->recurringMonthsOfYearNamed())); // days of month @@ -461,7 +537,7 @@ class IMipService { // Relative: Every 2 Years in July on the First Sunday, Saturday between 8:00 AM - 9:00 AM (America/Toronto) // Absolute: Every 2 Years in July on the 1st between 8:00 AM - 9:00 AM (America/Toronto) until July 31, 2026 // Relative: Every 2 Years in July on the First Sunday, Saturday between 8:00 AM - 9:00 AM (America/Toronto) until July 31, 2026 - return match ([($interval > 1), !empty($startTime), !empty($conclusion)]) { + return match ([($interval > 1), $startTime !== null, $conclusion !== null]) { [false, false, false] => $this->l10n->t('Every Year in %1$s on the %2$s for the entire day', [$months, $days]), [false, false, true] => $this->l10n->t('Every Year in %1$s on the %2$s for the entire day until %3$s', [$months, $days, $conclusion]), [false, true, false] => $this->l10n->t('Every Year in %1$s on the %2$s between %3$s - %4$s', [$months, $days, $startTime, $endTime]), @@ -485,9 +561,8 @@ class IMipService { */ public function generateWhenStringRecurringFixed(EventReader $er): string { // initialize - $startTime = ''; - $endTime = ''; - $conclusion = ''; + $startTime = null; + $conclusion = null; // time of the day if (!$er->entireDay()) { $startTime = $this->l10n->l('time', $er->startDateTime(), ['width' => 'short']); @@ -502,7 +577,7 @@ class IMipService { // Output produced in order: // On specific dates for the entire day until July 13, 2024 // On specific dates between 8:00 AM - 9:00 AM (America/Toronto) until July 13, 2024 - return match (!empty($startTime)) { + return match ($startTime !== null) { false => $this->l10n->t('On specific dates for the entire day until %1$s', [$conclusion]), true => $this->l10n->t('On specific dates between %1$s - %2$s until %3$s', [$startTime, $endTime, $conclusion]), }; @@ -519,6 +594,10 @@ class IMipService { */ public function generateOccurringString(EventReader $er): string { + // initialize + $occurrence = null; + $occurrence2 = null; + $occurrence3 = null; // reset to initial occurrence $er->recurrenceRewind(); // forward to current date @@ -545,19 +624,133 @@ class IMipService { // TRANSLATORS // Indicates when a calendar event will happen, shown on invitation emails // Output produced in order: - // In a day/week/month/year on July 1, 2024 - // In a day/week/month/year on July 1, 2024 then on July 3, 2024 - // In a day/week/month/year on July 1, 2024 then on July 3, 2024 and July 5, 2024 - // In 2 days/weeks/months/years on July 1, 2024 - // In 2 days/weeks/months/years on July 1, 2024 then on July 3, 2024 - // In 2 days/weeks/months/years on July 1, 2024 then on July 3, 2024 and July 5, 2024 - return match ([($occurrenceIn[0] > 1), !empty($occurrence2), !empty($occurrence3)]) { - [false, false, false] => $this->l10n->t('In a %1$s on %2$s', [$occurrenceIn[1], $occurrence]), - [false, true, false] => $this->l10n->t('In a %1$s on %2$s then on %3$s', [$occurrenceIn[1], $occurrence, $occurrence2]), - [false, true, true] => $this->l10n->t('In a %1$s on %2$s then on %3$s and %4$s', [$occurrenceIn[1], $occurrence, $occurrence2, $occurrence3]), - [true, false, false] => $this->l10n->t('In %1$s %2$s on %3$s', [$occurrenceIn[0], $occurrenceIn[1], $occurrence]), - [true, true, false] => $this->l10n->t('In %1$s %2$s on %3$s then on %4$s', [$occurrenceIn[0], $occurrenceIn[1], $occurrence, $occurrence2]), - [true, true, true] => $this->l10n->t('In %1$s %2$s on %3$s then on %4$s and %5$s', [$occurrenceIn[0], $occurrenceIn[1], $occurrence, $occurrence2, $occurrence3]), + // In a minute/hour/day/week/month/year on July 1, 2024 + // In a minute/hour/day/week/month/year on July 1, 2024 then on July 3, 2024 + // In a minute/hour/day/week/month/year on July 1, 2024 then on July 3, 2024 and July 5, 2024 + // In 2 minutes/hours/days/weeks/months/years on July 1, 2024 + // In 2 minutes/hours/days/weeks/months/years on July 1, 2024 then on July 3, 2024 + // In 2 minutes/hours/days/weeks/months/years on July 1, 2024 then on July 3, 2024 and July 5, 2024 + return match ([$occurrenceIn['scale'], $occurrence2 !== null, $occurrence3 !== null]) { + ['past', false, false] => $this->l10n->t( + 'In the past on %1$s', + [$occurrence] + ), + ['minute', false, false] => $this->l10n->n( + 'In a minute on %1$s', + 'In %n minutes on %1$s', + $occurrenceIn['interval'], + [$occurrence] + ), + ['hour', false, false] => $this->l10n->n( + 'In a hour on %1$s', + 'In %n hours on %1$s', + $occurrenceIn['interval'], + [$occurrence] + ), + ['day', false, false] => $this->l10n->n( + 'In a day on %1$s', + 'In %n days on %1$s', + $occurrenceIn['interval'], + [$occurrence] + ), + ['week', false, false] => $this->l10n->n( + 'In a week on %1$s', + 'In %n weeks on %1$s', + $occurrenceIn['interval'], + [$occurrence] + ), + ['month', false, false] => $this->l10n->n( + 'In a month on %1$s', + 'In %n months on %1$s', + $occurrenceIn['interval'], + [$occurrence] + ), + ['year', false, false] => $this->l10n->n( + 'In a year on %1$s', + 'In %n years on %1$s', + $occurrenceIn['interval'], + [$occurrence] + ), + ['past', true, false] => $this->l10n->t( + 'In the past on %1$s then on %2$s', + [$occurrence, $occurrence2] + ), + ['minute', true, false] => $this->l10n->n( + 'In a minute on %1$s then on %2$s', + 'In %n minutes on %1$s then on %2$s', + $occurrenceIn['interval'], + [$occurrence, $occurrence2] + ), + ['hour', true, false] => $this->l10n->n( + 'In a hour on %1$s then on %2$s', + 'In %n hours on %1$s then on %2$s', + $occurrenceIn['interval'], + [$occurrence, $occurrence2] + ), + ['day', true, false] => $this->l10n->n( + 'In a day on %1$s then on %2$s', + 'In %n days on %1$s then on %2$s', + $occurrenceIn['interval'], + [$occurrence, $occurrence2] + ), + ['week', true, false] => $this->l10n->n( + 'In a week on %1$s then on %2$s', + 'In %n weeks on %1$s then on %2$s', + $occurrenceIn['interval'], + [$occurrence, $occurrence2] + ), + ['month', true, false] => $this->l10n->n( + 'In a month on %1$s then on %2$s', + 'In %n months on %1$s then on %2$s', + $occurrenceIn['interval'], + [$occurrence, $occurrence2] + ), + ['year', true, false] => $this->l10n->n( + 'In a year on %1$s then on %2$s', + 'In %n years on %1$s then on %2$s', + $occurrenceIn['interval'], + [$occurrence, $occurrence2] + ), + ['past', true, true] => $this->l10n->t( + 'In the past on %1$s then on %2$s and %3$s', + [$occurrence, $occurrence2, $occurrence3] + ), + ['minute', true, true] => $this->l10n->n( + 'In a minute on %1$s then on %2$s and %3$s', + 'In %n minutes on %1$s then on %2$s and %3$s', + $occurrenceIn['interval'], + [$occurrence, $occurrence2, $occurrence3] + ), + ['hour', true, true] => $this->l10n->n( + 'In a hour on %1$s then on %2$s and %3$s', + 'In %n hours on %1$s then on %2$s and %3$s', + $occurrenceIn['interval'], + [$occurrence, $occurrence2, $occurrence3] + ), + ['day', true, true] => $this->l10n->n( + 'In a day on %1$s then on %2$s and %3$s', + 'In %n days on %1$s then on %2$s and %3$s', + $occurrenceIn['interval'], + [$occurrence, $occurrence2, $occurrence3] + ), + ['week', true, true] => $this->l10n->n( + 'In a week on %1$s then on %2$s and %3$s', + 'In %n weeks on %1$s then on %2$s and %3$s', + $occurrenceIn['interval'], + [$occurrence, $occurrence2, $occurrence3] + ), + ['month', true, true] => $this->l10n->n( + 'In a month on %1$s then on %2$s and %3$s', + 'In %n months on %1$s then on %2$s and %3$s', + $occurrenceIn['interval'], + [$occurrence, $occurrence2, $occurrence3] + ), + ['year', true, true] => $this->l10n->n( + 'In a year on %1$s then on %2$s and %3$s', + 'In %n years on %1$s then on %2$s and %3$s', + $occurrenceIn['interval'], + [$occurrence, $occurrence2, $occurrence3] + ), default => $this->l10n->t('Could not generate next recurrence statement') }; @@ -965,30 +1158,30 @@ class IMipService { public function minimizeInterval(\DateInterval $dateInterval): array { // evaluate if time interval is in the past if ($dateInterval->invert == 1) { - return [1, 'the past']; + return ['interval' => 1, 'scale' => 'past']; } // evaluate interval parts and return smallest time period if ($dateInterval->y > 0) { $interval = $dateInterval->y; - $scale = ($dateInterval->y > 1) ? 'years' : 'year'; + $scale = 'year'; } elseif ($dateInterval->m > 0) { $interval = $dateInterval->m; - $scale = ($dateInterval->m > 1) ? 'months' : 'month'; + $scale = 'month'; } elseif ($dateInterval->d >= 7) { $interval = (int)($dateInterval->d / 7); - $scale = ((int)($dateInterval->d / 7) > 1) ? 'weeks' : 'week'; + $scale = 'week'; } elseif ($dateInterval->d > 0) { $interval = $dateInterval->d; - $scale = ($dateInterval->d > 1) ? 'days' : 'day'; + $scale = 'day'; } elseif ($dateInterval->h > 0) { $interval = $dateInterval->h; - $scale = ($dateInterval->h > 1) ? 'hours' : 'hour'; + $scale = 'hour'; } else { $interval = $dateInterval->i; - $scale = 'minutes'; + $scale = 'minute'; } - return [$interval, $scale]; + return ['interval' => $interval, 'scale' => $scale]; } /** @@ -1047,12 +1240,12 @@ class IMipService { 'Second' => $this->l10n->t('Second'), 'Third' => $this->l10n->t('Third'), 'Fourth' => $this->l10n->t('Fourth'), - 'Fifty' => $this->l10n->t('Fifty'), + 'Fifth' => $this->l10n->t('Fifth'), 'Last' => $this->l10n->t('Last'), 'Second Last' => $this->l10n->t('Second Last'), 'Third Last' => $this->l10n->t('Third Last'), 'Fourth Last' => $this->l10n->t('Fourth Last'), - 'Fifty Last' => $this->l10n->t('Fifty Last'), + 'Fifth Last' => $this->l10n->t('Fifth Last'), }; } } diff --git a/apps/dav/lib/CalDAV/Schedule/Plugin.php b/apps/dav/lib/CalDAV/Schedule/Plugin.php index eeeebe16b88..abb3f578d04 100644 --- a/apps/dav/lib/CalDAV/Schedule/Plugin.php +++ b/apps/dav/lib/CalDAV/Schedule/Plugin.php @@ -138,7 +138,7 @@ class Plugin extends \Sabre\CalDAV\Schedule\Plugin { if ($result === null) { $result = []; } - + // iterate through items and html decode values foreach ($result as $key => $value) { $result[$key] = urldecode($value); @@ -197,12 +197,12 @@ class Plugin extends \Sabre\CalDAV\Schedule\Plugin { } // process request $this->processICalendarChange($currentObject, $vCal, $addresses, [], $modified); - + if ($currentObject) { // Destroy circular references so PHP will GC the object. $currentObject->destroy(); } - + } catch (SameOrganizerForAllComponentsException $e) { $this->handleSameOrganizerException($e, $vCal, $calendarPath); } @@ -430,12 +430,20 @@ EOF; } else { // Otherwise if we have really nothing, create a new calendar if ($currentCalendarDeleted) { - // If the calendar exists but is deleted, we need to purge it first - // This may cause some issues in a non synchronous database setup + // If the calendar exists but is in the trash bin, we try to rename its uri + // so that we can create the new one and still restore the previous one + // otherwise we just purge the calendar by removing it before recreating it $calendar = $this->getCalendar($calendarHome, $uri); if ($calendar instanceof Calendar) { - $calendar->disableTrashbin(); - $calendar->delete(); + $backend = $calendarHome->getCalDAVBackend(); + if ($backend instanceof CalDavBackend) { + // If the CalDAV backend supports moving calendars + $this->moveCalendar($backend, $principalUrl, $uri, $uri . '-back-' . time()); + } else { + // Otherwise just purge the calendar + $calendar->disableTrashbin(); + $calendar->delete(); + } } } $this->createCalendar($calendarHome, $principalUrl, $uri, $displayName); @@ -572,7 +580,7 @@ EOF; $homePath = $result[0][200]['{' . self::NS_CALDAV . '}calendar-home-set']->getHref(); /** @var Calendar $node */ foreach ($this->server->tree->getNodeForPath($homePath)->getChildren() as $node) { - + if (!$node instanceof ICalendar) { continue; } @@ -704,6 +712,10 @@ EOF; ]); } + private function moveCalendar(CalDavBackend $calDavBackend, string $principalUri, string $oldUri, string $newUri): void { + $calDavBackend->moveCalendar($oldUri, $principalUri, $principalUri, $newUri); + } + /** * Try to handle the given exception gracefully or throw it if necessary. * diff --git a/apps/dav/lib/Command/FixCalendarSyncCommand.php b/apps/dav/lib/Command/FixCalendarSyncCommand.php index bb269c92e15..cb31355c10d 100644 --- a/apps/dav/lib/Command/FixCalendarSyncCommand.php +++ b/apps/dav/lib/Command/FixCalendarSyncCommand.php @@ -43,7 +43,7 @@ class FixCalendarSyncCommand extends Command { $user = $this->userManager->get($userArg); if ($user === null) { $output->writeln("<error>User $userArg does not exist</error>"); - return 1; + return self::FAILURE; } $this->fixUserCalendars($user); @@ -54,7 +54,8 @@ class FixCalendarSyncCommand extends Command { }); $progress->finish(); } - return 0; + $output->writeln(''); + return self::SUCCESS; } private function fixUserCalendars(IUser $user, ?ProgressBar $progress = null): void { diff --git a/apps/dav/lib/Connector/Sabre/FilesPlugin.php b/apps/dav/lib/Connector/Sabre/FilesPlugin.php index ded3f321e13..a879e264459 100644 --- a/apps/dav/lib/Connector/Sabre/FilesPlugin.php +++ b/apps/dav/lib/Connector/Sabre/FilesPlugin.php @@ -203,6 +203,11 @@ class FilesPlugin extends ServerPlugin { if (!$sourceNodeFileInfo->isDeletable()) { throw new Forbidden($source . ' cannot be deleted'); } + + // The source is not allowed to be the parent of the target + if (str_starts_with($source, $target . '/')) { + throw new Forbidden($source . ' cannot be moved to it\'s parent'); + } } /** diff --git a/apps/dav/lib/Migration/Version1027Date20230504122946.php b/apps/dav/lib/Migration/Version1027Date20230504122946.php index f294cf192c2..89c192a8419 100644 --- a/apps/dav/lib/Migration/Version1027Date20230504122946.php +++ b/apps/dav/lib/Migration/Version1027Date20230504122946.php @@ -33,7 +33,7 @@ class Version1027Date20230504122946 extends SimpleMigrationStep { * @param array $options */ public function postSchemaChange(IOutput $output, Closure $schemaClosure, array $options): void { - if ($this->userManager->countSeenUsers() > 100 || array_sum($this->userManager->countUsers()) > 100) { + if ($this->userManager->countSeenUsers() > 100 || $this->userManager->countUsersTotal(100) >= 100) { $this->config->setAppValue('dav', 'needs_system_address_book_sync', 'yes'); $output->info('Could not sync system address books during update - too many user records have been found. Please call occ dav:sync-system-addressbook manually.'); return; diff --git a/apps/dav/lib/Search/TasksSearchProvider.php b/apps/dav/lib/Search/TasksSearchProvider.php index 176e758fd2b..15baf070e81 100644 --- a/apps/dav/lib/Search/TasksSearchProvider.php +++ b/apps/dav/lib/Search/TasksSearchProvider.php @@ -121,7 +121,7 @@ class TasksSearchProvider extends ACalendarSearchProvider { ): string { return $this->urlGenerator->getAbsoluteURL( $this->urlGenerator->linkToRoute('tasks.page.index') - . '#/calendars/' + . 'calendars/' . $calendarUri . '/tasks/' . $taskUri diff --git a/apps/dav/lib/ServerFactory.php b/apps/dav/lib/ServerFactory.php index 7a3f0b27747..f632ee6015d 100644 --- a/apps/dav/lib/ServerFactory.php +++ b/apps/dav/lib/ServerFactory.php @@ -10,10 +10,15 @@ declare(strict_types=1); namespace OCA\DAV; use OCA\DAV\CalDAV\InvitationResponse\InvitationResponseServer; +use OCA\DAV\Connector\Sabre\Server; class ServerFactory { public function createInviationResponseServer(bool $public): InvitationResponseServer { return new InvitationResponseServer(false); } + + public function createAttendeeAvailabilityServer(): Server { + return (new InvitationResponseServer(false))->getServer(); + } } diff --git a/apps/dav/lib/SystemTag/SystemTagList.php b/apps/dav/lib/SystemTag/SystemTagList.php index 63e69db0eda..546467f562e 100644 --- a/apps/dav/lib/SystemTag/SystemTagList.php +++ b/apps/dav/lib/SystemTag/SystemTagList.php @@ -54,6 +54,7 @@ class SystemTagList implements Element { SystemTagPlugin::ID_PROPERTYNAME => $tag->getId(), SystemTagPlugin::USERASSIGNABLE_PROPERTYNAME => $tag->isUserAssignable() ? 'true' : 'false', SystemTagPlugin::USERVISIBLE_PROPERTYNAME => $tag->isUserVisible() ? 'true' : 'false', + SystemTagPlugin::COLOR_PROPERTYNAME => $tag->getColor() ?? '', ]); $writer->write($tag->getName()); $writer->endElement(); diff --git a/apps/dav/lib/SystemTag/SystemTagPlugin.php b/apps/dav/lib/SystemTag/SystemTagPlugin.php index 8305944cb0b..428e71d91f4 100644 --- a/apps/dav/lib/SystemTag/SystemTagPlugin.php +++ b/apps/dav/lib/SystemTag/SystemTagPlugin.php @@ -18,6 +18,7 @@ use OCP\SystemTag\ISystemTag; use OCP\SystemTag\ISystemTagManager; use OCP\SystemTag\ISystemTagObjectMapper; use OCP\SystemTag\TagAlreadyExistsException; +use OCP\SystemTag\TagCreationForbiddenException; use OCP\Util; use Sabre\DAV\Exception\BadRequest; use Sabre\DAV\Exception\Conflict; @@ -189,6 +190,8 @@ class SystemTagPlugin extends \Sabre\DAV\ServerPlugin { return $tag; } catch (TagAlreadyExistsException $e) { throw new Conflict('Tag already exists', 0, $e); + } catch (TagCreationForbiddenException $e) { + throw new Forbidden('You don’t have right to create tags', 0, $e); } } @@ -376,7 +379,7 @@ class SystemTagPlugin extends \Sabre\DAV\ServerPlugin { if (!$node instanceof SystemTagNode && !$node instanceof SystemTagObjectType) { return; } - + $propPatch->handle([self::OBJECTIDS_PROPERTYNAME], function ($props) use ($node) { if (!$node instanceof SystemTagObjectType) { return false; @@ -394,7 +397,7 @@ class SystemTagPlugin extends \Sabre\DAV\ServerPlugin { if (count($objectTypes) !== 1 || $objectTypes[0] !== $node->getName()) { throw new BadRequest('Invalid object-ids property. All object types must be of the same type: ' . $node->getName()); } - + $this->tagMapper->setObjectIdsForTag($node->getSystemTag()->getId(), $node->getName(), array_keys($objects)); } |