From c16b72f588ffeae0ac58e646d0574b9121bfe0dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=B4me=20Chilliet?= Date: Thu, 28 Apr 2022 11:23:26 +0200 Subject: [PATCH 1/8] Add a method to get estimated export size in IMigrator MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Côme Chilliet --- lib/public/UserMigration/IMigrator.php | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/lib/public/UserMigration/IMigrator.php b/lib/public/UserMigration/IMigrator.php index d02e5df06836e..b7ad382bef22c 100644 --- a/lib/public/UserMigration/IMigrator.php +++ b/lib/public/UserMigration/IMigrator.php @@ -87,6 +87,14 @@ public function getDescription(): string; */ public function getVersion(): int; + /** + * Returns an estimate of the exported data size in KiB. + * Should be fast, favor performance over accuracy. + * + * @since 24.0.0 + */ + public function getExportEstimatedSize(): int; + /** * Checks whether it is able to import a version of the export format for this migrator * Use $importSource->getMigratorVersion($this->getId()) to get the version from the archive From dde192da4ae7e359b2869b8869daa02c89c4b2a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=B4me=20Chilliet?= Date: Thu, 28 Apr 2022 11:47:04 +0200 Subject: [PATCH 2/8] Implement getExportEstimatedSize in migrators MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Côme Chilliet --- .../lib/UserMigration/CalendarMigrator.php | 15 +++++++++++++ .../lib/UserMigration/ContactsMigrator.php | 15 +++++++++++++ .../lib/UserMigration/TrashbinMigrator.php | 17 +++++++++++++++ .../lib/UserMigration/AccountMigrator.php | 21 +++++++++++++++++++ lib/public/UserMigration/IMigrator.php | 2 +- 5 files changed, 69 insertions(+), 1 deletion(-) diff --git a/apps/dav/lib/UserMigration/CalendarMigrator.php b/apps/dav/lib/UserMigration/CalendarMigrator.php index 015ce6faa86d1..e6383bcc1ddcd 100644 --- a/apps/dav/lib/UserMigration/CalendarMigrator.php +++ b/apps/dav/lib/UserMigration/CalendarMigrator.php @@ -206,6 +206,21 @@ private function getUniqueCalendarUri(IUser $user, string $initialCalendarUri): return $calendarUri; } + /** + * {@inheritDoc} + */ + public function getExportEstimatedSize(IUser $user): int { + $principalUri = $this->getPrincipalUri($user); + + return array_sum(array_map( + function (ICalendar $calendar) use ($user): int { + // FIXME 1MiB by calendar, no idea if this is accurate and if we should go into more details + return 1000; + }, + $this->calendarManager->getCalendarsForPrincipal($principalUri), + )); + } + /** * {@inheritDoc} */ diff --git a/apps/dav/lib/UserMigration/ContactsMigrator.php b/apps/dav/lib/UserMigration/ContactsMigrator.php index aed41e5c82f4f..068500a1ba7ba 100644 --- a/apps/dav/lib/UserMigration/ContactsMigrator.php +++ b/apps/dav/lib/UserMigration/ContactsMigrator.php @@ -193,6 +193,21 @@ private function serializeCards(array $vCards): string { ); } + /** + * {@inheritDoc} + */ + public function getExportEstimatedSize(IUser $user): int { + $principalUri = $this->getPrincipalUri($user); + + return array_sum(array_map( + function (array $addressBookInfo) use ($user): int { + // FIXME 1MiB by addressbook, no idea if this is accurate and if we should go into more details + return 1000; + }, + $this->cardDavBackend->getAddressBooksForUser($principalUri), + )); + } + /** * {@inheritDoc} */ diff --git a/apps/files_trashbin/lib/UserMigration/TrashbinMigrator.php b/apps/files_trashbin/lib/UserMigration/TrashbinMigrator.php index dbc6267eb3aae..721ca59f9299e 100644 --- a/apps/files_trashbin/lib/UserMigration/TrashbinMigrator.php +++ b/apps/files_trashbin/lib/UserMigration/TrashbinMigrator.php @@ -63,6 +63,23 @@ public function __construct( $this->l10n = $l10n; } + /** + * {@inheritDoc} + */ + public function getExportEstimatedSize(IUser $user): int { + $uid = $user->getUID(); + + try { + $trashbinFolder = $this->root->get('/'.$uid.'/files_trashbin'); + if (!$trashbinFolder instanceof Folder) { + return 0; + } + return (int)ceil($trashbinFolder->getSize() / 1024); + } catch (\Throwable $e) { + return 0; + } + } + /** * {@inheritDoc} */ diff --git a/apps/settings/lib/UserMigration/AccountMigrator.php b/apps/settings/lib/UserMigration/AccountMigrator.php index 7b60a101ceeb9..733d4a0b75d62 100644 --- a/apps/settings/lib/UserMigration/AccountMigrator.php +++ b/apps/settings/lib/UserMigration/AccountMigrator.php @@ -68,6 +68,27 @@ public function __construct( $this->l10n = $l10n; } + /** + * {@inheritDoc} + */ + public function getExportEstimatedSize(IUser $user): int { + $uid = $user->getUID(); + + $size = 100; // 100KiB for account JSON + + try { + $avatar = $this->avatarManager->getAvatar($user->getUID()); + if ($avatar->isCustomAvatar()) { + $avatarFile = $avatar->getFile(-1); + $size += $avatarFile->getSize() / 1024; + } + } catch (Throwable $e) { + return 0; + } + + return (int)ceil($size); + } + /** * {@inheritDoc} */ diff --git a/lib/public/UserMigration/IMigrator.php b/lib/public/UserMigration/IMigrator.php index b7ad382bef22c..6915e9b18a754 100644 --- a/lib/public/UserMigration/IMigrator.php +++ b/lib/public/UserMigration/IMigrator.php @@ -93,7 +93,7 @@ public function getVersion(): int; * * @since 24.0.0 */ - public function getExportEstimatedSize(): int; + public function getExportEstimatedSize(IUser $user): int; /** * Checks whether it is able to import a version of the export format for this migrator From 4afa609ae2599cd45e031928575ed33741e36f31 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=B4me=20Chilliet?= Date: Tue, 24 May 2022 10:01:14 +0200 Subject: [PATCH 3/8] Move new IMigrator method to a specific interface ISizeEstimationMigrator MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Côme Chilliet --- apps/dav/lib/UserMigration/CalendarMigrator.php | 3 ++- apps/dav/lib/UserMigration/ContactsMigrator.php | 3 ++- apps/files_trashbin/lib/UserMigration/TrashbinMigrator.php | 3 ++- apps/settings/lib/UserMigration/AccountMigrator.php | 3 ++- 4 files changed, 8 insertions(+), 4 deletions(-) diff --git a/apps/dav/lib/UserMigration/CalendarMigrator.php b/apps/dav/lib/UserMigration/CalendarMigrator.php index e6383bcc1ddcd..2345acd43fd4b 100644 --- a/apps/dav/lib/UserMigration/CalendarMigrator.php +++ b/apps/dav/lib/UserMigration/CalendarMigrator.php @@ -42,6 +42,7 @@ 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; @@ -53,7 +54,7 @@ use Symfony\Component\Console\Output\OutputInterface; use Throwable; -class CalendarMigrator implements IMigrator { +class CalendarMigrator implements IMigrator, ISizeEstimationMigrator { use TMigratorBasicVersionHandling; diff --git a/apps/dav/lib/UserMigration/ContactsMigrator.php b/apps/dav/lib/UserMigration/ContactsMigrator.php index 068500a1ba7ba..5adf631f65e5a 100644 --- a/apps/dav/lib/UserMigration/ContactsMigrator.php +++ b/apps/dav/lib/UserMigration/ContactsMigrator.php @@ -39,6 +39,7 @@ use OCP\UserMigration\IExportDestination; use OCP\UserMigration\IImportSource; use OCP\UserMigration\IMigrator; +use OCP\UserMigration\ISizeEstimationMigrator; use OCP\UserMigration\TMigratorBasicVersionHandling; use Sabre\VObject\Component\VCard; use Sabre\VObject\Parser\Parser as VObjectParser; @@ -50,7 +51,7 @@ use Symfony\Component\Console\Output\OutputInterface; use Throwable; -class ContactsMigrator implements IMigrator { +class ContactsMigrator implements IMigrator, ISizeEstimationMigrator { use TMigratorBasicVersionHandling; diff --git a/apps/files_trashbin/lib/UserMigration/TrashbinMigrator.php b/apps/files_trashbin/lib/UserMigration/TrashbinMigrator.php index 721ca59f9299e..658f5015b0e37 100644 --- a/apps/files_trashbin/lib/UserMigration/TrashbinMigrator.php +++ b/apps/files_trashbin/lib/UserMigration/TrashbinMigrator.php @@ -36,11 +36,12 @@ use OCP\UserMigration\IExportDestination; use OCP\UserMigration\IImportSource; use OCP\UserMigration\IMigrator; +use OCP\UserMigration\ISizeEstimationMigrator; use OCP\UserMigration\TMigratorBasicVersionHandling; use OCP\UserMigration\UserMigrationException; use Symfony\Component\Console\Output\OutputInterface; -class TrashbinMigrator implements IMigrator { +class TrashbinMigrator implements IMigrator, ISizeEstimationMigrator { use TMigratorBasicVersionHandling; diff --git a/apps/settings/lib/UserMigration/AccountMigrator.php b/apps/settings/lib/UserMigration/AccountMigrator.php index 733d4a0b75d62..79955a59fdeb4 100644 --- a/apps/settings/lib/UserMigration/AccountMigrator.php +++ b/apps/settings/lib/UserMigration/AccountMigrator.php @@ -37,11 +37,12 @@ use OCP\UserMigration\IExportDestination; use OCP\UserMigration\IImportSource; use OCP\UserMigration\IMigrator; +use OCP\UserMigration\ISizeEstimationMigrator; use OCP\UserMigration\TMigratorBasicVersionHandling; use Symfony\Component\Console\Output\OutputInterface; use Throwable; -class AccountMigrator implements IMigrator { +class AccountMigrator implements IMigrator, ISizeEstimationMigrator { use TMigratorBasicVersionHandling; use TAccountsHelper; From 5a7752dcfaa0b360d6581019fc6f933b6a7589fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=B4me=20Chilliet?= Date: Tue, 24 May 2022 10:02:15 +0200 Subject: [PATCH 4/8] Add the ISizeEstimationMigrator interface for method getExportEstimatedSize MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Côme Chilliet --- lib/composer/composer/autoload_classmap.php | 1 + lib/composer/composer/autoload_static.php | 1 + lib/public/UserMigration/IMigrator.php | 8 ---- .../UserMigration/ISizeEstimationMigrator.php | 43 +++++++++++++++++++ 4 files changed, 45 insertions(+), 8 deletions(-) create mode 100644 lib/public/UserMigration/ISizeEstimationMigrator.php diff --git a/lib/composer/composer/autoload_classmap.php b/lib/composer/composer/autoload_classmap.php index 2c962b0fc6d6f..487815f44f282 100644 --- a/lib/composer/composer/autoload_classmap.php +++ b/lib/composer/composer/autoload_classmap.php @@ -563,6 +563,7 @@ 'OCP\\UserMigration\\IExportDestination' => $baseDir . '/lib/public/UserMigration/IExportDestination.php', 'OCP\\UserMigration\\IImportSource' => $baseDir . '/lib/public/UserMigration/IImportSource.php', 'OCP\\UserMigration\\IMigrator' => $baseDir . '/lib/public/UserMigration/IMigrator.php', + 'OCP\\UserMigration\\ISizeEstimationMigrator' => $baseDir . '/lib/public/UserMigration/ISizeEstimationMigrator.php', 'OCP\\UserMigration\\TMigratorBasicVersionHandling' => $baseDir . '/lib/public/UserMigration/TMigratorBasicVersionHandling.php', 'OCP\\UserMigration\\UserMigrationException' => $baseDir . '/lib/public/UserMigration/UserMigrationException.php', 'OCP\\UserStatus\\IManager' => $baseDir . '/lib/public/UserStatus/IManager.php', diff --git a/lib/composer/composer/autoload_static.php b/lib/composer/composer/autoload_static.php index da591ab0c0ff9..bc90bdf790f06 100644 --- a/lib/composer/composer/autoload_static.php +++ b/lib/composer/composer/autoload_static.php @@ -592,6 +592,7 @@ class ComposerStaticInit53792487c5a8370acc0b06b1a864ff4c 'OCP\\UserMigration\\IExportDestination' => __DIR__ . '/../../..' . '/lib/public/UserMigration/IExportDestination.php', 'OCP\\UserMigration\\IImportSource' => __DIR__ . '/../../..' . '/lib/public/UserMigration/IImportSource.php', 'OCP\\UserMigration\\IMigrator' => __DIR__ . '/../../..' . '/lib/public/UserMigration/IMigrator.php', + 'OCP\\UserMigration\\ISizeEstimationMigrator' => __DIR__ . '/../../..' . '/lib/public/UserMigration/ISizeEstimationMigrator.php', 'OCP\\UserMigration\\TMigratorBasicVersionHandling' => __DIR__ . '/../../..' . '/lib/public/UserMigration/TMigratorBasicVersionHandling.php', 'OCP\\UserMigration\\UserMigrationException' => __DIR__ . '/../../..' . '/lib/public/UserMigration/UserMigrationException.php', 'OCP\\UserStatus\\IManager' => __DIR__ . '/../../..' . '/lib/public/UserStatus/IManager.php', diff --git a/lib/public/UserMigration/IMigrator.php b/lib/public/UserMigration/IMigrator.php index 6915e9b18a754..d02e5df06836e 100644 --- a/lib/public/UserMigration/IMigrator.php +++ b/lib/public/UserMigration/IMigrator.php @@ -87,14 +87,6 @@ public function getDescription(): string; */ public function getVersion(): int; - /** - * Returns an estimate of the exported data size in KiB. - * Should be fast, favor performance over accuracy. - * - * @since 24.0.0 - */ - public function getExportEstimatedSize(IUser $user): int; - /** * Checks whether it is able to import a version of the export format for this migrator * Use $importSource->getMigratorVersion($this->getId()) to get the version from the archive diff --git a/lib/public/UserMigration/ISizeEstimationMigrator.php b/lib/public/UserMigration/ISizeEstimationMigrator.php new file mode 100644 index 0000000000000..05abe48ea8f8d --- /dev/null +++ b/lib/public/UserMigration/ISizeEstimationMigrator.php @@ -0,0 +1,43 @@ + + * + * @author Christopher Ng + * @author Côme Chilliet + * + * @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 . + * + */ + +namespace OCP\UserMigration; + +use OCP\IUser; + +/** + * @since 25.0.0 + */ +interface ISizeEstimationMigrator { + /** + * Returns an estimate of the exported data size in KiB. + * Should be fast, favor performance over accuracy. + * + * @since 25.0.0 + */ + public function getEstimatedExportSize(IUser $user): int; +} From 72fc8c907e7c709d212537f84ab124b3c66d56f7 Mon Sep 17 00:00:00 2001 From: Christopher Ng Date: Fri, 29 Apr 2022 01:45:47 +0000 Subject: [PATCH 5/8] Update method name Signed-off-by: Christopher Ng --- apps/dav/lib/UserMigration/CalendarMigrator.php | 2 +- apps/dav/lib/UserMigration/ContactsMigrator.php | 2 +- apps/files_trashbin/lib/UserMigration/TrashbinMigrator.php | 2 +- apps/settings/lib/UserMigration/AccountMigrator.php | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/apps/dav/lib/UserMigration/CalendarMigrator.php b/apps/dav/lib/UserMigration/CalendarMigrator.php index 2345acd43fd4b..5a296a2b5270d 100644 --- a/apps/dav/lib/UserMigration/CalendarMigrator.php +++ b/apps/dav/lib/UserMigration/CalendarMigrator.php @@ -210,7 +210,7 @@ private function getUniqueCalendarUri(IUser $user, string $initialCalendarUri): /** * {@inheritDoc} */ - public function getExportEstimatedSize(IUser $user): int { + public function getEstimatedExportSize(IUser $user): int { $principalUri = $this->getPrincipalUri($user); return array_sum(array_map( diff --git a/apps/dav/lib/UserMigration/ContactsMigrator.php b/apps/dav/lib/UserMigration/ContactsMigrator.php index 5adf631f65e5a..fc49828881099 100644 --- a/apps/dav/lib/UserMigration/ContactsMigrator.php +++ b/apps/dav/lib/UserMigration/ContactsMigrator.php @@ -197,7 +197,7 @@ private function serializeCards(array $vCards): string { /** * {@inheritDoc} */ - public function getExportEstimatedSize(IUser $user): int { + public function getEstimatedExportSize(IUser $user): int { $principalUri = $this->getPrincipalUri($user); return array_sum(array_map( diff --git a/apps/files_trashbin/lib/UserMigration/TrashbinMigrator.php b/apps/files_trashbin/lib/UserMigration/TrashbinMigrator.php index 658f5015b0e37..9c0334aa2f35b 100644 --- a/apps/files_trashbin/lib/UserMigration/TrashbinMigrator.php +++ b/apps/files_trashbin/lib/UserMigration/TrashbinMigrator.php @@ -67,7 +67,7 @@ public function __construct( /** * {@inheritDoc} */ - public function getExportEstimatedSize(IUser $user): int { + public function getEstimatedExportSize(IUser $user): int { $uid = $user->getUID(); try { diff --git a/apps/settings/lib/UserMigration/AccountMigrator.php b/apps/settings/lib/UserMigration/AccountMigrator.php index 79955a59fdeb4..321889788b8b5 100644 --- a/apps/settings/lib/UserMigration/AccountMigrator.php +++ b/apps/settings/lib/UserMigration/AccountMigrator.php @@ -72,7 +72,7 @@ public function __construct( /** * {@inheritDoc} */ - public function getExportEstimatedSize(IUser $user): int { + public function getEstimatedExportSize(IUser $user): int { $uid = $user->getUID(); $size = 100; // 100KiB for account JSON From b85f882c23edb565de55ef43613b6e34c41fd028 Mon Sep 17 00:00:00 2001 From: Christopher Ng Date: Fri, 29 Apr 2022 01:53:41 +0000 Subject: [PATCH 6/8] Skip avatar on failure Signed-off-by: Christopher Ng --- apps/settings/lib/UserMigration/AccountMigrator.php | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/apps/settings/lib/UserMigration/AccountMigrator.php b/apps/settings/lib/UserMigration/AccountMigrator.php index 321889788b8b5..bf1af10d46444 100644 --- a/apps/settings/lib/UserMigration/AccountMigrator.php +++ b/apps/settings/lib/UserMigration/AccountMigrator.php @@ -73,8 +73,6 @@ public function __construct( * {@inheritDoc} */ public function getEstimatedExportSize(IUser $user): int { - $uid = $user->getUID(); - $size = 100; // 100KiB for account JSON try { @@ -84,7 +82,7 @@ public function getEstimatedExportSize(IUser $user): int { $size += $avatarFile->getSize() / 1024; } } catch (Throwable $e) { - return 0; + // Skip avatar in size estimate on failure } return (int)ceil($size); From eb70231f704c64427f2b3bc9411a3c8962126a9b Mon Sep 17 00:00:00 2001 From: Christopher Ng Date: Fri, 29 Apr 2022 02:33:45 +0000 Subject: [PATCH 7/8] Update contacts estimation Signed-off-by: Christopher Ng --- .../lib/UserMigration/ContactsMigrator.php | 21 ++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/apps/dav/lib/UserMigration/ContactsMigrator.php b/apps/dav/lib/UserMigration/ContactsMigrator.php index fc49828881099..ae1a61ce4f400 100644 --- a/apps/dav/lib/UserMigration/ContactsMigrator.php +++ b/apps/dav/lib/UserMigration/ContactsMigrator.php @@ -48,6 +48,7 @@ use Sabre\VObject\UUIDUtil; use Safe\Exceptions\ArrayException; use Safe\Exceptions\StringsException; +use Symfony\Component\Console\Output\NullOutput; use Symfony\Component\Console\Output\OutputInterface; use Throwable; @@ -198,15 +199,21 @@ private function serializeCards(array $vCards): string { * {@inheritDoc} */ public function getEstimatedExportSize(IUser $user): int { - $principalUri = $this->getPrincipalUri($user); + $addressBookExports = $this->getAddressBookExports($user, new NullOutput()); + $addressBookCount = count($addressBookExports); - return array_sum(array_map( - function (array $addressBookInfo) use ($user): int { - // FIXME 1MiB by addressbook, no idea if this is accurate and if we should go into more details - return 1000; - }, - $this->cardDavBackend->getAddressBooksForUser($principalUri), + // 50B for each metadata JSON + $size = ($addressBookCount * 50) / 1024; + + $contactsCount = array_sum(array_map( + fn (array $data): int => count($data['vCards']), + $addressBookExports, )); + + // 350B for each contact + $size += ($contactsCount * 350) / 1024; + + return (int)ceil($size); } /** From a541f97dcccefe92ac51c5d7849b1596d4733747 Mon Sep 17 00:00:00 2001 From: Christopher Ng Date: Fri, 29 Apr 2022 03:03:01 +0000 Subject: [PATCH 8/8] Update calendar estimation Signed-off-by: Christopher Ng --- .../lib/UserMigration/CalendarMigrator.php | 23 ++++++++++++++----- 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/apps/dav/lib/UserMigration/CalendarMigrator.php b/apps/dav/lib/UserMigration/CalendarMigrator.php index 5a296a2b5270d..057f7dce77d81 100644 --- a/apps/dav/lib/UserMigration/CalendarMigrator.php +++ b/apps/dav/lib/UserMigration/CalendarMigrator.php @@ -51,6 +51,7 @@ 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; @@ -211,15 +212,25 @@ private function getUniqueCalendarUri(IUser $user, string $initialCalendarUri): * {@inheritDoc} */ public function getEstimatedExportSize(IUser $user): int { - $principalUri = $this->getPrincipalUri($user); + $calendarExports = $this->getCalendarExports($user, new NullOutput()); + $calendarCount = count($calendarExports); + + // 150B for top-level properties + $size = ($calendarCount * 150) / 1024; - return array_sum(array_map( - function (ICalendar $calendar) use ($user): int { - // FIXME 1MiB by calendar, no idea if this is accurate and if we should go into more details - return 1000; + $componentCount = array_sum(array_map( + function (array $data): int { + /** @var VCalendar $vCalendar */ + $vCalendar = $data['vCalendar']; + return count($vCalendar->getComponents()); }, - $this->calendarManager->getCalendarsForPrincipal($principalUri), + $calendarExports, )); + + // 450B for each component (events, todos, alarms, etc.) + $size += ($componentCount * 450) / 1024; + + return (int)ceil($size); } /**