diff --git a/apps/dav/lib/UserMigration/CalendarMigrator.php b/apps/dav/lib/UserMigration/CalendarMigrator.php index 015ce6faa86d1..057f7dce77d81 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; @@ -50,10 +51,11 @@ 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; -class CalendarMigrator implements IMigrator { +class CalendarMigrator implements IMigrator, ISizeEstimationMigrator { use TMigratorBasicVersionHandling; @@ -206,6 +208,31 @@ private function getUniqueCalendarUri(IUser $user, string $initialCalendarUri): return $calendarUri; } + /** + * {@inheritDoc} + */ + public function getEstimatedExportSize(IUser $user): int { + $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 (int)ceil($size); + } + /** * {@inheritDoc} */ diff --git a/apps/dav/lib/UserMigration/ContactsMigrator.php b/apps/dav/lib/UserMigration/ContactsMigrator.php index aed41e5c82f4f..ae1a61ce4f400 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; @@ -47,10 +48,11 @@ 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; -class ContactsMigrator implements IMigrator { +class ContactsMigrator implements IMigrator, ISizeEstimationMigrator { use TMigratorBasicVersionHandling; @@ -193,6 +195,27 @@ private function serializeCards(array $vCards): string { ); } + /** + * {@inheritDoc} + */ + public function getEstimatedExportSize(IUser $user): int { + $addressBookExports = $this->getAddressBookExports($user, new NullOutput()); + $addressBookCount = count($addressBookExports); + + // 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); + } + /** * {@inheritDoc} */ diff --git a/apps/files_trashbin/lib/UserMigration/TrashbinMigrator.php b/apps/files_trashbin/lib/UserMigration/TrashbinMigrator.php index dbc6267eb3aae..9c0334aa2f35b 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; @@ -63,6 +64,23 @@ public function __construct( $this->l10n = $l10n; } + /** + * {@inheritDoc} + */ + public function getEstimatedExportSize(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..bf1af10d46444 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; @@ -68,6 +69,25 @@ public function __construct( $this->l10n = $l10n; } + /** + * {@inheritDoc} + */ + public function getEstimatedExportSize(IUser $user): int { + $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) { + // Skip avatar in size estimate on failure + } + + return (int)ceil($size); + } + /** * {@inheritDoc} */ 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/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; +}