folderMapper = $folderMapper; $this->treeMapper = $treeMapper; $this->shareMapper = $shareMapper; $this->sharedFolderMapper = $sharedFolderMapper; $this->publicFolderMapper = $publicFolderMapper; $this->groupManager = $groupManager; $this->htmlImporter = $htmlImporter; $this->l10n = $l10n; $this->eventDispatcher = $eventDispatcher; } public function getRootFolder(string $userId) : Folder { return $this->folderMapper->findRootFolder($userId); } /** * @throws DoesNotExistException * @throws MultipleObjectsReturnedException */ public function findById(int $id) : Folder { return $this->folderMapper->find($id); } /** * @param $title * @param $parentFolderId * @return Folder * @throws DoesNotExistException * @throws MultipleObjectsReturnedException * @throws UnsupportedOperation */ public function create($title, $parentFolderId): Folder { /** * @var $parentFolder Folder */ $parentFolder = $this->folderMapper->find($parentFolderId); $folder = new Folder(); $folder->setTitle($title); $folder->setUserId($parentFolder->getUserId()); $this->folderMapper->insert($folder); $this->treeMapper->move(TreeMapper::TYPE_FOLDER, $folder->getId(), $parentFolderId); $this->eventDispatcher->dispatch(CreateEvent::class, new CreateEvent(TreeMapper::TYPE_FOLDER, $folder->getId())); return $folder; } /** * @param Folder $folder * @param $userId * @return Share|null */ public function findShareByDescendantAndUser(Folder $folder, $userId): ?Share { $shares = $this->shareMapper->findByOwnerAndUser($folder->getUserId(), $userId); foreach ($shares as $share) { if ($share->getFolderId() === $folder->getId() || $this->treeMapper->hasDescendant($share->getFolderId(), TreeMapper::TYPE_FOLDER, $folder->getId())) { return $share; } } return null; } /** * @param $userId * @param $folderId * @return Folder|SharedFolder * @throws DoesNotExistException * @throws MultipleObjectsReturnedException */ public function findSharedFolderOrFolder($userId, $folderId) { $folder = $this->folderMapper->find($folderId); if ($userId === null || $userId === $folder->getUserId()) { return $folder; } try { /** * @var $sharedFolder SharedFolder */ $sharedFolder = $this->sharedFolderMapper->findByFolderAndUser($folder->getId(), $userId); return $sharedFolder; } catch (DoesNotExistException $e) { // noop } return $folder; } /** * @param $userId * @param $folderId * @throws DoesNotExistException * @throws MultipleObjectsReturnedException * @throws UnsupportedOperation */ public function deleteSharedFolderOrFolder($userId, $folderId): void { /** * @var $folder Folder */ $folder = $this->folderMapper->find($folderId); if ($userId === null || $userId === $folder->getUserId()) { $this->treeMapper->deleteEntry(TreeMapper::TYPE_FOLDER, $folder->getId()); return; } try { // folder is shared folder /** * @var $sharedFolder SharedFolder */ $sharedFolder = $this->sharedFolderMapper->findByFolderAndUser($folder->getId(), $userId); $this->treeMapper->deleteEntry(TreeMapper::TYPE_SHARE, $sharedFolder->getId()); return; } catch (DoesNotExistException $e) { // noop } // folder is subfolder of share $this->treeMapper->deleteEntry(TreeMapper::TYPE_FOLDER, $folder->getId()); $this->folderMapper->delete($folder); } /** * @param $shareId * @throws DoesNotExistException * @throws MultipleObjectsReturnedException * @throws UnsupportedOperation */ public function deleteShare($shareId): void { $this->treeMapper->deleteShare($shareId); } /** * @param string $userId * @param int $folderId * @param string $title * @param int $parent_folder * @return Folder|SharedFolder * @throws DoesNotExistException * @throws MultipleObjectsReturnedException * @throws UnsupportedOperation * @throws \OCA\Bookmarks\Exception\UrlParseError */ public function updateSharedFolderOrFolder($userId, $folderId, $title = null, $parent_folder = null) { /** * @var $folder Folder */ $folder = $this->folderMapper->find($folderId); if ($userId !== null || $userId !== $folder->getUserId()) { try { // folder is shared folder $sharedFolder = $this->sharedFolderMapper->findByFolderAndUser($folder->getId(), $userId); if (isset($title)) { $sharedFolder->setTitle($title); $this->sharedFolderMapper->update($sharedFolder); } if (isset($parent_folder)) { $this->treeMapper->move(TreeMapper::TYPE_SHARE, $sharedFolder->getId(), $parent_folder); } return $sharedFolder; } catch (DoesNotExistException $e) { // noop } } if (isset($title)) { $folder->setTitle($title); $this->folderMapper->update($folder); $this->eventDispatcher->dispatch(UpdateEvent::class, new UpdateEvent(TreeMapper::TYPE_FOLDER, $folder->getId())); } if (isset($parent_folder)) { $parentFolder = $this->folderMapper->find($parent_folder); if ($parentFolder->getUserId() !== $folder->getUserId()) { if ($this->treeMapper->containsFoldersSharedToUser($folder, $parentFolder->getUserId())) { throw new UnsupportedOperation('Cannot move a folder by user A into a folder shared from user B if it already contains folders shared with B.'); } $this->treeMapper->changeFolderOwner($folder, $parentFolder->getUserId()); } $this->treeMapper->move(TreeMapper::TYPE_FOLDER, $folder->getId(), $parent_folder); } return $folder; } /** * @param $folderId * @return string * @throws DoesNotExistException * @throws MultipleObjectsReturnedException */ public function createFolderPublicToken($folderId): string { $this->folderMapper->find($folderId); try { /** @var PublicFolder $publicFolder */ $publicFolder = $this->publicFolderMapper->findByFolder($folderId); } catch (DoesNotExistException $e) { $publicFolder = new PublicFolder(); $publicFolder->setFolderId($folderId); $this->publicFolderMapper->insert($publicFolder); } return $publicFolder->getId(); } /** * @param $folderId * @throws DoesNotExistException * @throws MultipleObjectsReturnedException */ public function deleteFolderPublicToken($folderId): void { $publicFolder = $this->publicFolderMapper->findByFolder($folderId); $this->publicFolderMapper->delete($publicFolder); } /** * @param $folderId * @param $participant * @param int $type * @param bool $canWrite * @param bool $canShare * @return Share * @throws DoesNotExistException * @throws MultipleObjectsReturnedException * @throws UnsupportedOperation */ public function createShare($folderId, $participant, int $type, $canWrite = false, $canShare = false): Share { /** * @var $folder Folder */ $folder = $this->folderMapper->find($folderId); $share = new Share(); $share->setFolderId($folderId); $share->setOwner($folder->getUserId()); $share->setParticipant($participant); $share->setType($type); $share->setCanWrite($canWrite); $share->setCanShare($canShare); if ($type === IShare::TYPE_USER) { if ($participant === $folder->getUserId()) { throw new UnsupportedOperation('Cannot share with oneself'); } // If this folder already contains a share from this user, don't share it back. Would cause a loop. if ($this->treeMapper->containsSharedFolderFromUser($folder, $participant)) { throw new UnsupportedOperation('Cannot share this with user that shared some of its contents'); } $this->shareMapper->insert($share); $this->addSharedFolder($share, $folder, $participant); } elseif ($type === IShare::TYPE_GROUP) { $group = $this->groupManager->get($participant); if ($group === null) { throw new DoesNotExistException('Group does not exist'); } $this->shareMapper->insert($share); $users = $group->getUsers(); foreach ($users as $user) { // If I'm part of the group, don't add it twice if ($user->getUID() === $folder->getUserId()) { continue; } // If this folder is already shared with the user, don't add it twice. if ($this->treeMapper->isFolderSharedWithUser($folder->getId(), $user->getUID())) { continue; } // If this folder already contains a share from this user, don't share it back. Would cause a loop. if ($this->treeMapper->containsSharedFolderFromUser($folder, $user->getUID())) { continue; } $this->addSharedFolder($share, $folder, $user->getUID()); } } else { throw new UnsupportedOperation('Only users and groups are allowed as participants'); } return $share; } /** * @param Share $share * @param Folder $folder * @param string $userId * @throws MultipleObjectsReturnedException * @throws UnsupportedOperation */ public function addSharedFolder(Share $share, Folder $folder, string $userId): void { $sharedFolder = new SharedFolder(); $sharedFolder->setTitle($folder->getTitle()); $sharedFolder->setFolderId($folder->getId()); $sharedFolder->setUserId($userId); $rootFolder = $this->folderMapper->findRootFolder($userId); $sharedFolder = $this->sharedFolderMapper->insert($sharedFolder); $this->sharedFolderMapper->mount($sharedFolder->getId(), $share->getId()); $this->treeMapper->move(TreeMapper::TYPE_SHARE, $sharedFolder->getId(), $rootFolder->getId()); } /** * @param string $userId * @param $file * @param int $folder * @return array * @throws DoesNotExistException * @throws MultipleObjectsReturnedException * @throws AlreadyExistsError * @throws HtmlParseError * @throws UnauthorizedAccessError * @throws UserLimitExceededError */ public function importFile(string $userId, $file, $folder): array { $importFolderId = $folder; return $this->htmlImporter->importFile($userId, $file, $importFolderId); } }