new system prototype
This commit is contained in:
174
api/app_questionnaires.php
Normal file
174
api/app_questionnaires.php
Normal file
@ -0,0 +1,174 @@
|
||||
<?php
|
||||
/**
|
||||
* Android app API endpoint.
|
||||
*
|
||||
* GET (no params) -> ordered questionnaire list with conditions
|
||||
* GET ?id=<questionnaireID> -> single questionnaire in app JSON format
|
||||
* GET ?translations=1 -> all translations merged across all tables
|
||||
*/
|
||||
require_once __DIR__ . '/../common.php';
|
||||
require_once __DIR__ . '/../db_init.php';
|
||||
|
||||
header('Content-Type: application/json; charset=UTF-8');
|
||||
|
||||
$tokenRec = require_valid_token();
|
||||
|
||||
if ($_SERVER['REQUEST_METHOD'] !== 'GET') {
|
||||
http_response_code(405);
|
||||
echo json_encode(["error" => "Method not allowed"]);
|
||||
exit;
|
||||
}
|
||||
|
||||
[$pdo, $tmpDb, $lockFp] = qdb_open(false);
|
||||
|
||||
$qnID = $_GET['id'] ?? '';
|
||||
$translations = $_GET['translations'] ?? '';
|
||||
|
||||
if ($translations) {
|
||||
// Return all translations merged from all three tables, keyed by language
|
||||
$result = [];
|
||||
|
||||
// question translations: map questionID -> defaultText (the key), then lang -> text
|
||||
$rows = $pdo->query("
|
||||
SELECT q.defaultText AS stringKey, qt.languageCode, qt.text
|
||||
FROM question_translation qt
|
||||
JOIN question q ON q.questionID = qt.questionID
|
||||
")->fetchAll(PDO::FETCH_ASSOC);
|
||||
foreach ($rows as $r) {
|
||||
$result[$r['languageCode']][$r['stringKey']] = $r['text'];
|
||||
}
|
||||
|
||||
// answer option translations: map answerOptionID -> defaultText (the key)
|
||||
$rows = $pdo->query("
|
||||
SELECT ao.defaultText AS stringKey, aot.languageCode, aot.text
|
||||
FROM answer_option_translation aot
|
||||
JOIN answer_option ao ON ao.answerOptionID = aot.answerOptionID
|
||||
")->fetchAll(PDO::FETCH_ASSOC);
|
||||
foreach ($rows as $r) {
|
||||
$result[$r['languageCode']][$r['stringKey']] = $r['text'];
|
||||
}
|
||||
|
||||
// string translations (symptoms, hints, textKeys, etc.)
|
||||
$rows = $pdo->query("SELECT stringKey, languageCode, text FROM string_translation")->fetchAll(PDO::FETCH_ASSOC);
|
||||
foreach ($rows as $r) {
|
||||
$result[$r['languageCode']][$r['stringKey']] = $r['text'];
|
||||
}
|
||||
|
||||
qdb_discard($tmpDb, $lockFp);
|
||||
echo json_encode(["success" => true, "translations" => $result]);
|
||||
exit;
|
||||
}
|
||||
|
||||
if ($qnID) {
|
||||
// Single questionnaire in app JSON format
|
||||
$qn = $pdo->prepare("SELECT * FROM questionnaire WHERE questionnaireID = :id");
|
||||
$qn->execute([':id' => $qnID]);
|
||||
$qnRow = $qn->fetch(PDO::FETCH_ASSOC);
|
||||
if (!$qnRow) {
|
||||
qdb_discard($tmpDb, $lockFp);
|
||||
http_response_code(404);
|
||||
echo json_encode(["error" => "Questionnaire not found"]);
|
||||
exit;
|
||||
}
|
||||
|
||||
$stmt = $pdo->prepare("
|
||||
SELECT questionID, defaultText, type, orderIndex, configJson
|
||||
FROM question WHERE questionnaireID = :id ORDER BY orderIndex
|
||||
");
|
||||
$stmt->execute([':id' => $qnID]);
|
||||
$dbQuestions = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||
|
||||
$questions = [];
|
||||
foreach ($dbQuestions as $dbQ) {
|
||||
$localId = $dbQ['questionID'];
|
||||
$parts = explode('__', $localId);
|
||||
$shortId = end($parts);
|
||||
|
||||
$layout = $dbQ['type'];
|
||||
$config = json_decode($dbQ['configJson'], true) ?: [];
|
||||
|
||||
$q = [
|
||||
'id' => $shortId,
|
||||
'layout' => $layout,
|
||||
'question' => $dbQ['defaultText'],
|
||||
];
|
||||
|
||||
// Add type-specific config fields back to the top level
|
||||
if (isset($config['textKey'])) $q['textKey'] = $config['textKey'];
|
||||
if (isset($config['textKey1'])) $q['textKey1'] = $config['textKey1'];
|
||||
if (isset($config['textKey2'])) $q['textKey2'] = $config['textKey2'];
|
||||
if (isset($config['hint'])) $q['hint'] = $config['hint'];
|
||||
if (isset($config['hint1'])) $q['hint1'] = $config['hint1'];
|
||||
if (isset($config['hint2'])) $q['hint2'] = $config['hint2'];
|
||||
if (isset($config['symptoms'])) $q['symptoms'] = $config['symptoms'];
|
||||
if (isset($config['range'])) $q['range'] = $config['range'];
|
||||
if (isset($config['constraints'])) $q['constraints'] = $config['constraints'];
|
||||
if (isset($config['minSelection'])) $q['minSelection'] = $config['minSelection'];
|
||||
|
||||
// String spinner static options
|
||||
if ($layout === 'string_spinner' && isset($config['options'])) {
|
||||
$q['options'] = $config['options'];
|
||||
}
|
||||
|
||||
// Value spinner conditional navigation options
|
||||
if ($layout === 'value_spinner' && isset($config['valueOptions'])) {
|
||||
$q['options'] = $config['valueOptions'];
|
||||
}
|
||||
|
||||
// Answer options (for radio_question, multi_check_box_question, etc.)
|
||||
$ao = $pdo->prepare("
|
||||
SELECT defaultText, points, nextQuestionId
|
||||
FROM answer_option WHERE questionID = :qid ORDER BY orderIndex
|
||||
");
|
||||
$ao->execute([':qid' => $dbQ['questionID']]);
|
||||
$opts = $ao->fetchAll(PDO::FETCH_ASSOC);
|
||||
|
||||
if ($opts) {
|
||||
$optionsArr = [];
|
||||
$pointsMap = [];
|
||||
foreach ($opts as $opt) {
|
||||
$o = ['key' => $opt['defaultText']];
|
||||
if ($opt['nextQuestionId'] !== '') {
|
||||
$o['nextQuestionId'] = $opt['nextQuestionId'];
|
||||
}
|
||||
$optionsArr[] = $o;
|
||||
$pointsMap[$opt['defaultText']] = (int)$opt['points'];
|
||||
}
|
||||
$q['options'] = $optionsArr;
|
||||
|
||||
$hasNonZero = false;
|
||||
foreach ($pointsMap as $v) { if ($v !== 0) { $hasNonZero = true; break; } }
|
||||
$q['pointsMap'] = $pointsMap;
|
||||
}
|
||||
|
||||
$questions[] = $q;
|
||||
}
|
||||
|
||||
qdb_discard($tmpDb, $lockFp);
|
||||
echo json_encode([
|
||||
"meta" => ["id" => $qnID],
|
||||
"questions" => $questions,
|
||||
]);
|
||||
exit;
|
||||
}
|
||||
|
||||
// Default: ordered questionnaire list
|
||||
$rows = $pdo->query("
|
||||
SELECT questionnaireID, name, showPoints, conditionJson
|
||||
FROM questionnaire
|
||||
WHERE state = 'active'
|
||||
ORDER BY orderIndex
|
||||
")->fetchAll(PDO::FETCH_ASSOC);
|
||||
|
||||
$list = [];
|
||||
foreach ($rows as $r) {
|
||||
$list[] = [
|
||||
'id' => $r['questionnaireID'],
|
||||
'name' => $r['name'],
|
||||
'showPoints' => (bool)(int)$r['showPoints'],
|
||||
'condition' => json_decode($r['conditionJson'], true) ?: new stdClass(),
|
||||
];
|
||||
}
|
||||
|
||||
qdb_discard($tmpDb, $lockFp);
|
||||
echo json_encode($list);
|
||||
Reference in New Issue
Block a user