initial prototype based on nat-as-server
Some checks failed
PHPUnit / test (push) Has been cancelled
Some checks failed
PHPUnit / test (push) Has been cancelled
This commit is contained in:
244
handlers/questionnaires.php
Normal file
244
handlers/questionnaires.php
Normal file
@ -0,0 +1,244 @@
|
||||
<?php
|
||||
|
||||
$tokenRec = require_valid_token_web();
|
||||
|
||||
switch ($method) {
|
||||
|
||||
case 'GET':
|
||||
try {
|
||||
$opened = qdb_open_read_or_fail();
|
||||
[$pdo, $tmpDb, $lockFp] = $opened;
|
||||
[$rbacClause, $rbacParams] = rbac_client_filter($tokenRec, 'cl');
|
||||
$sql = "
|
||||
SELECT q.questionnaireID, q.name, q.version, q.state,
|
||||
q.orderIndex, q.showPoints, q.conditionJson, q.categoryKey,
|
||||
COUNT(qu.questionID) AS questionCount,
|
||||
(
|
||||
SELECT COUNT(*)
|
||||
FROM completed_questionnaire cq
|
||||
INNER JOIN client cl ON cl.clientCode = cq.clientCode
|
||||
WHERE cq.questionnaireID = q.questionnaireID
|
||||
AND $rbacClause
|
||||
) AS completedCount
|
||||
FROM questionnaire q
|
||||
LEFT JOIN question qu ON qu.questionnaireID = q.questionnaireID
|
||||
GROUP BY q.questionnaireID
|
||||
ORDER BY q.orderIndex, q.name
|
||||
";
|
||||
$stmt = $pdo->prepare($sql);
|
||||
$stmt->execute($rbacParams);
|
||||
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||
foreach ($rows as &$r) {
|
||||
$r['orderIndex'] = (int)$r['orderIndex'];
|
||||
$r['showPoints'] = (int)$r['showPoints'];
|
||||
$r['questionCount'] = (int)$r['questionCount'];
|
||||
$r['completedCount'] = (int)$r['completedCount'];
|
||||
$r['conditionJson'] = $r['conditionJson'] ?: '{}';
|
||||
}
|
||||
unset($r);
|
||||
$categoryKeys = qdb_list_category_keys_for_dashboard($pdo);
|
||||
qdb_discard($tmpDb, $lockFp);
|
||||
json_success(['questionnaires' => $rows, 'categoryKeys' => $categoryKeys]);
|
||||
} catch (Throwable $e) {
|
||||
qdb_handler_fail($e, 'Load questionnaires', null, $tmpDb ?? null, $lockFp ?? null);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'POST':
|
||||
require_role(['admin', 'supervisor'], $tokenRec);
|
||||
$body = read_json_body();
|
||||
|
||||
if (($body['action'] ?? '') === 'updateConditionMessageLabel') {
|
||||
$messageKey = trim((string)($body['messageKey'] ?? ''));
|
||||
$germanLabel = (string)($body['germanLabel'] ?? '');
|
||||
[$pdo, $tmpDb, $lockFp] = qdb_open_write_or_fail();
|
||||
try {
|
||||
qdb_set_app_string_german_label($pdo, $messageKey, $germanLabel);
|
||||
qdb_save($tmpDb, $lockFp);
|
||||
json_success([
|
||||
'messageKey' => qdb_validate_stable_key($messageKey, 'messageKey'),
|
||||
'germanLabel' => trim($germanLabel),
|
||||
]);
|
||||
} catch (Throwable $e) {
|
||||
qdb_handler_fail($e, 'Update condition message label', null, $tmpDb, $lockFp);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (($body['action'] ?? '') === 'updateCategoryLabel') {
|
||||
$categoryKey = trim((string)($body['categoryKey'] ?? ''));
|
||||
$germanLabel = (string)($body['germanLabel'] ?? '');
|
||||
[$pdo, $tmpDb, $lockFp] = qdb_open_write_or_fail();
|
||||
try {
|
||||
$stringKey = qdb_set_category_german_label($pdo, $categoryKey, $germanLabel);
|
||||
qdb_save($tmpDb, $lockFp);
|
||||
json_success([
|
||||
'categoryKey' => $categoryKey,
|
||||
'stringKey' => $stringKey,
|
||||
'germanLabel' => trim($germanLabel),
|
||||
]);
|
||||
} catch (Throwable $e) {
|
||||
qdb_handler_fail($e, 'Update category label', null, $tmpDb, $lockFp);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (($body['action'] ?? '') === 'deleteCategoryKey') {
|
||||
$categoryKey = trim((string)($body['categoryKey'] ?? ''));
|
||||
if ($categoryKey === '') {
|
||||
json_error('INVALID_FIELD', 'categoryKey is required', 400);
|
||||
}
|
||||
[$pdo, $tmpDb, $lockFp] = qdb_open_write_or_fail();
|
||||
try {
|
||||
$cleared = qdb_delete_category_key($pdo, $categoryKey);
|
||||
qdb_save($tmpDb, $lockFp);
|
||||
json_success(['deleted' => $categoryKey, 'questionnairesCleared' => $cleared]);
|
||||
} catch (Throwable $e) {
|
||||
qdb_handler_fail($e, 'Delete category key', null, $tmpDb, $lockFp);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (($body['action'] ?? '') === 'importBundle') {
|
||||
$bundle = $body['bundle'] ?? null;
|
||||
if (!is_array($bundle)) {
|
||||
json_error('MISSING_FIELDS', 'bundle object is required', 400);
|
||||
}
|
||||
$replaceIfExists = !empty($body['replaceIfExists']);
|
||||
[$pdo, $tmpDb, $lockFp] = qdb_open_write_or_fail();
|
||||
try {
|
||||
$pdo->exec('PRAGMA foreign_keys = OFF;');
|
||||
$result = qdb_import_questionnaires_bundle($pdo, $bundle, $replaceIfExists);
|
||||
$pdo->exec('PRAGMA foreign_keys = ON;');
|
||||
qdb_save($tmpDb, $lockFp);
|
||||
json_success($result);
|
||||
} catch (Throwable $e) {
|
||||
qdb_handler_fail($e, 'Import questionnaires', null, $tmpDb, $lockFp);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (empty($body['name'])) {
|
||||
json_error('NAME_REQUIRED', 'name is required', 400);
|
||||
}
|
||||
$id = bin2hex(random_bytes(16));
|
||||
$name = trim($body['name']);
|
||||
$version = trim($body['version'] ?? '');
|
||||
$state = trim($body['state'] ?? 'draft');
|
||||
$order = (int)($body['orderIndex'] ?? 0);
|
||||
$showPts = (int)($body['showPoints'] ?? 0);
|
||||
$condJson = $body['conditionJson'] ?? '{}';
|
||||
|
||||
[$pdo, $tmpDb, $lockFp] = qdb_open_write_or_fail();
|
||||
try {
|
||||
if ($order === 0) {
|
||||
$order = (int)$pdo->query("SELECT COALESCE(MAX(orderIndex),0)+1 FROM questionnaire")->fetchColumn();
|
||||
}
|
||||
$catKey = trim($body['categoryKey'] ?? '');
|
||||
if ($catKey !== '') {
|
||||
$catKey = qdb_normalize_stable_key($catKey);
|
||||
}
|
||||
$pdo->prepare("INSERT INTO questionnaire (questionnaireID, name, version, state, orderIndex, showPoints, conditionJson, categoryKey)
|
||||
VALUES (:id, :n, :v, :s, :o, :sp, :cj, :ck)")
|
||||
->execute([':id' => $id, ':n' => $name, ':v' => $version, ':s' => $state,
|
||||
':o' => $order, ':sp' => $showPts, ':cj' => $condJson, ':ck' => $catKey]);
|
||||
qdb_save($tmpDb, $lockFp);
|
||||
json_success(['questionnaire' => [
|
||||
'questionnaireID' => $id, 'name' => $name, 'version' => $version,
|
||||
'state' => $state, 'orderIndex' => $order, 'showPoints' => $showPts,
|
||||
'conditionJson' => $condJson, 'questionCount' => 0,
|
||||
]]);
|
||||
} catch (Throwable $e) {
|
||||
qdb_handler_fail($e, 'Create questionnaire', null, $tmpDb, $lockFp);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'PUT':
|
||||
require_role(['admin', 'supervisor'], $tokenRec);
|
||||
$body = read_json_body();
|
||||
if (empty($body['questionnaireID'])) {
|
||||
json_error('QUESTIONNAIRE_ID_REQUIRED', 'questionnaireID is required', 400);
|
||||
}
|
||||
$id = $body['questionnaireID'];
|
||||
|
||||
[$pdo, $tmpDb, $lockFp] = qdb_open_write_or_fail();
|
||||
try {
|
||||
$existing = $pdo->prepare('SELECT * FROM questionnaire WHERE questionnaireID = :id');
|
||||
$existing->execute([':id' => $id]);
|
||||
$row = $existing->fetch(PDO::FETCH_ASSOC);
|
||||
if (!$row) {
|
||||
qdb_discard($tmpDb, $lockFp);
|
||||
json_error('NOT_FOUND', 'Questionnaire not found', 404);
|
||||
}
|
||||
$name = trim($body['name'] ?? $row['name']);
|
||||
$version = trim($body['version'] ?? $row['version']);
|
||||
$state = trim($body['state'] ?? $row['state']);
|
||||
$order = (int)($body['orderIndex'] ?? $row['orderIndex']);
|
||||
$showPts = (int)($body['showPoints'] ?? $row['showPoints']);
|
||||
$condJson = $body['conditionJson'] ?? $row['conditionJson'];
|
||||
$catKey = array_key_exists('categoryKey', $body)
|
||||
? trim((string)$body['categoryKey'])
|
||||
: trim($row['categoryKey'] ?? '');
|
||||
if ($catKey !== '') {
|
||||
$catKey = qdb_normalize_stable_key($catKey);
|
||||
}
|
||||
|
||||
$pdo->prepare("UPDATE questionnaire SET name = :n, version = :v, state = :s,
|
||||
orderIndex = :o, showPoints = :sp, conditionJson = :cj, categoryKey = :ck
|
||||
WHERE questionnaireID = :id")
|
||||
->execute([':n' => $name, ':v' => $version, ':s' => $state,
|
||||
':o' => $order, ':sp' => $showPts, ':cj' => $condJson, ':ck' => $catKey, ':id' => $id]);
|
||||
qdb_save($tmpDb, $lockFp);
|
||||
json_success(['questionnaire' => [
|
||||
'questionnaireID' => $id, 'name' => $name, 'version' => $version, 'state' => $state,
|
||||
'orderIndex' => $order, 'showPoints' => $showPts, 'conditionJson' => $condJson,
|
||||
]]);
|
||||
} catch (Throwable $e) {
|
||||
qdb_handler_fail($e, 'Update questionnaire', null, $tmpDb, $lockFp);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'DELETE':
|
||||
require_role(['admin'], $tokenRec);
|
||||
$body = read_json_body();
|
||||
if (empty($body['questionnaireID'])) {
|
||||
json_error('QUESTIONNAIRE_ID_REQUIRED', 'questionnaireID is required', 400);
|
||||
}
|
||||
$id = $body['questionnaireID'];
|
||||
|
||||
[$pdo, $tmpDb, $lockFp] = qdb_open_write_or_fail();
|
||||
try {
|
||||
$pdo->exec('PRAGMA foreign_keys = OFF;');
|
||||
$pdo->beginTransaction();
|
||||
|
||||
$qIds = $pdo->prepare('SELECT questionID FROM question WHERE questionnaireID = :id');
|
||||
$qIds->execute([':id' => $id]);
|
||||
$questionIDs = $qIds->fetchAll(PDO::FETCH_COLUMN);
|
||||
|
||||
foreach ($questionIDs as $qid) {
|
||||
$aoIds = $pdo->prepare('SELECT answerOptionID FROM answer_option WHERE questionID = :qid');
|
||||
$aoIds->execute([':qid' => $qid]);
|
||||
$optionIDs = $aoIds->fetchAll(PDO::FETCH_COLUMN);
|
||||
foreach ($optionIDs as $aoid) {
|
||||
$pdo->prepare('DELETE FROM answer_option_translation WHERE answerOptionID = :id')->execute([':id' => $aoid]);
|
||||
}
|
||||
$pdo->prepare('DELETE FROM answer_option WHERE questionID = :qid')->execute([':qid' => $qid]);
|
||||
$pdo->prepare('DELETE FROM question_translation WHERE questionID = :qid')->execute([':qid' => $qid]);
|
||||
$pdo->prepare('DELETE FROM client_answer WHERE questionID = :qid')->execute([':qid' => $qid]);
|
||||
}
|
||||
$pdo->prepare('DELETE FROM question WHERE questionnaireID = :id')->execute([':id' => $id]);
|
||||
$pdo->prepare('DELETE FROM completed_questionnaire WHERE questionnaireID = :id')->execute([':id' => $id]);
|
||||
$pdo->prepare('DELETE FROM questionnaire WHERE questionnaireID = :id')->execute([':id' => $id]);
|
||||
|
||||
$pdo->commit();
|
||||
$pdo->exec('PRAGMA foreign_keys = ON;');
|
||||
qdb_save($tmpDb, $lockFp);
|
||||
json_success([]);
|
||||
} catch (Throwable $e) {
|
||||
qdb_handler_fail($e, 'Delete questionnaire', $pdo, $tmpDb, $lockFp);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
json_error('METHOD_NOT_ALLOWED', 'Method not allowed', 405);
|
||||
}
|
||||
Reference in New Issue
Block a user