enhanced questionnaire version handling and handling uploads from outdated questionnaires through automatic revisioning and checks
Some checks failed
PHPUnit / test (push) Has been cancelled

This commit is contained in:
2026-06-12 21:38:39 +02:00
parent 5dff24a232
commit b4d4de72f4
17 changed files with 1289 additions and 209 deletions

View File

@ -1,8 +1,11 @@
<?php
require_once __DIR__ . '/questionnaire_structure.php';
/**
* Validate Android app questionnaire submit payloads before persisting answers.
*
* @param array<string, mixed>|null $manifest Structure manifest for legacy revision submits
* @return list<array{questionID: string, code: string, message: string}>
*/
function qdb_validate_app_submit_payload(
@ -12,7 +15,8 @@ function qdb_validate_app_submit_payload(
array $shortIdMap,
array $shortIdToType,
array $symptomParentMap,
array $optionMap
array $optionMap,
?array $manifest = null
): array {
$errors = [];
@ -124,8 +128,13 @@ function qdb_validate_app_submit_payload(
}
}
if ($manifest !== null) {
return array_merge($errors, qdb_validate_required_answers_from_manifest($manifest, $answeredShort));
}
$qStmt = $pdo->prepare(
'SELECT questionID, type, isRequired, configJson FROM question WHERE questionnaireID = :qn'
'SELECT questionID, type, isRequired, configJson FROM question
WHERE questionnaireID = :qn AND ' . qdb_active_questions_clause('question')
);
$qStmt->execute([':qn' => $qnID]);
foreach ($qStmt->fetchAll(PDO::FETCH_ASSOC) as $qRow) {
@ -169,3 +178,44 @@ function qdb_validate_app_submit_payload(
return $errors;
}
/**
* @return list<array{questionID: string, code: string, message: string}>
*/
function qdb_validate_required_answers_from_manifest(array $manifest, array $answeredShort): array {
$errors = [];
foreach ($manifest['questions'] ?? [] as $qEntry) {
if (!is_array($qEntry) || empty($qEntry['isRequired'])) {
continue;
}
$shortId = (string)($qEntry['shortId'] ?? '');
$type = (string)($qEntry['type'] ?? '');
if ($shortId === '') {
continue;
}
if ($type === 'glass_scale_question') {
foreach ($qEntry['symptoms'] ?? [] as $symptomKey) {
$sk = trim((string)$symptomKey);
if ($sk === '') {
continue;
}
if (empty($answeredShort[$sk])) {
$errors[] = [
'questionID' => $sk,
'code' => 'MISSING_ANSWER',
'message' => 'Required symptom is not answered',
];
}
}
continue;
}
if (empty($answeredShort[$shortId])) {
$errors[] = [
'questionID' => $shortId,
'code' => 'MISSING_ANSWER',
'message' => 'Required question is not answered',
];
}
}
return $errors;
}