summaryrefslogtreecommitdiffstats
path: root/apps/dav
diff options
context:
space:
mode:
authorChristopher Ng <chrng8@gmail.com>2022-02-23 05:27:49 +0000
committerChristopher Ng <chrng8@gmail.com>2022-03-02 01:59:15 +0000
commit302a67f6853065122ef8648cdbdefc1504e8d350 (patch)
treede3c6e69c8859252ebc3127d7f0831611c3251d9 /apps/dav
parent4c3d68381b6bb1847a2b5b22dbfc61a83c529df6 (diff)
downloadnextcloud-server-302a67f6853065122ef8648cdbdefc1504e8d350.tar.gz
nextcloud-server-302a67f6853065122ef8648cdbdefc1504e8d350.zip
Integrate migrator
Signed-off-by: Christopher Ng <chrng8@gmail.com>
Diffstat (limited to 'apps/dav')
-rw-r--r--apps/dav/appinfo/info.xml2
-rw-r--r--apps/dav/composer/composer/autoload_classmap.php2
-rw-r--r--apps/dav/composer/composer/autoload_static.php2
-rw-r--r--apps/dav/lib/AppInfo/Application.php3
-rw-r--r--apps/dav/lib/Command/ExportCalendars.php83
-rw-r--r--apps/dav/lib/Command/ImportCalendar.php94
-rw-r--r--apps/dav/lib/UserMigration/CalendarMigrator.php140
-rw-r--r--apps/dav/tests/integration/UserMigration/CalendarMigratorTest.php8
8 files changed, 74 insertions, 260 deletions
diff --git a/apps/dav/appinfo/info.xml b/apps/dav/appinfo/info.xml
index 88c4ee03ac3..8462ed1816d 100644
--- a/apps/dav/appinfo/info.xml
+++ b/apps/dav/appinfo/info.xml
@@ -56,8 +56,6 @@
<command>OCA\DAV\Command\SyncBirthdayCalendar</command>
<command>OCA\DAV\Command\SyncSystemAddressBook</command>
<command>OCA\DAV\Command\RemoveInvalidShares</command>
- <command>OCA\DAV\Command\ExportCalendars</command>
- <command>OCA\DAV\Command\ImportCalendar</command>
</commands>
<settings>
diff --git a/apps/dav/composer/composer/autoload_classmap.php b/apps/dav/composer/composer/autoload_classmap.php
index bf0fe9cbf75..f4b17814817 100644
--- a/apps/dav/composer/composer/autoload_classmap.php
+++ b/apps/dav/composer/composer/autoload_classmap.php
@@ -124,8 +124,6 @@ return array(
'OCA\\DAV\\Command\\CreateAddressBook' => $baseDir . '/../lib/Command/CreateAddressBook.php',
'OCA\\DAV\\Command\\CreateCalendar' => $baseDir . '/../lib/Command/CreateCalendar.php',
'OCA\\DAV\\Command\\DeleteCalendar' => $baseDir . '/../lib/Command/DeleteCalendar.php',
- 'OCA\\DAV\\Command\\ExportCalendars' => $baseDir . '/../lib/Command/ExportCalendars.php',
- 'OCA\\DAV\\Command\\ImportCalendar' => $baseDir . '/../lib/Command/ImportCalendar.php',
'OCA\\DAV\\Command\\ListCalendars' => $baseDir . '/../lib/Command/ListCalendars.php',
'OCA\\DAV\\Command\\MoveCalendar' => $baseDir . '/../lib/Command/MoveCalendar.php',
'OCA\\DAV\\Command\\RemoveInvalidShares' => $baseDir . '/../lib/Command/RemoveInvalidShares.php',
diff --git a/apps/dav/composer/composer/autoload_static.php b/apps/dav/composer/composer/autoload_static.php
index 18bfd642960..d164ab2b1ce 100644
--- a/apps/dav/composer/composer/autoload_static.php
+++ b/apps/dav/composer/composer/autoload_static.php
@@ -139,8 +139,6 @@ class ComposerStaticInitDAV
'OCA\\DAV\\Command\\CreateAddressBook' => __DIR__ . '/..' . '/../lib/Command/CreateAddressBook.php',
'OCA\\DAV\\Command\\CreateCalendar' => __DIR__ . '/..' . '/../lib/Command/CreateCalendar.php',
'OCA\\DAV\\Command\\DeleteCalendar' => __DIR__ . '/..' . '/../lib/Command/DeleteCalendar.php',
- 'OCA\\DAV\\Command\\ExportCalendars' => __DIR__ . '/..' . '/../lib/Command/ExportCalendars.php',
- 'OCA\\DAV\\Command\\ImportCalendar' => __DIR__ . '/..' . '/../lib/Command/ImportCalendar.php',
'OCA\\DAV\\Command\\ListCalendars' => __DIR__ . '/..' . '/../lib/Command/ListCalendars.php',
'OCA\\DAV\\Command\\MoveCalendar' => __DIR__ . '/..' . '/../lib/Command/MoveCalendar.php',
'OCA\\DAV\\Command\\RemoveInvalidShares' => __DIR__ . '/..' . '/../lib/Command/RemoveInvalidShares.php',
diff --git a/apps/dav/lib/AppInfo/Application.php b/apps/dav/lib/AppInfo/Application.php
index 99521b61e8b..f29161d6976 100644
--- a/apps/dav/lib/AppInfo/Application.php
+++ b/apps/dav/lib/AppInfo/Application.php
@@ -80,6 +80,7 @@ use OCA\DAV\Listener\CardListener;
use OCA\DAV\Search\ContactsSearchProvider;
use OCA\DAV\Search\EventsSearchProvider;
use OCA\DAV\Search\TasksSearchProvider;
+use OCA\DAV\UserMigration\CalendarMigrator;
use OCP\AppFramework\App;
use OCP\AppFramework\Bootstrap\IBootContext;
use OCP\AppFramework\Bootstrap\IBootstrap;
@@ -165,6 +166,8 @@ class Application extends App implements IBootstrap {
$context->registerNotifierService(Notifier::class);
$context->registerCalendarProvider(CalendarProvider::class);
+
+ $context->registerUserMigrator(CalendarMigrator::class);
}
public function boot(IBootContext $context): void {
diff --git a/apps/dav/lib/Command/ExportCalendars.php b/apps/dav/lib/Command/ExportCalendars.php
deleted file mode 100644
index 770d6edc425..00000000000
--- a/apps/dav/lib/Command/ExportCalendars.php
+++ /dev/null
@@ -1,83 +0,0 @@
-<?php
-
-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/>.
- *
- */
-
-namespace OCA\DAV\Command;
-
-use OC\Core\Command\Base;
-use OCA\DAV\UserMigration\CalendarMigrator;
-use OCA\DAV\UserMigration\CalendarMigratorException;
-use OCP\IUser;
-use OCP\IUserManager;
-use Symfony\Component\Console\Input\InputArgument;
-use Symfony\Component\Console\Input\InputInterface;
-use Symfony\Component\Console\Output\OutputInterface;
-
-class ExportCalendars extends Base {
-
- /** @var IUserManager */
- private $userManager;
-
- /** @var CalendarMigrator */
- private $calendarMigrator;
-
- public function __construct(
- IUserManager $userManager,
- CalendarMigrator $calendarMigrator
- ) {
- parent::__construct();
- $this->userManager = $userManager;
- $this->calendarMigrator = $calendarMigrator;
- }
-
- protected function configure() {
- $this
- ->setName('dav:export-calendars')
- ->setDescription('Export the calendars of a user')
- ->addArgument(
- 'user',
- InputArgument::REQUIRED,
- 'User to export',
- );
- }
-
- protected function execute(InputInterface $input, OutputInterface $output): int {
- $user = $this->userManager->get($input->getArgument('user'));
-
- if (!$user instanceof IUser) {
- $output->writeln('<error>User ' . $input->getArgument('user') . ' does not exist</error>');
- return 1;
- }
-
- try {
- $this->calendarMigrator->export($user, $output);
- } catch (CalendarMigratorException $e) {
- $output->writeln('<error>' . $e->getMessage() . '</error>');
- return $e->getCode() !== 0 ? (int)$e->getCode() : 1;
- }
-
- return 0;
- }
-}
diff --git a/apps/dav/lib/Command/ImportCalendar.php b/apps/dav/lib/Command/ImportCalendar.php
deleted file mode 100644
index 193ecc3b29b..00000000000
--- a/apps/dav/lib/Command/ImportCalendar.php
+++ /dev/null
@@ -1,94 +0,0 @@
-<?php
-
-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/>.
- *
- */
-
-namespace OCA\DAV\Command;
-
-use OC\Core\Command\Base;
-use OCA\DAV\UserMigration\CalendarMigrator;
-use OCA\DAV\UserMigration\CalendarMigratorException;
-use OCP\IUser;
-use OCP\IUserManager;
-use Symfony\Component\Console\Input\InputArgument;
-use Symfony\Component\Console\Input\InputInterface;
-use Symfony\Component\Console\Output\OutputInterface;
-
-class ImportCalendar extends Base {
-
- /** @var IUserManager */
- private $userManager;
-
- /** @var CalendarMigrator */
- private $calendarMigrator;
-
- public function __construct(
- IUserManager $userManager,
- CalendarMigrator $calendarMigrator
- ) {
- parent::__construct();
- $this->userManager = $userManager;
- $this->calendarMigrator = $calendarMigrator;
- }
-
- protected function configure() {
- $this
- ->setName('dav:import-calendar')
- ->setDescription('Import a calendar to a user\'s account')
- ->addArgument(
- 'user',
- InputArgument::REQUIRED,
- 'User to import the calendar for',
- )
- ->addArgument(
- 'path',
- InputArgument::REQUIRED,
- 'Path to the *.ics file',
- );
- }
-
- protected function execute(InputInterface $input, OutputInterface $output): int {
- $user = $this->userManager->get($input->getArgument('user'));
-
- [
- 'basename' => $filename,
- 'dirname' => $srcDir,
- ] = pathinfo($input->getArgument('path'));
-
-
- if (!$user instanceof IUser) {
- $output->writeln('<error>User ' . $input->getArgument('user') . ' does not exist</error>');
- return 1;
- }
-
- try {
- $this->calendarMigrator->import($user, $srcDir, $filename, $output);
- } catch (CalendarMigratorException $e) {
- $output->writeln('<error>' . $e->getMessage() . '</error>');
- return $e->getCode() !== 0 ? (int)$e->getCode() : 1;
- }
-
- return 0;
- }
-}
diff --git a/apps/dav/lib/UserMigration/CalendarMigrator.php b/apps/dav/lib/UserMigration/CalendarMigrator.php
index c1252d7517a..6a36a7204e1 100644
--- a/apps/dav/lib/UserMigration/CalendarMigrator.php
+++ b/apps/dav/lib/UserMigration/CalendarMigrator.php
@@ -26,10 +26,7 @@ declare(strict_types=1);
namespace OCA\DAV\UserMigration;
-use function Safe\fopen;
use function Safe\substr;
-use OC\Files\Filesystem;
-use OC\Files\View;
use OCA\DAV\CalDAV\CalDavBackend;
use OCA\DAV\CalDAV\ICSExportPlugin\ICSExportPlugin;
use OCA\DAV\CalDAV\Plugin as CalDAVPlugin;
@@ -41,6 +38,10 @@ use OCP\Calendar\IManager as ICalendarManager;
use OCP\Defaults;
use OCP\IL10N;
use OCP\IUser;
+use OCP\UserMigration\IExportDestination;
+use OCP\UserMigration\IImportSource;
+use OCP\UserMigration\IMigrator;
+use OCP\UserMigration\TMigratorBasicVersionHandling;
use Sabre\DAV\Exception\BadRequest;
use Sabre\DAV\Version as SabreDavVersion;
use Sabre\VObject\Component as VObjectComponent;
@@ -52,7 +53,9 @@ use Sabre\VObject\UUIDUtil;
use Safe\Exceptions\FilesystemException;
use Symfony\Component\Console\Output\OutputInterface;
-class CalendarMigrator {
+class CalendarMigrator implements IMigrator {
+
+ use TMigratorBasicVersionHandling;
private CalDavBackend $calDavBackend;
@@ -67,11 +70,13 @@ class CalendarMigrator {
private SabreDavServer $sabreDavServer;
- public const USERS_URI_ROOT = 'principals/users/';
+ private const USERS_URI_ROOT = 'principals/users/';
+
+ private const FILENAME_EXT = '.ics';
- public const FILENAME_EXT = '.ics';
+ private const MIGRATED_URI_PREFIX = 'migrated-';
- public const MIGRATED_URI_PREFIX = 'migrated-';
+ private const EXPORT_ROOT = 'calendars/';
public function __construct(
CalDavBackend $calDavBackend,
@@ -86,12 +91,15 @@ class CalendarMigrator {
$this->defaults = $defaults;
$this->l10n = $l10n;
+ // Override trait property
+ $this->mandatory = true;
+
$root = new RootCollection();
$this->sabreDavServer = new SabreDavServer(new CachingTree($root));
$this->sabreDavServer->addPlugin(new CalDAVPlugin());
}
- public function getPrincipalUri(IUser $user): string {
+ private function getPrincipalUri(IUser $user): string {
return CalendarMigrator::USERS_URI_ROOT . $user->getUID();
}
@@ -101,7 +109,7 @@ class CalendarMigrator {
* @throws CalendarMigratorException
* @throws InvalidCalendarException
*/
- public function getCalendarExportData(IUser $user, ICalendar $calendar): array {
+ private function getCalendarExportData(IUser $user, ICalendar $calendar): array {
$userId = $user->getUID();
$calendarId = $calendar->getKey();
$calendarInfo = $this->calDavBackend->getCalendarById($calendarId);
@@ -157,7 +165,7 @@ class CalendarMigrator {
*
* @throws CalendarMigratorException
*/
- public function getCalendarExports(IUser $user): array {
+ private function getCalendarExports(IUser $user): array {
$principalUri = $this->getPrincipalUri($user);
return array_values(array_filter(array_map(
@@ -174,7 +182,7 @@ class CalendarMigrator {
)));
}
- public function getUniqueCalendarUri(IUser $user, string $initialCalendarUri): string {
+ private function getUniqueCalendarUri(IUser $user, string $initialCalendarUri): string {
$principalUri = $this->getPrincipalUri($user);
$initialCalendarUri = substr($initialCalendarUri, 0, strlen(CalendarMigrator::MIGRATED_URI_PREFIX)) === CalendarMigrator::MIGRATED_URI_PREFIX
? $initialCalendarUri
@@ -196,24 +204,11 @@ class CalendarMigrator {
}
/**
- * @throws CalendarMigratorException
+ * {@inheritDoc}
*/
- protected function writeExport(IUser $user, string $data, string $destDir, string $filename, OutputInterface $output): void {
- $userId = $user->getUID();
-
- \OC::$server->getUserFolder($userId);
- Filesystem::initMountPoints($userId);
-
- $view = new View();
+ public function export(IUser $user, IExportDestination $exportDestination, OutputInterface $output): void {
+ $output->writeln("Exporting calendars…");
- if ($view->file_put_contents("$destDir/$filename", $data) === false) {
- throw new CalendarMigratorException('Could not export calendar');
- }
-
- $output->writeln("<info>✅ Exported calendar of <$userId> into $destDir/$filename</info>");
- }
-
- public function export(IUser $user, OutputInterface $output): void {
$userId = $user->getUID();
try {
@@ -234,24 +229,16 @@ class CalendarMigrator {
// Set filename to sanitized calendar name appended with the date
$filename = preg_replace('/[^a-zA-Z0-9-_ ]/um', '', $name) . '_' . date('Y-m-d') . CalendarMigrator::FILENAME_EXT;
- $this->writeExport(
- $user,
- $vCalendar->serialize(),
- // TESTING directory does not automatically get created so just write to user directory, this will be put in a zip with all other user_migration data
- // "/$userId/export/$appId",
- "/$userId",
- $filename,
- $output,
- );
+ if ($exportDestination->addFileContents(CalendarMigrator::EXPORT_ROOT . $filename, $vCalendar->serialize()) === false) {
+ throw new CalendarMigratorException();
+ }
}
}
/**
- * Return an associative array mapping Time Zone ID to VTimeZone component
- *
* @return array<string, VTimeZone>
*/
- public function getCalendarTimezones(VCalendar $vCalendar): array {
+ private function getCalendarTimezones(VCalendar $vCalendar): array {
/** @var VTimeZone[] $calendarTimezones */
$calendarTimezones = array_values(array_filter(
$vCalendar->getComponents(),
@@ -270,7 +257,7 @@ class CalendarMigrator {
/**
* @return VTimeZone[]
*/
- public function getTimezonesForComponent(VCalendar $vCalendar, VObjectComponent $component): array {
+ private function getTimezonesForComponent(VCalendar $vCalendar, VObjectComponent $component): array {
$componentTimezoneIds = [];
foreach ($component->children() as $child) {
@@ -290,7 +277,7 @@ class CalendarMigrator {
)));
}
- public function sanitizeComponent(VObjectComponent $component): VObjectComponent {
+ private function sanitizeComponent(VObjectComponent $component): VObjectComponent {
// Operate on the component clone to prevent mutation of the original
$componentClone = clone $component;
@@ -310,7 +297,7 @@ class CalendarMigrator {
/**
* @return VObjectComponent[]
*/
- public function getRequiredImportComponents(VCalendar $vCalendar, VObjectComponent $component): array {
+ private function getRequiredImportComponents(VCalendar $vCalendar, VObjectComponent $component): array {
$component = $this->sanitizeComponent($component);
/** @var array<int, VTimeZone> $timezoneComponents */
$timezoneComponents = $this->getTimezonesForComponent($vCalendar, $component);
@@ -320,7 +307,7 @@ class CalendarMigrator {
];
}
- public function initCalendarObject(): VCalendar {
+ private function initCalendarObject(): VCalendar {
$vCalendarObject = new VCalendar();
$vCalendarObject->PRODID = $this->sabreDavServer::$exposeVersion
? '-//SabreDAV//SabreDAV ' . SabreDavVersion::VERSION . '//EN'
@@ -328,7 +315,7 @@ class CalendarMigrator {
return $vCalendarObject;
}
- public function importCalendarObject(int $calendarId, VCalendar $vCalendarObject): void {
+ private function importCalendarObject(int $calendarId, VCalendar $vCalendarObject): void {
try {
$this->calDavBackend->createCalendarObject(
$calendarId,
@@ -345,7 +332,7 @@ class CalendarMigrator {
/**
* @throws CalendarMigratorException
*/
- public function importCalendar(IUser $user, string $filename, string $initialCalendarUri, VCalendar $vCalendar): void {
+ private function importCalendar(IUser $user, string $filename, string $initialCalendarUri, VCalendar $vCalendar): void {
$principalUri = $this->getPrincipalUri($user);
$calendarUri = $this->getUniqueCalendarUri($user, $initialCalendarUri);
@@ -415,43 +402,50 @@ class CalendarMigrator {
}
/**
+ * {@inheritDoc}
+ *
* @throws FilesystemException
* @throws CalendarMigratorException
*/
- public function import(IUser $user, string $srcDir, string $filename, OutputInterface $output): void {
- $userId = $user->getUID();
-
- try {
- /** @var VCalendar $vCalendar */
- $vCalendar = VObjectReader::read(
- fopen("$srcDir/$filename", 'r'),
- VObjectReader::OPTION_FORGIVING,
- );
- } catch (FilesystemException $e) {
- throw new FilesystemException("Failed to read file: \"$srcDir/$filename\"");
+ public function import(IUser $user, IImportSource $importSource, OutputInterface $output): void {
+ if ($importSource->getMigratorVersion(static::class) === null) {
+ $output->writeln('No version for ' . static::class . ', skipping import…');
+ return;
}
- $problems = $vCalendar->validate();
- if (empty($problems)) {
- $splitFilename = explode('_', $filename, 2);
- if (count($splitFilename) !== 2) {
- $output->writeln("<error>Invalid filename, filename must be of the format: \"<calendar_name>_YYYY-MM-DD" . CalendarMigrator::FILENAME_EXT . "\"</error>");
- throw new CalendarMigratorException();
+ $output->writeln("Importing calendars…");
+
+ foreach ($importSource->getFolderListing(CalendarMigrator::EXPORT_ROOT) as $filename) {
+ try {
+ /** @var VCalendar $vCalendar */
+ $vCalendar = VObjectReader::read(
+ $importSource->getFileAsStream(CalendarMigrator::EXPORT_ROOT . $filename),
+ VObjectReader::OPTION_FORGIVING,
+ );
+ } catch (FilesystemException $e) {
+ throw new FilesystemException("Failed to read file: \"$filename\"");
}
- [$initialCalendarUri, $suffix] = $splitFilename;
- $this->importCalendar(
- $user,
- $filename,
- $initialCalendarUri,
- $vCalendar,
- );
+ $problems = $vCalendar->validate();
+ if (empty($problems)) {
+ $splitFilename = explode('_', $filename, 2);
+ if (count($splitFilename) !== 2) {
+ $output->writeln("<error>Invalid filename, expected filename of the format: \"<calendar_name>_YYYY-MM-DD" . CalendarMigrator::FILENAME_EXT . "\"</error>");
+ throw new CalendarMigratorException();
+ }
+ [$initialCalendarUri, $suffix] = $splitFilename;
- $vCalendar->destroy();
+ $this->importCalendar(
+ $user,
+ $filename,
+ $initialCalendarUri,
+ $vCalendar,
+ );
- $output->writeln("<info>✅ Imported calendar \"$filename\" into account of <$userId></info>");
- } else {
- throw new CalendarMigratorException("Invalid data contained in \"$srcDir/$filename\"");
+ $vCalendar->destroy();
+ } else {
+ throw new CalendarMigratorException("Invalid data contained in \"$filename\"");
+ }
}
}
}
diff --git a/apps/dav/tests/integration/UserMigration/CalendarMigratorTest.php b/apps/dav/tests/integration/UserMigration/CalendarMigratorTest.php
index 1f7bf630094..e2eb0c75d9b 100644
--- a/apps/dav/tests/integration/UserMigration/CalendarMigratorTest.php
+++ b/apps/dav/tests/integration/UserMigration/CalendarMigratorTest.php
@@ -97,7 +97,7 @@ class CalendarMigratorTest extends TestCase {
private function getSanitizedComponents(VCalendar $vCalendar): array {
return array_map(
// Elements of the serialized blob are sorted
- fn (VObjectComponent $component) => $this->migrator->sanitizeComponent($component)->serialize(),
+ fn (VObjectComponent $component) => $this->invokePrivate($this->migrator, 'sanitizeComponent', [$component])->serialize(),
$vCalendar->getComponents(),
);
}
@@ -111,9 +111,9 @@ class CalendarMigratorTest extends TestCase {
$problems = $importCalendar->validate();
$this->assertEmpty($problems);
- $this->migrator->importCalendar($user, $filename, $initialCalendarUri, $importCalendar);
+ $this->invokePrivate($this->migrator, 'importCalendar', [$user, $filename, $initialCalendarUri, $importCalendar]);
- $calendarExports = $this->migrator->getCalendarExports($user);
+ $calendarExports = $this->invokePrivate($this->migrator, 'getCalendarExports', [$user]);
$this->assertCount(1, $calendarExports);
/** @var VCalendar $exportCalendar */
@@ -125,7 +125,7 @@ class CalendarMigratorTest extends TestCase {
);
$this->assertEqualsCanonicalizing(
- // Components are sanitized on import
+ // Components are expected to be sanitized on import
$this->getSanitizedComponents($importCalendar),
$this->getComponents($exportCalendar),
);