351 lines
11 KiB
PHP
351 lines
11 KiB
PHP
<?php
|
|
|
|
ini_set("display_errors",1);
|
|
|
|
if (!isset($baseDir)) $baseDir = $_SERVER['DOCUMENT_ROOT'];
|
|
|
|
require_once $baseDir . '/../scripts/session_functions.php';
|
|
|
|
ini_wkvs_session();
|
|
|
|
check_user_permission('wk_leitung');
|
|
|
|
verify_csrf();
|
|
|
|
if (!isset($_FILES['configFile']) || $_FILES['configFile']['error'] !== UPLOAD_ERR_OK) {
|
|
echo json_encode([
|
|
'success' => 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);
|
|
}
|
|
}
|
|
|
|
|