summaryrefslogtreecommitdiffstats
path: root/apps/files_trashbin/lib
diff options
context:
space:
mode:
authorLouis Chemineau <louis@chmn.me>2023-11-29 19:05:35 +0100
committerbackportbot-nextcloud[bot] <backportbot-nextcloud[bot]@users.noreply.github.com>2023-11-30 09:44:51 +0000
commit86d88f6b00920eb1d87c498597a8f2528eeab60b (patch)
treef994a6b37f4479840fd695e099e1d00c45d6de25 /apps/files_trashbin/lib
parenta1434af01e787ede6231b895d0d6056654b41342 (diff)
downloadnextcloud-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.php52
-rw-r--r--apps/files_trashbin/lib/Events/NodeRestoredEvent.php38
-rw-r--r--apps/files_trashbin/lib/Trashbin.php65
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);
+ }
+ }
}