From e0d41aef0cdd620dad1462c44913b30f0ce48005 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20Molakvo=C3=A6=20=28skjnldsv=29?= Date: Tue, 28 Apr 2020 15:36:12 +0200 Subject: [PATCH] Insert Submission, new API MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: John Molakvoæ (skjnldsv) --- appinfo/routes.php | 2 +- lib/Controller/ApiController.php | 89 ++++++++++++++++++- lib/Controller/PageController.php | 77 +--------------- src/components/Questions/QuestionMultiple.vue | 23 ++++- src/views/Create.vue | 2 +- src/views/Submit.vue | 40 +++++++-- 6 files changed, 147 insertions(+), 86 deletions(-) diff --git a/appinfo/routes.php b/appinfo/routes.php index eaeb20d..23817ae 100644 --- a/appinfo/routes.php +++ b/appinfo/routes.php @@ -32,7 +32,6 @@ return [ ['name' => 'page#getResult', 'url' => '/{hash}/results', 'verb' => 'GET'], ['name' => 'page#goto_form', 'url' => '/{hash}', 'verb' => 'GET'], - ['name' => 'page#insert_submission', 'url' => '/insert/submission', 'verb' => 'POST'], // Forms ['name' => 'api#getForms', 'url' => '/api/v1/forms', 'verb' => 'GET'], @@ -53,6 +52,7 @@ return [ ['name' => 'api#deleteOption', 'url' => '/api/v1/option/{id}', 'verb' => 'DELETE'], ['name' => 'api#getSubmissions', 'url' => '/api/v1/submissions/{hash}', 'verb' => 'GET'], + ['name' => 'api#insertSubmission', 'url' => '/api/v1/submissions/insert', 'verb' => 'POST'], ['name' => 'system#get_site_users_and_groups', 'url' => '/get/siteusers', 'verb' => 'POST'], ] diff --git a/lib/Controller/ApiController.php b/lib/Controller/ApiController.php index be8b82d..98d6644 100644 --- a/lib/Controller/ApiController.php +++ b/lib/Controller/ApiController.php @@ -38,6 +38,7 @@ use OCP\AppFramework\Db\IMapperException; use OCP\ILogger; use OCP\IRequest; use OCP\IUser; +use OCP\IUserSession; use OCP\Security\ISecureRandom; use OCA\Forms\Db\Form; @@ -62,12 +63,13 @@ class ApiController extends Controller { /** @var ILogger */ private $logger; - /** @var string */ - private $userId; + /** @var IUserSession */ + private $userSession; public function __construct( IRequest $request, - $userId, + $userId, // TODO remove & replace with userSession below. + IUserSession $userSession, FormMapper $formMapper, SubmissionMapper $submissionMapper, AnswerMapper $answerMapper, @@ -77,6 +79,7 @@ class ApiController extends Controller { ) { parent::__construct(Application::APP_ID, $request); $this->userId = $userId; + $this->userSession = $userSession; $this->formMapper = $formMapper; $this->submissionMapper = $submissionMapper; $this->answerMapper = $answerMapper; @@ -603,4 +606,84 @@ class ApiController extends Controller { return new Http\JSONResponse($result); } + + /** + * @NoAdminRequired + * @PublicPage + * + * Process a new submission + * @param int $formId + * @param array $answers [question_id => arrayOfString] + */ + public function insertSubmission(int $formId, array $answers) { + $this->logger->debug('Inserting submission: formId: {formId}, answers: {answers}', [ + 'formId' => $formId, + 'answers' => $answers, + ]); + + try { + $form = $this->formMapper->findById($formId); + $questions = $this->getQuestions($formId); + } catch (IMapperException $e) { + $this->logger->debug('Could not find form'); + return new Http\JSONResponse(['message' => 'Could not find form'], Http::STATUS_BAD_REQUEST); + } + + $user = $this->userSession->getUser(); + // TODO check again hasUserAccess?! + + // Create Submission + $submission = new Submission(); + $submission->setFormId($formId); + $submission->setTimestamp(time()); + + // If not logged in or anonymous use anonID + if (!$user || $form->getIsAnonymous()){ + $anonID = "anon-user-". hash('md5', (time() + rand())); + $submission->setUserId($anonID); + } else { + $submission->setUserId($user->getUID()); + } + + // Insert new submission + $this->submissionMapper->insert($submission); + $submissionId = $submission->getId(); + + // Process Answers + foreach($answers as $questionId => $answerArray) { + // Search corresponding Question, skip processing if not found + $questionIndex = array_search($questionId, array_column($questions, 'id')); + if ($questionIndex === false) { + continue; + } else { + $question = $questions[$questionIndex]; + } + + foreach($answerArray as $answer) { + if($question['type'] === 'multiple' || $question['type'] === 'multiple_unique') { + // Search corresponding option, skip processing if not found + $optionIndex = array_search($answer, array_column($question['options'], 'id')); + if($optionIndex === false) { + continue; + } else { + $option = $question['options'][$optionIndex]; + } + + // Load option-text + $answerText = $option['text']; + + } else { + $answerText = $answer; // Not a multiple-question, answerText is given answer + } + + $answerEntity = new Answer(); + $answerEntity->setSubmissionId($submissionId); + $answerEntity->setQuestionId($question['id']); + $answerEntity->setText($answerText); + $this->answerMapper->insert($answerEntity); + } + } + + return new Http\JSONResponse([]); + } } diff --git a/lib/Controller/PageController.php b/lib/Controller/PageController.php index c2e028f..1cfa186 100644 --- a/lib/Controller/PageController.php +++ b/lib/Controller/PageController.php @@ -29,19 +29,16 @@ namespace OCA\Forms\Controller; +use Exception; use OCA\Forms\Db\Form; use OCA\Forms\Db\FormMapper; -use OCA\Forms\Db\Submission; -use OCA\Forms\Db\SubmissionMapper; -use OCA\Forms\Db\Answer; -use OCA\Forms\Db\AnswerMapper; - -use OCA\Forms\Db\OptionMapper; +use OCA\Forms\Db\Question; use OCA\Forms\Db\QuestionMapper; +use OCA\Forms\Db\Option; +use OCA\Forms\Db\OptionMapper; use OCP\AppFramework\Controller; use OCP\AppFramework\Db\DoesNotExistException; -use OCP\AppFramework\Http\RedirectResponse; use OCP\AppFramework\Http\TemplateResponse; use OCP\IGroupManager; use OCP\IRequest; @@ -57,12 +54,6 @@ class PageController extends Controller { /** @var FormMapper */ private $formMapper; - /** @var SubmissionMapper */ - private $submissionMapper; - - /** @var AnswerMapper */ - private $answerMapper; - /** @var IURLGenerator */ private $urlGenerator; @@ -82,8 +73,6 @@ class PageController extends Controller { FormMapper $formMapper, QuestionMapper $questionMapper, OptionMapper $optionMapper, - SubmissionMapper $SubmissionMapper, - AnswerMapper $AnswerMapper, IUserSession $userSession, IInitialStateService $initialStateService) { parent::__construct($appName, $request); @@ -94,8 +83,6 @@ class PageController extends Controller { $this->formMapper = $formMapper; $this->questionMapper = $questionMapper; $this->optionMapper = $optionMapper; - $this->submissionMapper = $SubmissionMapper; - $this->answerMapper = $AnswerMapper; $this->userSession = $userSession; $this->initialStateService = $initialStateService; } @@ -237,62 +224,6 @@ class PageController extends Controller { return new TemplateResponse($this->appName, 'main', [], $renderAs); } - /** - * @NoAdminRequired - * @PublicPage - * - * Process a new submission - * @param int $formId - * @param string $userId - * @param array $answers - * @param array $questions - * @return RedirectResponse - */ - public function insertSubmission(int $id, string $userId, array $answers, array $questions) { - - $form = $this->formMapper->findById($id); - $anonID = "anon-user-". hash('md5', (time() + rand())); - - // Insert Submission - $submission = new Submission(); - $submission->setFormId($id); - if ($form->getIsAnonymous()){ - $submission->setUserId($anonID); - - } else { - $submission->setUserId($userId); - } - $submission->setTimestamp(time()); - $this->submissionMapper->insert($submission); - $submissionId = $submission->getId(); - - //Insert Answers - foreach($questions as $question) { - // If question is answered, the questionText exists as key in $answers. Does not exist, when a (non-mandatory) question was not answered. - if (array_key_exists($question['text'], $answers)) { - if($question['type'] === "checkbox"){ - foreach(($answers[$question['text']]) as $ansText) { - $answer = new Answer(); - $answer->setSubmissionId($submissionId); - $answer->setQuestionId($question['id']); - $answer->setText($ansText); - $this->answerMapper->insert($answer); - } - } else { - $answer = new Answer(); - $answer->setSubmissionId($submissionId); - $answer->setQuestionId($question['id']); - $answer->setText($answers[$question['text']]); - $this->answerMapper->insert($answer); - } - } - } - - $hash = $form->getHash(); - $url = $this->urlGenerator->linkToRoute('forms.page.goto_form', ['hash' => $hash]); - return new RedirectResponse($url); - } - /** * @NoAdminRequired * Check if user has access to this form diff --git a/src/components/Questions/QuestionMultiple.vue b/src/components/Questions/QuestionMultiple.vue index f251774..56069b9 100644 --- a/src/components/Questions/QuestionMultiple.vue +++ b/src/components/Questions/QuestionMultiple.vue @@ -43,7 +43,8 @@ }" :name="`${id}-answer`" :required="true /* TODO: implement required option */" - :type="isUnique ? 'radio' : 'checkbox'"> + :type="isUnique ? 'radio' : 'checkbox'" + @change="onChange($event, answer.id)">