diff --git a/apps/files_trashbin/appinfo/info.xml b/apps/files_trashbin/appinfo/info.xml
index eb8f46dced..023cad1264 100644
--- a/apps/files_trashbin/appinfo/info.xml
+++ b/apps/files_trashbin/appinfo/info.xml
@@ -44,4 +44,8 @@ To prevent a user from running out of disk space, the Deleted files app will not
OCA\Files_Trashbin\Sabre\PropfindPlugin
+
+
+ OCA\Files_Trashbin\Trash\LegacyTrashBackend
+
diff --git a/apps/files_trashbin/composer/composer/autoload_classmap.php b/apps/files_trashbin/composer/composer/autoload_classmap.php
index 164d64333c..011e178a5b 100644
--- a/apps/files_trashbin/composer/composer/autoload_classmap.php
+++ b/apps/files_trashbin/composer/composer/autoload_classmap.php
@@ -19,6 +19,8 @@ return array(
'OCA\\Files_Trashbin\\Helper' => $baseDir . '/../lib/Helper.php',
'OCA\\Files_Trashbin\\Hooks' => $baseDir . '/../lib/Hooks.php',
'OCA\\Files_Trashbin\\Sabre\\AbstractTrash' => $baseDir . '/../lib/Sabre/AbstractTrash.php',
+ 'OCA\\Files_Trashbin\\Sabre\\AbstractTrashFile' => $baseDir . '/../lib/Sabre/AbstractTrashFile.php',
+ 'OCA\\Files_Trashbin\\Sabre\\AbstractTrashFolder' => $baseDir . '/../lib/Sabre/AbstractTrashFolder.php',
'OCA\\Files_Trashbin\\Sabre\\ITrash' => $baseDir . '/../lib/Sabre/ITrash.php',
'OCA\\Files_Trashbin\\Sabre\\PropfindPlugin' => $baseDir . '/../lib/Sabre/PropfindPlugin.php',
'OCA\\Files_Trashbin\\Sabre\\RestoreFolder' => $baseDir . '/../lib/Sabre/RestoreFolder.php',
@@ -30,5 +32,12 @@ return array(
'OCA\\Files_Trashbin\\Sabre\\TrashHome' => $baseDir . '/../lib/Sabre/TrashHome.php',
'OCA\\Files_Trashbin\\Sabre\\TrashRoot' => $baseDir . '/../lib/Sabre/TrashRoot.php',
'OCA\\Files_Trashbin\\Storage' => $baseDir . '/../lib/Storage.php',
+ 'OCA\\Files_Trashbin\\Trash\\BackendNotFoundException' => $baseDir . '/../lib/Trash/BackendNotFoundException.php',
+ 'OCA\\Files_Trashbin\\Trash\\ITrashBackend' => $baseDir . '/../lib/Trash/ITrashBackend.php',
+ 'OCA\\Files_Trashbin\\Trash\\ITrashItem' => $baseDir . '/../lib/Trash/ITrashItem.php',
+ 'OCA\\Files_Trashbin\\Trash\\ITrashManager' => $baseDir . '/../lib/Trash/ITrashManager.php',
+ 'OCA\\Files_Trashbin\\Trash\\LegacyTrashBackend' => $baseDir . '/../lib/Trash/LegacyTrashBackend.php',
+ 'OCA\\Files_Trashbin\\Trash\\TrashItem' => $baseDir . '/../lib/Trash/TrashItem.php',
+ 'OCA\\Files_Trashbin\\Trash\\TrashManager' => $baseDir . '/../lib/Trash/TrashManager.php',
'OCA\\Files_Trashbin\\Trashbin' => $baseDir . '/../lib/Trashbin.php',
);
diff --git a/apps/files_trashbin/composer/composer/autoload_static.php b/apps/files_trashbin/composer/composer/autoload_static.php
index 6ebb8c35f3..37144ec428 100644
--- a/apps/files_trashbin/composer/composer/autoload_static.php
+++ b/apps/files_trashbin/composer/composer/autoload_static.php
@@ -34,6 +34,8 @@ class ComposerStaticInitFiles_Trashbin
'OCA\\Files_Trashbin\\Helper' => __DIR__ . '/..' . '/../lib/Helper.php',
'OCA\\Files_Trashbin\\Hooks' => __DIR__ . '/..' . '/../lib/Hooks.php',
'OCA\\Files_Trashbin\\Sabre\\AbstractTrash' => __DIR__ . '/..' . '/../lib/Sabre/AbstractTrash.php',
+ 'OCA\\Files_Trashbin\\Sabre\\AbstractTrashFile' => __DIR__ . '/..' . '/../lib/Sabre/AbstractTrashFile.php',
+ 'OCA\\Files_Trashbin\\Sabre\\AbstractTrashFolder' => __DIR__ . '/..' . '/../lib/Sabre/AbstractTrashFolder.php',
'OCA\\Files_Trashbin\\Sabre\\ITrash' => __DIR__ . '/..' . '/../lib/Sabre/ITrash.php',
'OCA\\Files_Trashbin\\Sabre\\PropfindPlugin' => __DIR__ . '/..' . '/../lib/Sabre/PropfindPlugin.php',
'OCA\\Files_Trashbin\\Sabre\\RestoreFolder' => __DIR__ . '/..' . '/../lib/Sabre/RestoreFolder.php',
@@ -45,6 +47,13 @@ class ComposerStaticInitFiles_Trashbin
'OCA\\Files_Trashbin\\Sabre\\TrashHome' => __DIR__ . '/..' . '/../lib/Sabre/TrashHome.php',
'OCA\\Files_Trashbin\\Sabre\\TrashRoot' => __DIR__ . '/..' . '/../lib/Sabre/TrashRoot.php',
'OCA\\Files_Trashbin\\Storage' => __DIR__ . '/..' . '/../lib/Storage.php',
+ 'OCA\\Files_Trashbin\\Trash\\BackendNotFoundException' => __DIR__ . '/..' . '/../lib/Trash/BackendNotFoundException.php',
+ 'OCA\\Files_Trashbin\\Trash\\ITrashBackend' => __DIR__ . '/..' . '/../lib/Trash/ITrashBackend.php',
+ 'OCA\\Files_Trashbin\\Trash\\ITrashItem' => __DIR__ . '/..' . '/../lib/Trash/ITrashItem.php',
+ 'OCA\\Files_Trashbin\\Trash\\ITrashManager' => __DIR__ . '/..' . '/../lib/Trash/ITrashManager.php',
+ 'OCA\\Files_Trashbin\\Trash\\LegacyTrashBackend' => __DIR__ . '/..' . '/../lib/Trash/LegacyTrashBackend.php',
+ 'OCA\\Files_Trashbin\\Trash\\TrashItem' => __DIR__ . '/..' . '/../lib/Trash/TrashItem.php',
+ 'OCA\\Files_Trashbin\\Trash\\TrashManager' => __DIR__ . '/..' . '/../lib/Trash/TrashManager.php',
'OCA\\Files_Trashbin\\Trashbin' => __DIR__ . '/..' . '/../lib/Trashbin.php',
);
diff --git a/apps/files_trashbin/lib/AppInfo/Application.php b/apps/files_trashbin/lib/AppInfo/Application.php
index 8e4ec25556..06a34e0df8 100644
--- a/apps/files_trashbin/lib/AppInfo/Application.php
+++ b/apps/files_trashbin/lib/AppInfo/Application.php
@@ -24,8 +24,11 @@
namespace OCA\Files_Trashbin\AppInfo;
use OCA\DAV\Connector\Sabre\Principal;
+use OCA\Files_Trashbin\Trash\ITrashManager;
+use OCA\Files_Trashbin\Trash\TrashManager;
use OCP\AppFramework\App;
use OCA\Files_Trashbin\Expiration;
+use OCP\AppFramework\IAppContainer;
use OCP\AppFramework\Utility\ITimeFactory;
use OCA\Files_Trashbin\Capabilities;
@@ -61,5 +64,36 @@ class Application extends App {
\OC::$server->getConfig()
);
});
+
+ $container->registerService(ITrashManager::class, function(IAppContainer $c) {
+ return new TrashManager();
+ });
+
+ $this->registerTrashBackends();
+ }
+
+ public function registerTrashBackends() {
+ $server = $this->getContainer()->getServer();
+ $logger = $server->getLogger();
+ $appManager = $server->getAppManager();
+ /** @var ITrashManager $trashManager */
+ $trashManager = $this->getContainer()->getServer()->query(ITrashManager::class);
+ foreach($appManager->getInstalledApps() as $app) {
+ $appInfo = $appManager->getAppInfo($app);
+ if (isset($appInfo['trash'])) {
+ $backends = $appInfo['trash'];
+ foreach($backends as $backend) {
+ $class = $backend['@value'];
+ $for = $backend['@attributes']['for'];
+
+ try {
+ $backendObject = $server->query($class);
+ $trashManager->registerBackend($for, $backendObject);
+ } catch (\Exception $e) {
+ $logger->logException($e);
+ }
+ }
+ }
+ }
}
}
diff --git a/apps/files_trashbin/lib/Controller/PreviewController.php b/apps/files_trashbin/lib/Controller/PreviewController.php
index 8a1b31703b..f79e19a463 100644
--- a/apps/files_trashbin/lib/Controller/PreviewController.php
+++ b/apps/files_trashbin/lib/Controller/PreviewController.php
@@ -22,27 +22,31 @@ declare(strict_types=1);
* along with this program. If not, see .
*
*/
+
namespace OCA\Files_Trashbin\Controller;
+use OCA\Files_Trashbin\Trash\ITrashManager;
use OCP\AppFramework\Controller;
use OCP\AppFramework\Http;
use OCP\AppFramework\Http\DataResponse;
use OCP\AppFramework\Utility\ITimeFactory;
-use OCP\Files\File;
use OCP\Files\Folder;
use OCP\Files\IMimeTypeDetector;
use OCP\Files\IRootFolder;
use OCP\Files\NotFoundException;
use OCP\IPreview;
use OCP\IRequest;
+use OCP\IUserSession;
class PreviewController extends Controller {
-
/** @var IRootFolder */
private $rootFolder;
- /** @var string */
- private $userId;
+ /** @var ITrashManager */
+ private $trashManager;
+
+ /** @var IUserSession */
+ private $userSession;
/** @var IMimeTypeDetector */
private $mimeTypeDetector;
@@ -53,17 +57,21 @@ class PreviewController extends Controller {
/** @var ITimeFactory */
private $time;
- public function __construct(string $appName,
- IRequest $request,
- IRootFolder $rootFolder,
- string $userId,
- IMimeTypeDetector $mimeTypeDetector,
- IPreview $previewManager,
- ITimeFactory $time) {
+ public function __construct(
+ string $appName,
+ IRequest $request,
+ IRootFolder $rootFolder,
+ ITrashManager $trashManager,
+ IUserSession $userSession,
+ IMimeTypeDetector $mimeTypeDetector,
+ IPreview $previewManager,
+ ITimeFactory $time
+ ) {
parent::__construct($appName, $request);
+ $this->trashManager = $trashManager;
$this->rootFolder = $rootFolder;
- $this->userId = $userId;
+ $this->userSession = $userSession;
$this->mimeTypeDetector = $mimeTypeDetector;
$this->previewManager = $previewManager;
$this->time = $time;
@@ -86,39 +94,28 @@ class PreviewController extends Controller {
}
try {
- $userFolder = $this->rootFolder->getUserFolder($this->userId);
- /** @var Folder $trash */
- $trash = $userFolder->getParent()->get('files_trashbin/files');
- $trashFiles = $trash->getById($fileId);
-
- if (empty($trashFiles)) {
- throw new NotFoundException();
+ $file = $this->trashManager->getTrashNodeById($this->userSession->getUser(), $fileId);
+ if ($file === null) {
+ return new DataResponse([], Http::STATUS_NOT_FOUND);
}
-
- $trashFile = array_pop($trashFiles);
-
- if ($trashFile instanceof Folder) {
+ if ($file instanceof Folder) {
return new DataResponse([], Http::STATUS_BAD_REQUEST);
}
+ $pathParts = pathinfo($file->getName());
+ $extension = $pathParts['extension'];
+ $fileName = $pathParts['filename'];
/*
* Files in the root of the trashbin are timetamped.
* So we have to strip that in order to properly detect the mimetype of the file.
*/
- if ($trashFile->getParent()->getPath() === $trash->getPath()) {
- /** @var File $trashFile */
- $fileName = $trashFile->getName();
- $i = strrpos($fileName, '.');
- if ($i !== false) {
- $fileName = substr($fileName, 0, $i);
- }
-
+ if (preg_match('/d\d+/', $extension)) {
$mimeType = $this->mimeTypeDetector->detectPath($fileName);
} else {
- $mimeType = $this->mimeTypeDetector->detectPath($trashFile->getName());
+ $mimeType = $this->mimeTypeDetector->detectPath($file->getName());
}
- $f = $this->previewManager->getPreview($trashFile, $x, $y, true, IPreview::MODE_FILL, $mimeType);
+ $f = $this->previewManager->getPreview($file, $x, $y, true, IPreview::MODE_FILL, $mimeType);
$response = new Http\FileDisplayResponse($f, Http::STATUS_OK, ['Content-Type' => $f->getMimeType()]);
// Cache previews for 24H
diff --git a/apps/files_trashbin/lib/Sabre/AbstractTrash.php b/apps/files_trashbin/lib/Sabre/AbstractTrash.php
index 43f9cc0274..b4d13a41e3 100644
--- a/apps/files_trashbin/lib/Sabre/AbstractTrash.php
+++ b/apps/files_trashbin/lib/Sabre/AbstractTrash.php
@@ -1,4 +1,5 @@
*
@@ -21,13 +22,20 @@
namespace OCA\Files_Trashbin\Sabre;
+use OCA\Files_Trashbin\Trash\ITrashItem;
+use OCA\Files_Trashbin\Trash\ITrashManager;
use OCP\Files\FileInfo;
+use OCP\IUser;
abstract class AbstractTrash implements ITrash {
- /** @var FileInfo */
+ /** @var ITrashItem */
protected $data;
- public function __construct(FileInfo $data) {
+ /** @var ITrashManager */
+ protected $trashManager;
+
+ public function __construct(ITrashManager $trashManager, ITrashItem $data) {
+ $this->trashManager = $trashManager;
$this->data = $data;
}
@@ -36,7 +44,7 @@ abstract class AbstractTrash implements ITrash {
}
public function getDeletionTime(): int {
- return $this->data->getMtime();
+ return $this->data->getDeletedTime();
}
public function getFileId(): int {
@@ -66,4 +74,17 @@ abstract class AbstractTrash implements ITrash {
public function getName(): string {
return $this->data->getName();
}
+
+ public function getOriginalLocation(): string {
+ return $this->data->getOriginalLocation();
+ }
+
+ public function delete() {
+ $this->trashManager->removeItem($this->data);
+ }
+
+ public function restore(): bool {
+ $this->trashManager->restoreItem($this->data);
+ return true;
+ }
}
diff --git a/apps/files_trashbin/lib/Sabre/AbstractTrashFile.php b/apps/files_trashbin/lib/Sabre/AbstractTrashFile.php
new file mode 100644
index 0000000000..da7c94eb35
--- /dev/null
+++ b/apps/files_trashbin/lib/Sabre/AbstractTrashFile.php
@@ -0,0 +1,36 @@
+
+ *
+ * @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\Sabre;
+
+use Sabre\DAV\Exception\Forbidden;
+use Sabre\DAV\IFile;
+
+abstract class AbstractTrashFile extends AbstractTrash implements IFile , ITrash{
+ public function put($data) {
+ throw new Forbidden();
+ }
+
+ public function setName($name) {
+ throw new Forbidden();
+ }
+}
diff --git a/apps/files_trashbin/lib/Sabre/AbstractTrashFolder.php b/apps/files_trashbin/lib/Sabre/AbstractTrashFolder.php
new file mode 100644
index 0000000000..dd45dbd5c8
--- /dev/null
+++ b/apps/files_trashbin/lib/Sabre/AbstractTrashFolder.php
@@ -0,0 +1,77 @@
+
+ *
+ * @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\Sabre;
+
+use OCA\Files_Trashbin\Trash\ITrashItem;
+use OCP\Files\FileInfo;
+use Sabre\DAV\Exception\Forbidden;
+use Sabre\DAV\Exception\NotFound;
+use Sabre\DAV\ICollection;
+
+abstract class AbstractTrashFolder extends AbstractTrash implements ICollection, ITrash {
+ public function getChildren(): array {
+ $entries = $this->trashManager->listTrashFolder($this->data);
+
+ $children = array_map(function (ITrashItem $entry) {
+ if ($entry->getType() === FileInfo::TYPE_FOLDER) {
+ return new TrashFolderFolder($this->trashManager, $entry);
+ }
+ return new TrashFolderFile($this->trashManager, $entry);
+ }, $entries);
+
+ return $children;
+ }
+
+ public function getChild($name): ITrash {
+ $entries = $this->getChildren();
+
+ foreach ($entries as $entry) {
+ if ($entry->getName() === $name) {
+ return $entry;
+ }
+ }
+
+ throw new NotFound();
+ }
+
+ public function childExists($name): bool {
+ try {
+ $this->getChild($name);
+ return true;
+ } catch (NotFound $e) {
+ return false;
+ }
+ }
+
+ public function setName($name) {
+ throw new Forbidden();
+ }
+
+ public function createFile($name, $data = null) {
+ throw new Forbidden();
+ }
+
+ public function createDirectory($name) {
+ throw new Forbidden();
+ }
+}
diff --git a/apps/files_trashbin/lib/Sabre/RestoreFolder.php b/apps/files_trashbin/lib/Sabre/RestoreFolder.php
index 04f23db0ed..177064dbb4 100644
--- a/apps/files_trashbin/lib/Sabre/RestoreFolder.php
+++ b/apps/files_trashbin/lib/Sabre/RestoreFolder.php
@@ -31,14 +31,6 @@ use Sabre\DAV\INode;
class RestoreFolder implements ICollection, IMoveTarget {
-
- /** @var string */
- protected $userId;
-
- public function __construct(string $userId) {
- $this->userId = $userId;
- }
-
public function createFile($name, $data = null) {
throw new Forbidden();
}
diff --git a/apps/files_trashbin/lib/Sabre/RootCollection.php b/apps/files_trashbin/lib/Sabre/RootCollection.php
index be31d200f7..0b55953aa3 100644
--- a/apps/files_trashbin/lib/Sabre/RootCollection.php
+++ b/apps/files_trashbin/lib/Sabre/RootCollection.php
@@ -21,18 +21,27 @@ declare(strict_types=1);
* along with this program. If not, see .
*
*/
+
namespace OCA\Files_Trashbin\Sabre;
+use OCA\Files_Trashbin\Trash\ITrashManager;
use OCP\IConfig;
use Sabre\DAV\INode;
use Sabre\DAVACL\AbstractPrincipalCollection;
use Sabre\DAVACL\PrincipalBackend;
class RootCollection extends AbstractPrincipalCollection {
+ /** @var ITrashManager */
+ private $trashManager;
- public function __construct(PrincipalBackend\BackendInterface $principalBackend, IConfig $config) {
+ public function __construct(
+ ITrashManager $trashManager,
+ PrincipalBackend\BackendInterface $principalBackend,
+ IConfig $config
+ ) {
parent::__construct($principalBackend, 'principals/users');
+ $this->trashManager = $trashManager;
$this->disableListing = !$config->getSystemValue('debug', false);
}
@@ -47,12 +56,12 @@ class RootCollection extends AbstractPrincipalCollection {
* @return INode
*/
public function getChildForPrincipal(array $principalInfo): TrashHome {
- list(,$name) = \Sabre\Uri\split($principalInfo['uri']);
+ list(, $name) = \Sabre\Uri\split($principalInfo['uri']);
$user = \OC::$server->getUserSession()->getUser();
if (is_null($user) || $name !== $user->getUID()) {
throw new \Sabre\DAV\Exception\Forbidden();
}
- return new TrashHome($principalInfo);
+ return new TrashHome($principalInfo, $this->trashManager, $user);
}
public function getName(): string {
diff --git a/apps/files_trashbin/lib/Sabre/TrashFile.php b/apps/files_trashbin/lib/Sabre/TrashFile.php
index 840ca6a193..dd6500e5b8 100644
--- a/apps/files_trashbin/lib/Sabre/TrashFile.php
+++ b/apps/files_trashbin/lib/Sabre/TrashFile.php
@@ -21,46 +21,15 @@ declare(strict_types=1);
* along with this program. If not, see .
*
*/
+
namespace OCA\Files_Trashbin\Sabre;
-use OCP\Files\FileInfo;
-use Sabre\DAV\Exception\Forbidden;
-use Sabre\DAV\IFile;
-
-class TrashFile extends AbstractTrash implements IFile, ITrash {
- /** @var string */
- private $userId;
-
- public function __construct(string $userId, FileInfo $data) {
- $this->userId = $userId;
- parent::__construct($data);
- }
-
- public function put($data) {
- throw new Forbidden();
- }
-
+class TrashFile extends AbstractTrashFile {
public function get() {
- return $this->data->getStorage()->fopen($this->data->getInternalPath().'.d'.$this->getLastModified(), 'rb');
- }
-
- public function delete() {
- \OCA\Files_Trashbin\Trashbin::delete($this->data->getName(), $this->userId, $this->getLastModified());
+ return $this->data->getStorage()->fopen($this->data->getInternalPath() . '.d' . $this->getLastModified(), 'rb');
}
public function getName(): string {
return $this->data->getName() . '.d' . $this->getLastModified();
}
-
- public function setName($name) {
- throw new Forbidden();
- }
-
- public function restore(): bool {
- return \OCA\Files_Trashbin\Trashbin::restore($this->getName(), $this->data->getName(), $this->getLastModified());
- }
-
- public function getOriginalLocation(): string {
- return $this->data['extraData'];
- }
}
diff --git a/apps/files_trashbin/lib/Sabre/TrashFolder.php b/apps/files_trashbin/lib/Sabre/TrashFolder.php
index d884eefcc9..108aaf4f31 100644
--- a/apps/files_trashbin/lib/Sabre/TrashFolder.php
+++ b/apps/files_trashbin/lib/Sabre/TrashFolder.php
@@ -23,85 +23,9 @@ declare(strict_types=1);
*/
namespace OCA\Files_Trashbin\Sabre;
-use OCP\Files\FileInfo;
-use Sabre\DAV\Exception\Forbidden;
-use Sabre\DAV\Exception\NotFound;
-use Sabre\DAV\ICollection;
-
-class TrashFolder extends AbstractTrash implements ICollection, ITrash {
- /** @var string */
- private $userId;
-
- public function __construct(string $root, string $userId, FileInfo $data) {
- $this->userId = $userId;
- parent::__construct($data);
- }
-
- public function createFile($name, $data = null) {
- throw new Forbidden();
- }
-
- public function createDirectory($name) {
- throw new Forbidden();
- }
-
- public function getChild($name): ITrash {
- $entries = \OCA\Files_Trashbin\Helper::getTrashFiles($this->getName(), $this->userId);
-
- foreach ($entries as $entry) {
- if ($entry->getName() === $name) {
- if ($entry->getType() === FileInfo::TYPE_FOLDER) {
- return new TrashFolderFolder($this->getName(), $this->userId, $entry, $this->getOriginalLocation());
- }
- return new TrashFolderFile($this->getName(), $this->userId, $entry, $this->getOriginalLocation());
- }
- }
-
- throw new NotFound();
- }
-
- public function getChildren(): array {
- $entries = \OCA\Files_Trashbin\Helper::getTrashFiles($this->getName(), $this->userId);
-
- $children = array_map(function (FileInfo $entry) {
- if ($entry->getType() === FileInfo::TYPE_FOLDER) {
- return new TrashFolderFolder($this->getName(), $this->userId, $entry, $this->getOriginalLocation());
- }
- return new TrashFolderFile($this->getName(), $this->userId, $entry, $this->getOriginalLocation());
- }, $entries);
-
- return $children;
- }
-
- public function childExists($name): bool {
- $entries = \OCA\Files_Trashbin\Helper::getTrashFiles($this->getName(), $this->userId);
-
- foreach ($entries as $entry) {
- if ($entry->getName() === $name) {
- return true;
- }
- }
-
- return false;
- }
-
- public function delete() {
- \OCA\Files_Trashbin\Trashbin::delete($this->data->getName(), $this->userId, $this->getLastModified());
- }
+class TrashFolder extends AbstractTrashFolder {
public function getName(): string {
return $this->data->getName() . '.d' . $this->getLastModified();
}
-
- public function setName($name) {
- throw new Forbidden();
- }
-
- public function restore(): bool {
- return \OCA\Files_Trashbin\Trashbin::restore($this->getName(), $this->data->getName(), $this->getLastModified());
- }
-
- public function getOriginalLocation(): string {
- return $this->data['extraData'];
- }
}
diff --git a/apps/files_trashbin/lib/Sabre/TrashFolderFile.php b/apps/files_trashbin/lib/Sabre/TrashFolderFile.php
index 3e28d048b4..31ee9535b7 100644
--- a/apps/files_trashbin/lib/Sabre/TrashFolderFile.php
+++ b/apps/files_trashbin/lib/Sabre/TrashFolderFile.php
@@ -23,51 +23,9 @@ declare(strict_types=1);
*/
namespace OCA\Files_Trashbin\Sabre;
-use OCP\Files\FileInfo;
-use Sabre\DAV\Exception\Forbidden;
-use Sabre\DAV\IFile;
-
-class TrashFolderFile extends AbstractTrash implements IFile, ITrash {
- /** @var string */
- private $root;
-
- /** @var string */
- private $userId;
-
- /** @var string */
- private $location;
-
- public function __construct(string $root,
- string $userId,
- FileInfo $data,
- string $location) {
- $this->root = $root;
- $this->userId = $userId;
- $this->location = $location;
- parent::__construct($data);
- }
-
- public function put($data) {
- throw new Forbidden();
- }
+class TrashFolderFile extends AbstractTrashFile {
public function get() {
return $this->data->getStorage()->fopen($this->data->getInternalPath(), 'rb');
}
-
- public function delete() {
- \OCA\Files_Trashbin\Trashbin::delete($this->root . '/' . $this->getName(), $this->userId, null);
- }
-
- public function setName($name) {
- throw new Forbidden();
- }
-
- public function restore(): bool {
- return \OCA\Files_Trashbin\Trashbin::restore($this->root . '/' . $this->getName(), $this->data->getName(), null);
- }
-
- public function getOriginalLocation(): string {
- return $this->location . '/' . $this->getFilename();
- }
}
diff --git a/apps/files_trashbin/lib/Sabre/TrashFolderFolder.php b/apps/files_trashbin/lib/Sabre/TrashFolderFolder.php
index 4ee9a0e2db..5332b7dd4c 100644
--- a/apps/files_trashbin/lib/Sabre/TrashFolderFolder.php
+++ b/apps/files_trashbin/lib/Sabre/TrashFolderFolder.php
@@ -21,95 +21,8 @@ declare(strict_types=1);
* along with this program. If not, see .
*
*/
+
namespace OCA\Files_Trashbin\Sabre;
-use OCP\Files\FileInfo;
-use Sabre\DAV\Exception\Forbidden;
-use Sabre\DAV\Exception\NotFound;
-use Sabre\DAV\ICollection;
-
-class TrashFolderFolder extends AbstractTrash implements ICollection, ITrash {
-
- /** @var string */
- private $root;
-
- /** @var string */
- private $userId;
-
- /** @var string */
- private $location;
-
- public function __construct(string $root,
- string $userId,
- FileInfo $data,
- string $location) {
- $this->root = $root;
- $this->userId = $userId;
- $this->location = $location;
- parent::__construct($data);
- }
-
- public function createFile($name, $data = null) {
- throw new Forbidden();
- }
-
- public function createDirectory($name) {
- throw new Forbidden();
- }
-
- public function getChild($name): ITrash {
- $entries = \OCA\Files_Trashbin\Helper::getTrashFiles($this->root . '/' . $this->getName(), $this->userId);
-
- foreach ($entries as $entry) {
- if ($entry->getName() === $name) {
- if ($entry->getType() === FileInfo::TYPE_FOLDER) {
- return new TrashFolderFolder($this->root . '/' . $this->getName(), $this->userId, $entry, $this->getOriginalLocation());
- }
- return new TrashFolderFile($this->root . '/' . $this->getName(), $this->userId, $entry, $this->getOriginalLocation());
- }
- }
-
- throw new NotFound();
- }
-
- public function getChildren(): array {
- $entries = \OCA\Files_Trashbin\Helper::getTrashFiles($this->root . '/' . $this->getName(), $this->userId);
-
- $children = array_map(function (FileInfo $entry) {
- if ($entry->getType() === FileInfo::TYPE_FOLDER) {
- return new TrashFolderFolder($this->root.'/'.$this->getName(), $this->userId, $entry, $this->getOriginalLocation());
- }
- return new TrashFolderFile($this->root.'/'.$this->getName(), $this->userId, $entry, $this->getOriginalLocation());
- }, $entries);
-
- return $children;
- }
-
- public function childExists($name): bool {
- $entries = \OCA\Files_Trashbin\Helper::getTrashFiles($this->root . '/' . $this->getName(), $this->userId);
-
- foreach ($entries as $entry) {
- if ($entry->getName() === $name) {
- return true;
- }
- }
-
- return false;
- }
-
- public function delete() {
- \OCA\Files_Trashbin\Trashbin::delete($this->root . '/' . $this->getName(), $this->userId, null);
- }
-
- public function setName($name) {
- throw new Forbidden();
- }
-
- public function restore(): bool {
- return \OCA\Files_Trashbin\Trashbin::restore($this->root . '/' . $this->getName(), $this->data->getName(), null);
- }
-
- public function getOriginalLocation(): string {
- return $this->location . '/' . $this->getFilename();
- }
+class TrashFolderFolder extends AbstractTrashFolder {
}
diff --git a/apps/files_trashbin/lib/Sabre/TrashHome.php b/apps/files_trashbin/lib/Sabre/TrashHome.php
index d1c50c9c6a..12c2578bc3 100644
--- a/apps/files_trashbin/lib/Sabre/TrashHome.php
+++ b/apps/files_trashbin/lib/Sabre/TrashHome.php
@@ -21,19 +21,33 @@ declare(strict_types=1);
* along with this program. If not, see .
*
*/
+
namespace OCA\Files_Trashbin\Sabre;
+use OCA\Files_Trashbin\Trash\ITrashManager;
+use OCP\IUser;
use Sabre\DAV\Exception\Forbidden;
use Sabre\DAV\Exception\NotFound;
use Sabre\DAV\ICollection;
class TrashHome implements ICollection {
+ /** @var ITrashManager */
+ private $trashManager;
/** @var array */
private $principalInfo;
- public function __construct(array $principalInfo) {
+ /** @var IUser */
+ private $user;
+
+ public function __construct(
+ array $principalInfo,
+ ITrashManager $trashManager,
+ IUser $user
+ ) {
$this->principalInfo = $principalInfo;
+ $this->trashManager = $trashManager;
+ $this->user = $user;
}
public function delete() {
@@ -41,7 +55,7 @@ class TrashHome implements ICollection {
}
public function getName(): string {
- list(,$name) = \Sabre\Uri\split($this->principalInfo['uri']);
+ list(, $name) = \Sabre\Uri\split($this->principalInfo['uri']);
return $name;
}
@@ -58,24 +72,20 @@ class TrashHome implements ICollection {
}
public function getChild($name) {
- list(,$userId) = \Sabre\Uri\split($this->principalInfo['uri']);
-
if ($name === 'restore') {
- return new RestoreFolder($userId);
+ return new RestoreFolder();
}
if ($name === 'trash') {
- return new TrashRoot($userId);
+ return new TrashRoot($this->user, $this->trashManager);
}
throw new NotFound();
}
public function getChildren(): array {
- list(,$userId) = \Sabre\Uri\split($this->principalInfo['uri']);
-
return [
- new RestoreFolder($userId),
- new TrashRoot($userId),
+ new RestoreFolder(),
+ new TrashRoot($this->user, $this->trashManager)
];
}
diff --git a/apps/files_trashbin/lib/Sabre/TrashRoot.php b/apps/files_trashbin/lib/Sabre/TrashRoot.php
index 73b9d44d7e..45f27f48b1 100644
--- a/apps/files_trashbin/lib/Sabre/TrashRoot.php
+++ b/apps/files_trashbin/lib/Sabre/TrashRoot.php
@@ -23,18 +23,25 @@ declare(strict_types=1);
*/
namespace OCA\Files_Trashbin\Sabre;
+use OCA\Files_Trashbin\Trash\ITrashItem;
+use OCA\Files_Trashbin\Trash\ITrashManager;
use OCP\Files\FileInfo;
+use OCP\IUser;
use Sabre\DAV\Exception\Forbidden;
use Sabre\DAV\Exception\NotFound;
use Sabre\DAV\ICollection;
class TrashRoot implements ICollection {
- /** @var string */
- private $userId;
+ /** @var IUser */
+ private $user;
- public function __construct(string $userId) {
- $this->userId = $userId;
+ /** @var ITrashManager */
+ private $trashManager;
+
+ public function __construct(IUser $user, ITrashManager $trashManager) {
+ $this->user = $user;
+ $this->trashManager = $trashManager;
}
public function delete() {
@@ -57,44 +64,38 @@ class TrashRoot implements ICollection {
throw new Forbidden('Not allowed to create folders in the trashbin');
}
+ public function getChildren(): array {
+ $entries = $this->trashManager->listTrashRoot($this->user);
+
+ $children = array_map(function (ITrashItem $entry) {
+ if ($entry->getType() === FileInfo::TYPE_FOLDER) {
+ return new TrashFolder($this->trashManager, $entry);
+ }
+ return new TrashFile($this->trashManager, $entry);
+ }, $entries);
+
+ return $children;
+ }
+
public function getChild($name): ITrash {
- $entries = \OCA\Files_Trashbin\Helper::getTrashFiles('/', $this->userId);
+ $entries = $this->getChildren();
foreach ($entries as $entry) {
- if ($entry->getName() . '.d'.$entry->getMtime() === $name) {
- if ($entry->getType() === FileInfo::TYPE_FOLDER) {
- return new TrashFolder('/', $this->userId, $entry);
- }
- return new TrashFile($this->userId, $entry);
+ if ($entry->getName() === $name) {
+ return $entry;
}
}
throw new NotFound();
}
- public function getChildren(): array {
- $entries = \OCA\Files_Trashbin\Helper::getTrashFiles('/', $this->userId);
-
- $children = array_map(function (FileInfo $entry) {
- if ($entry->getType() === FileInfo::TYPE_FOLDER) {
- return new TrashFolder('/', $this->userId, $entry);
- }
- return new TrashFile($this->userId, $entry);
- }, $entries);
-
- return $children;
- }
-
public function childExists($name): bool {
- $entries = \OCA\Files_Trashbin\Helper::getTrashFiles('/', $this->userId);
-
- foreach ($entries as $entry) {
- if ($entry->getName() . '.d'.$entry->getMtime() === $name) {
- return true;
- }
+ try {
+ $this->getChild($name);
+ return true;
+ } catch (NotFound $e) {
+ return false;
}
-
- return false;
}
public function getLastModified(): int {
diff --git a/apps/files_trashbin/lib/Storage.php b/apps/files_trashbin/lib/Storage.php
index 54b47a6a19..0db634eeb9 100644
--- a/apps/files_trashbin/lib/Storage.php
+++ b/apps/files_trashbin/lib/Storage.php
@@ -31,34 +31,18 @@ use OC\Files\Filesystem;
use OC\Files\Storage\Wrapper\Wrapper;
use OC\Files\View;
use OCA\Files_Trashbin\Events\MoveToTrashEvent;
+use OCA\Files_Trashbin\Trash\ITrashManager;
use OCP\Encryption\Exceptions\GenericEncryptionException;
use OCP\Files\IRootFolder;
+use OCP\Files\Mount\IMountPoint;
use OCP\Files\Node;
use OCP\ILogger;
use OCP\IUserManager;
use Symfony\Component\EventDispatcher\EventDispatcher;
class Storage extends Wrapper {
-
+ /** @var IMountPoint */
private $mountPoint;
- // remember already deleted files to avoid infinite loops if the trash bin
- // move files across storages
- private $deletedFiles = array();
-
- /**
- * Disable trash logic
- *
- * @var bool
- */
- private static $disableTrash = false;
-
- /**
- * remember which file/folder was moved out of s shared folder
- * in this case we want to add a copy to the owners trash bin
- *
- * @var array
- */
- private static $moveOutOfSharedFolder = [];
/** @var IUserManager */
private $userManager;
@@ -72,21 +56,29 @@ class Storage extends Wrapper {
/** @var IRootFolder */
private $rootFolder;
+ /** @var ITrashManager */
+ private $trashManager;
+
/**
* Storage constructor.
*
* @param array $parameters
+ * @param ITrashManager $trashManager
* @param IUserManager|null $userManager
* @param ILogger|null $logger
* @param EventDispatcher|null $eventDispatcher
* @param IRootFolder|null $rootFolder
*/
- public function __construct($parameters,
- IUserManager $userManager = null,
- ILogger $logger = null,
- EventDispatcher $eventDispatcher = null,
- IRootFolder $rootFolder = null) {
+ public function __construct(
+ $parameters,
+ ITrashManager $trashManager = null,
+ IUserManager $userManager = null,
+ ILogger $logger = null,
+ EventDispatcher $eventDispatcher = null,
+ IRootFolder $rootFolder = null
+ ) {
$this->mountPoint = $parameters['mountPoint'];
+ $this->trashManager = $trashManager;
$this->userManager = $userManager;
$this->logger = $logger;
$this->eventDispatcher = $eventDispatcher;
@@ -94,81 +86,6 @@ class Storage extends Wrapper {
parent::__construct($parameters);
}
- /**
- * @internal
- */
- public static function preRenameHook($params) {
- // in cross-storage cases, a rename is a copy + unlink,
- // that last unlink must not go to trash, only exception:
- // if the file was moved from a shared storage to a local folder,
- // in this case the owner should get a copy in his trash bin so that
- // they can restore the files again
-
- $oldPath = $params['oldpath'];
- $newPath = dirname($params['newpath']);
- $currentUser = \OC::$server->getUserSession()->getUser();
-
- $fileMovedOutOfSharedFolder = false;
-
- try {
- if ($currentUser) {
- $currentUserId = $currentUser->getUID();
-
- $view = new View($currentUserId . '/files');
- $fileInfo = $view->getFileInfo($oldPath);
- if ($fileInfo) {
- $sourceStorage = $fileInfo->getStorage();
- $sourceOwner = $view->getOwner($oldPath);
- $targetOwner = $view->getOwner($newPath);
-
- if ($sourceOwner !== $targetOwner
- && $sourceStorage->instanceOfStorage('OCA\Files_Sharing\SharedStorage')
- ) {
- $fileMovedOutOfSharedFolder = true;
- }
- }
- }
- } catch (\Exception $e) {
- // do nothing, in this case we just disable the trashbin and continue
- \OC::$server->getLogger()->logException($e, [
- 'message' => 'Trashbin storage could not check if a file was moved out of a shared folder.',
- 'level' => ILogger::DEBUG,
- 'app' => 'files_trashbin',
- ]);
- }
-
- if($fileMovedOutOfSharedFolder) {
- self::$moveOutOfSharedFolder['/' . $currentUserId . '/files' . $oldPath] = true;
- } else {
- self::$disableTrash = true;
- }
-
- }
-
- /**
- * @internal
- */
- public static function postRenameHook($params) {
- self::$disableTrash = false;
- }
-
- /**
- * Rename path1 to path2 by calling the wrapped storage.
- *
- * @param string $path1 first path
- * @param string $path2 second path
- * @return bool
- */
- public function rename($path1, $path2) {
- $result = $this->storage->rename($path1, $path2);
- if ($result === false) {
- // when rename failed, the post_rename hook isn't triggered,
- // but we still want to reenable the trash logic
- self::$disableTrash = false;
- }
- return $result;
- }
-
/**
* Deletes the given file by moving it into the trashbin.
*
@@ -178,22 +95,15 @@ class Storage extends Wrapper {
*/
public function unlink($path) {
try {
- if (isset(self::$moveOutOfSharedFolder[$this->mountPoint . $path])) {
- $result = $this->doDelete($path, 'unlink', true);
- unset(self::$moveOutOfSharedFolder[$this->mountPoint . $path]);
- } else {
- $result = $this->doDelete($path, 'unlink');
- }
+ return $this->doDelete($path, 'unlink');
} catch (GenericEncryptionException $e) {
// in case of a encryption exception we delete the file right away
$this->logger->info(
- "Can't move file" . $path .
+ "Can't move file" . $path .
"to the trash bin, therefore it was deleted right away");
- $result = $this->storage->unlink($path);
+ return $this->storage->unlink($path);
}
-
- return $result;
}
/**
@@ -204,14 +114,7 @@ class Storage extends Wrapper {
* @return bool true if the operation succeeded, false otherwise
*/
public function rmdir($path) {
- if (isset(self::$moveOutOfSharedFolder[$this->mountPoint . $path])) {
- $result = $this->doDelete($path, 'rmdir', true);
- unset(self::$moveOutOfSharedFolder[$this->mountPoint . $path]);
- } else {
- $result = $this->doDelete($path, 'rmdir');
- }
-
- return $result;
+ return $this->doDelete($path, 'rmdir');
}
/**
@@ -221,7 +124,7 @@ class Storage extends Wrapper {
* @param $path
* @return bool
*/
- protected function shouldMoveToTrash($path){
+ protected function shouldMoveToTrash($path) {
// check if there is a app which want to disable the trash bin for this file
$fileId = $this->storage->getCache()->getId($path);
@@ -262,17 +165,16 @@ class Storage extends Wrapper {
*
* @param string $path path of file or folder to delete
* @param string $method either "unlink" or "rmdir"
- * @param bool $ownerOnly delete for owner only (if file gets moved out of a shared folder)
*
* @return bool true if the operation succeeded, false otherwise
*/
- private function doDelete($path, $method, $ownerOnly = false) {
- if (self::$disableTrash
- || !\OC::$server->getAppManager()->isEnabledForUser('files_trashbin')
+ private function doDelete($path, $method) {
+ if (
+ !\OC::$server->getAppManager()->isEnabledForUser('files_trashbin')
|| (pathinfo($path, PATHINFO_EXTENSION) === 'part')
|| $this->shouldMoveToTrash($path) === false
) {
- return call_user_func_array([$this->storage, $method], [$path]);
+ return call_user_func([$this->storage, $method], $path);
}
// check permissions before we continue, this is especially important for
@@ -281,28 +183,12 @@ class Storage extends Wrapper {
return false;
}
- $normalized = Filesystem::normalizePath($this->mountPoint . '/' . $path, true, false, true);
- $result = true;
- $view = Filesystem::getView();
- if (!isset($this->deletedFiles[$normalized]) && $view instanceof View) {
- $this->deletedFiles[$normalized] = $normalized;
- if ($filesPath = $view->getRelativePath($normalized)) {
- $filesPath = trim($filesPath, '/');
- $result = \OCA\Files_Trashbin\Trashbin::move2trash($filesPath, $ownerOnly);
- // in cross-storage cases the file will be copied
- // but not deleted, so we delete it here
- if ($result) {
- call_user_func_array([$this->storage, $method], [$path]);
- }
- } else {
- $result = call_user_func_array([$this->storage, $method], [$path]);
- }
- unset($this->deletedFiles[$normalized]);
- } else if ($this->storage->file_exists($path)) {
- $result = call_user_func_array([$this->storage, $method], [$path]);
+ $isMovedToTrash = $this->trashManager->moveToTrash($this, $path);
+ if (!$isMovedToTrash) {
+ return call_user_func([$this->storage, $method], $path);
+ } else {
+ return true;
}
-
- return $result;
}
/**
@@ -311,7 +197,8 @@ class Storage extends Wrapper {
public static function setupStorage() {
\OC\Files\Filesystem::addStorageWrapper('oc_trashbin', function ($mountPoint, $storage) {
return new \OCA\Files_Trashbin\Storage(
- array('storage' => $storage, 'mountPoint' => $mountPoint),
+ ['storage' => $storage, 'mountPoint' => $mountPoint],
+ \OC::$server->query(ITrashManager::class),
\OC::$server->getUserManager(),
\OC::$server->getLogger(),
\OC::$server->getEventDispatcher(),
@@ -320,4 +207,7 @@ class Storage extends Wrapper {
}, 1);
}
+ public function getMountPoint() {
+ return $this->mountPoint;
+ }
}
diff --git a/apps/files_trashbin/lib/Trash/BackendNotFoundException.php b/apps/files_trashbin/lib/Trash/BackendNotFoundException.php
new file mode 100644
index 0000000000..13289db7ab
--- /dev/null
+++ b/apps/files_trashbin/lib/Trash/BackendNotFoundException.php
@@ -0,0 +1,26 @@
+
+ *
+ * @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\Trash;
+
+class BackendNotFoundException extends \Exception {
+
+}
diff --git a/apps/files_trashbin/lib/Trash/ITrashBackend.php b/apps/files_trashbin/lib/Trash/ITrashBackend.php
new file mode 100644
index 0000000000..ebdf9720d7
--- /dev/null
+++ b/apps/files_trashbin/lib/Trash/ITrashBackend.php
@@ -0,0 +1,84 @@
+
+ *
+ * @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\Trash;
+
+use OCP\Files\FileInfo;
+use OCP\Files\Node;
+use OCP\Files\SimpleFS\ISimpleFile;
+use OCP\Files\Storage\IStorage;
+use OCP\IUser;
+
+/**
+ * @since 15.0.0
+ */
+interface ITrashBackend {
+ /**
+ * List all trash items in the root of the trashbin
+ *
+ * @param IUser $user
+ * @return ITrashItem[]
+ * @since 15.0.0
+ */
+ public function listTrashRoot(IUser $user): array;
+
+ /**
+ * List all trash items in a subfolder in the trashbin
+ *
+ * @param ITrashItem $folder
+ * @return ITrashItem[]
+ * @since 15.0.0
+ */
+ public function listTrashFolder(ITrashItem $folder): array;
+
+ /**
+ * Restore a trashbin item
+ *
+ * @param ITrashItem $item
+ * @since 15.0.0
+ */
+ public function restoreItem(ITrashItem $item);
+
+ /**
+ * Permanently remove an item from trash
+ *
+ * @param ITrashItem $item
+ * @since 15.0.0
+ */
+ public function removeItem(ITrashItem $item);
+
+ /**
+ * Move a file or folder to trash
+ *
+ * @param IStorage $storage
+ * @param string $internalPath
+ * @return boolean whether or not the file was moved to trash, if false then the file should be deleted normally
+ * @since 15.0.0
+ */
+ public function moveToTrash(IStorage $storage, string $internalPath): bool;
+
+ /**
+ * @param IUser $user
+ * @param int $fileId
+ * @return Node|null
+ */
+ public function getTrashNodeById(IUser $user, int $fileId);
+}
diff --git a/apps/files_trashbin/lib/Trash/ITrashItem.php b/apps/files_trashbin/lib/Trash/ITrashItem.php
new file mode 100644
index 0000000000..74348cf181
--- /dev/null
+++ b/apps/files_trashbin/lib/Trash/ITrashItem.php
@@ -0,0 +1,78 @@
+
+ *
+ * @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\Trash;
+
+use OCP\Files\FileInfo;
+use OCP\IUser;
+
+/**
+ * @since 15.0.0
+ */
+interface ITrashItem extends FileInfo {
+ /**
+ * Get the trash backend for this item
+ *
+ * @return ITrashBackend
+ * @since 15.0.0
+ */
+ public function getTrashBackend(): ITrashBackend;
+
+ /**
+ * Get the original location for the trash item
+ *
+ * @return string
+ * @since 15.0.0
+ */
+ public function getOriginalLocation(): string;
+
+ /**
+ * Get the timestamp that the file was moved to trash
+ *
+ * @return int
+ * @since 15.0.0
+ */
+ public function getDeletedTime(): int;
+
+ /**
+ * Get the path of the item relative to the users trashbin
+ *
+ * @return string
+ * @since 15.0.0
+ */
+ public function getTrashPath(): string;
+
+ /**
+ * Whether the item is a deleted item in the root of the trash, or a file in a subfolder
+ *
+ * @return bool
+ * @since 15.0.0
+ */
+ public function isRootItem(): bool;
+
+ /**
+ * Get the user for which this trash item applies
+ *
+ * @return IUser
+ * @since 15.0.0
+ */
+ public function getUser(): IUser;
+}
diff --git a/apps/files_trashbin/lib/Trash/ITrashManager.php b/apps/files_trashbin/lib/Trash/ITrashManager.php
new file mode 100644
index 0000000000..fcd51f2d37
--- /dev/null
+++ b/apps/files_trashbin/lib/Trash/ITrashManager.php
@@ -0,0 +1,56 @@
+
+ *
+ * @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\Trash;
+
+use OCP\IUser;
+
+interface ITrashManager extends ITrashBackend {
+ /**
+ * Add a backend for the trashbin
+ *
+ * @param string $storageType
+ * @param ITrashBackend $backend
+ * @since 15.0.0
+ */
+ public function registerBackend(string $storageType, ITrashBackend $backend);
+
+ /**
+ * List all trash items in the root of the trashbin
+ *
+ * @param IUser $user
+ * @return ITrashItem[]
+ * @since 15.0.0
+ */
+ public function listTrashRoot(IUser $user): array;
+
+ /**
+ * Temporally prevent files from being moved to the trash
+ *
+ * @since 15.0.0
+ */
+ public function pauseTrash();
+
+ /**
+ * @since 15.0.0
+ */
+ public function resumeTrash();
+}
diff --git a/apps/files_trashbin/lib/Trash/LegacyTrashBackend.php b/apps/files_trashbin/lib/Trash/LegacyTrashBackend.php
new file mode 100644
index 0000000000..b8519fa27c
--- /dev/null
+++ b/apps/files_trashbin/lib/Trash/LegacyTrashBackend.php
@@ -0,0 +1,128 @@
+
+ *
+ * @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\Trash;
+
+use OC\Files\Filesystem;
+use OC\Files\View;
+use OCA\Files_Trashbin\Helper;
+use OCA\Files_Trashbin\Storage;
+use OCA\Files_Trashbin\Trashbin;
+use OCP\Files\FileInfo;
+use OCP\Files\IRootFolder;
+use OCP\Files\NotFoundException;
+use OCP\Files\Storage\IStorage;
+use OCP\IUser;
+
+class LegacyTrashBackend implements ITrashBackend {
+ /** @var array */
+ private $deletedFiles = [];
+
+ /** @var IRootFolder */
+ private $rootFolder;
+
+ public function __construct(IRootFolder $rootFolder) {
+ $this->rootFolder = $rootFolder;
+ }
+
+ /**
+ * @param array $items
+ * @param IUser $user
+ * @param ITrashItem $parent
+ * @return ITrashItem[]
+ */
+ private function mapTrashItems(array $items, IUser $user, ITrashItem $parent = null): array {
+ $parentTrashPath = ($parent instanceof ITrashItem) ? $parent->getTrashPath() : '';
+ $isRoot = $parent === null;
+ return array_map(function (FileInfo $file) use ($parent, $parentTrashPath, $isRoot, $user) {
+ return new TrashItem(
+ $this,
+ $isRoot ? $file['extraData'] : $parent->getOriginalLocation() . '/' . $file->getName(),
+ $file->getMTime(),
+ $parentTrashPath . '/' . $file->getName() . ($isRoot ? '.d' . $file->getMtime() : ''),
+ $file,
+ $user
+ );
+ }, $items);
+ }
+
+ public function listTrashRoot(IUser $user): array {
+ $entries = Helper::getTrashFiles('/', $user->getUID());
+ return $this->mapTrashItems($entries, $user);
+ }
+
+ public function listTrashFolder(ITrashItem $folder): array {
+ $user = $folder->getUser();
+ $entries = Helper::getTrashFiles($folder->getTrashPath(), $user->getUID());
+ return $this->mapTrashItems($entries, $user ,$folder);
+ }
+
+ public function restoreItem(ITrashItem $item) {
+ Trashbin::restore($item->getTrashPath(), $item->getName(), $item->isRootItem() ? $item->getDeletedTime() : null);
+ }
+
+ public function removeItem(ITrashItem $item) {
+ $user = $item->getUser();
+ if ($item->isRootItem()) {
+ $path = substr($item->getTrashPath(), 0, -strlen('.d' . $item->getDeletedTime()));
+ Trashbin::delete($path, $user->getUID(), $item->getDeletedTime());
+ } else {
+ Trashbin::delete($item->getTrashPath(), $user->getUID(), null);
+ }
+
+ }
+
+ public function moveToTrash(IStorage $storage, string $internalPath): bool {
+ if (!$storage instanceof Storage) {
+ return false;
+ }
+ $normalized = Filesystem::normalizePath($storage->getMountPoint() . '/' . $internalPath, true, false, true);
+ $view = Filesystem::getView();
+ if (!isset($this->deletedFiles[$normalized]) && $view instanceof View) {
+ $this->deletedFiles[$normalized] = $normalized;
+ if ($filesPath = $view->getRelativePath($normalized)) {
+ $filesPath = trim($filesPath, '/');
+ $result = \OCA\Files_Trashbin\Trashbin::move2trash($filesPath);
+ } else {
+ $result = false;
+ }
+ unset($this->deletedFiles[$normalized]);
+ } else {
+ $result = false;
+ }
+
+ return $result;
+ }
+
+ public function getTrashNodeById(IUser $user, int $fileId) {
+ try {
+ $userFolder = $this->rootFolder->getUserFolder($user->getUID());
+ $trash = $userFolder->getParent()->get('files_trashbin/files');
+ $trashFiles = $trash->getById($fileId);
+ if (!$trashFiles) {
+ return null;
+ }
+ return $trashFiles ? array_pop($trashFiles) : null;
+ } catch (NotFoundException $e) {
+ return null;
+ }
+ }
+}
diff --git a/apps/files_trashbin/lib/Trash/TrashItem.php b/apps/files_trashbin/lib/Trash/TrashItem.php
new file mode 100644
index 0000000000..cd7079bcf2
--- /dev/null
+++ b/apps/files_trashbin/lib/Trash/TrashItem.php
@@ -0,0 +1,172 @@
+
+ *
+ * @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\Trash;
+
+use OCP\Files\FileInfo;
+use OCP\IUser;
+
+class TrashItem implements ITrashItem {
+ /** @var ITrashBackend */
+ private $backend;
+ /** @var string */
+ private $orignalLocation;
+ /** @var int */
+ private $deletedTime;
+ /** @var string */
+ private $trashPath;
+ /** @var FileInfo */
+ private $fileInfo;
+ /** @var IUser */
+ private $user;
+
+ public function __construct(
+ ITrashBackend $backend,
+ string $originalLocation,
+ int $deletedTime,
+ string $trashPath,
+ FileInfo $fileInfo,
+ IUser $user
+ ) {
+ $this->backend = $backend;
+ $this->orignalLocation = $originalLocation;
+ $this->deletedTime = $deletedTime;
+ $this->trashPath = $trashPath;
+ $this->fileInfo = $fileInfo;
+ $this->user = $user;
+ }
+
+ public function getTrashBackend(): ITrashBackend {
+ return $this->backend;
+ }
+
+ public function getOriginalLocation(): string {
+ return $this->orignalLocation;
+ }
+
+ public function getDeletedTime(): int {
+ return $this->deletedTime;
+ }
+
+ public function getTrashPath(): string {
+ return $this->trashPath;
+ }
+
+ public function isRootItem(): bool {
+ return substr_count($this->getTrashPath(), '/') === 1;
+ }
+
+ public function getUser(): IUser {
+ return $this->user;
+ }
+
+ public function getEtag() {
+ return $this->fileInfo->getEtag();
+ }
+
+ public function getSize() {
+ return $this->fileInfo->getSize();
+ }
+
+ public function getMtime() {
+ return $this->fileInfo->getMtime();
+ }
+
+ public function getName() {
+ return $this->fileInfo->getName();
+ }
+
+ public function getInternalPath() {
+ return $this->fileInfo->getInternalPath();
+ }
+
+ public function getPath() {
+ return $this->fileInfo->getPath();
+ }
+
+ public function getMimetype() {
+ return $this->fileInfo->getMimetype();
+ }
+
+ public function getMimePart() {
+ return $this->fileInfo->getMimePart();
+ }
+
+ public function getStorage() {
+ return $this->fileInfo->getStorage();
+ }
+
+ public function getId() {
+ return $this->fileInfo->getId();
+ }
+
+ public function isEncrypted() {
+ return $this->fileInfo->isEncrypted();
+ }
+
+ public function getPermissions() {
+ return $this->fileInfo->getPermissions();
+ }
+
+ public function getType() {
+ return $this->fileInfo->getType();
+ }
+
+ public function isReadable() {
+ return $this->fileInfo->isReadable();
+ }
+
+ public function isUpdateable() {
+ return $this->fileInfo->isUpdateable();
+ }
+
+ public function isCreatable() {
+ return $this->fileInfo->isCreatable();
+ }
+
+ public function isDeletable() {
+ return $this->fileInfo->isDeletable();
+ }
+
+ public function isShareable() {
+ return $this->fileInfo->isShareable();
+ }
+
+ public function isShared() {
+ return $this->fileInfo->isShared();
+ }
+
+ public function isMounted() {
+ return $this->fileInfo->isMounted();
+ }
+
+ public function getMountPoint() {
+ return $this->fileInfo->getMountPoint();
+ }
+
+ public function getOwner() {
+ return $this->fileInfo->getOwner();
+ }
+
+ public function getChecksum() {
+ return $this->fileInfo->getChecksum();
+ }
+}
diff --git a/apps/files_trashbin/lib/Trash/TrashManager.php b/apps/files_trashbin/lib/Trash/TrashManager.php
new file mode 100644
index 0000000000..50ab539c21
--- /dev/null
+++ b/apps/files_trashbin/lib/Trash/TrashManager.php
@@ -0,0 +1,125 @@
+
+ *
+ * @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\Trash;
+
+use OCP\Files\FileInfo;
+use OCP\Files\Mount\IMountPoint;
+use OCP\Files\Storage\IStorage;
+use OCP\IUser;
+
+class TrashManager implements ITrashManager {
+ /** @var ITrashBackend[] */
+ private $backends = [];
+
+ private $trashPaused = false;
+
+ public function registerBackend(string $storageType, ITrashBackend $backend) {
+ $this->backends[$storageType] = $backend;
+ }
+
+ /**
+ * @return ITrashBackend[]
+ */
+ private function getBackends(): array {
+ return $this->backends;
+ }
+
+ public function listTrashRoot(IUser $user): array {
+ $items = array_reduce($this->getBackends(), function (array $items, ITrashBackend $backend) use ($user) {
+ return array_merge($items, $backend->listTrashRoot($user));
+ }, []);
+ usort($items, function (ITrashItem $a, ITrashItem $b) {
+ return $a->getDeletedTime() - $b->getDeletedTime();
+ });
+ return $items;
+ }
+
+ private function getBackendForItem(ITrashItem $item) {
+ return $item->getTrashBackend();
+ }
+
+ public function listTrashFolder(ITrashItem $folder): array {
+ return $this->getBackendForItem($folder)->listTrashFolder($folder);
+ }
+
+ public function restoreItem(ITrashItem $item) {
+ return $this->getBackendForItem($item)->restoreItem($item);
+ }
+
+ public function removeItem(ITrashItem $item) {
+ $this->getBackendForItem($item)->removeItem($item);
+ }
+
+ /**
+ * @param IStorage $storage
+ * @return ITrashBackend
+ * @throws BackendNotFoundException
+ */
+ public function getBackendForStorage(IStorage $storage): ITrashBackend {
+ $fullType = get_class($storage);
+ $foundType = array_reduce(array_keys($this->backends), function ($type, $registeredType) use ($storage) {
+ if (
+ $storage->instanceOfStorage($registeredType) &&
+ ($type === '' || is_subclass_of($registeredType, $type))
+ ) {
+ return $registeredType;
+ } else {
+ return $type;
+ }
+ }, '');
+ if ($foundType === '') {
+ throw new BackendNotFoundException("Trash backend for $fullType not found");
+ } else {
+ return $this->backends[$foundType];
+ }
+ }
+
+ public function moveToTrash(IStorage $storage, string $internalPath): bool {
+ if ($this->trashPaused) {
+ return false;
+ }
+ try {
+ $backend = $this->getBackendForStorage($storage);
+ return $backend->moveToTrash($storage, $internalPath);
+ } catch (BackendNotFoundException $e) {
+ return false;
+ }
+ }
+
+ public function getTrashNodeById(IUser $user, int $fileId) {
+ foreach ($this->backends as $backend) {
+ $item = $backend->getTrashNodeById($user, $fileId);
+ if ($item !== null) {
+ return $item;
+ }
+ }
+ return null;
+ }
+
+ public function pauseTrash() {
+ $this->trashPaused = true;
+ }
+
+ public function resumeTrash() {
+ $this->trashPaused = false;
+ }
+}
diff --git a/apps/files_trashbin/lib/Trashbin.php b/apps/files_trashbin/lib/Trashbin.php
index b9a8a42a21..96c6a4c0af 100644
--- a/apps/files_trashbin/lib/Trashbin.php
+++ b/apps/files_trashbin/lib/Trashbin.php
@@ -976,8 +976,6 @@ class Trashbin {
\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');
- \OCP\Util::connectHook('OC_Filesystem', 'rename', 'OCA\Files_Trashbin\Storage', 'preRenameHook');
- \OCP\Util::connectHook('OC_Filesystem', 'post_rename', 'OCA\Files_Trashbin\Storage', 'postRenameHook');
}
/**
diff --git a/apps/files_trashbin/tests/Controller/PreviewControllerTest.php b/apps/files_trashbin/tests/Controller/PreviewControllerTest.php
index 9ceef07e7d..02bb63fa17 100644
--- a/apps/files_trashbin/tests/Controller/PreviewControllerTest.php
+++ b/apps/files_trashbin/tests/Controller/PreviewControllerTest.php
@@ -23,6 +23,7 @@
namespace OCA\Files_Trashbin\Tests\Controller;
use OCA\Files_Trashbin\Controller\PreviewController;
+use OCA\Files_Trashbin\Trash\ITrashManager;
use OCP\AppFramework\Http;
use OCP\AppFramework\Http\DataResponse;
use OCP\AppFramework\Http\FileDisplayResponse;
@@ -31,14 +32,14 @@ use OCP\Files\File;
use OCP\Files\Folder;
use OCP\Files\IMimeTypeDetector;
use OCP\Files\IRootFolder;
-use OCP\Files\NotFoundException;
use OCP\Files\SimpleFS\ISimpleFile;
use OCP\IPreview;
use OCP\IRequest;
+use OCP\IUser;
+use OCP\IUserSession;
use Test\TestCase;
class PreviewControllerTest extends TestCase {
-
/** @var IRootFolder|\PHPUnit_Framework_MockObject_MockObject */
private $rootFolder;
@@ -57,6 +58,12 @@ class PreviewControllerTest extends TestCase {
/** @var PreviewController */
private $controller;
+ /** @var ITrashManager|\PHPUnit_Framework_MockObject_MockObject */
+ private $trashManager;
+
+ /** @var IUserSession|\PHPUnit_Framework_MockObject_MockObject */
+ private $userSession;
+
public function setUp() {
parent::setUp();
@@ -65,12 +72,23 @@ class PreviewControllerTest extends TestCase {
$this->mimeTypeDetector = $this->createMock(IMimeTypeDetector::class);
$this->previewManager = $this->createMock(IPreview::class);
$this->time = $this->createMock(ITimeFactory::class);
+ $this->trashManager = $this->createMock(ITrashManager::class);
+ $this->userSession = $this->createMock(IUserSession::class);
+ $user = $this->createMock(IUser::class);
+ $user->expects($this->any())
+ ->method('getUID')
+ ->willReturn($this->userId);
+
+ $this->userSession->expects($this->any())
+ ->method('getUser')
+ ->willReturn($user);
$this->controller = new PreviewController(
'files_versions',
$this->createMock(IRequest::class),
$this->rootFolder,
- $this->userId,
+ $this->trashManager,
+ $this->userSession,
$this->mimeTypeDetector,
$this->previewManager,
$this->time
@@ -114,11 +132,15 @@ class PreviewControllerTest extends TestCase {
->with($this->equalTo(42))
->willReturn([$file]);
$file->method('getName')
- ->willReturn('file.1234');
+ ->willReturn('file.d1234');
$file->method('getParent')
->willReturn($trash);
+ $this->trashManager->expects($this->any())
+ ->method('getTrashNodeById')
+ ->willReturn($file);
+
$preview = $this->createMock(ISimpleFile::class);
$this->previewManager->method('getPreview')
->with($this->equalTo($file), 10, 10, true, IPreview::MODE_FILL, 'myMime')
@@ -177,6 +199,9 @@ class PreviewControllerTest extends TestCase {
->willReturn($trash);
$folder = $this->createMock(Folder::class);
+ $this->trashManager->expects($this->any())
+ ->method('getTrashNodeById')
+ ->willReturn($folder);
$trash->method('getById')
->with($this->equalTo(43))
->willReturn([$folder]);
diff --git a/apps/files_trashbin/tests/StorageTest.php b/apps/files_trashbin/tests/StorageTest.php
index 67e622aa1c..058d64d1aa 100644
--- a/apps/files_trashbin/tests/StorageTest.php
+++ b/apps/files_trashbin/tests/StorageTest.php
@@ -34,6 +34,7 @@ use OC\Files\Storage\Temporary;
use OC\Files\Filesystem;
use OCA\Files_Trashbin\Events\MoveToTrashEvent;
use OCA\Files_Trashbin\Storage;
+use OCA\Files_Trashbin\Trash\ITrashManager;
use OCP\Files\Cache\ICache;
use OCP\Files\IRootFolder;
use OCP\Files\Node;
@@ -546,6 +547,7 @@ class StorageTest extends \Test\TestCase {
->disableOriginalConstructor()->getMock();
$rootFolder = $this->createMock(IRootFolder::class);
$node = $this->getMockBuilder(Node::class)->disableOriginalConstructor()->getMock();
+ $trashManager = $this->createMock(ITrashManager::class);
$event = $this->getMockBuilder(MoveToTrashEvent::class)->disableOriginalConstructor()->getMock();
$event->expects($this->any())->method('shouldMoveToTrashBin')->willReturn(!$appDisablesTrash);
@@ -555,6 +557,7 @@ class StorageTest extends \Test\TestCase {
->setConstructorArgs(
[
['mountPoint' => $mountPoint, 'storage' => $tmpStorage],
+ $trashManager,
$userManager,
$logger,
$eventDispatcher,
diff --git a/lib/private/Files/Cache/Wrapper/CacheWrapper.php b/lib/private/Files/Cache/Wrapper/CacheWrapper.php
index bf0d12ba2e..da0a1b54e7 100644
--- a/lib/private/Files/Cache/Wrapper/CacheWrapper.php
+++ b/lib/private/Files/Cache/Wrapper/CacheWrapper.php
@@ -187,6 +187,12 @@ class CacheWrapper extends Cache {
$this->getCache()->move($source, $target);
}
+ protected function getMoveInfo($path) {
+ /** @var Cache $cache */
+ $cache = $this->getCache();
+ return $cache->getMoveInfo($path);
+ }
+
public function moveFromCache(ICache $sourceCache, $sourcePath, $targetPath) {
$this->getCache()->moveFromCache($sourceCache, $sourcePath, $targetPath);
}
diff --git a/lib/private/Files/FileInfo.php b/lib/private/Files/FileInfo.php
index 4c38ba769d..53f73f0f95 100644
--- a/lib/private/Files/FileInfo.php
+++ b/lib/private/Files/FileInfo.php
@@ -175,7 +175,7 @@ class FileInfo implements \OCP\Files\FileInfo, \ArrayAccess {
* @return string
*/
public function getName() {
- return basename($this->getPath());
+ return isset($this->data['name']) ? $this->data['name'] : basename($this->getPath());
}
/**
diff --git a/lib/private/Files/Filesystem.php b/lib/private/Files/Filesystem.php
index ba9c85deee..404ea4ed80 100644
--- a/lib/private/Files/Filesystem.php
+++ b/lib/private/Files/Filesystem.php
@@ -65,6 +65,7 @@ use OC\Files\Storage\StorageFactory;
use OC\Lockdown\Filesystem\NullStorage;
use OCP\Files\Config\IMountProvider;
use OCP\Files\NotFoundException;
+use OCP\Files\Storage\IStorageFactory;
use OCP\ILogger;
use OCP\IUserManager;
@@ -246,11 +247,11 @@ class Filesystem {
/**
* Returns the storage factory
*
- * @return \OCP\Files\Storage\IStorageFactory
+ * @return IStorageFactory
*/
public static function getLoader() {
if (!self::$loader) {
- self::$loader = new StorageFactory();
+ self::$loader = \OC::$server->query(IStorageFactory::class);
}
return self::$loader;
}
diff --git a/lib/private/Server.php b/lib/private/Server.php
index 5ea1b69739..e0bd808428 100644
--- a/lib/private/Server.php
+++ b/lib/private/Server.php
@@ -80,6 +80,7 @@ use OC\Files\Mount\ObjectHomeMountProvider;
use OC\Files\Node\HookConnector;
use OC\Files\Node\LazyRoot;
use OC\Files\Node\Root;
+use OC\Files\Storage\StorageFactory;
use OC\Files\View;
use OC\Http\Client\ClientService;
use OC\IntegrityCheck\Checker;
@@ -135,6 +136,7 @@ use OCP\Federation\ICloudFederationProviderManager;
use OCP\Federation\ICloudIdManager;
use OCP\Authentication\LoginCredentials\IStore;
use OCP\Files\NotFoundException;
+use OCP\Files\Storage\IStorageFactory;
use OCP\GlobalScale\IConfig;
use OCP\ICacheFactory;
use OCP\IDBConnection;
@@ -1174,6 +1176,10 @@ class Server extends ServerContainer implements IServerContainer {
});
$this->registerAlias(IContactsStore::class, ContactsStore::class);
+ $this->registerService(IStorageFactory::class, function() {
+ return new StorageFactory();
+ });
+
$this->registerAlias(IDashboardManager::class, Dashboard\DashboardManager::class);
$this->connectDispatcher();
@@ -2024,4 +2030,11 @@ class Server extends ServerContainer implements IServerContainer {
public function getRemoteInstanceFactory() {
return $this->query(IInstanceFactory::class);
}
+
+ /**
+ * @return IStorageFactory
+ */
+ public function getStorageFactory() {
+ return $this->query(IStorageFactory::class);
+ }
}
diff --git a/lib/public/IServerContainer.php b/lib/public/IServerContainer.php
index 639487660b..a3e494479b 100644
--- a/lib/public/IServerContainer.php
+++ b/lib/public/IServerContainer.php
@@ -584,4 +584,10 @@ interface IServerContainer extends IContainer {
* @since 13.0.0
*/
public function getRemoteInstanceFactory();
+
+ /**
+ * @return \OCP\Files\Storage\IStorageFactory
+ * @since 15.0.0
+ */
+ public function getStorageFactory();
}
diff --git a/resources/app-info.xsd b/resources/app-info.xsd
index 5c2ab89e21..fa06752c01 100644
--- a/resources/app-info.xsd
+++ b/resources/app-info.xsd
@@ -61,6 +61,8 @@
maxOccurs="1" />
+
@@ -653,11 +655,25 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-