diff options
author | John Molakvoæ <skjnldsv@users.noreply.github.com> | 2020-12-22 08:33:10 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-12-22 08:33:10 +0100 |
commit | a5c55891f5f7002b6dd2892b07e1cbddf57ff708 (patch) | |
tree | 1a9e0eea07be473c7212789e42902d57b98b448b /apps/dav | |
parent | 8e9af2bb56ac73e274fda7013a3f2fcf08717a25 (diff) | |
parent | fd01d2440268f97cb4c2365498688bb29044437d (diff) | |
download | nextcloud-server-a5c55891f5f7002b6dd2892b07e1cbddf57ff708.tar.gz nextcloud-server-a5c55891f5f7002b6dd2892b07e1cbddf57ff708.zip |
Merge pull request #24604 from nextcloud/feat/dav/move-calendar-rename
Allow to force rename a conflicting calendar
Diffstat (limited to 'apps/dav')
-rw-r--r-- | apps/dav/lib/CalDAV/CalDavBackend.php | 4 | ||||
-rw-r--r-- | apps/dav/lib/Command/MoveCalendar.php | 84 |
2 files changed, 71 insertions, 17 deletions
diff --git a/apps/dav/lib/CalDAV/CalDavBackend.php b/apps/dav/lib/CalDAV/CalDavBackend.php index 61fd7d1b0c3..2fecc7affc2 100644 --- a/apps/dav/lib/CalDAV/CalDavBackend.php +++ b/apps/dav/lib/CalDAV/CalDavBackend.php @@ -2741,11 +2741,13 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription * @param string $uriName * @param string $uriOrigin * @param string $uriDestination + * @param string $newUriName (optional) the new uriName */ - public function moveCalendar($uriName, $uriOrigin, $uriDestination) { + public function moveCalendar($uriName, $uriOrigin, $uriDestination, $newUriName = null) { $query = $this->db->getQueryBuilder(); $query->update('calendars') ->set('principaluri', $query->createNamedParameter($uriDestination)) + ->set('uri', $query->createNamedParameter($newUriName ?: $uriName)) ->where($query->expr()->eq('principaluri', $query->createNamedParameter($uriOrigin))) ->andWhere($query->expr()->eq('uri', $query->createNamedParameter($uriName))) ->execute(); diff --git a/apps/dav/lib/Command/MoveCalendar.php b/apps/dav/lib/Command/MoveCalendar.php index 04786e64780..00bf5966832 100644 --- a/apps/dav/lib/Command/MoveCalendar.php +++ b/apps/dav/lib/Command/MoveCalendar.php @@ -104,7 +104,7 @@ class MoveCalendar extends Command { ->addArgument('destinationuid', InputArgument::REQUIRED, 'User who will receive the calendar') - ->addOption('force', 'f', InputOption::VALUE_NONE, "Force the migration by removing existing shares"); + ->addOption('force', 'f', InputOption::VALUE_NONE, "Force the migration by removing existing shares and renaming calendars in case of conflicts"); } protected function execute(InputInterface $input, OutputInterface $output): int { @@ -122,6 +122,7 @@ class MoveCalendar extends Command { } $name = $input->getArgument('name'); + $newName = null; $calendar = $this->calDav->getCalendarByUri(self::URI_USERS . $userOrigin, $name); @@ -129,27 +130,85 @@ class MoveCalendar extends Command { throw new \InvalidArgumentException("User <$userOrigin> has no calendar named <$name>. You can run occ dav:list-calendars to list calendars URIs for this user."); } - if (null !== $this->calDav->getCalendarByUri(self::URI_USERS . $userDestination, $name)) { - throw new \InvalidArgumentException("User <$userDestination> already has a calendar named <$name>."); + // Calendar already exists + if ($this->calendarExists($userDestination, $name)) { + if ($input->getOption('force')) { + // Try to find a suitable name + $newName = $this->getNewCalendarName($userDestination, $name); + + // If we didn't find a suitable value after all the iterations, give up + if ($this->calendarExists($userDestination, $newName)) { + throw new \InvalidArgumentException("Unable to find a suitable calendar name for <$userDestination> with initial name <$name>."); + } + } else { + throw new \InvalidArgumentException("User <$userDestination> already has a calendar named <$name>."); + } } - $this->checkShares($calendar, $userOrigin, $userDestination, $input->getOption('force')); + $hadShares = $this->checkShares($calendar, $userOrigin, $userDestination, $input->getOption('force')); + if ($hadShares) { + /** + * Warn that share links have changed if there are shares + */ + $this->io->note([ + "Please note that moving calendar " . $calendar['uri'] . " from user <$userOrigin> to <$userDestination> has caused share links to change.", + "Sharees will need to change \"example.com/remote.php/dav/calendars/uid/" . $calendar['uri'] . "_shared_by_$userOrigin\" to \"example.com/remote.php/dav/calendars/uid/" . $newName ?: $calendar['uri'] . "_shared_by_$userDestination\"" + ]); + } - $this->calDav->moveCalendar($name, self::URI_USERS . $userOrigin, self::URI_USERS . $userDestination); + $this->calDav->moveCalendar($name, self::URI_USERS . $userOrigin, self::URI_USERS . $userDestination, $newName); - $this->io->success("Calendar <$name> was moved from user <$userOrigin> to <$userDestination>"); + $this->io->success("Calendar <$name> was moved from user <$userOrigin> to <$userDestination>" . ($newName ? " as <$newName>" : '')); return 0; } /** + * Check if the calendar exists for user + * + * @param string $userDestination + * @param string $name + * @return bool + */ + protected function calendarExists(string $userDestination, string $name): bool { + return null !== $this->calDav->getCalendarByUri(self::URI_USERS . $userDestination, $name); + } + + /** + * Try to find a suitable new calendar name that + * doesn't exists for the provided user + * + * @param string $userDestination + * @param string $name + * @return string + */ + protected function getNewCalendarName(string $userDestination, string $name): string { + $increment = 1; + $newName = $name . '-' . $increment; + while ($increment <= 10) { + $this->io->writeln("Trying calendar name <$newName>", OutputInterface::VERBOSITY_VERBOSE); + if (!$this->calendarExists($userDestination, $newName)) { + // New name is good to go + $this->io->writeln("Found proper new calendar name <$newName>", OutputInterface::VERBOSITY_VERBOSE); + break; + } + $newName = $name . '-' . $increment; + $increment++; + } + + return $newName; + } + + /** * Check that moving the calendar won't break shares * * @param array $calendar * @param string $userOrigin * @param string $userDestination * @param bool $force + * @return bool had any shares or not + * @throws \InvalidArgumentException */ - private function checkShares(array $calendar, string $userOrigin, string $userDestination, bool $force = false) { + private function checkShares(array $calendar, string $userOrigin, string $userDestination, bool $force = false): bool { $shares = $this->calDav->getShares($calendar['id']); foreach ($shares as $share) { list(, $prefix, $userOrGroup) = explode('/', $share['href'], 3); @@ -177,14 +236,7 @@ class MoveCalendar extends Command { } } } - /** - * Warn that share links have changed if there are shares - */ - if (count($shares) > 0) { - $this->io->note([ - "Please note that moving calendar " . $calendar['uri'] . " from user <$userOrigin> to <$userDestination> has caused share links to change.", - "Sharees will need to change \"example.com/remote.php/dav/calendars/uid/" . $calendar['uri'] . "_shared_by_$userOrigin\" to \"example.com/remote.php/dav/calendars/uid/" . $calendar['uri'] . "_shared_by_$userDestination\"" - ]); - } + + return count($shares) > 0; } } |