false, 'message' => 'Keine Config-Datei ausgewählt' ]); exit; } $wkvsJSONVersion = '1.0.0'; $type = 'wkl'; $data = include $baseDir . '/../scripts/db/db-verbindung-script.php'; if ($data['success'] === false){ echo json_encode(['success' => false, 'message' => $data['message']]); exit; } require $baseDir . '/../scripts/db/db-tables.php'; require $baseDir . '/../scripts/db/db-functions.php'; require $baseDir . '/../scripts/string-calculator/string-calculator-functions.php'; $saveDir = '/../private-files/config-uploads/'; $uploadDir = $baseDir . $saveDir; if (!is_dir($uploadDir)) { mkdir($uploadDir, 0755, true); } $tmpPath = $_FILES['configFile']['tmp_name']; $originalName = $_FILES['configFile']['name']; $extension = strtolower(pathinfo($originalName, PATHINFO_EXTENSION)); $allowedExt = ['json']; if (!in_array($extension, $allowedExt, true)) { echo json_encode(['success' => false, 'message' => 'Falsches Format (Endung)']); http_response_code(422); exit; } $finfo = new finfo(FILEINFO_MIME_TYPE); $mimeType = $finfo->file($tmpPath); $allowedMime = ['application/json']; if (!in_array($mimeType, $allowedMime, true)) { echo json_encode(['success' => false, 'message' => 'Dateiinhalt ist kein gültiges JSON']); http_response_code(422); exit; } $filename = date("Y_m_d_H_i_s") . '-wkvs-config.json'; $destination = $uploadDir . $filename; if (!move_uploaded_file($tmpPath, $destination)) { http_response_code(500); exit; } $JSONcontent = file_get_contents($destination); $content = json_decode($JSONcontent, true); if (json_last_error() !== JSON_ERROR_NONE) { die("Invalid JSON layout."); } if (!isset($content['metadata']['wkvs_json_version']) || $content['metadata']['wkvs_json_version'] !== $wkvsJSONVersion) { echo json_encode(['success' => false, 'message' => 'Inkompatible Datei-Version. (V ' . $wkvsJSONVersion . ' benötigt'. (isset($content['metadata']['wkvs_json_version']) ? ", benutzte Datei-Version: V " . $content['metadata']['wkvs_json_version'] : '') . ')' ]); unlink($destination); http_response_code(422); exit; } if (!isset($content['noten']) || !is_array($content['noten']) || !isset($content['disziplinen']) || !is_array($content['disziplinen'])) { echo json_encode(['success' => false, 'message' => 'Ungültige JSON-Struktur']); unlink($destination); http_response_code(422); exit; } $content['added_timestamp'] = date("Y-m-d H:i:s"); file_put_contents($destination, json_encode($content)); $allowedColumns = [ 'noten' => [ 'id', 'name', 'default_value', 'type', 'berechnung', 'berechnung_json', 'max_value', 'min_value', 'pro_geraet', 'anzahl_laeufe_json', 'geraete_json', 'nullstellen', 'display_string' ], 'disziplinen' => ['id', 'name', 'start_index', 'color_kampfrichter', 'audiofile'], 'zeitplan_typen' => ['id', 'name', 'has_endtime', 'display_index'], 'leistungsklassen' => ['id', 'programm', 'order_index', 'preis', 'aktiv'] ]; $tableTable = [ 'noten' => $tableNotenBezeichnungen, 'disziplinen' => $tableGeraete, 'zeitplan_typen' => $tableZeitplanTypes, 'leistungsklassen' => $tableProgramme ]; $successCount = 0; try { $mysqli->begin_transaction(); foreach ($allowedColumns as $type => $columns) { $tableName = "`" . $tableTable[$type] . "`"; $mysqli->query("DELETE FROM " . $tableName); $columnsSql = implode(', ', array_map(fn($col) => "`$col`", $columns)); $placeholdersSql = implode(', ', array_fill(0, count($columns), '?')); $sql = "INSERT INTO " . $tableName . " ($columnsSql) VALUES ($placeholdersSql)"; $typesString = str_repeat('s', count($columns)); $stmt = $mysqli->prepare($sql); foreach ($content[$type] as $index => $row) { $bindValues = []; foreach ($columns as $column) { if (!array_key_exists($column, $row) || $row[$column] === null) { $bindValues[] = null; } else { $bindValues[] = $row[$column]; } } $stmt->bind_param($typesString, ...$bindValues); $stmt->execute(); $successCount++; } $stmt->close(); } $rangNote = intval($content['rang_konfiguration']['rang_note_id'] ?? 0); $orderBestRang = $content['rang_konfiguration']['order_best_rang'] ?? ''; $allowableOrderValues = ['ASC', 'DESC']; if ($rangNote > 0) { $mysqli->query("INSERT INTO $tableVar (`name`, `value`) VALUES ('rangNote', '" . $rangNote . "') ON DUPLICATE KEY UPDATE `value` = VALUES(`value`)"); } if (in_array($orderBestRang, $allowableOrderValues, true)) { $mysqli->query("INSERT INTO $tableVar (`name`, `value`) VALUES ('orderBestRang', '" . $orderBestRang . "') ON DUPLICATE KEY UPDATE `value` = VALUES(`value`)"); } if (isset($content['bezeichnungen']['singular']) && $content['bezeichnungen']['singular'] !== null) { $stmt = $mysqli->prepare("INSERT INTO $tableVar (`name`, `value`) VALUES (?, ?) ON DUPLICATE KEY UPDATE `value` = VALUES(`value`)"); $varName = 'personEinzahl'; $stmt->bind_param("ss", $varName, $content['bezeichnungen']['singular']); $stmt->execute(); $stmt->close(); } if (isset($content['bezeichnungen']['plural']) && $content['bezeichnungen']['plural'] !== null) { $stmt = $mysqli->prepare("INSERT INTO $tableVar (`name`, `value`) VALUES (?, ?) ON DUPLICATE KEY UPDATE `value` = VALUES(`value`)"); $varName = 'personMehrzahl'; $stmt->bind_param("ss", $varName, $content['bezeichnungen']['plural']); $stmt->execute(); $stmt->close(); } $noten = db_select($mysqli, $tableNotenBezeichnungen, "id, berechnung, type"); $notenById = array_column($noten, null, 'id'); $berechnungen = []; foreach ($notenById as $id => $sn) { if ($sn['type'] === 'berechnung') { $berechnungen[] = $sn; } } if (empty($berechnungen)) { $mysqli->commit(); echo json_encode(['success' => true, 'message' => "Successfully imported $successCount rows."]); exit; } $notenRechner = new NotenRechner(); $dependencyMap = []; foreach ($berechnungen as $calc) { $neededIdsArrayWithRun = $notenRechner->getBenoetigteIdsComplexWithRun($calc['berechnung']); if (empty($neededIdsArrayWithRun) || count($neededIdsArrayWithRun) < 2) { continue; } $calcId = (int)$calc['id']; $neededIdsArray = $neededIdsArrayWithRun; unset($neededIdsArray['targetRun']); unset($neededIdsArray['targetGeraet']); $targetRunId = $neededIdsArrayWithRun['targetRun']; foreach ($neededIdsArray as $key => $needed) { $nId = (int)$needed['noteId']; $gId = is_numeric($needed['geraetId']) ? (int)$needed['geraetId'] : $needed['geraetId']; $nodeKey = $calcId . '|' . $gId . '|' . $targetRunId; if (!isset($dependencyMap[$nId])) { $dependencyMap[$nId] = []; } $dependencyMap[$nId][$nodeKey] = [$calcId, $gId, [$targetRunId]]; } } function getCompleteDependencyChain($id, $directMap, $visited = []) { if (!isset($directMap[$id])) { return []; } $allDependencies = []; foreach ($directMap[$id] as $nodeKey => $complexNode) { if (isset($visited[$nodeKey])) { continue; } $visited[$nodeKey] = true; $allDependencies[$nodeKey] = $complexNode; $childDependencies = getCompleteDependencyChain($complexNode[0], $directMap, $visited); foreach ($childDependencies as $childKey => $childNode) { $allDependencies[$childKey] = $childNode; $visited[$childKey] = true; } } return $allDependencies; } $flatDependencyMap = []; foreach (array_keys($notenById) as $id) { $chain = getCompleteDependencyChain($id, $dependencyMap); if (!empty($chain)) { $flatDependencyMap[$id] = array_values($chain); } } $resetSql = "UPDATE $tableNotenBezeichnungen SET `berechnung_json` = NULL"; $mysqli->query($resetSql); // Step 2: Prepare the statement $updateSql = "UPDATE $tableNotenBezeichnungen SET `berechnung_json` = ? WHERE id = ?"; $stmt = $mysqli->prepare($updateSql); foreach ($flatDependencyMap as $id => $completeDependencyArray) { if (empty($completeDependencyArray)) { continue; } $jsonString = json_encode($completeDependencyArray); $stmt->bind_param("si", $jsonString, $id); $stmt->execute(); } $stmt->close(); $mysqli->commit(); echo json_encode(['success' => true, 'message' => "Successfully imported $successCount rows."]); require_once $baseDir . '/../scripts/cache/cache-creators/regenerate-display-dependencies-cache.php'; require_once $baseDir . '/../scripts/cache/cache-creators/regenerate-noten-cache.php'; generateIntersectCache($mysqli, $baseDir); regenerate_noten_cache($mysqli, $tableNotenBezeichnungen, $baseDir); } catch (mysqli_sql_exception $e) { $mysqli->rollback(); unlink($destination); if ($e->getCode() === 1048) { http_response_code(400); echo json_encode(['success' => false, 'message' => "Import failed: A required data field is missing in your preset file."]); exit; } else { http_response_code(400); echo json_encode(['success' => false, 'message' => "Database error during import." . " Error Code: " . $e->getMessage()]); exit; } } finally { $mysqli->close(); $allFiles = glob($uploadDir . '*.json'); $timestamps = array_map(function($file) { $jsonContent = file_get_contents($file) ?? ''; $data = json_decode($jsonContent, true) ?? []; return $data['added_timestamp'] ?? 0; }, $allFiles); array_multisort($timestamps, SORT_DESC, $allFiles); $filesToDelete = array_slice($allFiles, 3); foreach ($filesToDelete as $file) { unlink($file); } }