238 lines
10 KiB
PHP
238 lines
10 KiB
PHP
<?php
|
|
|
|
$tokenRec = require_valid_token();
|
|
|
|
$validTypes = ['question', 'answer_option', 'string', 'language'];
|
|
|
|
switch ($method) {
|
|
|
|
case 'GET':
|
|
if (isset($_GET['languages'])) {
|
|
[$pdo, $tmpDb, $lockFp] = qdb_open(false);
|
|
$rows = $pdo->query("SELECT languageCode, name FROM language ORDER BY languageCode")->fetchAll(PDO::FETCH_ASSOC);
|
|
qdb_discard($tmpDb, $lockFp);
|
|
json_success(["languages" => $rows]);
|
|
}
|
|
|
|
$qnID = $_GET['questionnaireID'] ?? '';
|
|
if ($qnID) {
|
|
[$pdo, $tmpDb, $lockFp] = qdb_open(false);
|
|
|
|
$languages = $pdo->query("SELECT languageCode, name FROM language ORDER BY languageCode")->fetchAll(PDO::FETCH_ASSOC);
|
|
|
|
$qStmt = $pdo->prepare("
|
|
SELECT q.questionID, q.defaultText, q.configJson
|
|
FROM question q WHERE q.questionnaireID = :id ORDER BY q.orderIndex
|
|
");
|
|
$qStmt->execute([':id' => $qnID]);
|
|
$dbQuestions = $qStmt->fetchAll(PDO::FETCH_ASSOC);
|
|
|
|
$entries = [];
|
|
$stringKeys = [];
|
|
|
|
foreach ($dbQuestions as $dbQ) {
|
|
$entries[] = ['key' => $dbQ['defaultText'], 'type' => 'question', 'entityId' => $dbQ['questionID']];
|
|
|
|
$aoStmt = $pdo->prepare("SELECT answerOptionID, defaultText FROM answer_option WHERE questionID = :qid ORDER BY orderIndex");
|
|
$aoStmt->execute([':qid' => $dbQ['questionID']]);
|
|
foreach ($aoStmt->fetchAll(PDO::FETCH_ASSOC) as $ao) {
|
|
$entries[] = ['key' => $ao['defaultText'], 'type' => 'answer_option', 'entityId' => $ao['answerOptionID']];
|
|
}
|
|
|
|
$config = json_decode($dbQ['configJson'] ?: '{}', true) ?: [];
|
|
foreach (['textKey','textKey1','textKey2','hint','hint1','hint2'] as $field) {
|
|
if (!empty($config[$field])) $stringKeys[$config[$field]] = true;
|
|
}
|
|
if (!empty($config['symptoms']) && is_array($config['symptoms'])) {
|
|
foreach ($config['symptoms'] as $s) $stringKeys[$s] = true;
|
|
}
|
|
}
|
|
|
|
foreach (array_keys($stringKeys) as $sk) {
|
|
$entries[] = ['key' => $sk, 'type' => 'string', 'entityId' => $sk];
|
|
}
|
|
|
|
$translations = [];
|
|
|
|
$qIds = array_filter(array_map(fn($e) => $e['type'] === 'question' ? $e['entityId'] : null, $entries));
|
|
if ($qIds) {
|
|
$ph = implode(',', array_fill(0, count($qIds), '?'));
|
|
$stmt = $pdo->prepare("SELECT questionID AS entityId, languageCode, text FROM question_translation WHERE questionID IN ($ph)");
|
|
$stmt->execute(array_values($qIds));
|
|
foreach ($stmt->fetchAll(PDO::FETCH_ASSOC) as $r) {
|
|
$translations[$r['entityId']][$r['languageCode']] = $r['text'];
|
|
}
|
|
}
|
|
|
|
$aoIds = array_filter(array_map(fn($e) => $e['type'] === 'answer_option' ? $e['entityId'] : null, $entries));
|
|
if ($aoIds) {
|
|
$ph = implode(',', array_fill(0, count($aoIds), '?'));
|
|
$stmt = $pdo->prepare("SELECT answerOptionID AS entityId, languageCode, text FROM answer_option_translation WHERE answerOptionID IN ($ph)");
|
|
$stmt->execute(array_values($aoIds));
|
|
foreach ($stmt->fetchAll(PDO::FETCH_ASSOC) as $r) {
|
|
$translations[$r['entityId']][$r['languageCode']] = $r['text'];
|
|
}
|
|
}
|
|
|
|
$sKeys = array_filter(array_map(fn($e) => $e['type'] === 'string' ? $e['entityId'] : null, $entries));
|
|
if ($sKeys) {
|
|
$ph = implode(',', array_fill(0, count($sKeys), '?'));
|
|
$stmt = $pdo->prepare("SELECT stringKey AS entityId, languageCode, text FROM string_translation WHERE stringKey IN ($ph)");
|
|
$stmt->execute(array_values($sKeys));
|
|
foreach ($stmt->fetchAll(PDO::FETCH_ASSOC) as $r) {
|
|
$translations[$r['entityId']][$r['languageCode']] = $r['text'];
|
|
}
|
|
}
|
|
|
|
foreach ($entries as &$e) {
|
|
$e['translations'] = $translations[$e['entityId']] ?? (object)[];
|
|
}
|
|
unset($e);
|
|
|
|
qdb_discard($tmpDb, $lockFp);
|
|
json_success(["languages" => $languages, "entries" => $entries]);
|
|
}
|
|
|
|
$type = $_GET['type'] ?? '';
|
|
$id = $_GET['id'] ?? '';
|
|
if (!in_array($type, $validTypes, true) || (!$id && $type !== 'string')) {
|
|
json_error('BAD_REQUEST', 'type (question|answer_option|string) and id required', 400);
|
|
}
|
|
|
|
[$pdo, $tmpDb, $lockFp] = qdb_open(false);
|
|
if ($type === 'question') {
|
|
$stmt = $pdo->prepare("SELECT languageCode, text FROM question_translation WHERE questionID = :id");
|
|
$stmt->execute([':id' => $id]);
|
|
} elseif ($type === 'answer_option') {
|
|
$stmt = $pdo->prepare("SELECT languageCode, text FROM answer_option_translation WHERE answerOptionID = :id");
|
|
$stmt->execute([':id' => $id]);
|
|
} else {
|
|
if ($id) {
|
|
$stmt = $pdo->prepare("SELECT stringKey, languageCode, text FROM string_translation WHERE stringKey = :id");
|
|
$stmt->execute([':id' => $id]);
|
|
} else {
|
|
$stmt = $pdo->query("SELECT stringKey, languageCode, text FROM string_translation ORDER BY stringKey, languageCode");
|
|
}
|
|
}
|
|
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
|
qdb_discard($tmpDb, $lockFp);
|
|
json_success(["translations" => $rows]);
|
|
break;
|
|
|
|
case 'PUT':
|
|
require_role(['admin', 'supervisor'], $tokenRec);
|
|
$body = read_json_body();
|
|
$type = $body['type'] ?? '';
|
|
|
|
if ($type === 'language') {
|
|
$lang = trim($body['languageCode'] ?? '');
|
|
$name = trim($body['name'] ?? '');
|
|
if (!$lang) {
|
|
json_error('MISSING_FIELDS', 'languageCode required', 400);
|
|
}
|
|
[$pdo, $tmpDb, $lockFp] = qdb_open(true);
|
|
try {
|
|
$pdo->prepare("INSERT INTO language (languageCode, name) VALUES (:lc, :n)
|
|
ON CONFLICT(languageCode) DO UPDATE SET name = excluded.name")
|
|
->execute([':lc' => $lang, ':n' => $name]);
|
|
qdb_save($tmpDb, $lockFp);
|
|
json_success([]);
|
|
} catch (Throwable $e) {
|
|
qdb_discard($tmpDb, $lockFp);
|
|
error_log($e->getMessage());
|
|
json_error('SERVER_ERROR', 'Server error', 500);
|
|
}
|
|
break;
|
|
}
|
|
|
|
$id = $body['id'] ?? '';
|
|
$lang = trim($body['languageCode'] ?? '');
|
|
$text = $body['text'] ?? '';
|
|
if (!in_array($type, $validTypes, true) || !$id || !$lang) {
|
|
json_error('MISSING_FIELDS', 'type, id, and languageCode required', 400);
|
|
}
|
|
|
|
[$pdo, $tmpDb, $lockFp] = qdb_open(true);
|
|
try {
|
|
if ($type === 'question') {
|
|
$pdo->prepare("INSERT INTO question_translation (questionID, languageCode, text)
|
|
VALUES (:id, :lang, :t)
|
|
ON CONFLICT(questionID, languageCode) DO UPDATE SET text = excluded.text")
|
|
->execute([':id' => $id, ':lang' => $lang, ':t' => $text]);
|
|
} elseif ($type === 'answer_option') {
|
|
$pdo->prepare("INSERT INTO answer_option_translation (answerOptionID, languageCode, text)
|
|
VALUES (:id, :lang, :t)
|
|
ON CONFLICT(answerOptionID, languageCode) DO UPDATE SET text = excluded.text")
|
|
->execute([':id' => $id, ':lang' => $lang, ':t' => $text]);
|
|
} else {
|
|
$pdo->prepare("INSERT INTO string_translation (stringKey, languageCode, text)
|
|
VALUES (:id, :lang, :t)
|
|
ON CONFLICT(stringKey, languageCode) DO UPDATE SET text = excluded.text")
|
|
->execute([':id' => $id, ':lang' => $lang, ':t' => $text]);
|
|
}
|
|
qdb_save($tmpDb, $lockFp);
|
|
json_success([]);
|
|
} catch (Throwable $e) {
|
|
qdb_discard($tmpDb, $lockFp);
|
|
error_log($e->getMessage());
|
|
json_error('SERVER_ERROR', 'Server error', 500);
|
|
}
|
|
break;
|
|
|
|
case 'DELETE':
|
|
require_role(['admin', 'supervisor'], $tokenRec);
|
|
$body = read_json_body();
|
|
$type = $body['type'] ?? '';
|
|
|
|
if ($type === 'language') {
|
|
$lang = trim($body['languageCode'] ?? '');
|
|
if (!$lang) {
|
|
json_error('MISSING_FIELDS', 'languageCode required', 400);
|
|
}
|
|
[$pdo, $tmpDb, $lockFp] = qdb_open(true);
|
|
try {
|
|
$pdo->prepare("DELETE FROM language WHERE languageCode = :lc")->execute([':lc' => $lang]);
|
|
$pdo->prepare("DELETE FROM question_translation WHERE languageCode = :lc")->execute([':lc' => $lang]);
|
|
$pdo->prepare("DELETE FROM answer_option_translation WHERE languageCode = :lc")->execute([':lc' => $lang]);
|
|
$pdo->prepare("DELETE FROM string_translation WHERE languageCode = :lc")->execute([':lc' => $lang]);
|
|
qdb_save($tmpDb, $lockFp);
|
|
json_success([]);
|
|
} catch (Throwable $e) {
|
|
qdb_discard($tmpDb, $lockFp);
|
|
error_log($e->getMessage());
|
|
json_error('SERVER_ERROR', 'Server error', 500);
|
|
}
|
|
break;
|
|
}
|
|
|
|
$id = $body['id'] ?? '';
|
|
$lang = trim($body['languageCode'] ?? '');
|
|
if (!in_array($type, $validTypes, true) || !$id || !$lang) {
|
|
json_error('MISSING_FIELDS', 'type, id, and languageCode required', 400);
|
|
}
|
|
|
|
[$pdo, $tmpDb, $lockFp] = qdb_open(true);
|
|
try {
|
|
if ($type === 'question') {
|
|
$pdo->prepare("DELETE FROM question_translation WHERE questionID = :id AND languageCode = :lang")
|
|
->execute([':id' => $id, ':lang' => $lang]);
|
|
} elseif ($type === 'answer_option') {
|
|
$pdo->prepare("DELETE FROM answer_option_translation WHERE answerOptionID = :id AND languageCode = :lang")
|
|
->execute([':id' => $id, ':lang' => $lang]);
|
|
} else {
|
|
$pdo->prepare("DELETE FROM string_translation WHERE stringKey = :id AND languageCode = :lang")
|
|
->execute([':id' => $id, ':lang' => $lang]);
|
|
}
|
|
qdb_save($tmpDb, $lockFp);
|
|
json_success([]);
|
|
} catch (Throwable $e) {
|
|
qdb_discard($tmpDb, $lockFp);
|
|
error_log($e->getMessage());
|
|
json_error('SERVER_ERROR', 'Server error', 500);
|
|
}
|
|
break;
|
|
|
|
default:
|
|
json_error('METHOD_NOT_ALLOWED', 'Method not allowed', 405);
|
|
}
|