aboutsummaryrefslogtreecommitdiffstats
path: root/apps/dav/lib/UserMigration/CalendarMigrator.php
diff options
context:
space:
mode:
Diffstat (limited to 'apps/dav/lib/UserMigration/CalendarMigrator.php')
-rw-r--r--apps/dav/lib/UserMigration/CalendarMigrator.php105
1 files changed, 52 insertions, 53 deletions
diff --git a/apps/dav/lib/UserMigration/CalendarMigrator.php b/apps/dav/lib/UserMigration/CalendarMigrator.php
index 015ce6faa86..73e9c375490 100644
--- a/apps/dav/lib/UserMigration/CalendarMigrator.php
+++ b/apps/dav/lib/UserMigration/CalendarMigrator.php
@@ -3,30 +3,12 @@
declare(strict_types=1);
/**
- * @copyright 2022 Christopher Ng <chrng8@gmail.com>
- *
- * @author Christopher Ng <chrng8@gmail.com>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2022 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OCA\DAV\UserMigration;
-use function Safe\substr;
use OCA\DAV\AppInfo\Application;
use OCA\DAV\CalDAV\CalDavBackend;
use OCA\DAV\CalDAV\ICSExportPlugin\ICSExportPlugin;
@@ -42,6 +24,7 @@ use OCP\IUser;
use OCP\UserMigration\IExportDestination;
use OCP\UserMigration\IImportSource;
use OCP\UserMigration\IMigrator;
+use OCP\UserMigration\ISizeEstimationMigrator;
use OCP\UserMigration\TMigratorBasicVersionHandling;
use Sabre\VObject\Component as VObjectComponent;
use Sabre\VObject\Component\VCalendar;
@@ -49,25 +32,15 @@ use Sabre\VObject\Component\VTimeZone;
use Sabre\VObject\Property\ICalendar\DateTime;
use Sabre\VObject\Reader as VObjectReader;
use Sabre\VObject\UUIDUtil;
-use Safe\Exceptions\StringsException;
+use Symfony\Component\Console\Output\NullOutput;
use Symfony\Component\Console\Output\OutputInterface;
use Throwable;
+use function substr;
-class CalendarMigrator implements IMigrator {
+class CalendarMigrator implements IMigrator, ISizeEstimationMigrator {
use TMigratorBasicVersionHandling;
- private CalDavBackend $calDavBackend;
-
- private ICalendarManager $calendarManager;
-
- // ICSExportPlugin is injected as the mergeObjects() method is required and is not to be used as a SabreDAV server plugin
- private ICSExportPlugin $icsExportPlugin;
-
- private Defaults $defaults;
-
- private IL10N $l10n;
-
private SabreDavServer $sabreDavServer;
private const USERS_URI_ROOT = 'principals/users/';
@@ -79,18 +52,12 @@ class CalendarMigrator implements IMigrator {
private const EXPORT_ROOT = Application::APP_ID . '/calendars/';
public function __construct(
- CalDavBackend $calDavBackend,
- ICalendarManager $calendarManager,
- ICSExportPlugin $icsExportPlugin,
- Defaults $defaults,
- IL10N $l10n
+ private CalDavBackend $calDavBackend,
+ private ICalendarManager $calendarManager,
+ private ICSExportPlugin $icsExportPlugin,
+ private Defaults $defaults,
+ private IL10N $l10n,
) {
- $this->calDavBackend = $calDavBackend;
- $this->calendarManager = $calendarManager;
- $this->icsExportPlugin = $icsExportPlugin;
- $this->defaults = $defaults;
- $this->l10n = $l10n;
-
$root = new RootCollection();
$this->sabreDavServer = new SabreDavServer(new CachingTree($root));
$this->sabreDavServer->addPlugin(new CalDAVPlugin());
@@ -181,14 +148,18 @@ class CalendarMigrator implements IMigrator {
)));
}
+ /**
+ * @throws InvalidCalendarException
+ */
private function getUniqueCalendarUri(IUser $user, string $initialCalendarUri): string {
$principalUri = $this->getPrincipalUri($user);
- try {
- $initialCalendarUri = substr($initialCalendarUri, 0, strlen(CalendarMigrator::MIGRATED_URI_PREFIX)) === CalendarMigrator::MIGRATED_URI_PREFIX
- ? $initialCalendarUri
- : CalendarMigrator::MIGRATED_URI_PREFIX . $initialCalendarUri;
- } catch (StringsException $e) {
- throw new CalendarMigratorException('Failed to get unique calendar URI', 0, $e);
+
+ $initialCalendarUri = substr($initialCalendarUri, 0, strlen(CalendarMigrator::MIGRATED_URI_PREFIX)) === CalendarMigrator::MIGRATED_URI_PREFIX
+ ? $initialCalendarUri
+ : CalendarMigrator::MIGRATED_URI_PREFIX . $initialCalendarUri;
+
+ if ($initialCalendarUri === '') {
+ throw new InvalidCalendarException();
}
$existingCalendarUris = array_map(
@@ -209,6 +180,31 @@ class CalendarMigrator implements IMigrator {
/**
* {@inheritDoc}
*/
+ public function getEstimatedExportSize(IUser $user): int|float {
+ $calendarExports = $this->getCalendarExports($user, new NullOutput());
+ $calendarCount = count($calendarExports);
+
+ // 150B for top-level properties
+ $size = ($calendarCount * 150) / 1024;
+
+ $componentCount = array_sum(array_map(
+ function (array $data): int {
+ /** @var VCalendar $vCalendar */
+ $vCalendar = $data['vCalendar'];
+ return count($vCalendar->getComponents());
+ },
+ $calendarExports,
+ ));
+
+ // 450B for each component (events, todos, alarms, etc.)
+ $size += ($componentCount * 450) / 1024;
+
+ return ceil($size);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
public function export(IUser $user, IExportDestination $exportDestination, OutputInterface $output): void {
$output->writeln('Exporting calendars into ' . CalendarMigrator::EXPORT_ROOT . '…');
@@ -430,17 +426,20 @@ class CalendarMigrator implements IMigrator {
VObjectReader::OPTION_FORGIVING,
);
} catch (Throwable $e) {
- throw new CalendarMigratorException("Failed to read file \"$importPath\"", 0, $e);
+ $output->writeln("Failed to read file \"$importPath\", skipping…");
+ continue;
}
$problems = $vCalendar->validate();
if (!empty($problems)) {
- throw new CalendarMigratorException("Invalid calendar data contained in \"$importPath\"");
+ $output->writeln("Invalid calendar data contained in \"$importPath\", skipping…");
+ continue;
}
$splitFilename = explode('.', $filename, 2);
if (count($splitFilename) !== 2) {
- throw new CalendarMigratorException("Invalid filename \"$filename\", expected filename of the format \"<calendar_name>" . CalendarMigrator::FILENAME_EXT . '"');
+ $output->writeln("Invalid filename \"$filename\", expected filename of the format \"<calendar_name>" . CalendarMigrator::FILENAME_EXT . '", skipping…');
+ continue;
}
[$initialCalendarUri, $ext] = $splitFilename;