enhanced questionnaire handling with stable key validation, improved note management, and added option key support

This commit is contained in:
2026-05-26 15:40:35 +02:00
parent 1b3d74d822
commit 7671c9f329
10 changed files with 876 additions and 100 deletions

View File

@ -17,6 +17,8 @@ case 'GET':
foreach ($options as &$o) {
$o['points'] = (int)$o['points'];
$o['orderIndex'] = (int)$o['orderIndex'];
$o['optionKey'] = qdb_option_key($o);
$o['labelGerman'] = qdb_option_german_label($pdo, $o['answerOptionID'], $o['defaultText']);
$tr = $pdo->prepare('SELECT languageCode, text FROM answer_option_translation WHERE answerOptionID = :id');
$tr->execute([':id' => $o['answerOptionID']]);
$o['translations'] = $tr->fetchAll(PDO::FETCH_ASSOC);
@ -29,13 +31,14 @@ case 'GET':
case 'POST':
require_role(['admin', 'supervisor'], $tokenRec);
$body = read_json_body();
if (empty($body['questionID']) || !isset($body['defaultText'])) {
json_error('MISSING_FIELDS', 'questionID and defaultText required', 400);
if (empty($body['questionID']) || empty($body['optionKey']) || !isset($body['defaultText'])) {
json_error('MISSING_FIELDS', 'questionID, optionKey, and defaultText (German label) required', 400);
}
$id = bin2hex(random_bytes(16));
$qID = $body['questionID'];
$optKey = qdb_validate_stable_key((string)$body['optionKey'], 'Option key');
$text = trim($body['defaultText']);
qdb_require_non_empty_german($text);
qdb_require_non_empty_german($text, 'German label');
$points = (int)($body['points'] ?? 0);
$order = (int)($body['orderIndex'] ?? 0);
$nextQ = trim($body['nextQuestionId'] ?? '');
@ -53,14 +56,17 @@ case 'POST':
$max->execute([':id' => $qID]);
$order = (int)$max->fetchColumn();
}
qdb_assert_unique_option_key($pdo, $qID, $optKey);
$pdo->prepare('INSERT INTO answer_option (answerOptionID, questionID, defaultText, points, orderIndex, nextQuestionId) VALUES (:id, :qid, :t, :p, :o, :nq)')
->execute([':id' => $id, ':qid' => $qID, ':t' => $text, ':p' => $points, ':o' => $order, ':nq' => $nextQ]);
->execute([':id' => $id, ':qid' => $qID, ':t' => $optKey, ':p' => $points, ':o' => $order, ':nq' => $nextQ]);
qdb_upsert_source_translation($pdo, 'answer_option', $id, $text);
qdb_save($tmpDb, $lockFp);
json_success(['answerOption' => [
'answerOptionID' => $id,
'questionID' => $qID,
'defaultText' => $text,
'optionKey' => $optKey,
'defaultText' => $optKey,
'labelGerman' => $text,
'points' => $points,
'orderIndex' => $order,
'nextQuestionId' => $nextQ,
@ -90,20 +96,32 @@ case 'PUT':
qdb_discard($tmpDb, $lockFp);
json_error('NOT_FOUND', 'Answer option not found', 404);
}
$text = trim($body['defaultText'] ?? $row['defaultText']);
qdb_require_non_empty_german($text);
$optKey = isset($body['optionKey'])
? qdb_validate_stable_key((string)$body['optionKey'], 'Option key')
: qdb_option_key($row);
if ($optKey === '') {
json_error('MISSING_FIELDS', 'optionKey is required', 400);
}
$labelGerman = trim($body['defaultText'] ?? $body['labelGerman'] ?? '');
if ($labelGerman === '') {
$labelGerman = qdb_option_german_label($pdo, $id, $row['defaultText']);
}
qdb_require_non_empty_german($labelGerman, 'German label');
qdb_assert_unique_option_key($pdo, $row['questionID'], $optKey, $id);
$points = (int)($body['points'] ?? $row['points']);
$order = (int)($body['orderIndex'] ?? $row['orderIndex']);
$nextQ = trim($body['nextQuestionId'] ?? $row['nextQuestionId']);
$pdo->prepare('UPDATE answer_option SET defaultText = :t, points = :p, orderIndex = :o, nextQuestionId = :nq WHERE answerOptionID = :id')
->execute([':t' => $text, ':p' => $points, ':o' => $order, ':nq' => $nextQ, ':id' => $id]);
qdb_upsert_source_translation($pdo, 'answer_option', $id, $text);
->execute([':t' => $optKey, ':p' => $points, ':o' => $order, ':nq' => $nextQ, ':id' => $id]);
qdb_upsert_source_translation($pdo, 'answer_option', $id, $labelGerman);
qdb_save($tmpDb, $lockFp);
json_success(['answerOption' => [
'answerOptionID' => $id,
'questionID' => $row['questionID'],
'defaultText' => $text,
'optionKey' => $optKey,
'defaultText' => $optKey,
'labelGerman' => $labelGerman,
'points' => $points,
'orderIndex' => $order,
'nextQuestionId' => $nextQ,