$err]); exit; } [$pdo, $tmpDb, $lockFp] = qdb_open(true); try { $pdo->beginTransaction(); foreach ($orderData as $orderIdx => $entry) { $filename = $entry['file']; $showPoints = (int)($entry['showPoints'] ?? 0); $condition = json_encode($entry['condition'] ?? new stdClass()); $jsonPath = $assetsDir . '/' . $filename; $qData = json_decode(file_get_contents($jsonPath), true); if (!$qData) { throw new Exception("Could not parse $filename"); } $questionnaireID = $qData['meta']['id']; $name = str_replace('_', ' ', preg_replace('/^questionnaire_\d+_/', '', $questionnaireID)); $name = ucwords($name); out("Importing: $questionnaireID ($name)", $isCli); $pdo->prepare("INSERT OR REPLACE INTO questionnaire (questionnaireID, name, version, state, orderIndex, showPoints, conditionJson) VALUES (:id, :n, :v, :s, :o, :sp, :cj)") ->execute([ ':id' => $questionnaireID, ':n' => $name, ':v' => '1.0', ':s' => 'active', ':o' => $orderIdx, ':sp' => $showPoints, ':cj' => $condition, ]); $questions = $qData['questions'] ?? []; foreach ($questions as $qIdx => $q) { $qLocalId = $q['id']; $layout = $q['layout']; $qKey = $q['question'] ?? ''; $questionID = $questionnaireID . '__' . $qLocalId; $config = []; if (isset($q['textKey'])) $config['textKey'] = $q['textKey']; if (isset($q['textKey1'])) $config['textKey1'] = $q['textKey1']; if (isset($q['textKey2'])) $config['textKey2'] = $q['textKey2']; if (isset($q['hint'])) $config['hint'] = $q['hint']; if (isset($q['hint1'])) $config['hint1'] = $q['hint1']; if (isset($q['hint2'])) $config['hint2'] = $q['hint2']; if (isset($q['symptoms'])) $config['symptoms'] = $q['symptoms']; if (isset($q['range'])) $config['range'] = $q['range']; if (isset($q['constraints'])) $config['constraints'] = $q['constraints']; if (isset($q['minSelection'])) $config['minSelection'] = $q['minSelection']; if (isset($q['maxLength'])) $config['maxLength'] = (int)$q['maxLength']; if (!empty($q['multiline'])) $config['multiline'] = true; if (isset($q['otherNextQuestionId'])) $config['otherNextQuestionId'] = $q['otherNextQuestionId']; if (isset($q['otherOptionKey'])) $config['otherOptionKey'] = $q['otherOptionKey']; if (isset($q['config']) && is_array($q['config'])) { foreach (['otherNextQuestionId', 'otherOptionKey', 'hint', 'maxLength', 'multiline', 'textKey'] as $ck) { if (isset($q['config'][$ck])) { $config[$ck] = $q['config'][$ck]; } } } if ($layout === 'string_spinner' && isset($q['options']) && is_array($q['options']) && isset($q['options'][0]) && is_string($q['options'][0])) { $config['options'] = $q['options']; } if ($layout === 'value_spinner' && isset($q['options']) && is_array($q['options'])) { $valueOptions = []; foreach ($q['options'] as $vo) { if (is_array($vo) && isset($vo['value'])) { $valueOptions[] = $vo; } } if ($valueOptions) { $config['valueOptions'] = $valueOptions; } } $configJson = !empty($config) ? json_encode($config) : '{}'; $pdo->prepare("INSERT OR REPLACE INTO question (questionID, questionnaireID, defaultText, type, orderIndex, isRequired, configJson) VALUES (:id, :qnid, :dt, :ty, :oi, :ir, :cj)") ->execute([ ':id' => $questionID, ':qnid' => $questionnaireID, ':dt' => $qKey, ':ty' => $layout, ':oi' => $qIdx, ':ir' => 0, ':cj' => $configJson, ]); if (isset($q['options']) && is_array($q['options'])) { $hasObjects = isset($q['options'][0]) && is_array($q['options'][0]); if ($hasObjects) { $pointsMap = $q['pointsMap'] ?? []; foreach ($q['options'] as $optIdx => $opt) { $optKey = $opt['key'] ?? ''; if (!$optKey) continue; $nextQId = ''; if (isset($opt['nextQuestionId'])) { $nextQId = $opt['nextQuestionId']; } $pts = (int)($pointsMap[$optKey] ?? 0); $answerOptionID = $questionID . '__opt_' . $optIdx; $pdo->prepare("INSERT OR REPLACE INTO answer_option (answerOptionID, questionID, defaultText, points, orderIndex, nextQuestionId) VALUES (:id, :qid, :dt, :p, :oi, :nq)") ->execute([ ':id' => $answerOptionID, ':qid' => $questionID, ':dt' => $optKey, ':p' => $pts, ':oi' => $optIdx, ':nq' => $nextQId, ]); } } } } out(" -> " . count($questions) . " questions imported", $isCli); } $pdo->commit(); qdb_save($tmpDb, $lockFp); if ($isCli) { echo "\nImport complete.\n"; } else { echo json_encode(["success" => true, "message" => "Import complete"]); } } catch (Throwable $e) { if ($pdo->inTransaction()) $pdo->rollBack(); qdb_discard($tmpDb, $lockFp); if ($isCli) { die("ERROR: " . $e->getMessage() . "\n"); } http_response_code(500); error_log($e->getMessage()); echo json_encode(["error" => "Server error"]); }