diff --git a/apps/dav/appinfo/info.xml b/apps/dav/appinfo/info.xml index e0f4608e8c2b5..11827babc43da 100644 --- a/apps/dav/appinfo/info.xml +++ b/apps/dav/appinfo/info.xml @@ -56,6 +56,7 @@ OCA\DAV\Command\ClearCalendarUnshares + OCA\DAV\Command\ClearContactsPhotoCache OCA\DAV\Command\CreateAddressBook OCA\DAV\Command\CreateCalendar OCA\DAV\Command\CreateSubscription diff --git a/apps/dav/appinfo/v1/carddav.php b/apps/dav/appinfo/v1/carddav.php index 0220332297ee4..bcd66e4709068 100644 --- a/apps/dav/appinfo/v1/carddav.php +++ b/apps/dav/appinfo/v1/carddav.php @@ -23,7 +23,6 @@ use OCP\Accounts\IAccountManager; use OCP\App\IAppManager; use OCP\EventDispatcher\IEventDispatcher; -use OCP\Files\AppData\IAppDataFactory; use OCP\IConfig; use OCP\IDBConnection; use OCP\IGroupManager; @@ -98,10 +97,7 @@ $server->addPlugin(new \Sabre\DAV\Sync\Plugin()); $server->addPlugin(new \Sabre\CardDAV\VCFExportPlugin()); -$server->addPlugin(new ImageExportPlugin(new PhotoCache( - Server::get(IAppDataFactory::class)->get('dav-photocache'), - Server::get(LoggerInterface::class) -))); +$server->addPlugin(new ImageExportPlugin(Server::get(PhotoCache::class))); $server->addPlugin(new ExceptionLoggerPlugin('carddav', Server::get(LoggerInterface::class))); $server->addPlugin(Server::get(CardDavRateLimitingPlugin::class)); $server->addPlugin(Server::get(CardDavValidatePlugin::class)); diff --git a/apps/dav/composer/composer/autoload_classmap.php b/apps/dav/composer/composer/autoload_classmap.php index 913f5b46d9886..f17c9ca3b7b32 100644 --- a/apps/dav/composer/composer/autoload_classmap.php +++ b/apps/dav/composer/composer/autoload_classmap.php @@ -156,6 +156,7 @@ 'OCA\\DAV\\CardDAV\\Validation\\CardDavValidatePlugin' => $baseDir . '/../lib/CardDAV/Validation/CardDavValidatePlugin.php', 'OCA\\DAV\\CardDAV\\Xml\\Groups' => $baseDir . '/../lib/CardDAV/Xml/Groups.php', 'OCA\\DAV\\Command\\ClearCalendarUnshares' => $baseDir . '/../lib/Command/ClearCalendarUnshares.php', + 'OCA\\DAV\\Command\\ClearContactsPhotoCache' => $baseDir . '/../lib/Command/ClearContactsPhotoCache.php', 'OCA\\DAV\\Command\\CreateAddressBook' => $baseDir . '/../lib/Command/CreateAddressBook.php', 'OCA\\DAV\\Command\\CreateCalendar' => $baseDir . '/../lib/Command/CreateCalendar.php', 'OCA\\DAV\\Command\\CreateSubscription' => $baseDir . '/../lib/Command/CreateSubscription.php', diff --git a/apps/dav/composer/composer/autoload_static.php b/apps/dav/composer/composer/autoload_static.php index 6369511343e0a..26e935ad35117 100644 --- a/apps/dav/composer/composer/autoload_static.php +++ b/apps/dav/composer/composer/autoload_static.php @@ -171,6 +171,7 @@ class ComposerStaticInitDAV 'OCA\\DAV\\CardDAV\\Validation\\CardDavValidatePlugin' => __DIR__ . '/..' . '/../lib/CardDAV/Validation/CardDavValidatePlugin.php', 'OCA\\DAV\\CardDAV\\Xml\\Groups' => __DIR__ . '/..' . '/../lib/CardDAV/Xml/Groups.php', 'OCA\\DAV\\Command\\ClearCalendarUnshares' => __DIR__ . '/..' . '/../lib/Command/ClearCalendarUnshares.php', + 'OCA\\DAV\\Command\\ClearContactsPhotoCache' => __DIR__ . '/..' . '/../lib/Command/ClearContactsPhotoCache.php', 'OCA\\DAV\\Command\\CreateAddressBook' => __DIR__ . '/..' . '/../lib/Command/CreateAddressBook.php', 'OCA\\DAV\\Command\\CreateCalendar' => __DIR__ . '/..' . '/../lib/Command/CreateCalendar.php', 'OCA\\DAV\\Command\\CreateSubscription' => __DIR__ . '/..' . '/../lib/Command/CreateSubscription.php', diff --git a/apps/dav/lib/AppInfo/Application.php b/apps/dav/lib/AppInfo/Application.php index edf7dd1214fab..9d5921a1e83a5 100644 --- a/apps/dav/lib/AppInfo/Application.php +++ b/apps/dav/lib/AppInfo/Application.php @@ -20,7 +20,6 @@ use OCA\DAV\CalDAV\Reminder\Notifier; use OCA\DAV\Capabilities; use OCA\DAV\CardDAV\ContactsManager; -use OCA\DAV\CardDAV\PhotoCache; use OCA\DAV\CardDAV\SyncService; use OCA\DAV\Events\AddressBookCreatedEvent; use OCA\DAV\Events\AddressBookDeletedEvent; @@ -82,7 +81,6 @@ use OCP\Contacts\IManager as IContactsManager; use OCP\DB\Events\AddMissingIndicesEvent; use OCP\Federation\Events\TrustedServerRemovedEvent; -use OCP\Files\AppData\IAppDataFactory; use OCP\IUserSession; use OCP\Server; use OCP\Settings\Events\DeclarativeSettingsGetValueEvent; @@ -112,12 +110,6 @@ public function __construct() { public function register(IRegistrationContext $context): void { $context->registerServiceAlias('CardDAVSyncService', SyncService::class); - $context->registerService(PhotoCache::class, function (ContainerInterface $c) { - return new PhotoCache( - $c->get(IAppDataFactory::class)->get('dav-photocache'), - $c->get(LoggerInterface::class) - ); - }); $context->registerService(AppCalendarPlugin::class, function (ContainerInterface $c) { return new AppCalendarPlugin( $c->get(ICalendarManager::class), diff --git a/apps/dav/lib/CardDAV/PhotoCache.php b/apps/dav/lib/CardDAV/PhotoCache.php index 2f1999b6b1cd9..29f1b0240efd9 100644 --- a/apps/dav/lib/CardDAV/PhotoCache.php +++ b/apps/dav/lib/CardDAV/PhotoCache.php @@ -3,8 +3,10 @@ * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later */ + namespace OCA\DAV\CardDAV; +use OCP\Files\AppData\IAppDataFactory; use OCP\Files\IAppData; use OCP\Files\NotFoundException; use OCP\Files\NotPermittedException; @@ -19,6 +21,7 @@ use Sabre\VObject\Reader; class PhotoCache { + private ?IAppData $photoCacheAppData = null; /** @var array */ public const ALLOWED_CONTENT_TYPES = [ @@ -30,12 +33,9 @@ class PhotoCache { 'image/avif' => 'avif', ]; - /** - * PhotoCache constructor. - */ public function __construct( - protected IAppData $appData, - protected LoggerInterface $logger, + private IAppDataFactory $appDataFactory, + private LoggerInterface $logger, ) { } @@ -142,13 +142,12 @@ private function getFile(ISimpleFolder $folder, $size): ISimpleFile { private function getFolder(int $addressBookId, string $cardUri, bool $createIfNotExists = true): ISimpleFolder { $hash = md5($addressBookId . ' ' . $cardUri); try { - return $this->appData->getFolder($hash); + return $this->getPhotoCacheAppData()->getFolder($hash); } catch (NotFoundException $e) { if ($createIfNotExists) { - return $this->appData->newFolder($hash); - } else { - throw $e; + return $this->getPhotoCacheAppData()->newFolder($hash); } + throw $e; } } @@ -265,4 +264,11 @@ public function delete($addressBookId, $cardUri) { // that's OK, nothing to do } } + + private function getPhotoCacheAppData(): IAppData { + if ($this->photoCacheAppData === null) { + $this->photoCacheAppData = $this->appDataFactory->get('dav-photocache'); + } + return $this->photoCacheAppData; + } } diff --git a/apps/dav/lib/Command/ClearContactsPhotoCache.php b/apps/dav/lib/Command/ClearContactsPhotoCache.php new file mode 100644 index 0000000000000..82e64c3145a63 --- /dev/null +++ b/apps/dav/lib/Command/ClearContactsPhotoCache.php @@ -0,0 +1,75 @@ +appDataFactory->get('dav-photocache'); + + $folders = $photoCacheAppData->getDirectoryListing(); + $countFolders = count($folders); + + if ($countFolders === 0) { + $output->writeln('No cached contact photos found.'); + return self::SUCCESS; + } + + $output->writeln('Found ' . count($folders) . ' cached contact photos.'); + + /** @var QuestionHelper $helper */ + $helper = $this->getHelper('question'); + $question = new ConfirmationQuestion('Please confirm to clear the contacts photo cache [y/n] ', true); + + if ($helper->ask($input, $output, $question) === false) { + $output->writeln('Clearing the contacts photo cache aborted.'); + return self::SUCCESS; + } + + $progressBar = new ProgressBar($output, $countFolders); + $progressBar->start(); + + foreach ($folders as $folder) { + try { + $folder->delete(); + } catch (NotPermittedException) { + } + $progressBar->advance(); + } + + $progressBar->finish(); + + $output->writeln(''); + $output->writeln('Contacts photo cache cleared.'); + + return self::SUCCESS; + } +} diff --git a/apps/dav/lib/Server.php b/apps/dav/lib/Server.php index f1595bab3916d..d1029afa2623c 100644 --- a/apps/dav/lib/Server.php +++ b/apps/dav/lib/Server.php @@ -72,7 +72,6 @@ use OCP\Defaults; use OCP\Diagnostics\IEventLogger; use OCP\EventDispatcher\IEventDispatcher; -use OCP\Files\AppData\IAppDataFactory; use OCP\Files\IFilenameValidator; use OCP\Files\IRootFolder; use OCP\FilesMetadata\IFilesMetadataManager; @@ -216,10 +215,7 @@ public function __construct( $this->server->addPlugin(new VCFExportPlugin()); $this->server->addPlugin(new MultiGetExportPlugin()); $this->server->addPlugin(new HasPhotoPlugin()); - $this->server->addPlugin(new ImageExportPlugin(new PhotoCache( - \OCP\Server::get(IAppDataFactory::class)->get('dav-photocache'), - $logger) - )); + $this->server->addPlugin(new ImageExportPlugin(\OCP\Server::get(PhotoCache::class))); $this->server->addPlugin(\OCP\Server::get(CardDavRateLimitingPlugin::class)); $this->server->addPlugin(\OCP\Server::get(CardDavValidatePlugin::class)); diff --git a/lib/private/Repair.php b/lib/private/Repair.php index c5069bff48e5c..7fbf776d9a140 100644 --- a/lib/private/Repair.php +++ b/lib/private/Repair.php @@ -61,6 +61,7 @@ use OCP\AppFramework\Utility\ITimeFactory; use OCP\Collaboration\Resources\IManager; use OCP\EventDispatcher\IEventDispatcher; +use OCP\Files\AppData\IAppDataFactory; use OCP\IAppConfig; use OCP\IConfig; use OCP\IDBConnection; @@ -173,7 +174,7 @@ public static function getRepairSteps(): array { \OCP\Server::get(ClearGeneratedAvatarCache::class), new AddPreviewBackgroundCleanupJob(\OC::$server->getJobList()), new AddCleanupUpdaterBackupsJob(\OC::$server->getJobList()), - new CleanupCardDAVPhotoCache(\OC::$server->getConfig(), \OC::$server->getAppDataDir('dav-photocache'), \OC::$server->get(LoggerInterface::class)), + new CleanupCardDAVPhotoCache(\OC::$server->getConfig(), \OCP\Server::get(IAppDataFactory::class), \OC::$server->get(LoggerInterface::class)), new AddClenupLoginFlowV2BackgroundJob(\OC::$server->getJobList()), new RemoveLinkShares(\OC::$server->getDatabaseConnection(), \OC::$server->getConfig(), \OC::$server->getGroupManager(), \OC::$server->get(INotificationManager::class), \OCP\Server::get(ITimeFactory::class)), new ClearCollectionsAccessCache(\OC::$server->getConfig(), \OCP\Server::get(IManager::class)), diff --git a/lib/private/Repair/NC16/CleanupCardDAVPhotoCache.php b/lib/private/Repair/NC16/CleanupCardDAVPhotoCache.php index a9cbbb4cbbf55..646dd2c5e83e7 100644 --- a/lib/private/Repair/NC16/CleanupCardDAVPhotoCache.php +++ b/lib/private/Repair/NC16/CleanupCardDAVPhotoCache.php @@ -6,9 +6,10 @@ * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later */ + namespace OC\Repair\NC16; -use OCP\Files\IAppData; +use OCP\Files\AppData\IAppDataFactory; use OCP\Files\NotFoundException; use OCP\Files\SimpleFS\ISimpleFolder; use OCP\IConfig; @@ -27,18 +28,11 @@ * photo could be returned for this vcard. These invalid files are removed by this migration step. */ class CleanupCardDAVPhotoCache implements IRepairStep { - /** @var IConfig */ - private $config; - - /** @var IAppData */ - private $appData; - - private LoggerInterface $logger; - - public function __construct(IConfig $config, IAppData $appData, LoggerInterface $logger) { - $this->config = $config; - $this->appData = $appData; - $this->logger = $logger; + public function __construct( + private IConfig $config, + private IAppDataFactory $appDataFactory, + private LoggerInterface $logger, + ) { } public function getName(): string { @@ -46,8 +40,10 @@ public function getName(): string { } private function repair(IOutput $output): void { + $photoCacheAppData = $this->appDataFactory->get('dav-photocache'); + try { - $folders = $this->appData->getDirectoryListing(); + $folders = $photoCacheAppData->getDirectoryListing(); } catch (NotFoundException $e) { return; } catch (RuntimeException $e) {