diff --git a/lib/Controller/ApiController.php b/lib/Controller/ApiController.php index e98d5c188..1285f0f77 100644 --- a/lib/Controller/ApiController.php +++ b/lib/Controller/ApiController.php @@ -46,8 +46,10 @@ use OCP\AppFramework\OCS\OCSNotFoundException; use OCP\AppFramework\OCSController; use OCP\BackgroundJob\IJobList; +use OCP\Files\Folder; use OCP\Files\IMimeTypeDetector; use OCP\Files\IRootFolder; +use OCP\Files\NotFoundException; use OCP\IL10N; use OCP\IRequest; use OCP\IUser; @@ -742,6 +744,10 @@ public function deleteQuestion(int $formId, int $questionId): DataResponse { $question->setOrder(0); $this->questionMapper->update($question); + if ($question->getType() === Constants::ANSWER_TYPE_FILE) { + $this->deleteQuestionFolder($form, $question); + } + // Update all question-order > deleted order. $formQuestions = $this->questionMapper->findByForm($formId); foreach ($formQuestions as $question) { @@ -761,6 +767,43 @@ public function deleteQuestion(int $formId, int $questionId): DataResponse { return new DataResponse($questionId); } + /** + * Delete question folders from all submissions + * @param Form $form The form + * @param Question $question The question + */ + private function deleteQuestionFolder(Form $form, Question $question): void { + try { + $userFolder = $this->rootFolder->getUserFolder($form->getOwnerId()); + $formFolderPath = $this->formsService->getFormUploadedFilesFolderPath($form); + + $formFolder = $userFolder->get($formFolderPath); + if (!$formFolder instanceof Folder) { + return; + } + $questionFolderPrefix = $question->getId() . ' - '; + + // Iterate through submission folders and delete matching question folders + foreach ($formFolder->getDirectoryListing() as $submissionFolder) { + if (!$submissionFolder instanceof Folder) { + continue; + } + foreach ($submissionFolder->getDirectoryListing() as $node) { + if (str_starts_with($node->getName(), $questionFolderPrefix)) { + $node->delete(); + } + } + } + } catch (NotFoundException) { + // Do nothing + } catch (\Throwable $e) { + $this->logger->warning('Failed to delete question folders: {error}', [ + 'error' => $e->getMessage(), + 'questionId' => $question->getId(), + ]); + } + } + /** * Updates the Order of all Questions of a Form * @@ -1589,7 +1632,7 @@ public function deleteSubmission(int $formId, int $submissionId): DataResponse { } // Delete submission (incl. Answers) - $this->submissionMapper->deleteById($submissionId); + $this->submissionMapper->deleteById($form, $submissionId); $this->formMapper->update($form); return new DataResponse($submissionId); @@ -1743,7 +1786,7 @@ public function uploadFiles(int $formId, int $questionId, string $shareHash = '' } else { $folder = $userFolder->newFolder($path); } - /** @var \OCP\Files\Folder $folder */ + /** @var Folder $folder */ $fileName = $folder->getNonExistingName($uploadedFile['name']); $file = $folder->newFile($fileName, file_get_contents($uploadedFile['tmp_name'])); @@ -1819,7 +1862,7 @@ private function storeAnswersForQuestion(Form $form, $submissionId, array $quest } else { $folder = $userFolder->newFolder($path); } - /** @var \OCP\Files\Folder $folder */ + /** @var Folder $folder */ $file = $userFolder->getById($uploadedFile->getFileId())[0]; $name = $folder->getNonExistingName($file->getName()); diff --git a/lib/Db/AnswerMapper.php b/lib/Db/AnswerMapper.php index 2420f6b34..600b127db 100644 --- a/lib/Db/AnswerMapper.php +++ b/lib/Db/AnswerMapper.php @@ -54,4 +54,48 @@ public function deleteBySubmission(int $submissionId): void { $qb->executeStatement(); } + + /** + * Collect all fileIds for answers of a specific submission + * @param int $submissionId + * @return int[] Array of fileIds + */ + public function findFileIdsBySubmission(int $submissionId): array { + $qb = $this->db->getQueryBuilder(); + + $qb->select('file_id') + ->from($this->getTableName()) + ->where( + $qb->expr()->eq('submission_id', $qb->createNamedParameter($submissionId, IQueryBuilder::PARAM_INT)) + ) + ->andWhere($qb->expr()->isNotNull('file_id')); + + $result = $qb->executeQuery(); + $rows = $result->fetchFirstColumn(); + $result->closeCursor(); + + return array_map('intval', $rows); + } + + /** + * Collect all fileIds for answers of a specific question + * @param int $questionId + * @return int[] Array of fileIds + */ + public function findFileIdsByQuestion(int $questionId): array { + $qb = $this->db->getQueryBuilder(); + + $qb->select('file_id') + ->from($this->getTableName()) + ->where( + $qb->expr()->eq('question_id', $qb->createNamedParameter($questionId, IQueryBuilder::PARAM_INT)) + ) + ->andWhere($qb->expr()->isNotNull('file_id')); + + $result = $qb->executeQuery(); + $rows = $result->fetchFirstColumn(); + $result->closeCursor(); + + return array_map('intval', $rows); + } } diff --git a/lib/Db/FormMapper.php b/lib/Db/FormMapper.php index 9187b9835..10a9d9cf0 100644 --- a/lib/Db/FormMapper.php +++ b/lib/Db/FormMapper.php @@ -12,8 +12,12 @@ use OCP\AppFramework\Db\Entity; use OCP\AppFramework\Db\QBMapper; use OCP\DB\QueryBuilder\IQueryBuilder; +use OCP\Files\Folder; +use OCP\Files\IRootFolder; +use OCP\Files\NotFoundException; use OCP\IDBConnection; use OCP\Share\IShare; +use Psr\Log\LoggerInterface; /** * @extends QBMapper