This commit is contained in:
106
common.php
106
common.php
@ -1728,6 +1728,7 @@ function qdb_translation_row_label(array $e): string {
|
||||
|
||||
/** Export one questionnaire with structure + all translations (portable JSON). */
|
||||
function qdb_export_questionnaire_bundle(PDO $pdo, string $qnID): ?array {
|
||||
require_once __DIR__ . '/lib/scoring.php';
|
||||
$qn = $pdo->prepare('SELECT * FROM questionnaire WHERE questionnaireID = :id');
|
||||
$qn->execute([':id' => $qnID]);
|
||||
$qnRow = $qn->fetch(PDO::FETCH_ASSOC);
|
||||
@ -1779,6 +1780,7 @@ function qdb_export_questionnaire_bundle(PDO $pdo, string $qnID): ?array {
|
||||
'isRequired' => (int)$dbQ['isRequired'],
|
||||
'config' => $config,
|
||||
'answerOptions' => $optionsOut,
|
||||
'scoreRules' => qdb_get_score_rules_for_question($pdo, $dbQ['questionID']),
|
||||
'translations' => qdb_fetch_translation_map($pdo, 'question', $dbQ['questionID']),
|
||||
];
|
||||
}
|
||||
@ -1823,14 +1825,21 @@ function qdb_export_all_questionnaires_bundle(PDO $pdo): array {
|
||||
}
|
||||
}
|
||||
return [
|
||||
'exportVersion' => 1,
|
||||
'exportVersion' => 2,
|
||||
'exportedAt' => time(),
|
||||
'sourceLanguage' => QDB_SOURCE_LANGUAGE,
|
||||
'questionnaireCount' => count($items),
|
||||
'questionnaires' => $items,
|
||||
'scoringProfiles' => qdb_export_scoring_profiles_bundle($pdo),
|
||||
];
|
||||
}
|
||||
|
||||
/** Export all scoring profiles for bundle portability. */
|
||||
function qdb_export_scoring_profiles_bundle(PDO $pdo): array {
|
||||
require_once __DIR__ . '/lib/scoring.php';
|
||||
return qdb_list_scoring_profiles($pdo);
|
||||
}
|
||||
|
||||
/** Remove questionnaire and related rows (no client_answer cleanup for other qns). */
|
||||
function qdb_delete_questionnaire_cascade(PDO $pdo, string $qnID): void {
|
||||
$qIds = $pdo->prepare('SELECT questionID FROM question WHERE questionnaireID = :id');
|
||||
@ -1957,6 +1966,11 @@ function qdb_import_questionnaire_bundle(PDO $pdo, array $item, bool $replaceIfE
|
||||
qdb_apply_translation_map($pdo, 'question', $questionID, is_array($qTr) ? $qTr : []);
|
||||
qdb_sync_question_note_strings($pdo, $questionKey, $config);
|
||||
|
||||
if (!empty($q['scoreRules']) && is_array($q['scoreRules'])) {
|
||||
require_once __DIR__ . '/lib/scoring.php';
|
||||
qdb_sync_question_score_rules($pdo, $questionID, $q['scoreRules']);
|
||||
}
|
||||
|
||||
foreach ($q['answerOptions'] ?? [] as $opt) {
|
||||
$optKey = trim((string)($opt['optionKey'] ?? ''));
|
||||
$optGerman = trim($opt['defaultText'] ?? '');
|
||||
@ -2213,12 +2227,102 @@ function qdb_import_questionnaires_bundle(PDO $pdo, array $bundle, bool $replace
|
||||
foreach ($items as $item) {
|
||||
$results[] = qdb_import_questionnaire_bundle($pdo, $item, $replaceIfExists);
|
||||
}
|
||||
if (!empty($bundle['scoringProfiles']) && is_array($bundle['scoringProfiles'])) {
|
||||
qdb_import_scoring_profiles_bundle($pdo, $bundle['scoringProfiles'], $replaceIfExists);
|
||||
}
|
||||
return [
|
||||
'imported' => count($results),
|
||||
'results' => $results,
|
||||
];
|
||||
}
|
||||
|
||||
/** Import scoring profiles from a questionnaire bundle. */
|
||||
function qdb_import_scoring_profiles_bundle(PDO $pdo, array $profiles, bool $replaceIfExists = false): void {
|
||||
require_once __DIR__ . '/lib/scoring.php';
|
||||
foreach ($profiles as $profile) {
|
||||
if (!is_array($profile)) {
|
||||
continue;
|
||||
}
|
||||
$wantedId = trim($profile['profileID'] ?? '');
|
||||
$name = trim($profile['name'] ?? '');
|
||||
if ($name === '') {
|
||||
continue;
|
||||
}
|
||||
$exists = false;
|
||||
if ($wantedId !== '') {
|
||||
$chk = $pdo->prepare('SELECT 1 FROM scoring_profile WHERE profileID = :id');
|
||||
$chk->execute([':id' => $wantedId]);
|
||||
$exists = (bool)$chk->fetch();
|
||||
}
|
||||
if ($exists && $replaceIfExists) {
|
||||
$pdo->prepare('DELETE FROM scoring_profile WHERE profileID = :id')->execute([':id' => $wantedId]);
|
||||
$profileID = $wantedId;
|
||||
} elseif ($exists) {
|
||||
$profileID = bin2hex(random_bytes(16));
|
||||
} else {
|
||||
$profileID = $wantedId !== '' ? $wantedId : bin2hex(random_bytes(16));
|
||||
}
|
||||
$now = time();
|
||||
$pdo->prepare(
|
||||
'INSERT INTO scoring_profile (profileID, name, description, isActive,
|
||||
greenMin, greenMax, yellowMin, yellowMax, redMin, createdAt, updatedAt)
|
||||
VALUES (:id, :name, :desc, :act, :gmin, :gmax, :ymin, :ymax, :rmin, :ca, :ua)'
|
||||
)->execute([
|
||||
':id' => $profileID,
|
||||
':name' => $name,
|
||||
':desc' => trim($profile['description'] ?? ''),
|
||||
':act' => !empty($profile['isActive']) ? 1 : 0,
|
||||
':gmin' => (int)($profile['greenMin'] ?? 0),
|
||||
':gmax' => (int)($profile['greenMax'] ?? 12),
|
||||
':ymin' => (int)($profile['yellowMin'] ?? ((int)($profile['greenMax'] ?? 12) + 1)),
|
||||
':ymax' => (int)($profile['yellowMax'] ?? 36),
|
||||
':rmin' => (int)($profile['redMin'] ?? ((int)($profile['yellowMax'] ?? 36) + 1)),
|
||||
':ca' => (int)($profile['createdAt'] ?? $now),
|
||||
':ua' => (int)($profile['updatedAt'] ?? $now),
|
||||
]);
|
||||
$members = [];
|
||||
foreach ($profile['questionnaires'] ?? [] as $idx => $row) {
|
||||
if (!is_array($row)) {
|
||||
continue;
|
||||
}
|
||||
$qnID = trim((string)($row['questionnaireID'] ?? ''));
|
||||
if ($qnID === '') {
|
||||
continue;
|
||||
}
|
||||
$chk = $pdo->prepare('SELECT 1 FROM questionnaire WHERE questionnaireID = :id');
|
||||
$chk->execute([':id' => $qnID]);
|
||||
if (!$chk->fetch()) {
|
||||
continue;
|
||||
}
|
||||
$members[] = [
|
||||
'questionnaireID' => $qnID,
|
||||
'weight' => (float)($row['weight'] ?? 1.0),
|
||||
'orderIndex' => (int)($row['orderIndex'] ?? $idx),
|
||||
];
|
||||
}
|
||||
if ($members !== []) {
|
||||
qdb_sync_profile_questionnaire_members($pdo, $profileID, $members);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function qdb_sync_profile_questionnaire_members(PDO $pdo, string $profileID, array $members): void {
|
||||
$pdo->prepare('DELETE FROM scoring_profile_questionnaire WHERE profileID = :pid')
|
||||
->execute([':pid' => $profileID]);
|
||||
$ins = $pdo->prepare(
|
||||
'INSERT INTO scoring_profile_questionnaire (profileID, questionnaireID, weight, orderIndex)
|
||||
VALUES (:pid, :qn, :w, :o)'
|
||||
);
|
||||
foreach ($members as $m) {
|
||||
$ins->execute([
|
||||
':pid' => $profileID,
|
||||
':qn' => $m['questionnaireID'],
|
||||
':w' => $m['weight'],
|
||||
':o' => $m['orderIndex'],
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
// --- AES-256-CBC: IV(16) + CIPHERTEXT ---
|
||||
function aes256_cbc_encrypt_bytes(string $plain, string $key): string {
|
||||
$key = str_pad(substr($key, 0, 32), 32, "\0");
|
||||
|
||||
Reference in New Issue
Block a user