From e9c105e11ed3012b49d8d8f8b2112b3bf55ae36a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20M=C3=BCller?= <1005065+DeepDiver1975@users.noreply.github.com> Date: Fri, 29 Oct 2021 12:07:13 +0200 Subject: [PATCH] feat: add before_moveToTrash hook + add fileId to delete hook --- apps/files_trashbin/lib/Trashbin.php | 83 ++++++++++++++++++---------- 1 file changed, 53 insertions(+), 30 deletions(-) diff --git a/apps/files_trashbin/lib/Trashbin.php b/apps/files_trashbin/lib/Trashbin.php index 2a0f1ebb4d1c..76fba0e8b29b 100644 --- a/apps/files_trashbin/lib/Trashbin.php +++ b/apps/files_trashbin/lib/Trashbin.php @@ -43,9 +43,11 @@ use OCP\Encryption\Keys\IStorage; use OCP\Files\ForbiddenException; use OCP\Files\NotFoundException; +use OCP\Files\Storage\IStorageWithTrash; use OCP\Files\StorageNotAvailableException; use OCP\Lock\LockedException; use OCP\User; +use OCP\Util; use Symfony\Component\EventDispatcher\GenericEvent; use OCP\Files\Folder; use OCP\Files\IRootFolder; @@ -266,7 +268,7 @@ public static function insertTrashEntry($user, $targetFilename, $targetLocation, $query = \OC_DB::prepare("INSERT INTO `*PREFIX*files_trash` (`id`,`timestamp`,`location`,`user`) VALUES (?,?,?,?)"); $result = $query->execute([$targetFilename, $timestamp, $targetLocation, $user]); if (!$result) { - \OCP\Util::writeLog('files_trashbin', 'trash bin database couldn\'t be updated for the files owner', \OCP\Util::ERROR); + Util::writeLog('files_trashbin', 'trash bin database couldn\'t be updated for the files owner', Util::ERROR); } } @@ -278,6 +280,7 @@ public static function insertTrashEntry($user, $targetFilename, $targetLocation, * isn't any trashbin available */ public static function move2trash($file_path) { + // get the user for which the filesystem is setup $root = Filesystem::getRoot(); list(, $user) = \explode('/', $root); @@ -315,11 +318,25 @@ public static function move2trash($file_path) { $timestamp = \time(); $trashPath = '/files_trashbin/files/' . $filename . '.d' . $timestamp; + $trashVersionsPath = '/files_trashbin/versions/' . $filename . '.d' . $timestamp; /** @var \OC\Files\Storage\Storage $trashStorage */ list($trashStorage, $trashInternalPath) = $ownerView->resolvePath($trashPath); + list($trashVersionStorage, $trashVersionInternalPath) = $ownerView->resolvePath($trashVersionsPath); /** @var \OC\Files\Storage\Storage $sourceStorage */ list($sourceStorage, $sourceInternalPath) = $ownerView->resolvePath('/files/' . $ownerPath); + + Util::emitHook('\OCA\Files_Trashbin\Trashbin', 'before_moveToTrash', [ + 'filePath' => Filesystem::normalizePath($file_path), + 'trashPath' => Filesystem::normalizePath($filename . '.d' . $timestamp), + 'sourceStorage' => $sourceStorage, + 'sourceInternalPath' => $sourceInternalPath, + 'trashStorage' => $trashStorage, + 'trashInternalPath' => $trashInternalPath, + 'trashVersionStorage' => $trashVersionStorage, + 'trashVersionInternalPath' => $trashVersionInternalPath, + ]); + try { $moveSuccessful = true; if ($trashStorage->file_exists($trashInternalPath)) { @@ -331,7 +348,7 @@ public static function move2trash($file_path) { if ($trashStorage->file_exists($trashInternalPath)) { $trashStorage->unlink($trashInternalPath); } - \OCP\Util::writeLog('files_trashbin', 'Couldn\'t move ' . $file_path . ' to the trash bin', \OCP\Util::ERROR); + Util::writeLog('files_trashbin', 'Couldn\'t move ' . $file_path . ' to the trash bin', Util::ERROR); } if ($sourceStorage->file_exists($sourceInternalPath)) { // failed to delete the original file, abort @@ -349,9 +366,9 @@ public static function move2trash($file_path) { $query = \OC_DB::prepare("INSERT INTO `*PREFIX*files_trash` (`id`,`timestamp`,`location`,`user`) VALUES (?,?,?,?)"); $result = $query->execute([$filename, $timestamp, $location, $owner]); if (!$result) { - \OCP\Util::writeLog('files_trashbin', 'trash bin database couldn\'t be updated', \OCP\Util::ERROR); + Util::writeLog('files_trashbin', 'trash bin database couldn\'t be updated', Util::ERROR); } - \OCP\Util::emitHook('\OCA\Files_Trashbin\Trashbin', 'post_moveToTrash', ['filePath' => Filesystem::normalizePath($file_path), + Util::emitHook('\OCA\Files_Trashbin\Trashbin', 'post_moveToTrash', ['filePath' => Filesystem::normalizePath($file_path), 'trashPath' => Filesystem::normalizePath($filename . '.d' . $timestamp)]); self::retainVersions($filename, $owner, $ownerPath, $timestamp, $sourceStorage); @@ -491,8 +508,8 @@ public static function restore($file, $filename, $timestamp, $targetLocation = n if ($timestamp) { $location = self::getLocation($user, $filename, $timestamp); if ($location === false) { - \OCP\Util::writeLog('files_trashbin', 'Original location of file ' . $filename . - ' not found in database, hence restoring into user\'s root instead', \OCP\Util::DEBUG); + Util::writeLog('files_trashbin', 'Original location of file ' . $filename . + ' not found in database, hence restoring into user\'s root instead', Util::DEBUG); } else { // if location no longer exists, restore file in the root directory if ($location !== '/' && @@ -525,8 +542,10 @@ public static function restore($file, $filename, $timestamp, $targetLocation = n $view->chroot('/' . $user . '/files'); $view->touch('/' . $targetLocation, $mtime); $view->chroot($fakeRoot); - \OCP\Util::emitHook('\OCA\Files_Trashbin\Trashbin', 'post_restore', ['filePath' => Filesystem::normalizePath('/' . $targetLocation), - 'trashPath' => Filesystem::normalizePath($file)]); + Util::emitHook('\OCA\Files_Trashbin\Trashbin', 'post_restore', [ + 'filePath' => Filesystem::normalizePath('/' . $targetLocation), + 'trashPath' => Filesystem::normalizePath($file) + ]); self::restoreVersions($view, $file, $filename, $targetLocation, $timestamp); @@ -597,7 +616,7 @@ public static function deleteAll() { // 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()); + $filePaths[$fileInfo->getId()] = $view->getRelativePath($fileInfo->getPath()); } unset($fileInfos); // save memory @@ -605,8 +624,8 @@ public static function deleteAll() { \OC_Hook::emit('\OCP\Trashbin', 'preDeleteAll', ['paths' => $filePaths]); // Single-File Hooks - foreach ($filePaths as $path) { - self::emitTrashbinPreDelete($user, $path); + foreach ($filePaths as $fileId => $path) { + self::emitTrashbinPreDelete($user, $path, $fileId); } // actual file deletion @@ -618,8 +637,8 @@ public static function deleteAll() { \OC_Hook::emit('\OCP\Trashbin', 'deleteAll', ['paths' => $filePaths]); // Single-File Hooks - foreach ($filePaths as $path) { - self::emitTrashbinPostDelete($user, $path); + foreach ($filePaths as $fileId => $path) { + self::emitTrashbinPostDelete($user, $path, $fileId); } $view->mkdir('files_trashbin'); @@ -634,12 +653,14 @@ public static function deleteAll() { * @param string $uid * @param string $path */ - protected static function emitTrashbinPreDelete($uid, $path) { + protected static function emitTrashbinPreDelete($uid, $path, $fileId) { \OC_Hook::emit( '\OCP\Trashbin', - 'preDelete', - ['path' => $path, 'user' => $uid] - ); + 'preDelete', [ + 'path' => $path, + 'user' => $uid, + 'fileId' => $fileId + ]); } /** @@ -648,12 +669,13 @@ protected static function emitTrashbinPreDelete($uid, $path) { * @param string $uid * @param string $path */ - protected static function emitTrashbinPostDelete($uid, $path) { + protected static function emitTrashbinPostDelete($uid, $path, $fileId) { \OC_Hook::emit( '\OCP\Trashbin', - 'delete', - ['path' => $path, 'user' => $uid] - ); + 'delete', [ + 'path' => $path, + 'user' => $uid, + 'fileId' => $fileId]); } /** @@ -688,9 +710,10 @@ public static function delete($filename, $user, $timestamp = null) { } else { $size += $view->filesize('/files_trashbin/files/' . $file); } - self::emitTrashbinPreDelete($user, "/files_trashbin/files/$file"); + $fileId = $view->getFileInfo('/files_trashbin/files/' . $file); + self::emitTrashbinPreDelete($user, "/files_trashbin/files/$file", $fileId); $view->unlink('/files_trashbin/files/' . $file); - self::emitTrashbinPostDelete($user, "/files_trashbin/files/$file"); + self::emitTrashbinPostDelete($user, "/files_trashbin/files/$file", $fileId); return $size; } @@ -960,15 +983,15 @@ function (GenericEvent $event) { */ public static function registerHooks() { // create storage wrapper on setup - \OCP\Util::connectHook('OC_Filesystem', 'preSetup', 'OCA\Files_Trashbin\Storage', 'setupStorage'); + 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'); + 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'); + 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'); - \OCP\Util::connectHook('OC_Filesystem', 'rename', 'OCA\Files_Trashbin\Storage', 'preRenameHook'); - \OCP\Util::connectHook('OC_Filesystem', 'post_rename', 'OCA\Files_Trashbin\Storage', 'postRenameHook'); + Util::connectHook('OC_Filesystem', 'delete', 'OCA\Files_Trashbin\Trashbin', 'ensureFileScannedHook'); + Util::connectHook('OC_Filesystem', 'rename', 'OCA\Files_Trashbin\Storage', 'preRenameHook'); + Util::connectHook('OC_Filesystem', 'post_rename', 'OCA\Files_Trashbin\Storage', 'postRenameHook'); } /** @@ -1025,6 +1048,6 @@ public static function isEmpty($user) { * @return string */ public static function preview_icon($path) { - return \OCP\Util::linkToRoute('core_ajax_trashbin_preview', ['x' => 32, 'y' => 32, 'file' => $path]); + return Util::linkToRoute('core_ajax_trashbin_preview', ['x' => 32, 'y' => 32, 'file' => $path]); } }