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); } }