diff --git a/apps/files_trashbin/lib/AppInfo/Application.php b/apps/files_trashbin/lib/AppInfo/Application.php index 41466a865ac7f..b52e40bc13744 100644 --- a/apps/files_trashbin/lib/AppInfo/Application.php +++ b/apps/files_trashbin/lib/AppInfo/Application.php @@ -28,16 +28,23 @@ use OCA\DAV\Connector\Sabre\Principal; use OCA\Files_Trashbin\Capabilities; use OCA\Files_Trashbin\Expiration; +use OCA\Files_Trashbin\Listener\EventListener; +use OCA\Files_Trashbin\Storage; use OCA\Files_Trashbin\Trash\ITrashManager; use OCA\Files_Trashbin\Trash\TrashManager; +use OCA\Files_Trashbin\Trashbin; use OCA\Files_Trashbin\UserMigration\TrashbinMigrator; use OCP\AppFramework\App; use OCP\AppFramework\Bootstrap\IBootContext; use OCP\AppFramework\Bootstrap\IBootstrap; use OCP\AppFramework\Bootstrap\IRegistrationContext; use OCP\App\IAppManager; +use OCP\Files\Events\BeforeFileSystemSetupEvent; +use OCP\Files\Events\Node\BeforeNodeDeletedEvent; +use OCP\Files\Events\Node\NodeWrittenEvent; use OCP\ILogger; use OCP\IServerContainer; +use OCP\User\Events\BeforeUserDeletedEvent; class Application extends App implements IBootstrap { public const APP_ID = 'files_trashbin'; @@ -55,20 +62,18 @@ public function register(IRegistrationContext $context): void { $context->registerServiceAlias('principalBackend', Principal::class); $context->registerUserMigrator(TrashbinMigrator::class); + + $context->registerEventListener(NodeWrittenEvent::class, EventListener::class); + $context->registerEventListener(BeforeUserDeletedEvent::class, EventListener::class); + + // pre and post-rename, disable trash logic for the copy+unlink case + $context->registerEventListener(BeforeNodeDeletedEvent::class, Trashbin::class); + $context->registerEventListener(BeforeFileSystemSetupEvent::class, Storage::class); } public function boot(IBootContext $context): void { $context->injectFn([$this, 'registerTrashBackends']); - // create storage wrapper on setup - \OCP\Util::connectHook('OC_Filesystem', 'preSetup', 'OCA\Files_Trashbin\Storage', 'setupStorage'); - //Listen to delete user signal - \OCP\Util::connectHook('OC_User', 'pre_deleteUser', 'OCA\Files_Trashbin\Hooks', 'deleteUser_hook'); - //Listen to post write hook - \OCP\Util::connectHook('OC_Filesystem', 'post_write', 'OCA\Files_Trashbin\Hooks', 'post_write_hook'); - // pre and post-rename, disable trash logic for the copy+unlink case - \OCP\Util::connectHook('OC_Filesystem', 'delete', 'OCA\Files_Trashbin\Trashbin', 'ensureFileScannedHook'); - \OCA\Files\App::getNavigationManager()->add(function () { $l = \OC::$server->getL10N(self::APP_ID); return [ diff --git a/apps/files_trashbin/lib/Hooks.php b/apps/files_trashbin/lib/Hooks.php deleted file mode 100644 index 4f4cf8bb7055d..0000000000000 --- a/apps/files_trashbin/lib/Hooks.php +++ /dev/null @@ -1,48 +0,0 @@ - - * @author Christoph Wurst - * @author Morris Jobke - * @author Robin McCorkell - * @author Vincent Petry - * - * @license AGPL-3.0 - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * 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, version 3, - * along with this program. If not, see - * - */ -namespace OCA\Files_Trashbin; - -class Hooks { - - /** - * clean up user specific settings if user gets deleted - * @param array $params array with uid - * - * This function is connected to the pre_deleteUser signal of OC_Users - * to remove the used space for the trash bin stored in the database - */ - public static function deleteUser_hook($params) { - $uid = $params['uid']; - Trashbin::deleteUser($uid); - } - - public static function post_write_hook($params) { - $user = \OC_User::getUser(); - if (!empty($user)) { - Trashbin::resizeTrash($user); - } - } -} diff --git a/apps/files_trashbin/lib/Listener/EventListener.php b/apps/files_trashbin/lib/Listener/EventListener.php new file mode 100644 index 0000000000000..64f1f4dbadc39 --- /dev/null +++ b/apps/files_trashbin/lib/Listener/EventListener.php @@ -0,0 +1,59 @@ + + * + * @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 OCA\Files_Trashbin\Listener; + +use OCA\Files_Trashbin\Storage; +use OCA\Files_Trashbin\Trashbin; +use OCP\EventDispatcher\Event; +use OCP\EventDispatcher\IEventListener; +use OCP\Files\Events\BeforeFileSystemSetupEvent; +use OCP\Files\Events\Node\NodeWrittenEvent; +use OCP\User\Events\BeforeUserDeletedEvent; + +class EventListener implements IEventListener { + private ?string $userId; + + public function __construct(?string $userId = null) { + $this->userId = $userId; + } + + public function handle(Event $event): void { + if ($event instanceof NodeWrittenEvent) { + // Resize trash + if (!empty($this->userId)) { + Trashbin::resizeTrash($this->userId); + } + } + + // Clean up user specific settings if user gets deleted + if ($event instanceof BeforeUserDeletedEvent) { + Trashbin::deleteUser($event->getUser()->getUID()); + } + + if ($event instanceof BeforeFileSystemSetupEvent) { + Storage::setupStorage(); + } + } +} diff --git a/apps/files_trashbin/lib/Storage.php b/apps/files_trashbin/lib/Storage.php index f08d8d25a55a9..18c9448301ad2 100644 --- a/apps/files_trashbin/lib/Storage.php +++ b/apps/files_trashbin/lib/Storage.php @@ -37,48 +37,30 @@ use OCP\Files\Mount\IMountPoint; use OCP\Files\Node; use OCP\Files\Storage\IStorage; -use OCP\ILogger; use OCP\IUserManager; +use Psr\Log\LoggerInterface; use Symfony\Component\EventDispatcher\EventDispatcherInterface; class Storage extends Wrapper { - /** @var IMountPoint */ - private $mountPoint; - - /** @var IUserManager */ - private $userManager; - - /** @var ILogger */ - private $logger; - - /** @var EventDispatcherInterface */ - private $eventDispatcher; - - /** @var IRootFolder */ - private $rootFolder; - - /** @var ITrashManager */ - private $trashManager; - - private $trashEnabled = true; + private IMountPoint $mountPoint; + private ?IUserManager $userManager; + private ?LoggerInterface $logger; + private ?EventDispatcherInterface $eventDispatcher; + private ?IRootFolder $rootFolder; + private ?ITrashManager $trashManager; + private bool $trashEnabled = true; /** * Storage constructor. - * * @param array $parameters - * @param ITrashManager $trashManager - * @param IUserManager|null $userManager - * @param ILogger|null $logger - * @param EventDispatcherInterface|null $eventDispatcher - * @param IRootFolder|null $rootFolder */ public function __construct( $parameters, - ITrashManager $trashManager = null, - IUserManager $userManager = null, - ILogger $logger = null, - EventDispatcherInterface $eventDispatcher = null, - IRootFolder $rootFolder = null + ?ITrashManager $trashManager = null, + ?IUserManager $userManager = null, + ?LoggerInterface $logger = null, + ?EventDispatcherInterface $eventDispatcher = null, + ?IRootFolder $rootFolder = null ) { $this->mountPoint = $parameters['mountPoint']; $this->trashManager = $trashManager; diff --git a/apps/files_trashbin/lib/Trashbin.php b/apps/files_trashbin/lib/Trashbin.php index 4631f9e9d5bfe..ff89f724d52f8 100644 --- a/apps/files_trashbin/lib/Trashbin.php +++ b/apps/files_trashbin/lib/Trashbin.php @@ -44,6 +44,7 @@ */ namespace OCA\Files_Trashbin; +use OC\Files\Node\Node; use OC_User; use OC\Files\Cache\Cache; use OC\Files\Cache\CacheEntry; @@ -54,6 +55,9 @@ use OCA\Files_Trashbin\AppInfo\Application; use OCA\Files_Trashbin\Command\Expire; use OCP\AppFramework\Utility\ITimeFactory; +use OCP\EventDispatcher\Event; +use OCP\EventDispatcher\IEventListener; +use OCP\Files\Events\Node\BeforeNodeDeletedEvent; use OCP\Files\File; use OCP\Files\Folder; use OCP\Files\NotFoundException; @@ -62,7 +66,7 @@ use OCP\Lock\LockedException; use Psr\Log\LoggerInterface; -class Trashbin { +class Trashbin implements IEventListener { // unit: percentage; 50% of available disk space/quota public const DEFAULTMAXSIZE = 50; @@ -77,14 +81,12 @@ class Trashbin { /** * Ensure we don't need to scan the file during the move to trash * by triggering the scan in the pre-hook - * - * @param array $params */ - public static function ensureFileScannedHook($params) { + public static function ensureFileScannedHook(Node $node): void { try { - self::getUidAndFilename($params['path']); + self::getUidAndFilename($node->getPath()); } catch (NotFoundException $e) { - // nothing to scan for non existing files + // Nothing to scan for non existing files } } @@ -1142,4 +1144,11 @@ public static function isEmpty($user) { public static function preview_icon($path) { return \OC::$server->getURLGenerator()->linkToRoute('core_ajax_trashbin_preview', ['x' => 32, 'y' => 32, 'file' => $path]); } + + public function handle(Event $event): void { + if ($event instanceof BeforeNodeDeletedEvent) { + self::ensureFileScannedHook($event->getNode()); + + } + } } diff --git a/lib/private/Files/SetupManager.php b/lib/private/Files/SetupManager.php index e0575ea92a58e..c5523cd166a73 100644 --- a/lib/private/Files/SetupManager.php +++ b/lib/private/Files/SetupManager.php @@ -43,6 +43,7 @@ use OCP\Files\Config\IHomeMountProvider; use OCP\Files\Config\IMountProvider; use OCP\Files\Config\IUserMountCache; +use OCP\Files\Events\BeforeFileSystemSetupEvent; use OCP\Files\Events\InvalidateMountCacheEvent; use OCP\Files\Events\Node\FilesystemTornDownEvent; use OCP\Files\Mount\IMountManager; @@ -81,6 +82,7 @@ class SetupManager { private LoggerInterface $logger; private IConfig $config; private bool $listeningForProviders; + private IEventDispatcher $dispatcher; public function __construct( IEventLogger $eventLogger, @@ -93,7 +95,8 @@ public function __construct( IUserSession $userSession, ICacheFactory $cacheFactory, LoggerInterface $logger, - IConfig $config + IConfig $config, + IEventDispatcher $dispatcher ) { $this->eventLogger = $eventLogger; $this->mountProviderCollection = $mountProviderCollection; @@ -107,6 +110,7 @@ public function __construct( $this->cache = $cacheFactory->createDistributed('setupmanager::'); $this->listeningForProviders = false; $this->config = $config; + $this->dispatcher = $dispatcher; $this->setupListeners(); } @@ -222,8 +226,12 @@ private function oneTimeUserSetup(IUser $user) { $this->setupUsers[] = $user->getUID(); $prevLogging = Filesystem::logWarningWhenAddingStorageWrapper(false); + // TODO remove hook OC_Hook::emit('OC_Filesystem', 'preSetup', ['user' => $user->getUID()]); + $event = new BeforeFileSystemSetupEvent($user); + $this->dispatcher->dispatchTyped($event); + Filesystem::logWarningWhenAddingStorageWrapper($prevLogging); $userDir = '/' . $user->getUID() . '/files'; diff --git a/lib/public/Files/Events/BeforeFileSystemSetupEvent.php b/lib/public/Files/Events/BeforeFileSystemSetupEvent.php new file mode 100644 index 0000000000000..9669eaf4595e0 --- /dev/null +++ b/lib/public/Files/Events/BeforeFileSystemSetupEvent.php @@ -0,0 +1,41 @@ + + * + * @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\Files\Events; + +use OCP\EventDispatcher\Event; +use OCP\IUser; + +class BeforeFileSystemSetupEvent extends Event { + private IUser $user; + + public function __construct(IUser $user) { + parent::__construct(); + $this->user = $user; + } + + public function getUser(): IUser { + return $this->user; + } +}