diff options
author | Louis Chemineau <louis@chmn.me> | 2023-11-29 19:05:35 +0100 |
---|---|---|
committer | backportbot-nextcloud[bot] <backportbot-nextcloud[bot]@users.noreply.github.com> | 2023-11-30 09:44:51 +0000 |
commit | 86d88f6b00920eb1d87c498597a8f2528eeab60b (patch) | |
tree | f994a6b37f4479840fd695e099e1d00c45d6de25 /apps/files_trashbin/lib | |
parent | a1434af01e787ede6231b895d0d6056654b41342 (diff) | |
download | nextcloud-server-86d88f6b00920eb1d87c498597a8f2528eeab60b.tar.gz nextcloud-server-86d88f6b00920eb1d87c498597a8f2528eeab60b.zip |
Synchronize operation on live photo files
Signed-off-by: Louis Chemineau <louis@chmn.me>
Diffstat (limited to 'apps/files_trashbin/lib')
-rw-r--r-- | apps/files_trashbin/lib/Events/BeforeNodeRestoredEvent.php | 52 | ||||
-rw-r--r-- | apps/files_trashbin/lib/Events/NodeRestoredEvent.php | 38 | ||||
-rw-r--r-- | apps/files_trashbin/lib/Trashbin.php | 65 |
3 files changed, 151 insertions, 4 deletions
diff --git a/apps/files_trashbin/lib/Events/BeforeNodeRestoredEvent.php b/apps/files_trashbin/lib/Events/BeforeNodeRestoredEvent.php new file mode 100644 index 00000000000..9c1bf4e8910 --- /dev/null +++ b/apps/files_trashbin/lib/Events/BeforeNodeRestoredEvent.php @@ -0,0 +1,52 @@ +<?php + +declare(strict_types=1); + +/** + * @copyright Copyright (c) 2023 Louis Chemineau <louis@chmn.me> + * + * @author Louis Chemineau <louis@chmn.me> + * + * @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\Files_Trashbin\Events; + +use Exception; +use OCP\Files\Events\Node\AbstractNodesEvent; +use OCP\Files\Node; + +/** + * @since 28.0.0 + */ +class BeforeNodeRestoredEvent extends AbstractNodesEvent { + public function __construct(Node $source, Node $target, private bool &$run) { + parent::__construct($source, $target); + } + + /** + * @return never + */ + public function abortOperation(\Throwable $ex = null) { + $this->stopPropagation(); + $this->run = false; + if ($ex !== null) { + throw $ex; + } else { + throw new Exception('Operation aborted'); + } + } +} diff --git a/apps/files_trashbin/lib/Events/NodeRestoredEvent.php b/apps/files_trashbin/lib/Events/NodeRestoredEvent.php new file mode 100644 index 00000000000..2f73fff7c0e --- /dev/null +++ b/apps/files_trashbin/lib/Events/NodeRestoredEvent.php @@ -0,0 +1,38 @@ +<?php + +declare(strict_types=1); + +/** + * @copyright Copyright (c) 2023 Louis Chemineau <louis@chmn.me> + * + * @author Louis Chemineau <louis@chmn.me> + * + * @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\Files_Trashbin\Events; + +use OCP\Files\Events\Node\AbstractNodesEvent; +use OCP\Files\Node; + +/** + * @since 28.0.0 + */ +class NodeRestoredEvent extends AbstractNodesEvent { + public function __construct(Node $source, Node $target) { + parent::__construct($source, $target); + } +} diff --git a/apps/files_trashbin/lib/Trashbin.php b/apps/files_trashbin/lib/Trashbin.php index 051665acde1..442abc13670 100644 --- a/apps/files_trashbin/lib/Trashbin.php +++ b/apps/files_trashbin/lib/Trashbin.php @@ -44,19 +44,27 @@ */ namespace OCA\Files_Trashbin; +use Exception; use OC\Files\Cache\Cache; use OC\Files\Cache\CacheEntry; use OC\Files\Cache\CacheQueryBuilder; use OC\Files\Filesystem; +use OC\Files\Node\File; +use OC\Files\Node\Folder; +use OC\Files\Node\NonExistingFile; +use OC\Files\Node\NonExistingFolder; use OC\Files\ObjectStore\ObjectStoreStorage; use OC\Files\View; use OC_User; use OCA\Files_Trashbin\AppInfo\Application; use OCA\Files_Trashbin\Command\Expire; +use OCA\Files_Trashbin\Events\BeforeNodeRestoredEvent; +use OCA\Files_Trashbin\Events\NodeRestoredEvent; use OCP\App\IAppManager; use OCP\AppFramework\Utility\ITimeFactory; -use OCP\Files\File; -use OCP\Files\Folder; +use OCP\EventDispatcher\IEventDispatcher; +use OCP\Files\IRootFolder; +use OCP\Files\Node; use OCP\Files\NotFoundException; use OCP\Files\NotPermittedException; use OCP\FilesMetadata\IFilesMetadataManager; @@ -508,6 +516,21 @@ class Trashbin { if (!$view->isCreatable(dirname($target))) { throw new NotPermittedException("Can't restore trash item because the target folder is not writable"); } + + $sourcePath = Filesystem::normalizePath($file); + $targetPath = Filesystem::normalizePath('/' . $location . '/' . $uniqueFilename); + + $sourceNode = self::getNodeForPath($sourcePath); + $targetNode = self::getNodeForPath($targetPath); + $run = true; + $event = new BeforeNodeRestoredEvent($sourceNode, $targetNode, $run); + $dispatcher = \OC::$server->get(IEventDispatcher::class); + $dispatcher->dispatchTyped($event); + + if (!$run) { + return false; + } + $restoreResult = $view->rename($source, $target); // handle the restore result @@ -516,8 +539,13 @@ class Trashbin { $view->chroot('/' . $user . '/files'); $view->touch('/' . $location . '/' . $uniqueFilename, $mtime); $view->chroot($fakeRoot); - \OCP\Util::emitHook('\OCA\Files_Trashbin\Trashbin', 'post_restore', ['filePath' => Filesystem::normalizePath('/' . $location . '/' . $uniqueFilename), - 'trashPath' => Filesystem::normalizePath($file)]); + \OCP\Util::emitHook('\OCA\Files_Trashbin\Trashbin', 'post_restore', ['filePath' => $targetPath, 'trashPath' => $sourcePath]); + + $sourceNode = self::getNodeForPath($sourcePath); + $targetNode = self::getNodeForPath($targetPath); + $event = new NodeRestoredEvent($sourceNode, $targetNode); + $dispatcher = \OC::$server->get(IEventDispatcher::class); + $dispatcher->dispatchTyped($event); self::restoreVersions($view, $file, $filename, $uniqueFilename, $location, $timestamp); @@ -1151,4 +1179,33 @@ class Trashbin { } return $trashFilename; } + + private static function getNodeForPath(string $path): Node { + $user = OC_User::getUser(); + $rootFolder = \OC::$server->get(IRootFolder::class); + + if ($user !== false) { + $userFolder = $rootFolder->getUserFolder($user); + /** @var Folder */ + $trashFolder = $userFolder->getParent()->get('files_trashbin/files'); + try { + return $trashFolder->get($path); + } catch (NotFoundException $ex) { + } + } + + $view = \OC::$server->get(View::class); + $fsView = Filesystem::getView(); + if ($fsView === null) { + throw new Exception('View should not be null'); + } + + $fullPath = $fsView->getAbsolutePath($path); + + if (Filesystem::is_dir($path)) { + return new NonExistingFolder($rootFolder, $view, $fullPath); + } else { + return new NonExistingFile($rootFolder, $view, $fullPath); + } + } } |