Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/nextcloud/groupfolders.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--appinfo/info.xml4
-rw-r--r--lib/AppInfo/Application.php27
-rw-r--r--lib/Folder/FolderManager.php34
-rw-r--r--lib/Migration/Version104000Date20180918132853.php59
-rw-r--r--lib/Mount/GroupFolderStorage.php39
-rw-r--r--lib/Mount/MountProvider.php35
-rw-r--r--lib/Trash/GroupTrashItem.php33
-rw-r--r--lib/Trash/TrashBackend.php237
-rw-r--r--lib/Trash/TrashManager.php63
9 files changed, 498 insertions, 33 deletions
diff --git a/appinfo/info.xml b/appinfo/info.xml
index d8566944..0800bbaf 100644
--- a/appinfo/info.xml
+++ b/appinfo/info.xml
@@ -36,4 +36,8 @@ Note: encrypting the contents of group folders is currently not supported.]]></d
<admin>OCA\GroupFolders\Settings\Admin</admin>
<admin-section>OCA\GroupFolders\Settings\Section</admin-section>
</settings>
+
+ <trash>
+ <backend for="OCA\GroupFolders\Mount\GroupFolderStorage">OCA\GroupFolders\Trash\TrashBackend</backend>
+ </trash>
</info>
diff --git a/lib/AppInfo/Application.php b/lib/AppInfo/Application.php
index 98c3e3aa..7b41a950 100644
--- a/lib/AppInfo/Application.php
+++ b/lib/AppInfo/Application.php
@@ -24,6 +24,8 @@ namespace OCA\GroupFolders\AppInfo;
use OC\Group\Manager;
use OCA\GroupFolders\Folder\FolderManager;
use OCA\GroupFolders\Mount\MountProvider;
+use OCA\GroupFolders\Trash\TrashBackend;
+use OCA\GroupFolders\Trash\TrashManager;
use OCP\AppFramework\App;
use OCP\AppFramework\IAppContainer;
use OCP\Files\NotFoundException;
@@ -35,25 +37,36 @@ class Application extends App {
parent::__construct('groupfolders', $urlParams);
$container = $this->getContainer();
- $container->registerService(FolderManager::class, function (IAppContainer $c) {
- return new FolderManager($c->getServer()->getDatabaseConnection());
+
+ $container->registerService('GroupAppFolder', function(IAppContainer $c) {
+ try {
+ return $c->getServer()->getRootFolder()->get('__groupfolders');
+ } catch (NotFoundException $e) {
+ return $c->getServer()->getRootFolder()->newFolder('__groupfolders');
+ }
});
$container->registerService(MountProvider::class, function (IAppContainer $c) {
$rootProvider = function () use ($c) {
- try {
- return $c->getServer()->getRootFolder()->get('__groupfolders');
- } catch (NotFoundException $e) {
- return $c->getServer()->getRootFolder()->newFolder('__groupfolders');
- }
+ return $c->query('GroupAppFolder');
};
return new MountProvider(
$c->getServer()->getGroupManager(),
$c->query(FolderManager::class),
+ $c->getServer()->getStorageFactory(),
$rootProvider
);
});
+
+ $container->registerService(TrashBackend::class, function(IAppContainer $c) {
+ return new TrashBackend(
+ $c->query(FolderManager::class),
+ $c->query(TrashManager::class),
+ $c->query('GroupAppFolder'),
+ $c->query(MountProvider::class)
+ );
+ });
}
public function register() {
diff --git a/lib/Folder/FolderManager.php b/lib/Folder/FolderManager.php
index a6a779ac..47de8b48 100644
--- a/lib/Folder/FolderManager.php
+++ b/lib/Folder/FolderManager.php
@@ -24,16 +24,19 @@ namespace OCA\GroupFolders\Folder;
use OCP\Constants;
use OCP\DB\QueryBuilder\IQueryBuilder;
use OCP\IDBConnection;
+use OCP\IGroupManager;
+use OCP\IUser;
class FolderManager {
/** @var IDBConnection */
private $connection;
- /**
- * @param IDBConnection $connection
- */
- public function __construct(IDBConnection $connection) {
+ /** @var IGroupManager */
+ private $groupManager;
+
+ public function __construct(IDBConnection $connection, IGroupManager $groupManager) {
$this->connection = $connection;
+ $this->groupManager = $groupManager;
}
public function getAllFolders() {
@@ -252,4 +255,27 @@ class FolderManager {
->where($query->expr()->eq('group_id', $query->createNamedParameter($groupId)));
$query->execute();
}
+
+ /**
+ * @param IUser $user
+ * @return array[]
+ */
+ public function getFoldersForUser(IUser $user) {
+ $groups = $this->groupManager->getUserGroupIds($user);
+ $folders = array_reduce($groups, function ($folders, $groupId) {
+ return array_merge($folders, $this->getFoldersForGroup($groupId));
+ }, []);
+
+ $mergedFolders = [];
+ foreach ($folders as $folder) {
+ $id = $folder['folder_id'];
+ if (isset($mergedFolders[$id])) {
+ $mergedFolders[$id]['permissions'] |= $folder['permissions'];
+ } else {
+ $mergedFolders[$id] = $folder;
+ }
+ }
+
+ return array_values($mergedFolders);
+ }
}
diff --git a/lib/Migration/Version104000Date20180918132853.php b/lib/Migration/Version104000Date20180918132853.php
new file mode 100644
index 00000000..4a0f2549
--- /dev/null
+++ b/lib/Migration/Version104000Date20180918132853.php
@@ -0,0 +1,59 @@
+<?php
+
+declare(strict_types=1);
+
+namespace OCA\GroupFolders\Migration;
+
+use Closure;
+use OCP\DB\ISchemaWrapper;
+use OCP\Migration\SimpleMigrationStep;
+use OCP\Migration\IOutput;
+
+/**
+ * Auto-generated migration step: Please modify to your needs!
+ */
+class Version104000Date20180918132853 extends SimpleMigrationStep {
+ public function name(): string {
+ return 'Add group_folders_trash table';
+ }
+
+ public function description(): string {
+ return 'Adds table to store trashbin information for group folders';
+ }
+
+ public function changeSchema(IOutput $output, Closure $schemaClosure, array $options) {
+ /** @var ISchemaWrapper $schema */
+ $schema = $schemaClosure();
+
+ if (!$schema->hasTable('group_folders_trash')) {
+ $table = $schema->createTable('group_folders_trash');
+ $table->addColumn('trash_id', 'bigint', [
+ 'autoincrement' => true,
+ 'notnull' => true,
+ 'length' => 6,
+ ]);
+ $table->addColumn('name', 'string', [
+ 'notnull' => true,
+ 'length' => 250,
+ ]);
+ $table->addColumn('original_location', 'string', [
+ 'notnull' => true,
+ 'length' => 4000,
+ ]);
+ $table->addColumn('deleted_time', 'bigint', [
+ 'notnull' => true,
+ 'length' => 6,
+ ]);
+ $table->addColumn('folder_id', 'bigint', [
+ 'notnull' => true,
+ 'length' => 6,
+ ]);
+ $table->setPrimaryKey(['trash_id']);
+ $table->addIndex(['folder_id'], 'groups_folder_trash_folder');
+ $table->addIndex(['folder_id', 'name'], 'groups_folder_name');
+ $table->addUniqueIndex(['folder_id', 'name', 'deleted_time'], 'groups_folder_trash_unique');
+ }
+
+ return $schema;
+ }
+}
diff --git a/lib/Mount/GroupFolderStorage.php b/lib/Mount/GroupFolderStorage.php
new file mode 100644
index 00000000..ce278dde
--- /dev/null
+++ b/lib/Mount/GroupFolderStorage.php
@@ -0,0 +1,39 @@
+<?php
+/**
+ * @copyright Copyright (c) 2018 Robin Appelman <robin@icewind.nl>
+ *
+ * @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\GroupFolders\Mount;
+
+
+use OC\Files\Storage\Wrapper\Quota;
+
+class GroupFolderStorage extends Quota {
+ /** @var int */
+ private $folderId;
+
+ public function __construct($parameters) {
+ parent::__construct($parameters);
+ $this->folderId = $parameters['folder_id'];
+ }
+
+ public function getFolderId() {
+ return $this->folderId;
+ }
+}
diff --git a/lib/Mount/MountProvider.php b/lib/Mount/MountProvider.php
index df913591..e3719888 100644
--- a/lib/Mount/MountProvider.php
+++ b/lib/Mount/MountProvider.php
@@ -23,7 +23,6 @@ namespace OCA\GroupFolders\Mount;
use OC\Files\Storage\Wrapper\Jail;
use OC\Files\Storage\Wrapper\PermissionsMask;
-use OC\Files\Storage\Wrapper\Quota;
use OCA\GroupFolders\Folder\FolderManager;
use OCP\Files\Config\IMountProvider;
use OCP\Files\Folder;
@@ -46,34 +45,23 @@ class MountProvider implements IMountProvider {
/** @var FolderManager */
private $folderManager;
+ /** @var IStorageFactory */
+ private $storageFactory;
+
/**
* @param IGroupManager $groupProvider
* @param FolderManager $folderManager
* @param callable $rootProvider
*/
- public function __construct(IGroupManager $groupProvider, FolderManager $folderManager, $rootProvider) {
+ public function __construct(IGroupManager $groupProvider, FolderManager $folderManager, IStorageFactory $storageFactory, callable $rootProvider) {
$this->groupProvider = $groupProvider;
$this->folderManager = $folderManager;
+ $this->storageFactory = $storageFactory;
$this->rootProvider = $rootProvider;
}
public function getFoldersForUser(IUser $user) {
- $groups = $this->groupProvider->getUserGroupIds($user);
- $folders = array_reduce($groups, function ($folders, $groupId) {
- return array_merge($folders, $this->folderManager->getFoldersForGroup($groupId));
- }, []);
-
- $mergedFolders = [];
- foreach ($folders as $folder) {
- $id = $folder['folder_id'];
- if (isset($mergedFolders[$id])) {
- $mergedFolders[$id]['permissions'] |= $folder['permissions'];
- } else {
- $mergedFolders[$id] = $folder;
- }
- }
-
- return array_values($mergedFolders);
+ return $this->folderManager->getFoldersForUser($user);
}
public function getMountsForUser(IUser $user, IStorageFactory $loader) {
@@ -91,7 +79,7 @@ class MountProvider implements IMountProvider {
* @param int $quota
* @return IMountPoint
*/
- private function getMount($id, $mountPoint, $permissions, $quota) {
+ public function getMount($id, $mountPoint, $permissions, $quota) {
$folder = $this->getFolder($id);
$baseStorage = new Jail([
'storage' => $folder->getStorage(),
@@ -101,14 +89,17 @@ class MountProvider implements IMountProvider {
'storage' => $baseStorage,
'mask' => $permissions
]);
- $quotaStorage = new Quota([
+ $quotaStorage = new GroupFolderStorage([
'storage' => $maskedStore,
- 'quota' => $quota
+ 'quota' => $quota,
+ 'folder_id' => $id
]);
return new GroupMountPoint(
$quotaStorage,
- $mountPoint
+ $mountPoint,
+ null,
+ $this->storageFactory
);
}
diff --git a/lib/Trash/GroupTrashItem.php b/lib/Trash/GroupTrashItem.php
new file mode 100644
index 00000000..8bb7568f
--- /dev/null
+++ b/lib/Trash/GroupTrashItem.php
@@ -0,0 +1,33 @@
+<?php
+/**
+ * @copyright Copyright (c) 2018 Robin Appelman <robin@icewind.nl>
+ *
+ * @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\GroupFolders\Trash;
+
+use OCA\Files_Trashbin\Trash\TrashItem;
+
+class GroupTrashItem extends TrashItem {
+ /** @var Fold */
+ private $groupFolder;
+
+ public function isRootItem(): bool {
+ return substr_count($this->getTrashPath(), '/') === 2;
+ }
+}
diff --git a/lib/Trash/TrashBackend.php b/lib/Trash/TrashBackend.php
new file mode 100644
index 00000000..efd3e1b3
--- /dev/null
+++ b/lib/Trash/TrashBackend.php
@@ -0,0 +1,237 @@
+<?php
+/**
+ * @copyright Copyright (c) 2018 Robin Appelman <robin@icewind.nl>
+ *
+ * @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\GroupFolders\Trash;
+
+use OCA\Files_Trashbin\Trash\ITrashBackend;
+use OCA\Files_Trashbin\Trash\ITrashItem;
+use OCA\Files_Trashbin\Trash\TrashItem;
+use OCA\GroupFolders\Folder\FolderManager;
+use OCA\GroupFolders\Mount\GroupFolderStorage;
+use OCA\GroupFolders\Mount\MountProvider;
+use OCP\Files\Folder;
+use OCP\Files\Node;
+use OCP\Files\NotFoundException;
+use OCP\Files\Storage\IStorage;
+use OCP\IUser;
+
+class TrashBackend implements ITrashBackend {
+ /** @var FolderManager */
+ private $folderManager;
+
+ /** @var TrashManager */
+ private $trashManager;
+
+ /** @var Folder */
+ private $appFolder;
+
+ /** @var MountProvider */
+ private $mountProvider;
+
+ public function __construct(
+ FolderManager $folderManager,
+ TrashManager $trashManager,
+ Folder $appFolder,
+ MountProvider $mountProvider
+ ) {
+ $this->folderManager = $folderManager;
+ $this->trashManager = $trashManager;
+ $this->appFolder = $appFolder;
+ $this->mountProvider = $mountProvider;
+ }
+
+ public function listTrashRoot(IUser $user): array {
+ $folders = $this->folderManager->getFoldersForUser($user);
+ return $this->getTrashForFolders($user, array_map(function (array $folder) {
+ return $folder['folder_id'];
+ }, $folders));
+ }
+
+ public function listTrashFolder(ITrashItem $trashItem): array {
+ $user = $trashItem->getUser();
+ $folder = $this->getNodeForTrashItem($user, $trashItem);
+ if (!$folder instanceof Folder) {
+ return [];
+ }
+ $content = $folder->getDirectoryListing();
+ return array_map(function (Node $node) use ($trashItem, $user) {
+ return new GroupTrashItem(
+ $this,
+ $trashItem->getOriginalLocation() . '/' . $node->getName(),
+ $trashItem->getDeletedTime(),
+ $trashItem->getTrashPath() . '/' . $node->getName(),
+ $node,
+ $user
+ );
+ }, $content);
+ }
+
+ public function restoreItem(ITrashItem $item) {
+ $user = $item->getUser();
+ list(, $folderId) = explode('/', $item->getTrashPath());
+ $node = $this->getNodeForTrashItem($user, $item);
+ if ($node === null) {
+ throw new NotFoundException();
+ }
+
+ $trashStorage = $node->getStorage();
+ $targetFolder = $this->mountProvider->getFolder($folderId);
+ $originalLocation = $item->getOriginalLocation();
+ $parent = dirname($originalLocation);
+ if ($parent === '.') {
+ $parent = '';
+ }
+ if ($parent !== '' && !$targetFolder->nodeExists($parent)) {
+ $originalLocation = basename($originalLocation);
+ }
+ $targetLocation = $targetFolder->getInternalPath() . '/' . $originalLocation;
+ $targetFolder->getStorage()->moveFromStorage($trashStorage, $node->getInternalPath(), $targetLocation);
+ $targetFolder->getStorage()->getCache()->moveFromCache($trashStorage->getCache(), $node->getInternalPath(), $targetLocation);
+ $this->trashManager->removeItem($folderId, $item->getName(), $item->getDeletedTime());
+ }
+
+ public function removeItem(ITrashItem $item) {
+ $user = $item->getUser();
+ list(, $folderId) = explode('/', $item->getTrashPath());
+ $node = $this->getNodeForTrashItem($user, $item);
+ if ($node === null) {
+ throw new NotFoundException();
+ }
+ $node->getStorage()->unlink($node->getInternalPath());
+ $node->getStorage()->getCache()->remove($node->getInternalPath());
+ if ($item->isRootItem()) {
+ $this->trashManager->removeItem($folderId, $item->getName(), $item->getDeletedTime());
+ }
+ }
+
+ public function moveToTrash(IStorage $storage, string $internalPath): bool {
+ if ($storage->instanceOfStorage(GroupFolderStorage::class)) {
+ /** @var GroupFolderStorage $storage */
+ $name = basename($internalPath);
+ $folderId = $storage->getFolderId();
+ $trashFolder = $this->getTrashFolder($folderId);
+ $trashStorage = $trashFolder->getStorage();
+ $time = time();
+ $trashName = $name . '.d' . $time;
+ $targetInternalPath = $trashFolder->getInternalPath() . '/' . $trashName;
+ $trashStorage->moveFromStorage($storage, $internalPath, $targetInternalPath);
+ $this->trashManager->addTrashItem($folderId, $name, $time, $internalPath);
+ $trashStorage->getCache()->moveFromCache($storage->getCache(), $internalPath, $targetInternalPath);
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ private function userHasAccessToFolder(IUser $user, int $folderId) {
+ $folders = $this->folderManager->getFoldersForUser($user);
+ $folderIds = array_map(function (array $folder) {
+ return $folder['folder_id'];
+ }, $folders);
+ return in_array($folderId, $folderIds);
+ }
+
+ /**
+ * @param IUser $user
+ * @param ITrashItem $trashItem
+ * @return null|Node
+ */
+ private function getNodeForTrashItem(IUser $user, ITrashItem $trashItem) {
+ list(, $folderId, $path) = explode('/', $trashItem->getTrashPath(), 3);
+ $folders = $this->folderManager->getFoldersForUser($user);
+ foreach ($folders as $groupFolder) {
+ if ($groupFolder['folder_id'] === (int)$folderId) {
+ $trashRoot = $this->getTrashFolder($folderId);
+ try {
+ $node = $trashRoot->get($path);
+ return $node;
+ } catch (NotFoundException $e) {
+ return null;
+ }
+ }
+ }
+ return null;
+ }
+
+ private function getTrashFolder($folderId) {
+ try {
+ return $this->appFolder->get('trash/' . $folderId);
+ } catch (NotFoundException $e) {
+ /** @var Folder $trashRoot */
+ $trashRoot = $this->appFolder->nodeExists('trash') ? $this->appFolder->get('trash') : $this->appFolder->newFolder('trash');
+ return $trashRoot->newFolder($folderId);
+ }
+ }
+
+ private function getTrashForFolders(IUser $user, array $folderIds) {
+ $rows = $this->trashManager->listTrashForFolders($folderIds);
+ $indexedRows = [];
+ foreach ($rows as $row) {
+ $key = $row['folder_id'] . '/' . $row['name'] . '/' . $row['deleted_time'];
+ $indexedRows[$key] = $row;
+ }
+ $items = [];
+ foreach ($folderIds as $folderId) {
+ $trashFolder = $this->getTrashFolder($folderId);
+ $content = $trashFolder->getDirectoryListing();
+ foreach ($content as $item) {
+ $pathParts = pathinfo($item->getName());
+ $timestamp = substr($pathParts['extension'], 1);
+ $name = $pathParts['filename'];
+ $key = $folderId . '/' . $name . '/' . $timestamp;
+ $originalLocation = isset($indexedRows[$key]) ? $indexedRows[$key]['original_location'] : '';
+ $info = $item->getFileInfo();
+ $info['name'] = $name;
+ $items[] = new GroupTrashItem(
+ $this,
+ $originalLocation,
+ $timestamp,
+ '/' . $folderId . '/' . $item->getName(),
+ $info,
+ $user
+ );
+ }
+ }
+ return $items;
+ }
+
+ public function getTrashNodeById(IUser $user, int $fileId) {
+ try {
+ /** @var Folder $trashFolder */
+ $trashFolder = $this->appFolder->get('trash');
+ $storage = $this->appFolder->getStorage();
+ $path = $storage->getCache()->getPathById($fileId);
+ if (!$path) {
+ return null;
+ }
+ $absolutePath = $this->appFolder->getMountPoint()->getMountPoint() . $path;
+ $relativePath = $trashFolder->getRelativePath($absolutePath);
+ list(, $folderId) = explode('/', $relativePath);
+ if ($this->userHasAccessToFolder($user, (int)$folderId)) {
+ return $trashFolder->get($relativePath);
+ } else {
+ return null;
+ }
+ } catch (NotFoundException $e) {
+ return null;
+ }
+ }
+}
diff --git a/lib/Trash/TrashManager.php b/lib/Trash/TrashManager.php
new file mode 100644
index 00000000..ef5e8504
--- /dev/null
+++ b/lib/Trash/TrashManager.php
@@ -0,0 +1,63 @@
+<?php
+/**
+ * @copyright Copyright (c) 2018 Robin Appelman <robin@icewind.nl>
+ *
+ * @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\GroupFolders\Trash;
+
+use OCP\DB\QueryBuilder\IQueryBuilder;
+use OCP\IDBConnection;
+
+class TrashManager {
+ /** @var IDBConnection */
+ private $connection;
+
+ public function __construct(IDBConnection $connection) {
+ $this->connection = $connection;
+ }
+
+ public function listTrashForFolders(array $folderIds): array {
+ $query = $this->connection->getQueryBuilder();
+ $query->select(['trash_id', 'name', 'deleted_time', 'original_location', 'folder_id'])
+ ->from('group_folders_trash')
+ ->where($query->expr()->in('folder_id', $query->createNamedParameter($folderIds, IQueryBuilder::PARAM_INT_ARRAY)));
+ return $query->execute()->fetchAll();
+ }
+
+ public function addTrashItem(int $folderId, string $name, int $deletedTime, string $originalLocation) {
+ $query = $this->connection->getQueryBuilder();
+ $query->insert('group_folders_trash')
+ ->values([
+ 'folder_id' => $query->createNamedParameter($folderId, IQueryBuilder::PARAM_INT),
+ 'name' => $query->createNamedParameter($name),
+ 'deleted_time' => $query->createNamedParameter($deletedTime, IQueryBuilder::PARAM_INT),
+ 'original_location' => $query->createNamedParameter($originalLocation),
+ ]);
+ $query->execute();
+ }
+
+ public function removeItem(int $folderId, string $name, int $deletedTime) {
+ $query = $this->connection->getQueryBuilder();
+ $query->delete('group_folders_trash')
+ ->where($query->expr()->eq('folder_id', $query->createNamedParameter($folderId, IQueryBuilder::PARAM_INT)))
+ ->andWhere($query->expr()->eq('name', $query->createNamedParameter($name)))
+ ->andWhere($query->expr()->eq('deleted_time', $query->createNamedParameter($deletedTime, IQueryBuilder::PARAM_INT)));
+ $query->execute();
+ }
+}