From a0e91fbf7b4b69d9239bafb866dd5c7362a5b2c6 Mon Sep 17 00:00:00 2001 From: Jonathan Treffler Date: Wed, 24 Jan 2024 20:57:47 +0100 Subject: [PATCH] added DiffTaskResultService, including revert logic --- lib/Exceptions/AlreadyRevertedException.php | 9 ++ .../ChangesMadeSinceDiffException.php | 9 ++ lib/Service/DiffTaskResultService.php | 145 ++++++++++++++++++ 3 files changed, 163 insertions(+) create mode 100644 lib/Exceptions/AlreadyRevertedException.php create mode 100644 lib/Exceptions/ChangesMadeSinceDiffException.php create mode 100644 lib/Service/DiffTaskResultService.php diff --git a/lib/Exceptions/AlreadyRevertedException.php b/lib/Exceptions/AlreadyRevertedException.php new file mode 100644 index 0000000..24a2ff7 --- /dev/null +++ b/lib/Exceptions/AlreadyRevertedException.php @@ -0,0 +1,9 @@ +mapper = $mapper; + $this->diffTaskMapper = $diffTaskMapper; + $this->pathManager = $pathManager; + } + + /** + * @return DiffTaskResult[] + */ + public function findAll(int $taskId): array { + return $this->mapper->findAll($taskId); + } + + /** + * @return never + */ + private function handleException ($e, $criteria) { + if ($e instanceof DoesNotExistException || + $e instanceof MultipleObjectsReturnedException) { + throw new NotFoundException($e->getMessage(), $criteria); + } else { + throw $e; + } + } + + public function find(int $id): DiffTaskResult { + try { + return $this->mapper->find($id); + } catch(Exception $e) { + $this->handleException($e, ["id" => $id]); + } + } + + public function revert(int $id, string $userId) { + $diffTaskResult = $this->find($id); + + if($diffTaskResult->getReverted()) { + throw new AlreadyRevertedException; + } + + $taskId = $diffTaskResult->getTaskId(); + $diffTask = $this->diffTaskMapper->find($taskId, $userId); + + $snapshotPath = $this->pathManager->getGroupFolderSnapshotDirectory($diffTask->getGroupfolderId(), $diffTask->getRelativePath(), $diffTask->getSnapshotId()); + + $gruenerFolder = $this->pathManager->getGroupfolderMountById($diffTask->getGroupfolderId())->get($diffTask->getRelativePath()); + + switch($diffTaskResult->getType()) { + case "CREATION": + $currentFile = $this->getSubfolderMustExist($gruenerFolder, $diffTaskResult->getCurrentPath()); + $currentFile->delete(); + break; + case "RENAME": + $currentFile = $this->getSubfolderMustExist($gruenerFolder, $diffTaskResult->getCurrentPath()); + $beforeDirectory = $this->getOrCreateSubdirectoryByFilepath($gruenerFolder, $diffTaskResult->getBeforePath()); + + $currentFile->move($beforeDirectory->getPath() . DIRECTORY_SEPARATOR . basename($diffTaskResult->getBeforePath())); + break; + case "DELETION": + $beforeFileFilesystemPath = $snapshotPath . DIRECTORY_SEPARATOR . $diffTaskResult->getBeforePath(); + + $beforeDirectory = $this->getOrCreateSubdirectoryByFilepath($gruenerFolder, $diffTaskResult->getBeforePath()); + $restoredFile = $beforeDirectory->newFile(basename($diffTaskResult->getBeforePath())); + + $this->copyFilesystemFileToNextcloudFile($beforeFileFilesystemPath, $restoredFile); + break; + case "EDIT": + $currentFile = $this->getSubfolderMustExist($gruenerFolder, $diffTaskResult->getCurrentPath()); + $beforeFileFilesystemPath = $snapshotPath . DIRECTORY_SEPARATOR . $diffTaskResult->getBeforePath(); + + $this->copyFilesystemFileToNextcloudFile($beforeFileFilesystemPath, $currentFile); + break; + default: + throw new \Exception; + } + + return $this->mapper->markReverted($id); + } + + private function getSubfolderMustExist(\OCP\Files\Folder $parent, string $path) { + if($parent->nodeExists($path)) { + return $parent->get($path); + } else { + throw new ChangesMadeSinceDiffException; + } + } + + private function getOrCreateSubdirectoryByFilepath(\OCP\Files\Folder $parent, string $filepath) { + $pathSplit = explode('/', trim($filepath, '/')); + array_pop($pathSplit); + + $beforeDirectory = $parent; + foreach($pathSplit as $subdir) { + if($beforeDirectory->nodeExists($subdir)) { + $temp = $beforeDirectory->get($subdir); + if($temp instanceof \OCP\Files\Folder) { + $beforeDirectory = $temp; + } else { + throw new ChangesMadeSinceDiffException; + } + } else { + $beforeDirectory = $beforeDirectory->newFolder($subdir); + } + } + + return $beforeDirectory; + } + + private function copyFilesystemFileToNextcloudFile(string $filesystemPath, \OCP\Files\File $nextcloudFile) { + $snapshotFileStream = fopen($filesystemPath, 'r'); + $snapshotFileMtime = filemtime($filesystemPath); + + $restoredFileStream = $nextcloudFile->fopen('w'); + + stream_copy_to_stream($snapshotFileStream, $restoredFileStream); + + fclose($snapshotFileStream); + fclose($restoredFileStream); + + $nextcloudFile->touch($snapshotFileMtime); + } +} \ No newline at end of file