зеркало из https://github.com/nextcloud/forms.git
Merge pull request #895 from nextcloud/validate_submission
This commit is contained in:
Коммит
87dd08eb84
|
@ -973,6 +973,11 @@ class ApiController extends OCSController {
|
|||
throw new OCSForbiddenException('Already submitted');
|
||||
}
|
||||
|
||||
// Is the submission valid
|
||||
if (!$this->submissionService->validateSubmission($questions, $answers)) {
|
||||
throw new OCSBadRequestException('At least one submitted answer is not valid');
|
||||
}
|
||||
|
||||
// Create Submission
|
||||
$submission = new Submission();
|
||||
$submission->setFormId($formId);
|
||||
|
|
|
@ -26,6 +26,7 @@ namespace OCA\Forms\Service;
|
|||
|
||||
use DateTimeZone;
|
||||
|
||||
use OCA\Forms\Constants;
|
||||
use OCA\Forms\Db\FormMapper;
|
||||
use OCA\Forms\Db\QuestionMapper;
|
||||
use OCA\Forms\Db\SubmissionMapper;
|
||||
|
@ -240,4 +241,54 @@ class SubmissionService {
|
|||
|
||||
return $csv->getContent();
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate all answers against the questions
|
||||
* @param array $questions Array of the questions of the form
|
||||
* @param array $answers Array of the submitted answers
|
||||
* @return boolean If the submission is valid
|
||||
*/
|
||||
public function validateSubmission(array $questions, array $answers): bool {
|
||||
|
||||
// Check by questions
|
||||
foreach ($questions as $question) {
|
||||
$questionId = $question['id'];
|
||||
$questionAnswered = array_key_exists($questionId, $answers);
|
||||
|
||||
// Check if all required questions have an answer
|
||||
if ($question['isRequired'] && (!$questionAnswered || !array_filter($answers[$questionId], 'strlen'))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Perform further checks only for answered questions
|
||||
// TODO Check if date questions have valid answers
|
||||
if ($questionAnswered) {
|
||||
// Check if non multiple questions have not more than one answer
|
||||
if ($question['type'] !== Constants::ANSWER_TYPE_MULTIPLE && count($answers[$questionId]) > 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check if all answers are within the possible options
|
||||
if (in_array($question['type'], Constants::ANSWER_PREDEFINED)) {
|
||||
foreach ($answers[$questionId] as $answer) {
|
||||
// Search corresponding option, return false if non-existent
|
||||
if (array_search($answer, array_column($question['options'], 'id')) === false) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Check for excess answers
|
||||
foreach ($answers as $id => $answerArray) {
|
||||
// Search corresponding question, return false if not found
|
||||
$questionIndex = array_search($id, array_column($questions, 'id'));
|
||||
if ($questionIndex === false) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -462,4 +462,118 @@ class FilterTest extends TestCase {
|
|||
|
||||
return $dataExpectation;
|
||||
}
|
||||
|
||||
// Data for validation of Submissions
|
||||
public function dataValidateSubmission() {
|
||||
return [
|
||||
'required-not-answered' => [
|
||||
// Questions
|
||||
[
|
||||
['id' => 1, 'type' => 'short', 'isRequired' => true]
|
||||
],
|
||||
// Answers
|
||||
[],
|
||||
// Expected Result
|
||||
false
|
||||
],
|
||||
'required-not-answered-string' => [
|
||||
// Questions
|
||||
[
|
||||
['id' => 1, 'type' => 'short', 'isRequired' => true]
|
||||
],
|
||||
// Answers
|
||||
[
|
||||
'1' => ['']
|
||||
],
|
||||
// Expected Result
|
||||
false
|
||||
],
|
||||
'more-than-allowed' => [
|
||||
// Questions
|
||||
[
|
||||
['id' => 1, 'type' => 'multiple_unique', 'isRequired' => false, 'options' => [
|
||||
['id' => 3],
|
||||
['id' => 5]
|
||||
]]
|
||||
],
|
||||
// Answers
|
||||
[
|
||||
'1' => [3,5]
|
||||
],
|
||||
// Expected Result
|
||||
false
|
||||
],
|
||||
'option-not-known' => [
|
||||
// Questions
|
||||
[
|
||||
['id' => 1, 'type' => 'multiple', 'isRequired' => false, 'options' => [
|
||||
['id' => 3],
|
||||
['id' => 5]
|
||||
]],
|
||||
],
|
||||
// Answers
|
||||
[
|
||||
'1' => [3,10]
|
||||
],
|
||||
// Expected Result
|
||||
false
|
||||
],
|
||||
'question-not-known' => [
|
||||
// Questions
|
||||
[
|
||||
['id' => 1, 'type' => 'short', 'isRequired' => false]
|
||||
],
|
||||
// Answers
|
||||
[
|
||||
'2' => ['answer']
|
||||
],
|
||||
// Expected Result
|
||||
false
|
||||
],
|
||||
'full-good-submission' => [
|
||||
// Questions
|
||||
[
|
||||
['id' => 1, 'type' => 'short', 'isRequired' => false],
|
||||
['id' => 2, 'type' => 'long', 'isRequired' => true],
|
||||
['id' => 3, 'type' => 'date', 'isRequired' => true],
|
||||
['id' => 4, 'type' => 'datetime', 'isRequired' => false],
|
||||
['id' => 5, 'type' => 'multiple', 'isRequired' => false, 'options' => [
|
||||
['id' => 1],
|
||||
['id' => 2]
|
||||
]],
|
||||
['id' => 6, 'type' => 'multiple_unique', 'isRequired' => false, 'options' => [
|
||||
['id' => 3],
|
||||
['id' => 4]
|
||||
]],
|
||||
['id' => 7, 'type' => 'dropdown', 'isRequired' => true, 'options' => [
|
||||
['id' => 5],
|
||||
['id' => 6]
|
||||
]],
|
||||
],
|
||||
// Answers
|
||||
[
|
||||
'1' => ['answer'],
|
||||
'2' => ['answerABitLonger'],
|
||||
'3' => ['28. April 2021'],
|
||||
'4' => ['20. April 2021 04:40'],
|
||||
'5' => [1,2],
|
||||
'6' => [4],
|
||||
'7' => [5],
|
||||
],
|
||||
// Expected Result
|
||||
true
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider dataValidateSubmission
|
||||
*
|
||||
* @param array $questions
|
||||
* @param array $answers
|
||||
* @param bool $expected
|
||||
*/
|
||||
public function testValidateSubmission(array $questions, array $answers, bool $expected) {
|
||||
$this->assertEquals($expected, $this->submissionService->validateSubmission($questions, $answers));
|
||||
}
|
||||
};
|
||||
|
|
Загрузка…
Ссылка в новой задаче