From ac029d18395df32f95f03d895a0502f6af9e7f8d Mon Sep 17 00:00:00 2001 From: Carl Schwan Date: Wed, 6 Aug 2025 13:40:37 +0200 Subject: [PATCH] refactor(trash): Port deletion code of Trashbin to node based API Instead of using a mix of View and Node based file system manipulation, use the 'new' node based API everywhere. Replace the hooks used in the admin_audit related to the deletion to new typed event that expose the deleted nodes. And remove old calculateSize to get the size of the deleted folder and instead rely on the Node::getSize information. Signed-off-by: Carl Schwan Signed-off-by: Carl Schwan --- .../composer/composer/autoload_classmap.php | 2 +- .../composer/composer/autoload_static.php | 2 +- apps/admin_audit/lib/Actions/Trashbin.php | 22 --- apps/admin_audit/lib/AppInfo/Application.php | 14 +- .../lib/Listener/TrashbinEventListener.php | 34 ++++ .../composer/composer/autoload_classmap.php | 4 + .../composer/composer/autoload_static.php | 4 + .../lib/Events/BeforeDeleteAllEvent.php | 34 ++++ .../lib/Events/BeforeNodeDeletedEvent.php | 28 +++ .../lib/Events/DeleteAllEvent.php | 34 ++++ .../lib/Events/NodeDeletedEvent.php | 28 +++ apps/files_trashbin/lib/Sabre/TrashRoot.php | 4 +- apps/files_trashbin/lib/Trashbin.php | 185 ++++++++---------- build/psalm-baseline.xml | 10 - 14 files changed, 255 insertions(+), 150 deletions(-) delete mode 100644 apps/admin_audit/lib/Actions/Trashbin.php create mode 100644 apps/admin_audit/lib/Listener/TrashbinEventListener.php create mode 100644 apps/files_trashbin/lib/Events/BeforeDeleteAllEvent.php create mode 100644 apps/files_trashbin/lib/Events/BeforeNodeDeletedEvent.php create mode 100644 apps/files_trashbin/lib/Events/DeleteAllEvent.php create mode 100644 apps/files_trashbin/lib/Events/NodeDeletedEvent.php diff --git a/apps/admin_audit/composer/composer/autoload_classmap.php b/apps/admin_audit/composer/composer/autoload_classmap.php index b67d90e768921..b51ac378c7850 100644 --- a/apps/admin_audit/composer/composer/autoload_classmap.php +++ b/apps/admin_audit/composer/composer/autoload_classmap.php @@ -11,7 +11,6 @@ 'OCA\\AdminAudit\\Actions\\Files' => $baseDir . '/../lib/Actions/Files.php', 'OCA\\AdminAudit\\Actions\\Sharing' => $baseDir . '/../lib/Actions/Sharing.php', 'OCA\\AdminAudit\\Actions\\TagManagement' => $baseDir . '/../lib/Actions/TagManagement.php', - 'OCA\\AdminAudit\\Actions\\Trashbin' => $baseDir . '/../lib/Actions/Trashbin.php', 'OCA\\AdminAudit\\Actions\\Versions' => $baseDir . '/../lib/Actions/Versions.php', 'OCA\\AdminAudit\\AppInfo\\Application' => $baseDir . '/../lib/AppInfo/Application.php', 'OCA\\AdminAudit\\AuditLogger' => $baseDir . '/../lib/AuditLogger.php', @@ -25,5 +24,6 @@ 'OCA\\AdminAudit\\Listener\\GroupManagementEventListener' => $baseDir . '/../lib/Listener/GroupManagementEventListener.php', 'OCA\\AdminAudit\\Listener\\SecurityEventListener' => $baseDir . '/../lib/Listener/SecurityEventListener.php', 'OCA\\AdminAudit\\Listener\\SharingEventListener' => $baseDir . '/../lib/Listener/SharingEventListener.php', + 'OCA\\AdminAudit\\Listener\\TrashbinEventListener' => $baseDir . '/../lib/Listener/TrashbinEventListener.php', 'OCA\\AdminAudit\\Listener\\UserManagementEventListener' => $baseDir . '/../lib/Listener/UserManagementEventListener.php', ); diff --git a/apps/admin_audit/composer/composer/autoload_static.php b/apps/admin_audit/composer/composer/autoload_static.php index f8fd457edd8d5..d43dfb6b36bfe 100644 --- a/apps/admin_audit/composer/composer/autoload_static.php +++ b/apps/admin_audit/composer/composer/autoload_static.php @@ -26,7 +26,6 @@ class ComposerStaticInitAdminAudit 'OCA\\AdminAudit\\Actions\\Files' => __DIR__ . '/..' . '/../lib/Actions/Files.php', 'OCA\\AdminAudit\\Actions\\Sharing' => __DIR__ . '/..' . '/../lib/Actions/Sharing.php', 'OCA\\AdminAudit\\Actions\\TagManagement' => __DIR__ . '/..' . '/../lib/Actions/TagManagement.php', - 'OCA\\AdminAudit\\Actions\\Trashbin' => __DIR__ . '/..' . '/../lib/Actions/Trashbin.php', 'OCA\\AdminAudit\\Actions\\Versions' => __DIR__ . '/..' . '/../lib/Actions/Versions.php', 'OCA\\AdminAudit\\AppInfo\\Application' => __DIR__ . '/..' . '/../lib/AppInfo/Application.php', 'OCA\\AdminAudit\\AuditLogger' => __DIR__ . '/..' . '/../lib/AuditLogger.php', @@ -40,6 +39,7 @@ class ComposerStaticInitAdminAudit 'OCA\\AdminAudit\\Listener\\GroupManagementEventListener' => __DIR__ . '/..' . '/../lib/Listener/GroupManagementEventListener.php', 'OCA\\AdminAudit\\Listener\\SecurityEventListener' => __DIR__ . '/..' . '/../lib/Listener/SecurityEventListener.php', 'OCA\\AdminAudit\\Listener\\SharingEventListener' => __DIR__ . '/..' . '/../lib/Listener/SharingEventListener.php', + 'OCA\\AdminAudit\\Listener\\TrashbinEventListener' => __DIR__ . '/..' . '/../lib/Listener/TrashbinEventListener.php', 'OCA\\AdminAudit\\Listener\\UserManagementEventListener' => __DIR__ . '/..' . '/../lib/Listener/UserManagementEventListener.php', ); diff --git a/apps/admin_audit/lib/Actions/Trashbin.php b/apps/admin_audit/lib/Actions/Trashbin.php deleted file mode 100644 index c1e994da3a527..0000000000000 --- a/apps/admin_audit/lib/Actions/Trashbin.php +++ /dev/null @@ -1,22 +0,0 @@ -log('File "%s" deleted from trash bin.', - ['path' => $params['path']], ['path'] - ); - } - - public function restore(array $params): void { - $this->log('File "%s" restored from trash bin.', - ['path' => $params['filePath']], ['path'] - ); - } -} diff --git a/apps/admin_audit/lib/AppInfo/Application.php b/apps/admin_audit/lib/AppInfo/Application.php index 63a1d065bc8e1..0f22de87b14db 100644 --- a/apps/admin_audit/lib/AppInfo/Application.php +++ b/apps/admin_audit/lib/AppInfo/Application.php @@ -26,7 +26,10 @@ use OCA\AdminAudit\Listener\GroupManagementEventListener; use OCA\AdminAudit\Listener\SecurityEventListener; use OCA\AdminAudit\Listener\SharingEventListener; +use OCA\AdminAudit\Listener\TrashbinEventListener; use OCA\AdminAudit\Listener\UserManagementEventListener; +use OCA\Files_Trashbin\Events\BeforeNodeDeletedEvent as TrashbinBeforeNodeDeletedEvent; +use OCA\Files_Trashbin\Events\NodeRestoredEvent; use OCA\Files_Versions\Events\VersionRestoredEvent; use OCP\App\Events\AppDisableEvent; use OCP\App\Events\AppEnableEvent; @@ -123,6 +126,10 @@ public function register(IRegistrationContext $context): void { // Console events $context->registerEventListener(ConsoleEvent::class, ConsoleEventListener::class); + + // Trashbin events + $context->registerEventListener(TrashbinBeforeNodeDeletedEvent::class, TrashbinEventListener::class); + $context->registerEventListener(NodeRestoredEvent::class, TrashbinEventListener::class); } public function boot(IBootContext $context): void { @@ -144,7 +151,6 @@ private function registerLegacyHooks(IAuditLogger $logger, ContainerInterface $s $eventDispatcher = $serverContainer->get(IEventDispatcher::class); $this->sharingLegacyHooks($logger); $this->fileHooks($logger, $eventDispatcher); - $this->trashbinHooks($logger); $this->versionsHooks($logger); $this->tagHooks($logger, $eventDispatcher); } @@ -216,10 +222,4 @@ private function versionsHooks(IAuditLogger $logger): void { $versionsActions = new Versions($logger); Util::connectHook('\OCP\Versions', 'delete', $versionsActions, 'delete'); } - - private function trashbinHooks(IAuditLogger $logger): void { - $trashActions = new Trashbin($logger); - Util::connectHook('\OCP\Trashbin', 'preDelete', $trashActions, 'delete'); - Util::connectHook('\OCA\Files_Trashbin\Trashbin', 'post_restore', $trashActions, 'restore'); - } } diff --git a/apps/admin_audit/lib/Listener/TrashbinEventListener.php b/apps/admin_audit/lib/Listener/TrashbinEventListener.php new file mode 100644 index 0000000000000..131fea4953ccb --- /dev/null +++ b/apps/admin_audit/lib/Listener/TrashbinEventListener.php @@ -0,0 +1,34 @@ + + */ +class TrashbinEventListener extends Action implements IEventListener { + + public function handle(Event $event): void { + if ($event instanceof BeforeNodeDeletedEvent) { + $this->log('File "%s" deleted from trash bin.', + ['path' => $event->getSource()->getPath()], ['path'] + ); + } elseif ($event instanceof NodeRestoredEvent) { + $this->log('File "%s" restored from trash bin.', + ['path' => $event->getTarget()->getPath()], ['path'] + ); + } + } +} diff --git a/apps/files_trashbin/composer/composer/autoload_classmap.php b/apps/files_trashbin/composer/composer/autoload_classmap.php index 23e2e7baff64c..be2ec71eaf26b 100644 --- a/apps/files_trashbin/composer/composer/autoload_classmap.php +++ b/apps/files_trashbin/composer/composer/autoload_classmap.php @@ -16,8 +16,12 @@ 'OCA\\Files_Trashbin\\Command\\RestoreAllFiles' => $baseDir . '/../lib/Command/RestoreAllFiles.php', 'OCA\\Files_Trashbin\\Command\\Size' => $baseDir . '/../lib/Command/Size.php', 'OCA\\Files_Trashbin\\Controller\\PreviewController' => $baseDir . '/../lib/Controller/PreviewController.php', + 'OCA\\Files_Trashbin\\Events\\BeforeDeleteAllEvent' => $baseDir . '/../lib/Events/BeforeDeleteAllEvent.php', + 'OCA\\Files_Trashbin\\Events\\BeforeNodeDeletedEvent' => $baseDir . '/../lib/Events/BeforeNodeDeletedEvent.php', 'OCA\\Files_Trashbin\\Events\\BeforeNodeRestoredEvent' => $baseDir . '/../lib/Events/BeforeNodeRestoredEvent.php', + 'OCA\\Files_Trashbin\\Events\\DeleteAllEvent' => $baseDir . '/../lib/Events/DeleteAllEvent.php', 'OCA\\Files_Trashbin\\Events\\MoveToTrashEvent' => $baseDir . '/../lib/Events/MoveToTrashEvent.php', + 'OCA\\Files_Trashbin\\Events\\NodeDeletedEvent' => $baseDir . '/../lib/Events/NodeDeletedEvent.php', 'OCA\\Files_Trashbin\\Events\\NodeRestoredEvent' => $baseDir . '/../lib/Events/NodeRestoredEvent.php', 'OCA\\Files_Trashbin\\Exceptions\\CopyRecursiveException' => $baseDir . '/../lib/Exceptions/CopyRecursiveException.php', 'OCA\\Files_Trashbin\\Expiration' => $baseDir . '/../lib/Expiration.php', diff --git a/apps/files_trashbin/composer/composer/autoload_static.php b/apps/files_trashbin/composer/composer/autoload_static.php index fc60429926139..0606643c4fea9 100644 --- a/apps/files_trashbin/composer/composer/autoload_static.php +++ b/apps/files_trashbin/composer/composer/autoload_static.php @@ -31,8 +31,12 @@ class ComposerStaticInitFiles_Trashbin 'OCA\\Files_Trashbin\\Command\\RestoreAllFiles' => __DIR__ . '/..' . '/../lib/Command/RestoreAllFiles.php', 'OCA\\Files_Trashbin\\Command\\Size' => __DIR__ . '/..' . '/../lib/Command/Size.php', 'OCA\\Files_Trashbin\\Controller\\PreviewController' => __DIR__ . '/..' . '/../lib/Controller/PreviewController.php', + 'OCA\\Files_Trashbin\\Events\\BeforeDeleteAllEvent' => __DIR__ . '/..' . '/../lib/Events/BeforeDeleteAllEvent.php', + 'OCA\\Files_Trashbin\\Events\\BeforeNodeDeletedEvent' => __DIR__ . '/..' . '/../lib/Events/BeforeNodeDeletedEvent.php', 'OCA\\Files_Trashbin\\Events\\BeforeNodeRestoredEvent' => __DIR__ . '/..' . '/../lib/Events/BeforeNodeRestoredEvent.php', + 'OCA\\Files_Trashbin\\Events\\DeleteAllEvent' => __DIR__ . '/..' . '/../lib/Events/DeleteAllEvent.php', 'OCA\\Files_Trashbin\\Events\\MoveToTrashEvent' => __DIR__ . '/..' . '/../lib/Events/MoveToTrashEvent.php', + 'OCA\\Files_Trashbin\\Events\\NodeDeletedEvent' => __DIR__ . '/..' . '/../lib/Events/NodeDeletedEvent.php', 'OCA\\Files_Trashbin\\Events\\NodeRestoredEvent' => __DIR__ . '/..' . '/../lib/Events/NodeRestoredEvent.php', 'OCA\\Files_Trashbin\\Exceptions\\CopyRecursiveException' => __DIR__ . '/..' . '/../lib/Exceptions/CopyRecursiveException.php', 'OCA\\Files_Trashbin\\Expiration' => __DIR__ . '/..' . '/../lib/Expiration.php', diff --git a/apps/files_trashbin/lib/Events/BeforeDeleteAllEvent.php b/apps/files_trashbin/lib/Events/BeforeDeleteAllEvent.php new file mode 100644 index 0000000000000..da719adbeb2b8 --- /dev/null +++ b/apps/files_trashbin/lib/Events/BeforeDeleteAllEvent.php @@ -0,0 +1,34 @@ +deletedNodes; + } +} diff --git a/apps/files_trashbin/lib/Events/BeforeNodeDeletedEvent.php b/apps/files_trashbin/lib/Events/BeforeNodeDeletedEvent.php new file mode 100644 index 0000000000000..03f7fdcc7cd63 --- /dev/null +++ b/apps/files_trashbin/lib/Events/BeforeNodeDeletedEvent.php @@ -0,0 +1,28 @@ +source; + } +} diff --git a/apps/files_trashbin/lib/Events/DeleteAllEvent.php b/apps/files_trashbin/lib/Events/DeleteAllEvent.php new file mode 100644 index 0000000000000..ca1000d15d0a6 --- /dev/null +++ b/apps/files_trashbin/lib/Events/DeleteAllEvent.php @@ -0,0 +1,34 @@ +deletedNodes; + } +} diff --git a/apps/files_trashbin/lib/Events/NodeDeletedEvent.php b/apps/files_trashbin/lib/Events/NodeDeletedEvent.php new file mode 100644 index 0000000000000..8e47ab593c870 --- /dev/null +++ b/apps/files_trashbin/lib/Events/NodeDeletedEvent.php @@ -0,0 +1,28 @@ +source; + } +} diff --git a/apps/files_trashbin/lib/Sabre/TrashRoot.php b/apps/files_trashbin/lib/Sabre/TrashRoot.php index dd89583d9a1b3..a66e8747207f5 100644 --- a/apps/files_trashbin/lib/Sabre/TrashRoot.php +++ b/apps/files_trashbin/lib/Sabre/TrashRoot.php @@ -19,7 +19,6 @@ use Sabre\DAV\ICollection; class TrashRoot implements ICollection { - public function __construct( private IUser $user, private ITrashManager $trashManager, @@ -31,7 +30,7 @@ public function delete() { throw new Forbidden('Not allowed to delete items from the trash bin'); } - Trashbin::deleteAll(); + Trashbin::deleteAll($this->user); foreach ($this->trashManager->listTrashRoot($this->user) as $trashItem) { $this->trashManager->removeItem($trashItem); } @@ -67,6 +66,7 @@ public function getChildren(): array { } public function getChild($name): ITrash { + /** @var list $entries */ $entries = $this->getChildren(); foreach ($entries as $entry) { diff --git a/apps/files_trashbin/lib/Trashbin.php b/apps/files_trashbin/lib/Trashbin.php index dd71e8ec28e46..3b6f9f0a89727 100644 --- a/apps/files_trashbin/lib/Trashbin.php +++ b/apps/files_trashbin/lib/Trashbin.php @@ -18,7 +18,9 @@ use OC_User; use OCA\Files_Trashbin\AppInfo\Application; use OCA\Files_Trashbin\Command\Expire; +use OCA\Files_Trashbin\Events\BeforeDeleteAllEvent; use OCA\Files_Trashbin\Events\BeforeNodeRestoredEvent; +use OCA\Files_Trashbin\Events\DeleteAllEvent; use OCA\Files_Trashbin\Events\NodeRestoredEvent; use OCA\Files_Trashbin\Exceptions\CopyRecursiveException; use OCA\Files_Versions\Storage; @@ -42,6 +44,7 @@ use OCP\IConfig; use OCP\IDBConnection; use OCP\IURLGenerator; +use OCP\IUser; use OCP\IUserManager; use OCP\Lock\ILockingProvider; use OCP\Lock\LockedException; @@ -590,47 +593,50 @@ private static function restoreVersions(View $view, $file, $filename, $uniqueFil /** * delete all files from the trash */ - public static function deleteAll() { - $user = OC_User::getUser(); - $userRoot = \OC::$server->getUserFolder($user)->getParent(); - $view = new View('/' . $user); - $fileInfos = $view->getDirectoryContent('files_trashbin/files'); + public static function deleteAll(IUser $user) { + $rootFolder = Server::get(IRootFolder::class); + $dispatcher = Server::get(IEventDispatcher::class); + $dbConnection = Server::get(IDBConnection::class); + + $userRoot = $rootFolder->getUserFolder($user->getUID())->getParent(); try { - $trash = $userRoot->get('files_trashbin'); - } catch (NotFoundException $e) { + /** @var Folder $trashRoot */ + $trashRoot = $userRoot->get('files_trashbin'); + /** @var Folder $trashFilesRoot */ + $trashFilesRoot = $trashRoot->get('files'); + } catch (NotFoundException) { + return false; + } catch (NotPermittedException) { return false; } - // Array to store the relative path in (after the file is deleted, the view won't be able to relativise the path anymore) - $filePaths = []; - foreach ($fileInfos as $fileInfo) { - $filePaths[] = $view->getRelativePath($fileInfo->getPath()); - } - unset($fileInfos); // save memory - - // Bulk PreDelete-Hook - \OC_Hook::emit('\OCP\Trashbin', 'preDeleteAll', ['paths' => $filePaths]); + $trashNodes = $trashFilesRoot->getDirectoryListing(); + $beforeDeleteAllEvent = new BeforeDeleteAllEvent($trashNodes); + $dispatcher->dispatchTyped($beforeDeleteAllEvent); // Single-File Hooks - foreach ($filePaths as $path) { - self::emitTrashbinPreDelete($path); + foreach ($trashNodes as $trashNode) { + $event = new Events\BeforeNodeDeletedEvent($trashNode); + $dispatcher->dispatchTyped($event); } // actual file deletion - $trash->delete(); + $trashRoot->delete(); - $query = Server::get(IDBConnection::class)->getQueryBuilder(); + $query = $dbConnection->getQueryBuilder(); $query->delete('files_trash') - ->where($query->expr()->eq('user', $query->createNamedParameter($user))); + ->where($query->expr()->eq('user', $query->createNamedParameter($user->getUID()))); $query->executeStatement(); // Bulk PostDelete-Hook - \OC_Hook::emit('\OCP\Trashbin', 'deleteAll', ['paths' => $filePaths]); + $deleteAllEvent = new DeleteAllEvent($trashNodes); + $dispatcher->dispatchTyped($deleteAllEvent); // Single-File Hooks - foreach ($filePaths as $path) { - self::emitTrashbinPostDelete($path); + foreach ($trashNodes as $trashNode) { + $event = new Events\NodeDeletedEvent($trashNode); + $dispatcher->dispatchTyped($event); } $trash = $userRoot->newFolder('files_trashbin'); @@ -640,39 +646,31 @@ public static function deleteAll() { } /** - * wrapper function to emit the 'preDelete' hook of \OCP\Trashbin before a file is deleted - * - * @param string $path - */ - protected static function emitTrashbinPreDelete($path) { - \OC_Hook::emit('\OCP\Trashbin', 'preDelete', ['path' => $path]); - } - - /** - * wrapper function to emit the 'delete' hook of \OCP\Trashbin after a file has been deleted - * - * @param string $path - */ - protected static function emitTrashbinPostDelete($path) { - \OC_Hook::emit('\OCP\Trashbin', 'delete', ['path' => $path]); - } - - /** - * delete file from trash bin permanently + * Delete file from trash bin permanently * * @param string $filename path to the file - * @param string $user - * @param int $timestamp of deletion time - * + * @param ?int $timestamp of deletion time * @return int|float size of deleted files */ - public static function delete($filename, $user, $timestamp = null) { - $userRoot = \OC::$server->getUserFolder($user)->getParent(); - $view = new View('/' . $user); + public static function delete(string $filename, string $user, ?int $timestamp = null): int|float { + $rootFolder = Server::get(IRootFolder::class); + $appManager = Server::get(IAppManager::class); + $dispatcher = Server::get(IEventDispatcher::class); + $dbConnection = Server::get(IDBConnection::class); + + $userRoot = $rootFolder->getUserFolder($user)->getParent(); + + try { + /** @var Folder $trashRoot */ + $trashRoot = $userRoot->get('files_trashbin'); + } catch (NotFoundException|NotPermittedException) { + return 0; + } + $size = 0; if ($timestamp) { - $query = Server::get(IDBConnection::class)->getQueryBuilder(); + $query = $dbConnection->getQueryBuilder(); $query->delete('files_trash') ->where($query->expr()->eq('user', $query->createNamedParameter($user))) ->andWhere($query->expr()->eq('id', $query->createNamedParameter($filename))) @@ -684,48 +682,52 @@ public static function delete($filename, $user, $timestamp = null) { $file = $filename; } - $size += self::deleteVersions($view, $file, $filename, $timestamp, $user); + if ($appManager->isEnabledForUser('files_versions')) { + size += Trashbin::deleteVersions($trashRoot, $file, $filename, $timestamp, $user); + } try { $node = $userRoot->get('/files_trashbin/files/' . $file); - } catch (NotFoundException $e) { + } catch (NotFoundException) { return $size; } - if ($node instanceof Folder) { - $size += self::calculateSize(new View('/' . $user . '/files_trashbin/files/' . $file)); - } elseif ($node instanceof File) { - $size += $view->filesize('/files_trashbin/files/' . $file); - } + $size += $node->getSize(); + + $event = new Events\BeforeNodeDeletedEvent($node); + $dispatcher->dispatchTyped($event); - self::emitTrashbinPreDelete('/files_trashbin/files/' . $file); $node->delete(); - self::emitTrashbinPostDelete('/files_trashbin/files/' . $file); + + $event = new Events\NodeDeletedEvent($node); + $dispatcher->dispatchTyped($event); return $size; } /** - * @param string $file - * @param string $filename - * @param ?int $timestamp + * Delete version files corresponding to a given file from trash bin permanently. */ - private static function deleteVersions(View $view, $file, $filename, $timestamp, string $user): int|float { + private static function deleteVersions(Folder $trashRoot, string $file, string $filename, ?int $timestamp, string $user): int|float { $size = 0; - if (Server::get(IAppManager::class)->isEnabledForUser('files_versions')) { - if ($view->is_dir('files_trashbin/versions/' . $file)) { - $size += self::calculateSize(new View('/' . $user . '/files_trashbin/versions/' . $file)); - $view->unlink('files_trashbin/versions/' . $file); - } elseif ($versions = self::getVersionsFromTrash($filename, $timestamp, $user)) { - foreach ($versions as $v) { - if ($timestamp) { - $size += $view->filesize('/files_trashbin/versions/' . static::getTrashFilename($filename . '.v' . $v, $timestamp)); - $view->unlink('/files_trashbin/versions/' . static::getTrashFilename($filename . '.v' . $v, $timestamp)); - } else { - $size += $view->filesize('/files_trashbin/versions/' . $filename . '.v' . $v); - $view->unlink('/files_trashbin/versions/' . $filename . '.v' . $v); - } + try { + $fileVersion = $trashRoot->get('versions/' . $file); + } catch (NotFoundException) { + } + + if ($fileVersion) { + $size += $fileVersion->getSize(); + $fileVersion->delete(); + } elseif ($versions = self::getVersionsFromTrash($filename, $timestamp, $user)) { + foreach ($versions as $v) { + if ($timestamp) { + $node = $trashRoot->get('/files_trashbin/versions/' . static::getTrashFilename($filename . '.v' . $v, $timestamp)); + } else { + $node = $trashRoot->get('/files_trashbin/versions/' . $filename . '.v' . $v); } + + $size += $node->getSize(); + $node->delete(); } } return $size; @@ -1078,37 +1080,6 @@ private static function getUniqueFilename($location, $filename, View $view) { return $filename; } - /** - * get the size from a given root folder - * - * @param View $view file view on the root folder - * @return int|float size of the folder - */ - private static function calculateSize(View $view): int|float { - $root = Server::get(IConfig::class)->getSystemValue('datadirectory', \OC::$SERVERROOT . '/data') . $view->getAbsolutePath(''); - if (!file_exists($root)) { - return 0; - } - $iterator = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($root), \RecursiveIteratorIterator::CHILD_FIRST); - $size = 0; - - /** - * RecursiveDirectoryIterator on an NFS path isn't iterable with foreach - * This bug is fixed in PHP 5.5.9 or before - * See #8376 - */ - $iterator->rewind(); - while ($iterator->valid()) { - $path = $iterator->current(); - $relpath = substr($path, strlen($root) - 1); - if (!$view->is_dir($relpath)) { - $size += $view->filesize($relpath); - } - $iterator->next(); - } - return $size; - } - /** * get current size of trash bin from a given user * diff --git a/build/psalm-baseline.xml b/build/psalm-baseline.xml index 621e368f0a3f5..fb6e79024f693 100644 --- a/build/psalm-baseline.xml +++ b/build/psalm-baseline.xml @@ -11,8 +11,6 @@ - - @@ -1644,14 +1642,6 @@ - - - - - - - -