New Filestructure for Docker
This commit is contained in:
@@ -0,0 +1,38 @@
|
||||
<?php
|
||||
|
||||
if (!isset($baseDir)) {
|
||||
$baseDir = $_SERVER['DOCUMENT_ROOT'];
|
||||
}
|
||||
|
||||
require_once $baseDir . '/../scripts/session_functions.php';
|
||||
|
||||
ini_wkvs_session();
|
||||
|
||||
verify_csrf();
|
||||
|
||||
$accessPermission = trim($_POST['accessPermission'] ?? '');
|
||||
|
||||
$access = preg_replace("/[\W]/", "", trim($_POST['access'] ?? ''));
|
||||
$accesstype = preg_replace("/[\W]/", "", trim($_POST['accesstype'] ?? ''));
|
||||
|
||||
if ($accessPermission === '' || $access === '' || $accesstype === '') {
|
||||
echo json_encode(['success' => false, 'message' => 'Parameters not correctly set']);
|
||||
http_response_code(400);
|
||||
exit;
|
||||
}
|
||||
|
||||
require $baseDir . "/../scripts/websocket/ws-create-token.php";
|
||||
|
||||
if ($accessPermission === "R") {
|
||||
$token = generateWSReadToken($accesstype, $access);
|
||||
} elseif ($accessPermission === "W") {
|
||||
check_multiple_allowed_permissions(['kampfrichter', 'wk_leitung']);
|
||||
$token = generateWSAdminToken($accesstype, $access);
|
||||
} else {
|
||||
http_response_code(403);
|
||||
exit;
|
||||
}
|
||||
|
||||
$responseBool = $token != null;
|
||||
|
||||
echo json_encode(['success' => $responseBool, 'token' => $token]);
|
||||
@@ -0,0 +1,41 @@
|
||||
<?php
|
||||
|
||||
if (!isset($baseDir)) {
|
||||
$baseDir = $_SERVER['DOCUMENT_ROOT'];
|
||||
}
|
||||
|
||||
require_once $baseDir . '/../scripts/session_functions.php';
|
||||
|
||||
ini_wkvs_session();
|
||||
|
||||
verify_csrf();
|
||||
|
||||
$new_value = $_POST['freigabe'] ?? '';
|
||||
|
||||
$type = $_POST['type'] ?? 'nan';
|
||||
|
||||
$allowedTypes = ['kampfrichter', 'trainer'];
|
||||
|
||||
if (in_array($type, $allowedTypes)) {
|
||||
check_user_permission($type);
|
||||
} else {
|
||||
echo json_encode(['success' => false, 'message' => 'no permissions']);
|
||||
exit;
|
||||
}
|
||||
|
||||
if (!$new_value) {
|
||||
echo json_encode('Invalid Input');
|
||||
exit;
|
||||
}
|
||||
|
||||
if ($type === 'kampfrichter'){
|
||||
$_SESSION['selectedFreigabeIdKampfrichter'] = $new_value;
|
||||
}
|
||||
|
||||
if ($type === 'trainer'){
|
||||
$_SESSION['selectedFreigabeTrainer'] = $new_value;
|
||||
}
|
||||
|
||||
// ---------- Return JSON ----------
|
||||
echo json_encode(['success' => true, 'message' => 'SESSION updated']);
|
||||
exit;
|
||||
@@ -0,0 +1,4 @@
|
||||
upload_max_filesize = 50M
|
||||
post_max_size = 55M
|
||||
max_execution_time = 120
|
||||
max_input_time = 120
|
||||
@@ -0,0 +1,150 @@
|
||||
<?php
|
||||
|
||||
if (!isset($baseDir)) $baseDir = $_SERVER['DOCUMENT_ROOT'];
|
||||
|
||||
require_once $baseDir . '/../scripts/session_functions.php';
|
||||
|
||||
ini_wkvs_session();
|
||||
|
||||
check_multiple_allowed_permissions(['trainer', 'wk_leitung']);
|
||||
|
||||
verify_csrf();
|
||||
|
||||
$isTrainer = isset($_SESSION['access_granted_trainer']) && $_SESSION['access_granted_trainer'];
|
||||
$userId = $isTrainer ? intval($_SESSION['user_id_trainer'] ?? 0) : intval($_SESSION['user_id_wk_leitung'] ?? 0);
|
||||
|
||||
// Allow large uploads and enough memory for GD processing
|
||||
ini_set('memory_limit', '256M');
|
||||
ini_set('max_execution_time', '120');
|
||||
|
||||
|
||||
if (!isset($_FILES['music_file']) || $_FILES['music_file']['error'] !== UPLOAD_ERR_OK) {
|
||||
echo json_encode([
|
||||
'success' => false,
|
||||
'message' => 'Keine Musik' . $_FILES['music_file']['error'] ?? 'NO ERROR KNOWN'
|
||||
]);
|
||||
exit;
|
||||
}
|
||||
|
||||
$type = ($isTrainer) ? 'tr' : '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';
|
||||
|
||||
$saveDir = '/files/music/';
|
||||
|
||||
$normalDir = $saveDir;
|
||||
|
||||
$uploadDir = $baseDir . $saveDir;
|
||||
|
||||
$maxLengthMusic = 0;
|
||||
|
||||
if ($isTrainer) {
|
||||
$geraet_id = (int) $_POST['geraetId'] ?? 0;
|
||||
|
||||
$geraet_exists = db_get_var($mysqli, "SELECT 1 FROM $db_tabelle_disziplinen WHERE `id` = ?", [$geraet_id]);
|
||||
|
||||
if ($geraet_exists === null) {
|
||||
http_response_code(400);
|
||||
echo json_encode(['success' => false, 'message' => 'Invalides Gerät angegeben.']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$geraet_max_duration_audio_db = db_get_var($mysqli, "SELECT `audiofile_max_duration` FROM $db_tabelle_disziplinen WHERE `id` = ?", [$geraet_id]);
|
||||
|
||||
$maxLengthMusic = (int) $geraet_max_duration_audio_db;
|
||||
}
|
||||
|
||||
if (!is_dir($uploadDir)) {
|
||||
mkdir($uploadDir, 0755, true);
|
||||
}
|
||||
|
||||
|
||||
$tmpPath = $_FILES['music_file']['tmp_name'];
|
||||
$originalName = $_FILES['music_file']['name'];
|
||||
$extension = strtolower(pathinfo($originalName, PATHINFO_EXTENSION));
|
||||
|
||||
$allowedExt = ['mp3', 'wav', 'ogg'];
|
||||
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 = ['audio/mpeg', 'audio/wav', 'audio/x-wav', 'audio/ogg', 'application/ogg'];
|
||||
|
||||
if (!in_array($mimeType, $allowedMime, true)) {
|
||||
echo json_encode(['success' => false, 'message' => 'Dateiinhalt ist kein gültiges Audio']);
|
||||
http_response_code(422);
|
||||
exit;
|
||||
}
|
||||
|
||||
|
||||
$filename = uniqid('userupload_', true) . '.' . $extension;
|
||||
$destination = $uploadDir . $filename;
|
||||
$normalPath = $normalDir . $filename;
|
||||
|
||||
|
||||
if (!move_uploaded_file($tmpPath, $destination)) {
|
||||
http_response_code(500);
|
||||
exit;
|
||||
}
|
||||
|
||||
if ($isTrainer && $maxLengthMusic !== null && intval($maxLengthMusic) !== 0) {
|
||||
require $baseDir . '/../composer/vendor/autoload.php';
|
||||
|
||||
$getID3 = new getID3;
|
||||
$fileInfo = $getID3->analyze($destination);
|
||||
|
||||
if (empty($fileInfo['playtime_seconds'])) {
|
||||
http_response_code(400);
|
||||
echo json_encode([
|
||||
'success' => false,
|
||||
'message' => 'Fehler beim Bestimmen der Musiklänge'
|
||||
]);
|
||||
exit;
|
||||
}
|
||||
|
||||
$duration = (float) $fileInfo['playtime_seconds'];
|
||||
|
||||
if ($duration > intval($maxLengthMusic)) {
|
||||
unlink($destination);
|
||||
echo json_encode([
|
||||
'success' => false,
|
||||
'message' => 'Musik zu lange (über ' . intval($maxLengthMusic) . ' Sekunden)'
|
||||
]);
|
||||
http_response_code(422);
|
||||
exit;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
$sql = "INSERT INTO $db_tabelle_audiofiles (`file_name`,`file_path`,`edited_by`) VALUES (?, ?, ?)";
|
||||
|
||||
$stmt = $mysqli->prepare($sql);
|
||||
$stmt->bind_param("ssi", $originalName, $normalPath, $userId);
|
||||
|
||||
if (!$stmt->execute()) {
|
||||
http_response_code(500);
|
||||
exit;
|
||||
}
|
||||
|
||||
$id = $mysqli->insert_id;
|
||||
|
||||
$stmt->close();
|
||||
|
||||
echo json_encode([
|
||||
'success' => true,
|
||||
'id' => $id,
|
||||
'filename' => $originalName,
|
||||
'filepath' => $normalPath
|
||||
]);
|
||||
@@ -0,0 +1,77 @@
|
||||
<?php
|
||||
header('Content-Type: application/json');
|
||||
|
||||
if (!isset($baseDir)) {
|
||||
$baseDir = $_SERVER['DOCUMENT_ROOT'];
|
||||
}
|
||||
|
||||
require_once $baseDir . '/../scripts/session_functions.php';
|
||||
|
||||
ini_wkvs_session();
|
||||
|
||||
check_user_permission('wk_leitung');
|
||||
|
||||
verify_csrf();
|
||||
|
||||
// ---------- Get and sanitize input ----------
|
||||
$type = isset($_POST['type']) ? preg_replace('/[^a-zA-Z0-9 _-]/', '', $_POST['type']) : '';
|
||||
|
||||
$allowed_types = ['logo','scoring','ctext'];
|
||||
if (!in_array($type, $allowed_types)) {
|
||||
echo json_encode(['success' => false, 'message' => 'Invalid type']);
|
||||
exit;
|
||||
}
|
||||
|
||||
if ($type === 'ctext'){
|
||||
$ctext = isset($_POST['ctext']) ? $_POST['ctext'] : '';
|
||||
}
|
||||
|
||||
$folder = realpath($baseDir.'/externe-geraete/json');
|
||||
if ($folder === false) {
|
||||
echo json_encode([
|
||||
'success' => false,
|
||||
'message' => 'Could not find displays folder.'
|
||||
]);
|
||||
exit;
|
||||
}
|
||||
|
||||
$filename = 'config.json';
|
||||
$filepath = $folder . '/' . $filename;
|
||||
|
||||
if (!is_writable($folder)) {
|
||||
echo json_encode(['success' => false, 'message' => 'Folder not writable: ' . $folder]);
|
||||
exit;
|
||||
}
|
||||
|
||||
|
||||
$jsonString = file_get_contents($filepath);
|
||||
|
||||
// decode JSON, fallback to empty array if invalid
|
||||
$oldjson = json_decode($jsonString, true) ?? [];
|
||||
|
||||
$oldjson["type"] = $type;
|
||||
|
||||
if ($type === 'ctext'){
|
||||
$oldjson["ctext"] = $ctext;
|
||||
}
|
||||
|
||||
$jsonData = json_encode($oldjson);
|
||||
|
||||
|
||||
|
||||
// Write file
|
||||
if (file_put_contents($filepath, $jsonData) === false) {
|
||||
echo json_encode([
|
||||
'success' => false,
|
||||
'message' => 'Failed to write JSON file: ' . $filepath
|
||||
]);
|
||||
exit;
|
||||
}
|
||||
|
||||
// ---------- Return JSON ----------
|
||||
echo json_encode([
|
||||
'success' => true,
|
||||
'message' => 'JSON type updated',
|
||||
'disable_start_button' => true
|
||||
]);
|
||||
exit;
|
||||
@@ -0,0 +1,4 @@
|
||||
upload_max_filesize = 50M
|
||||
post_max_size = 55M
|
||||
max_execution_time = 120
|
||||
max_input_time = 120
|
||||
@@ -0,0 +1,97 @@
|
||||
<?php
|
||||
|
||||
header('Content-Type: application/json');
|
||||
|
||||
if (!isset($baseDir)) {
|
||||
$baseDir = $_SERVER['DOCUMENT_ROOT'];
|
||||
}
|
||||
|
||||
require_once $baseDir . '/../scripts/session_functions.php';
|
||||
|
||||
ini_wkvs_session();
|
||||
|
||||
check_user_permission('wk_leitung');
|
||||
|
||||
verify_csrf();
|
||||
|
||||
$type = 'wkl';
|
||||
|
||||
$data = require $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';
|
||||
|
||||
$allowedTypes = [
|
||||
'wkName',
|
||||
'displayCTextLogo',
|
||||
'displayCTextWKName',
|
||||
'displayColourLogo',
|
||||
'displayTextColourLogo',
|
||||
'displayColorScoringBg',
|
||||
'displayColorScoringBgSoft',
|
||||
'displayColorScoringShadowColor',
|
||||
'displayColorScoringBorderColor',
|
||||
'displayColorScoringPanel',
|
||||
'displayColorScoringPanelSoft',
|
||||
'displayColorScoringPanelText',
|
||||
'displayColorScoringPanelTextSoft',
|
||||
'displayColorScoringPanelTextNoteL',
|
||||
'displayColorScoringPanelTextNoteR',
|
||||
'displayIdNoteL',
|
||||
'displayIdNoteR',
|
||||
'rechnungenName',
|
||||
'rechnungenVorname',
|
||||
'rechnungenStrasse',
|
||||
'rechnungenHausnummer',
|
||||
'rechnungenPostleitzahl',
|
||||
'rechnungenOrt',
|
||||
'rechnungenIBAN',
|
||||
'maxLengthMusic',
|
||||
'linkWebseite',
|
||||
'rangNote',
|
||||
'orderBestRang',
|
||||
'rechnungenPostversand',
|
||||
'rechnungenPostversandKosten',
|
||||
'personEinzahl',
|
||||
'personMehrzahl',
|
||||
'rankLivePublic',
|
||||
'riegeneinteilungPublic'
|
||||
];
|
||||
|
||||
$type = $_POST['type'] ? trim($_POST['type']) : '';
|
||||
|
||||
if (!in_array($type, $allowedTypes)) {
|
||||
echo json_encode(['success' => false, 'message' => 'Invalid input']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$value = $_POST['value'] ? trim($_POST['value']) : null;
|
||||
|
||||
// ---------- Step 2: Get values from DB ----------
|
||||
|
||||
|
||||
$stmt = $mysqli->prepare("INSERT INTO $db_tabelle_var (`name`, `value`) VALUES (?, ?) ON DUPLICATE KEY UPDATE `value` = VALUES(`value`)");
|
||||
|
||||
if (!$stmt) {
|
||||
echo json_encode(['success' => false, 'message' => 'Critical db error']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$stmt->bind_param("ss", $type, $value);
|
||||
$success = $stmt->execute();
|
||||
$stmt->close();
|
||||
|
||||
if (!$success) {
|
||||
echo json_encode(['success' => false, 'message' => 'Insert failed']);
|
||||
exit;
|
||||
}
|
||||
|
||||
// Return JSON
|
||||
echo json_encode([
|
||||
'success' => true
|
||||
]);
|
||||
exit;
|
||||
@@ -0,0 +1,93 @@
|
||||
<?php
|
||||
header('Content-Type: application/json');
|
||||
|
||||
if (!isset($baseDir)) {
|
||||
$baseDir = $_SERVER['DOCUMENT_ROOT'];
|
||||
}
|
||||
|
||||
require_once $baseDir . '/../scripts/session_functions.php';
|
||||
|
||||
ini_wkvs_session();
|
||||
|
||||
check_user_permission('wk_leitung');
|
||||
|
||||
verify_csrf();
|
||||
|
||||
require $baseDir . '/../scripts/db/db-functions.php';
|
||||
require $baseDir . '/../scripts/db/db-tables.php';
|
||||
|
||||
$type = 'wkl';
|
||||
$dbconnection = require $baseDir . '/../scripts/db/db-verbindung-script.php';
|
||||
|
||||
if ($dbconnection['success'] !== true){
|
||||
echo json_encode(['success' => false, 'message' => 'Critical DB Error.']);
|
||||
exit;
|
||||
}
|
||||
|
||||
require_once $baseDir . '/../scripts/cache/cache-creators/regenerate-display-dependencies-cache.php';
|
||||
|
||||
$action = $_POST['action'] ?? '';
|
||||
|
||||
if ($action === 'add') {
|
||||
$name = trim($_POST['name'] ?? '');
|
||||
$start_index = intval($_POST['start_index'] ?? 0);
|
||||
$color = trim($_POST['color'] ?? '#424242');
|
||||
$audiofile = intval($_POST['audiofile'] ?? 0);
|
||||
$audiofile_max_duration = (int) $_POST['audiofileMaxDuration'] ?? 0;
|
||||
|
||||
if ($name === '') {
|
||||
echo json_encode(['success' => false, 'message' => 'Name ist erforderlich.']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$stmt = $mysqli->prepare("INSERT INTO $db_tabelle_disziplinen (`name`, `start_index`, `color_kampfrichter`, `audiofile`, `audiofile_max_duration`) VALUES (?, ?, ?, ?, ?)");
|
||||
$stmt->bind_param("sisii", $name, $start_index, $color, $audiofile, $audiofile_max_duration);
|
||||
$success = $stmt->execute();
|
||||
$new_id = $mysqli->insert_id;
|
||||
$stmt->close();
|
||||
|
||||
if ($success) {
|
||||
echo json_encode(['success' => true, 'id' => $new_id]);
|
||||
} else {
|
||||
echo json_encode(['success' => false, 'message' => 'Fehler beim Hinzufügen.']);
|
||||
}
|
||||
|
||||
generateIntersectCache($mysqli, $baseDir);
|
||||
|
||||
} elseif ($action === 'update') {
|
||||
$id = intval($_POST['id'] ?? 0);
|
||||
$field = $_POST['field'] ?? '';
|
||||
$value = $_POST['value'] ?? '';
|
||||
$audiofile = intval($_POST['audiofile'] ?? 0);
|
||||
|
||||
$allowedFields = ['name', 'start_index', 'color_kampfrichter', 'audiofile', 'audiofile_max_duration'];
|
||||
if ($id > 0 && in_array($field, $allowedFields)) {
|
||||
if ($field === 'start_index' || $field === 'audiofile' || $field === 'audiofile_max_duration') {
|
||||
$value = intval($value);
|
||||
}
|
||||
|
||||
$updated = db_update($mysqli, $db_tabelle_disziplinen, [$field => $value], ['id' => $id]);
|
||||
if ($updated !== false) {
|
||||
echo json_encode(['success' => true]);
|
||||
} else {
|
||||
echo json_encode(['success' => false, 'message' => 'DB Update failed.']);
|
||||
}
|
||||
} else {
|
||||
echo json_encode(['success' => false, 'message' => 'Invalid parameters.']);
|
||||
}
|
||||
|
||||
} elseif ($action === 'delete') {
|
||||
$id = intval($_POST['id'] ?? 0);
|
||||
|
||||
if ($id > 0) {
|
||||
db_delete($mysqli, $db_tabelle_disziplinen, ['id' => $id]);
|
||||
echo json_encode(['success' => true]);
|
||||
} else {
|
||||
echo json_encode(['success' => false, 'message' => 'Invalid ID.']);
|
||||
}
|
||||
|
||||
generateIntersectCache($mysqli, $baseDir);
|
||||
|
||||
} else {
|
||||
echo json_encode(['success' => false, 'message' => 'Action not found.']);
|
||||
}
|
||||
@@ -0,0 +1,281 @@
|
||||
<?php
|
||||
ini_set("display_errors",1);
|
||||
header('Content-Type: application/json');
|
||||
|
||||
if (!isset($baseDir)) {
|
||||
$baseDir = $_SERVER['DOCUMENT_ROOT'];
|
||||
}
|
||||
|
||||
require_once $baseDir . '/../scripts/session_functions.php';
|
||||
|
||||
ini_wkvs_session();
|
||||
|
||||
check_user_permission('wk_leitung');
|
||||
|
||||
verify_csrf();
|
||||
|
||||
require $baseDir . '/../scripts/db/db-functions.php';
|
||||
require $baseDir . '/../scripts/db/db-tables.php';
|
||||
|
||||
require $baseDir . '/../scripts/string-calculator/string-calculator-functions.php';
|
||||
|
||||
|
||||
$type = 'wkl';
|
||||
$dbconnection = require $baseDir . '/../scripts/db/db-verbindung-script.php';
|
||||
|
||||
if ($dbconnection['success'] !== true){
|
||||
echo json_encode(['success' => false, 'message' => 'Critical DB Error.']);
|
||||
exit;
|
||||
}
|
||||
|
||||
require_once $baseDir . '/../scripts/cache/cache-creators/regenerate-display-dependencies-cache.php';
|
||||
require_once $baseDir . '/../scripts/cache/cache-creators/regenerate-noten-cache.php';
|
||||
|
||||
|
||||
|
||||
$recalculateJSONs = false;
|
||||
|
||||
$action = $_POST['action'] ?? '';
|
||||
|
||||
if ($action === 'add') {
|
||||
$name = trim($_POST['name'] ?? '');
|
||||
$type_val = $_POST['type_val'] ?? 'input';
|
||||
$berechnung = trim($_POST['berechnung'] ?? '');
|
||||
$pro_geraet = intval($_POST['pro_geraet'] ?? 0);
|
||||
$default_value = (isset($_POST['default_value'])) ? floatval($_POST['default_value']) : null;
|
||||
$min_value = (isset($_POST['min_value'])) ? floatval($_POST['min_value']) : null;
|
||||
$max_value = (isset($_POST['max_value'])) ? floatval($_POST['max_value']) : null;
|
||||
|
||||
$id = (isset($_POST['id'])) ? floatval($_POST['id']) : 1;
|
||||
|
||||
if (!$id) {
|
||||
echo json_encode(['success' => false, 'message' => 'Id ist erforderlich.']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$stmt = $mysqli->prepare("SELECT 1 FROM $db_tabelle_wertungstypen WHERE id = ?");
|
||||
$stmt->bind_param("i", $id);
|
||||
$stmt->execute();
|
||||
|
||||
$result = $stmt->get_result();
|
||||
|
||||
if ($result->num_rows > 0) {
|
||||
echo json_encode([
|
||||
'success' => false,
|
||||
'message' => 'Eine Note mit dieser Id existiert bereits.'
|
||||
]);
|
||||
$stmt->close();
|
||||
exit;
|
||||
}
|
||||
|
||||
$stmt->close();
|
||||
|
||||
|
||||
if (!$name) {
|
||||
echo json_encode(['success' => false, 'message' => 'Name ist erforderlich.']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$stmt = $mysqli->prepare("INSERT INTO $db_tabelle_wertungstypen (id, name, type, berechnung, pro_geraet, default_value, min_value, max_value) VALUES (?, ?, ?, ?, ?, ?, ?, ?)");
|
||||
$stmt->bind_param("isssisss", $id, $name, $type_val, $berechnung, $pro_geraet, $default_value, $min_value, $max_value);
|
||||
$success = $stmt->execute();
|
||||
$new_id = $mysqli->insert_id;
|
||||
$stmt->close();
|
||||
|
||||
$recalculateJSONs = true;
|
||||
|
||||
if ($success) {
|
||||
regenerate_noten_cache($mysqli, $db_tabelle_wertungstypen, $baseDir);
|
||||
generateIntersectCache($mysqli, $baseDir);
|
||||
if (!$recalculateJSONs) { echo json_encode(['success' => true, 'id' => $new_id]); }
|
||||
} else {
|
||||
echo json_encode(['success' => false, 'message' => 'Fehler beim Hinzufügen.']);
|
||||
exit;
|
||||
}
|
||||
|
||||
} elseif ($action === 'update') {
|
||||
$id = intval($_POST['id'] ?? 0);
|
||||
$field = $_POST['field'] ?? '';
|
||||
$value = $_POST['value'] ?? '';
|
||||
|
||||
$allowedFields = ['name', 'type', 'berechnung', 'pro_geraet', 'geraete_json', 'anzahl_laeufe_json', 'default_value', 'min_value', 'max_value', 'zeige_auf_rangliste', 'nullstellen', 'display_string', 'groesse_auf_rangliste'];
|
||||
if ($id > 0 && in_array($field, $allowedFields)) {
|
||||
if ($field === 'pro_geraet') {
|
||||
$value = intval($value);
|
||||
}
|
||||
|
||||
if ($field === 'berechnung' || $field === 'type') {
|
||||
$recalculateJSONs = true;
|
||||
}
|
||||
|
||||
$updated = db_update($mysqli, $db_tabelle_wertungstypen, [$field => $value], ['id' => $id]);
|
||||
if ($updated !== false) {
|
||||
regenerate_noten_cache($mysqli, $db_tabelle_wertungstypen, $baseDir);
|
||||
generateIntersectCache($mysqli, $baseDir);
|
||||
if (!$recalculateJSONs) { echo json_encode(['success' => true]); }
|
||||
} else {
|
||||
echo json_encode(['success' => false, 'message' => 'DB Update failed.']);
|
||||
exit;
|
||||
}
|
||||
} else {
|
||||
echo json_encode(['success' => false, 'message' => 'Invalid parameters.']);
|
||||
exit;
|
||||
}
|
||||
|
||||
} elseif ($action === 'delete') {
|
||||
$id = intval($_POST['id'] ?? 0);
|
||||
|
||||
if ($id > 0) {
|
||||
db_delete($mysqli, $db_tabelle_wertungstypen, ['id' => $id]);
|
||||
regenerate_noten_cache($mysqli, $db_tabelle_wertungstypen, $baseDir);
|
||||
generateIntersectCache($mysqli, $baseDir);
|
||||
echo json_encode(['success' => true]);
|
||||
} else {
|
||||
echo json_encode(['success' => false, 'message' => 'Invalid ID.']);
|
||||
}
|
||||
|
||||
} else {
|
||||
echo json_encode(['success' => false, 'message' => 'Action not found.']);
|
||||
exit;
|
||||
}
|
||||
|
||||
if ($recalculateJSONs) {
|
||||
$noten = db_select($mysqli, $db_tabelle_wertungstypen, "id, berechnung, type");
|
||||
|
||||
// 1. Re-index the array so the keys match the database IDs
|
||||
$notenById = array_column($noten, null, 'id');
|
||||
|
||||
$berechnungen = [];
|
||||
foreach ($notenById as $id => $sn) {
|
||||
if ($sn['type'] === 'berechnung') {
|
||||
$berechnungen[] = $sn;
|
||||
}
|
||||
}
|
||||
|
||||
if (empty($berechnungen)) {
|
||||
echo json_encode(['success' => true, 'message' => "Keine Berechnungen ausgewählt"]);
|
||||
exit;
|
||||
}
|
||||
|
||||
$notenRechner = new NotenRechner();
|
||||
|
||||
// 1. Build the direct map
|
||||
// Format: [ Changed_Note_ID => [ "CalcId|GeraetId" => [CalcId, GeraetId] ] ]
|
||||
$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'];
|
||||
$target_geraet_id = $neededIdsArrayWithRun['targetGeraet'];
|
||||
|
||||
foreach ($neededIdsArray as $key => $needed) {
|
||||
|
||||
$nId = (int)$needed['noteId'];
|
||||
|
||||
// Keep geraetId as integer if it's a number (e.g., 3), otherwise string ('S')
|
||||
$gId = is_numeric($needed['geraetId']) ? (int)$needed['geraetId'] : $needed['geraetId'];
|
||||
|
||||
// Create a unique string key so we don't store exact duplicates
|
||||
$nodeKey = $calcId . '|' . $gId . '|' . $targetRunId . '|' . $target_geraet_id; // e.g., "10|S|R2" or "12|3|RA"
|
||||
|
||||
if (!isset($dependencyMap[$nId])) {
|
||||
$dependencyMap[$nId] = [];
|
||||
}
|
||||
|
||||
// Store it as the "little array" you requested: [DependentCalcId, GeraetId]
|
||||
$dependencyMap[$nId][$nodeKey] = [$calcId, $gId, [$targetRunId, $target_geraet_id]];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// 2. Our recursive helper function (Updated for complex nodes)
|
||||
function getCompleteDependencyChain($id, $directMap, $visited = [])
|
||||
{
|
||||
// If this ID doesn't have anything depending on it, return empty
|
||||
if (!isset($directMap[$id])) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$allDependencies = [];
|
||||
|
||||
foreach ($directMap[$id] as $nodeKey => $complexNode) {
|
||||
// CIRCULAR DEPENDENCY CHECK:
|
||||
// We check against the string key (e.g., "10|S") to prevent infinite loops
|
||||
if (isset($visited[$nodeKey])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// 1. Mark this specific node as visited
|
||||
$visited[$nodeKey] = true;
|
||||
|
||||
// 2. Add the little array [CalcId, GeraetId] to our master list
|
||||
$allDependencies[$nodeKey] = $complexNode;
|
||||
|
||||
// 3. Recursively find everything that depends on THIS calculation ID
|
||||
// $complexNode[0] is the dependent Calc ID
|
||||
$childDependencies = getCompleteDependencyChain($complexNode[0], $directMap, $visited);
|
||||
|
||||
// 4. Merge the child results into our master list safely
|
||||
foreach ($childDependencies as $childKey => $childNode) {
|
||||
$allDependencies[$childKey] = $childNode;
|
||||
$visited[$childKey] = true; // Ensure the parent loop knows this was visited
|
||||
}
|
||||
}
|
||||
|
||||
return $allDependencies;
|
||||
}
|
||||
|
||||
|
||||
// 3. Create the final flattened map for ALL IDs
|
||||
$flatDependencyMap = [];
|
||||
|
||||
foreach (array_keys($notenById) as $id) {
|
||||
$chain = getCompleteDependencyChain($id, $dependencyMap);
|
||||
|
||||
// Only add it if dependencies exist
|
||||
if (!empty($chain)) {
|
||||
// array_values() removes the "10|S" string keys, turning it into a perfect
|
||||
// 0-indexed array for clean JSON encoding: [[10, "S"], [12, 3]]
|
||||
$flatDependencyMap[$id] = array_values($chain);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// 4. Database Updates
|
||||
// Step 1: Reset all rows to NULL in a single query
|
||||
$resetSql = "UPDATE $db_tabelle_wertungstypen SET `berechnung_json` = NULL";
|
||||
$mysqli->query($resetSql);
|
||||
|
||||
// Step 2: Prepare the statement
|
||||
$updateSql = "UPDATE $db_tabelle_wertungstypen SET `berechnung_json` = ? WHERE id = ?";
|
||||
$stmt = $mysqli->prepare($updateSql);
|
||||
|
||||
foreach ($flatDependencyMap as $id => $completeDependencyArray) {
|
||||
if (empty($completeDependencyArray)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$jsonString = json_encode($completeDependencyArray);
|
||||
|
||||
// Bind parameters: 's' for string (JSON), 'i' for integer (ID)
|
||||
$stmt->bind_param("si", $jsonString, $id);
|
||||
$stmt->execute();
|
||||
}
|
||||
|
||||
$stmt->close();
|
||||
|
||||
echo json_encode(['success' => true, 'message' => "Abhaengigkeiten berechnet"]);
|
||||
exit;
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
<?php
|
||||
|
||||
header('Content-Type: application/json');
|
||||
|
||||
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($_POST['css_content'])) {
|
||||
http_response_code(400);
|
||||
echo json_encode(['success' => false, 'message' => 'Missing css_content parameter.']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$css_content = $_POST['css_content'] ?? '';
|
||||
|
||||
if (strlen($css_content) > 200000) {
|
||||
http_response_code(400);
|
||||
echo json_encode(['success' => false, 'message' => 'File size too large.']);
|
||||
exit;
|
||||
}
|
||||
|
||||
if (preg_match('/javascript:/i', $css_content) || preg_match('/<script/i', $css_content)) {
|
||||
http_response_code(400);
|
||||
echo json_encode(['success' => false, 'message' => 'Invalid characters detected.']);
|
||||
exit;
|
||||
}
|
||||
|
||||
file_put_contents($baseDir . '/intern/css/user.css', $css_content);
|
||||
|
||||
http_response_code(200);
|
||||
echo json_encode(['success' => true, 'message' => 'CSS saved successfully.']);
|
||||
exit;
|
||||
@@ -0,0 +1,205 @@
|
||||
<?php
|
||||
/**
|
||||
* Upload Image API
|
||||
* Accepts multipart/form-data POST with 'image' file.
|
||||
* Converts JPG/PNG to WebP (resized to max 2400px), saves to /files/img/admin_upload/{uid}.webp
|
||||
* Returns JSON: { success: true }
|
||||
*/
|
||||
|
||||
// Allow large uploads and enough memory for GD processing
|
||||
ini_set('memory_limit', '256M');
|
||||
ini_set('upload_max_filesize', '50M');
|
||||
ini_set('post_max_size', '55M');
|
||||
ini_set('max_execution_time', '120');
|
||||
|
||||
const MAX_DIMENSION = 2400;
|
||||
const MAX_DIMENSION_ICON = 1000;
|
||||
const WEBP_QUALITY = 80;
|
||||
|
||||
$baseDir = $_SERVER['DOCUMENT_ROOT'];
|
||||
|
||||
header('Content-Type: application/json');
|
||||
|
||||
if (!isset($baseDir)) {
|
||||
$baseDir = $_SERVER['DOCUMENT_ROOT'];
|
||||
}
|
||||
|
||||
require_once $baseDir . '/../scripts/session_functions.php';
|
||||
|
||||
ini_wkvs_session();
|
||||
|
||||
check_user_permission('wk_leitung');
|
||||
|
||||
verify_csrf();
|
||||
|
||||
|
||||
// Only accept POST
|
||||
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
|
||||
http_response_code(405);
|
||||
echo json_encode(['success' => false, 'message' => 'Method not allowed']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$allowedTypes = ['Kampfrichter', 'Trainer', 'Wk_leitung', 'Otl', 'icon', 'logo-normal'];
|
||||
|
||||
if (!isset($_POST['type']) || !in_array($_POST['type'], $allowedTypes)) {
|
||||
http_response_code(400);
|
||||
echo json_encode(['success' => false, 'message' => 'Typ nicht angegeben oder nicht erlaubt']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$pngs = ['icon', 'logo-normal'];
|
||||
|
||||
$type = $_POST['type'];
|
||||
$isIcon = in_array($type, $pngs);
|
||||
|
||||
// Check if $_FILES is empty entirely (can happen if post_max_size exceeded)
|
||||
if (empty($_FILES)) {
|
||||
http_response_code(400);
|
||||
echo json_encode([
|
||||
'success' => false,
|
||||
'message' => 'No files received. The file may exceed the server upload limit).',
|
||||
]);
|
||||
exit;
|
||||
}
|
||||
|
||||
// Check specific file field
|
||||
if (!isset($_FILES['image'])) {
|
||||
http_response_code(400);
|
||||
echo json_encode([
|
||||
'success' => false,
|
||||
'message' => 'No "image" field in upload. Received fields: ' . implode(', ', array_keys($_FILES)),
|
||||
]);
|
||||
exit;
|
||||
}
|
||||
|
||||
if ($_FILES['image']['error'] !== UPLOAD_ERR_OK) {
|
||||
http_response_code(400);
|
||||
$errors = [
|
||||
UPLOAD_ERR_INI_SIZE => 'File exceeds upload_max_filesize',
|
||||
UPLOAD_ERR_FORM_SIZE => 'File exceeds form MAX_FILE_SIZE',
|
||||
UPLOAD_ERR_PARTIAL => 'File was only partially uploaded',
|
||||
UPLOAD_ERR_NO_FILE => 'No file was uploaded',
|
||||
UPLOAD_ERR_NO_TMP_DIR => 'Missing temp directory',
|
||||
UPLOAD_ERR_CANT_WRITE => 'Failed to write to disk',
|
||||
];
|
||||
$code = $_FILES['image']['error'];
|
||||
$msg = $errors[$code] ?? "Unknown error code: $code";
|
||||
echo json_encode(['success' => false, 'message' => $msg]);
|
||||
exit;
|
||||
}
|
||||
|
||||
$file = $_FILES['image'];
|
||||
$tmpPath = $file['tmp_name'];
|
||||
|
||||
// Validate MIME type
|
||||
$finfo = new finfo(FILEINFO_MIME_TYPE);
|
||||
$mime = $finfo->file($tmpPath);
|
||||
|
||||
$allowedMimes = ['image/jpeg', 'image/png', 'image/webp', 'image/gif'];
|
||||
if (!in_array($mime, $allowedMimes, true)) {
|
||||
http_response_code(415);
|
||||
echo json_encode(['success' => false, 'message' => "Unsupported file type: $mime"]);
|
||||
exit;
|
||||
}
|
||||
|
||||
// Target directory
|
||||
|
||||
|
||||
if ($isIcon) {
|
||||
$uploadDir = $baseDir . '/intern/img/';
|
||||
} else {
|
||||
$uploadDir = $baseDir . '/intern/img/login';
|
||||
}
|
||||
|
||||
if (!is_dir($uploadDir)) {
|
||||
mkdir($uploadDir, 0755, true);
|
||||
}
|
||||
|
||||
// Load image into GD
|
||||
$srcImage = null;
|
||||
switch ($mime) {
|
||||
case 'image/jpeg':
|
||||
$srcImage = @imagecreatefromjpeg($tmpPath);
|
||||
break;
|
||||
case 'image/png':
|
||||
$srcImage = @imagecreatefrompng($tmpPath);
|
||||
break;
|
||||
case 'image/webp':
|
||||
$srcImage = @imagecreatefromwebp($tmpPath);
|
||||
break;
|
||||
case 'image/gif':
|
||||
$srcImage = @imagecreatefromgif($tmpPath);
|
||||
break;
|
||||
}
|
||||
|
||||
if (!$srcImage) {
|
||||
http_response_code(500);
|
||||
echo json_encode(['success' => false, 'message' => 'Failed to load image into GD. It may be corrupt or too large.']);
|
||||
exit;
|
||||
}
|
||||
|
||||
|
||||
// ── Resize if needed ────────────────────────────────
|
||||
$origW = imagesx($srcImage);
|
||||
$origH = imagesy($srcImage);
|
||||
|
||||
$maxDimension = ($isIcon) ? MAX_DIMENSION_ICON : MAX_DIMENSION;
|
||||
|
||||
if ($origW > $maxDimension || $origH > $maxDimension) {
|
||||
// Calculate new dimensions keeping aspect ratio
|
||||
if ($origW >= $origH) {
|
||||
$newW = $maxDimension;
|
||||
$newH = intval(round($origH * ($maxDimension / $origW)));
|
||||
} else {
|
||||
$newH = $maxDimension;
|
||||
$newW = intval(round($origW * ($maxDimension / $origH)));
|
||||
}
|
||||
|
||||
$resized = imagecreatetruecolor($newW, $newH);
|
||||
|
||||
// Preserve transparency
|
||||
imagealphablending($resized, false);
|
||||
imagesavealpha($resized, true);
|
||||
$transparent = imagecolorallocatealpha($resized, 0, 0, 0, 127);
|
||||
imagefill($resized, 0, 0, $transparent);
|
||||
|
||||
imagecopyresampled($resized, $srcImage, 0, 0, 0, 0, $newW, $newH, $origW, $origH);
|
||||
imagedestroy($srcImage);
|
||||
$srcImage = $resized;
|
||||
} else {
|
||||
// Still preserve transparency
|
||||
imagepalettetotruecolor($srcImage);
|
||||
imagealphablending($srcImage, true);
|
||||
imagesavealpha($srcImage, true);
|
||||
}
|
||||
|
||||
if ($isIcon) {
|
||||
// ── Save as PNG ────────────────────────────────────
|
||||
$filename = $type . '.png';
|
||||
$destPath = $uploadDir . '/' . $filename;
|
||||
$webPath = '/intern/img/' . $filename;
|
||||
|
||||
$pngCompression = 6;
|
||||
|
||||
$success = imagepng($srcImage, $destPath, $pngCompression);
|
||||
} else {
|
||||
// ── Save as WebP ────────────────────────────────────
|
||||
$filename = 'bg' . $_POST['type'] . '.webp';
|
||||
$destPath = $uploadDir . '/' . $filename;
|
||||
$webPath = '/intern/img/admin_upload/' . $filename;
|
||||
|
||||
$success = imagewebp($srcImage, $destPath, WEBP_QUALITY);
|
||||
}
|
||||
|
||||
imagedestroy($srcImage);
|
||||
|
||||
if (!$success) {
|
||||
http_response_code(500);
|
||||
echo json_encode(['success' => false, 'message' => 'Failed to convert to WebP']);
|
||||
exit;
|
||||
}
|
||||
|
||||
echo json_encode([
|
||||
'success' => true
|
||||
]);
|
||||
@@ -0,0 +1,87 @@
|
||||
<?php
|
||||
header('Content-Type: application/json');
|
||||
|
||||
if (!isset($baseDir)) {
|
||||
$baseDir = $_SERVER['DOCUMENT_ROOT'];
|
||||
}
|
||||
|
||||
require_once $baseDir . '/../scripts/session_functions.php';
|
||||
|
||||
ini_wkvs_session();
|
||||
|
||||
check_user_permission('wk_leitung');
|
||||
|
||||
verify_csrf();
|
||||
|
||||
require $baseDir . '/../scripts/db/db-functions.php';
|
||||
require $baseDir . '/../scripts/db/db-tables.php';
|
||||
|
||||
|
||||
$type = 'wkl';
|
||||
$dbconnection = require $baseDir . '/../scripts/db/db-verbindung-script.php';
|
||||
|
||||
if ($dbconnection['success'] !== true){
|
||||
echo json_encode(['success' => false, 'message' => 'Critical DB Error.']);
|
||||
exit;
|
||||
}
|
||||
|
||||
|
||||
$action = $_POST['action'] ?? '';
|
||||
|
||||
if ($action === 'add') {
|
||||
$name = trim($_POST['name'] ?? '');
|
||||
$has_endtime = intval($_POST['has_endtime'] ?? 0);
|
||||
$index = intval($_POST['index'] ?? 0);
|
||||
|
||||
if (!$name) {
|
||||
echo json_encode(['success' => false, 'message' => 'Name ist erforderlich.']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$stmt = $mysqli->prepare("INSERT INTO $db_tabelle_zeitplan_types (`name`, `has_endtime`, `display_index`) VALUES (?, ?, ?)");
|
||||
$stmt->bind_param("sii", $name, $has_endtime, $index);
|
||||
$success = $stmt->execute();
|
||||
$new_id = $mysqli->insert_id;
|
||||
$stmt->close();
|
||||
|
||||
if ($success) {
|
||||
echo json_encode(['success' => true, 'id' => $new_id]);
|
||||
} else {
|
||||
echo json_encode(['success' => false, 'message' => 'Fehler beim Hinzufügen.']);
|
||||
}
|
||||
|
||||
} elseif ($action === 'update') {
|
||||
$id = intval($_POST['id'] ?? 0);
|
||||
$field = $_POST['field'] ?? '';
|
||||
$value = $_POST['value'] ?? '';
|
||||
$audiofile = intval($_POST['audiofile'] ?? 0);
|
||||
|
||||
$allowedFields = ['name', 'has_endtime', 'display_index'];
|
||||
if ($id > 0 && in_array($field, $allowedFields)) {
|
||||
if ($field === 'display_index') {
|
||||
$value = intval($value);
|
||||
}
|
||||
|
||||
$updated = db_update($mysqli, $db_tabelle_zeitplan_types, [$field => $value], ['id' => $id]);
|
||||
if ($updated !== false) {
|
||||
echo json_encode(['success' => true]);
|
||||
} else {
|
||||
echo json_encode(['success' => false, 'message' => 'DB Update failed.']);
|
||||
}
|
||||
} else {
|
||||
echo json_encode(['success' => false, 'message' => 'Invalid parameters.']);
|
||||
}
|
||||
|
||||
} elseif ($action === 'delete') {
|
||||
$id = intval($_POST['id'] ?? 0);
|
||||
|
||||
if ($id > 0) {
|
||||
db_delete($mysqli, $db_tabelle_zeitplan_types, ['id' => $id]);
|
||||
echo json_encode(['success' => true]);
|
||||
} else {
|
||||
echo json_encode(['success' => false, 'message' => 'Invalid ID.']);
|
||||
}
|
||||
|
||||
} else {
|
||||
echo json_encode(['success' => false, 'message' => 'Action not found.']);
|
||||
}
|
||||
@@ -0,0 +1,111 @@
|
||||
<?php
|
||||
|
||||
if (!isset($baseDir)) $baseDir = $_SERVER['DOCUMENT_ROOT'];
|
||||
|
||||
require_once $baseDir . '/../scripts/session_functions.php';
|
||||
|
||||
ini_wkvs_session();
|
||||
|
||||
check_user_permission('wk_leitung');
|
||||
|
||||
verify_csrf();
|
||||
|
||||
$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';
|
||||
|
||||
try {
|
||||
$mysqli->set_charset("utf8mb4");
|
||||
|
||||
// 4. Fetch all rows ordered by ID so the layout hierarchy is preserved
|
||||
$sql = "SELECT * FROM `$db_tabelle_wertungstypen` ORDER BY `id` ASC";
|
||||
$result = $mysqli->query($sql);
|
||||
|
||||
$exportData = [];
|
||||
|
||||
while ($row = $result->fetch_assoc()) {
|
||||
$presetItem = [];
|
||||
|
||||
foreach ($row as $columnName => $value) {
|
||||
if ($columnName === 'berechnung_json') {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($value === null) {
|
||||
$presetItem[$columnName] = null;
|
||||
} elseif (is_numeric($value)) {
|
||||
$presetItem[$columnName] = (strpos($value, '.') !== false) ? (float)$value : (int)$value;
|
||||
} else {
|
||||
$presetItem[$columnName] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
$exportDataDisc[] = $presetItem;
|
||||
}
|
||||
|
||||
$result->free();
|
||||
|
||||
$geraete = db_select($mysqli, $db_tabelle_disziplinen, '*', '', [], 'start_index ASC');
|
||||
$programme = db_select($mysqli, $db_tabelle_kategorien, '*', '', [], 'id ASC');
|
||||
$zeitplanTypen = db_select($mysqli, $db_tabelle_zeitplan_types, '*', '', [], 'id ASC');
|
||||
$rangNote = db_get_var($mysqli, "SELECT `value` FROM $db_tabelle_var WHERE `name` = ?", ['rangNote']);
|
||||
$wkName = db_get_var($mysqli, "SELECT `value` FROM $db_tabelle_var WHERE `name` = ?", ['wkName']);
|
||||
$orderBestRang = db_get_var($mysqli, "SELECT `value` FROM $db_tabelle_var WHERE `name` = ?", ['orderBestRang']);
|
||||
|
||||
$personEinzahl = db_get_variable($mysqli, $db_tabelle_var, ['personEinzahl']);
|
||||
if ($personEinzahl === null) $personEinzahl = 'Person';
|
||||
|
||||
$personMehrzahl = db_get_variable($mysqli, $db_tabelle_var, ['personMehrzahl']);
|
||||
if ($personMehrzahl === null) $personMehrzahl = 'Personen';
|
||||
|
||||
$mysqli->close();
|
||||
|
||||
$exportData = [
|
||||
'metadata' => [
|
||||
'erstellt_am' => date("d.m.Y H:i"),
|
||||
'ersteller' => $_SERVER['HTTP_HOST'],
|
||||
'erstellt_mit' => 'WKVS Auto-Export',
|
||||
'wkvs_json_version' => '1.0.0',
|
||||
'titel' => 'WKVS Preset ' . $wkName . ' (V 1.0.0)'
|
||||
],
|
||||
'noten' => $exportDataDisc,
|
||||
'disziplinen' => $geraete,
|
||||
'zeitplan_typen' => $zeitplanTypen,
|
||||
'rang_konfiguration' => [
|
||||
'rang_note_id' => $rangNote,
|
||||
'order_best_rang' => $orderBestRang
|
||||
],
|
||||
"leistungsklassen" => $programme,
|
||||
"bezeichnungen" =>[
|
||||
"singular" => $personEinzahl,
|
||||
"plural"=> $personMehrzahl
|
||||
]
|
||||
];
|
||||
|
||||
$jsonOutput = json_encode($exportData, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);
|
||||
|
||||
// 6. Force Browser File Download
|
||||
$fileName = 'WKVS-preset-config-' . date('Y-m-d_H-i') . '.json';
|
||||
|
||||
header('Content-Type: application/json; charset=utf-8');
|
||||
header('Content-Disposition: attachment; filename="' . $fileName . '"');
|
||||
header('Expires: 0');
|
||||
header('Cache-Control: must-revalidate');
|
||||
header('Pragma: public');
|
||||
header('Content-Length: ' . strlen($jsonOutput));
|
||||
|
||||
echo $jsonOutput;
|
||||
exit;
|
||||
|
||||
} catch (mysqli_sql_exception $e) {
|
||||
http_response_code(500);
|
||||
echo "Database export failed";
|
||||
}
|
||||
@@ -0,0 +1,350 @@
|
||||
<?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' => $db_tabelle_wertungstypen,
|
||||
'disziplinen' => $db_tabelle_disziplinen,
|
||||
'zeitplan_typen' => $db_tabelle_zeitplan_types,
|
||||
'leistungsklassen' => $db_tabelle_kategorien
|
||||
];
|
||||
|
||||
$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 $db_tabelle_var (`name`, `value`) VALUES ('rangNote', '" . $rangNote . "') ON DUPLICATE KEY UPDATE `value` = VALUES(`value`)");
|
||||
}
|
||||
|
||||
if (in_array($orderBestRang, $allowableOrderValues, true)) {
|
||||
$mysqli->query("INSERT INTO $db_tabelle_var (`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 $db_tabelle_var (`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 $db_tabelle_var (`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, $db_tabelle_wertungstypen, "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 $db_tabelle_wertungstypen SET `berechnung_json` = NULL";
|
||||
$mysqli->query($resetSql);
|
||||
|
||||
// Step 2: Prepare the statement
|
||||
$updateSql = "UPDATE $db_tabelle_wertungstypen 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, $db_tabelle_wertungstypen, $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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,85 @@
|
||||
<?php
|
||||
header('Content-Type: application/json');
|
||||
|
||||
if (!isset($baseDir)) {
|
||||
$baseDir = $_SERVER['DOCUMENT_ROOT'];
|
||||
}
|
||||
|
||||
ini_set('display_errors', 1);
|
||||
|
||||
require_once $baseDir . '/../scripts/session_functions.php';
|
||||
|
||||
ini_wkvs_session();
|
||||
|
||||
check_user_permission('wk_leitung');
|
||||
check_user_permission('kampfrichter');
|
||||
|
||||
require_once $baseDir . '/../scripts/delete_request_type_functions.php';
|
||||
|
||||
parse_input_to_delete();
|
||||
|
||||
verify_delete_csrf($_DELETE);
|
||||
|
||||
$programm_id = (int) ($_DELETE['programmId'] ?? 0);
|
||||
|
||||
if ($programm_id <= 0) {
|
||||
http_response_code(400);
|
||||
echo json_encode(['success' => false, 'message' => 'Keine valide Programm-ID']);
|
||||
exit;
|
||||
}
|
||||
|
||||
require $baseDir . '/../scripts/db/db-functions.php';
|
||||
require $baseDir . '/../scripts/db/db-tables.php';
|
||||
|
||||
|
||||
$type = 'wkl';
|
||||
|
||||
$dbconnection = require $baseDir . '/../scripts/db/db-verbindung-script.php';
|
||||
|
||||
if ($dbconnection['success'] !== true){
|
||||
echo 'Critical DB Error.';
|
||||
exit;
|
||||
}
|
||||
|
||||
$programm_name = db_get_var($mysqli, "SELECT `programm` FROM $db_tabelle_kategorien WHERE id = ? LIMIT 1", [$programm_id]) ?: null;
|
||||
|
||||
if ($programm_name === null) {
|
||||
echo json_encode(['success' => true, 'message' => 'Dieses Programm existiert nicht.']);
|
||||
http_response_code(400);
|
||||
exit;
|
||||
}
|
||||
|
||||
$personen = db_select($mysqli, $db_tabelle_teilnehmende, "id", '`programm` = ?', [$programm_name]);
|
||||
|
||||
if (count($personen) < 1) {
|
||||
echo json_encode(['success' => true, 'message' => 'Es existieren keine Personen mit diesem Programm.']);
|
||||
http_response_code(400);
|
||||
exit;
|
||||
}
|
||||
|
||||
$personen_id_array = array_column($personen, 'id');
|
||||
|
||||
$parram_array = array_fill(0, count($personen_id_array), "?");
|
||||
$parram_string = implode(', ', $parram_array);
|
||||
|
||||
$current_wk_id = (int) db_get_variable($mysqli, $db_tabelle_var, ['current_wk_id']) ?: 0;
|
||||
|
||||
$value_array = array_merge($personen_id_array, [$current_wk_id]);
|
||||
|
||||
$stmt = $mysqli->prepare("DELETE FROM $db_tabelle_wertungen WHERE `person_id` IN ($parram_string) AND `wk_id` = ?");
|
||||
|
||||
$types_string = str_repeat("i", count($personen_id_array)) . "i";
|
||||
$stmt->bind_param($types_string, ...$value_array);
|
||||
|
||||
$stmt->execute();
|
||||
$stmt->close();
|
||||
|
||||
$stmt = $mysqli->prepare("DELETE FROM $db_tabelle_wertungen_log WHERE `person_id` IN ($parram_string) AND `wk_id` = ?");
|
||||
|
||||
$stmt->bind_param($types_string, ...$value_array);
|
||||
|
||||
$stmt->execute();
|
||||
$stmt->close();
|
||||
|
||||
echo json_encode(['success' => true, 'message' => 'Noten gelöscht']);
|
||||
http_response_code(200);
|
||||
@@ -0,0 +1,87 @@
|
||||
<?php
|
||||
|
||||
header('Content-Type: application/json');
|
||||
|
||||
if (!isset($baseDir)) {
|
||||
$baseDir = $_SERVER['DOCUMENT_ROOT'];
|
||||
}
|
||||
|
||||
require_once $baseDir . '/../scripts/session_functions.php';
|
||||
|
||||
ini_wkvs_session();
|
||||
|
||||
check_user_permission('kampfrichter');
|
||||
|
||||
verify_csrf();
|
||||
|
||||
if (!isset($baseDir)) {
|
||||
$baseDir = $_SERVER['DOCUMENT_ROOT'];
|
||||
}
|
||||
|
||||
$type = 'kr';
|
||||
$data = require $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';
|
||||
|
||||
$abt_id = intval($_POST['abteilungId'] ?? 1);
|
||||
|
||||
// Determine current year
|
||||
$current_year = date('Y');
|
||||
$monat = date('n');
|
||||
if ($monat > 6) $current_year++;
|
||||
|
||||
// Prepare SQL statement
|
||||
$stmt = $mysqli->prepare("
|
||||
SELECT
|
||||
t.id AS person_id
|
||||
FROM $db_tabelle_teilnehmende_gruppen tab
|
||||
INNER JOIN $db_tabelle_teilnehmende t ON tab.turnerin_id = t.id
|
||||
INNER JOIN $db_tabelle_gruppen ab ON ab.id = tab.abteilung_id
|
||||
WHERE ab.id = ?
|
||||
ORDER BY t.id ASC
|
||||
");
|
||||
|
||||
$stmt->bind_param('i', $abt_id);
|
||||
$stmt->execute();
|
||||
|
||||
$result = $stmt->get_result();
|
||||
$personen = $result->fetch_all(MYSQLI_ASSOC);
|
||||
|
||||
$indexedPersonen = array_column($personen, null, 'person_id');
|
||||
|
||||
// Close statement
|
||||
$stmt->close();
|
||||
|
||||
// 1. Get the IDs from the first query results
|
||||
$personenIds = array_column($personen, 'person_id');
|
||||
|
||||
if (empty($personenIds)) {
|
||||
echo json_encode(["success" => false, "message" => "Keine Notenänderungen vorhanden"]);
|
||||
http_response_code(400);
|
||||
exit;
|
||||
}
|
||||
|
||||
$placeholders = implode(',', array_fill(0, count($personenIds), '?'));
|
||||
|
||||
$current_wk_id = (int) db_get_variable($mysqli, $db_tabelle_var, ['current_wk_id']) ?: 0;
|
||||
|
||||
$sqlNotenChanges = "DELETE FROM $db_tabelle_wertungen_log WHERE person_id IN ($placeholders) AND `wk_id` = ?";
|
||||
$stmtNotenChanges = $mysqli->prepare($sqlNotenChanges);
|
||||
|
||||
$paramsArray = array_merge($personenIds, [$current_wk_id]);
|
||||
|
||||
$types = str_repeat('i', count($personenIds)) . 's';
|
||||
|
||||
$stmtNotenChanges->bind_param($types, ...$paramsArray);
|
||||
|
||||
$stmtNotenChanges->execute();
|
||||
$stmtNotenChanges->close();
|
||||
|
||||
echo json_encode(["success" => true, "message" => "Notenänderung für Abteilung " . $abt_id . " gelöscht"]);
|
||||
http_response_code(200);
|
||||
@@ -0,0 +1,60 @@
|
||||
<?php
|
||||
|
||||
header('Content-Type: application/json');
|
||||
|
||||
if (!isset($baseDir)) {
|
||||
$baseDir = $_SERVER['DOCUMENT_ROOT'];
|
||||
}
|
||||
|
||||
require_once $baseDir . '/../scripts/session_functions.php';
|
||||
|
||||
ini_wkvs_session();
|
||||
|
||||
check_user_permission('kampfrichter');
|
||||
|
||||
verify_csrf();
|
||||
|
||||
if (!isset($baseDir)) {
|
||||
$baseDir = $_SERVER['DOCUMENT_ROOT'];
|
||||
}
|
||||
|
||||
$type = 'kr';
|
||||
$data = require $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';
|
||||
|
||||
$wkName = db_get_var($mysqli, "SELECT `value` FROM $db_tabelle_var WHERE `name` = ?", ['wkName']);
|
||||
|
||||
$mysqli->close();
|
||||
|
||||
if ($wkName === null) {
|
||||
echo json_encode(["success" => false, "message" => "Keinen Wettkampfname angegeben. Setzen unter: /intern/wk-leitung/einstellungen"]);
|
||||
http_response_code(400);
|
||||
exit;
|
||||
}
|
||||
|
||||
$programm = trim($_POST['prog'] ?? '');
|
||||
|
||||
$current_year = date('Y');
|
||||
$monat = date('n');
|
||||
if ($monat > 6) $current_year++;
|
||||
|
||||
$dir = $baseDir . '/files/ranglisten/';
|
||||
$localPath = $dir . str_replace("/", "", str_replace(" ", "_", $wkName)) . "_Ergebnisse_" . str_replace("/", "", $programm) . "_" . $current_year . ".pdf";
|
||||
|
||||
if (!file_exists($localPath)) {
|
||||
echo json_encode(["success" => false, "message" => "Diese Rangliste existiert nicht."]);
|
||||
http_response_code(400);
|
||||
exit;
|
||||
}
|
||||
|
||||
unlink($localPath);
|
||||
|
||||
echo json_encode(["success" => true, "message" => "Rangliste gelöscht"]);
|
||||
http_response_code(200);
|
||||
@@ -0,0 +1,341 @@
|
||||
<?php
|
||||
|
||||
header('Content-Type: application/json');
|
||||
|
||||
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('kampfrichter');
|
||||
|
||||
verify_csrf();
|
||||
|
||||
// Validate editId from POST
|
||||
if (isset($_POST['editId'])) {
|
||||
$editId = intval($_POST['editId']);
|
||||
if ($editId === false || $editId < 1) {
|
||||
echo json_encode(['success' => false, 'message' => 'Falsche Personen ID']);
|
||||
exit;
|
||||
}
|
||||
}
|
||||
|
||||
$editId = filter_var($editId, FILTER_VALIDATE_INT);
|
||||
|
||||
if ($editId === false) {
|
||||
echo json_encode(['success' => true]);
|
||||
exit;
|
||||
}
|
||||
|
||||
require $baseDir . '/../scripts/db/db-functions.php';
|
||||
require $baseDir . '/../scripts/db/db-tables.php';
|
||||
|
||||
$type = 'kr';
|
||||
|
||||
$data = require $baseDir . '/../scripts/db/db-verbindung-script.php';
|
||||
|
||||
if (!($data['success'] ?? false)) {
|
||||
echo json_encode(['success' => false, 'message' => $data['message']]);
|
||||
exit;
|
||||
}
|
||||
|
||||
$is_payed = db_get_var($mysqli, "SELECT 1 FROM $db_tabelle_teilnehmende WHERE id = ? AND ((bezahltoverride = ?) OR (bezahlt = ? AND bezahltoverride = ?))", [$editId, 4, 4, 0]);
|
||||
|
||||
if ($is_payed != '1') {
|
||||
echo json_encode(['success'=> false, 'message'=> 'Startgebühr nicht bezahlt']);
|
||||
http_response_code(400);
|
||||
exit;
|
||||
}
|
||||
|
||||
$isAdmin = (($_SESSION['selectedFreigabeIdKampfrichter'] ?? '') === 'A') ? true : false;
|
||||
|
||||
$disciplines = db_select($mysqli, $db_tabelle_disziplinen, 'id', '', [], 'start_index ASC');
|
||||
|
||||
$disciplines = array_column($disciplines, "id");
|
||||
|
||||
$requested_discipline = trim($_POST['geraet'] ?? '');
|
||||
|
||||
$all_disciplines = false;
|
||||
|
||||
if ($isAdmin && $requested_discipline === 'A') {
|
||||
$all_disciplines = true;
|
||||
} else {
|
||||
$requested_discipline = (int) $requested_discipline;
|
||||
|
||||
if (!in_array($requested_discipline, $disciplines)) {
|
||||
echo json_encode(['success' => false, 'message' => 'Falsche Geräte ID']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$discipline = $requested_discipline;
|
||||
}
|
||||
|
||||
if ($all_disciplines) {
|
||||
$stmt = $mysqli->prepare("SELECT t.`name`, t.`vorname`, t.`programm`, p.id as programm_id FROM $db_tabelle_teilnehmende t LEFT JOIN $db_tabelle_kategorien p ON p.programm = t.programm WHERE t.id = ?");
|
||||
} else {
|
||||
|
||||
$disciplines = [$discipline];
|
||||
|
||||
|
||||
$stmt = $mysqli->prepare("
|
||||
SELECT
|
||||
t.name,
|
||||
t.vorname,
|
||||
t.programm,
|
||||
p.id as programm_id,
|
||||
agg.abteilung,
|
||||
agg.geraeteIndex,
|
||||
agg.startIndex
|
||||
FROM $db_tabelle_teilnehmende t
|
||||
LEFT JOIN $db_tabelle_kategorien p ON p.programm = t.programm
|
||||
LEFT JOIN (
|
||||
SELECT
|
||||
ta.turnerin_id,
|
||||
GROUP_CONCAT(DISTINCT a.name SEPARATOR ', ') AS abteilung,
|
||||
GROUP_CONCAT(DISTINCT g.start_index SEPARATOR ', ') AS geraeteIndex,
|
||||
ta.turnerin_index AS startIndex
|
||||
FROM $db_tabelle_teilnehmende_gruppen ta
|
||||
INNER JOIN $db_tabelle_gruppen a
|
||||
ON a.id = ta.abteilung_id
|
||||
LEFT JOIN $db_tabelle_disziplinen g
|
||||
ON g.id = ta.geraet_id
|
||||
GROUP BY ta.turnerin_id
|
||||
) agg ON agg.turnerin_id = t.id
|
||||
WHERE t.id = ?
|
||||
");
|
||||
|
||||
}
|
||||
$stmt->bind_param('i', $editId);
|
||||
|
||||
$stmt->execute();
|
||||
|
||||
$result = $stmt->get_result();
|
||||
$dbresult = $result->fetch_all(MYSQLI_ASSOC);
|
||||
|
||||
$stmt->close();
|
||||
|
||||
if (!$dbresult || !is_array($dbresult) || count($dbresult) < 1) {
|
||||
echo json_encode(['success' => false, 'message' => 'Falsche Personen ID']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$current_wk_id = (int) db_get_variable($mysqli, $db_tabelle_var, ['current_wk_id']) ?: 0;
|
||||
|
||||
if ($all_disciplines) {
|
||||
$stmt = $mysqli->prepare("SELECT `note_bezeichnung_id`, `value`, `geraet_id`, `run_number` FROM $db_tabelle_wertungen WHERE `person_id` = ? AND `wk_id` = ?");
|
||||
|
||||
$stmt->bind_param('si', $editId, $current_wk_id);
|
||||
} else {
|
||||
$stmt = $mysqli->prepare("SELECT `note_bezeichnung_id`, `value`, `geraet_id`, `run_number` FROM $db_tabelle_wertungen WHERE `person_id` = ? AND `geraet_id` = ? AND `wk_id` = ?");
|
||||
|
||||
$stmt->bind_param('ssi', $editId, $discipline, $current_wk_id);
|
||||
}
|
||||
|
||||
$stmt->execute();
|
||||
|
||||
$result = $stmt->get_result();
|
||||
$notenDB = $result->fetch_all(MYSQLI_ASSOC);
|
||||
|
||||
|
||||
$indexedNotenDB = [];
|
||||
foreach ($notenDB as $sn) {
|
||||
$indexedNotenDB[$sn['geraet_id']][$sn['note_bezeichnung_id']][$sn['run_number']] = $sn['value'];
|
||||
}
|
||||
|
||||
|
||||
$stmt->close();
|
||||
|
||||
$stmt = $mysqli->prepare("SELECT `id`, `default_value`, `nullstellen`, `pro_geraet`, `geraete_json`, `anzahl_laeufe_json` FROM $db_tabelle_wertungstypen");
|
||||
|
||||
$stmt->execute();
|
||||
|
||||
$result = $stmt->get_result();
|
||||
$notenConfig = $result->fetch_all(MYSQLI_ASSOC);
|
||||
|
||||
$stmt->close();
|
||||
|
||||
$displayIdNoteL = intval(db_get_var($mysqli, "SELECT `value` FROM $db_tabelle_var WHERE `name` = ?", ['displayIdNoteL'])) ?? 0;
|
||||
$displayIdNoteR = intval(db_get_var($mysqli, "SELECT `value` FROM $db_tabelle_var WHERE `name` = ?", ['displayIdNoteR'])) ?? 0;
|
||||
|
||||
if ($displayIdNoteL !== 0 && $displayIdNoteR !== 0) {
|
||||
$displayNoten = [$displayIdNoteR => 0, $displayIdNoteL => 0];
|
||||
}
|
||||
|
||||
|
||||
$noten = [];
|
||||
|
||||
$row = $dbresult[0];
|
||||
|
||||
$programm_id = $row['programm_id'];
|
||||
|
||||
foreach ($disciplines as $d) {
|
||||
foreach ($notenConfig as $snC) {
|
||||
$allowedGeraete = !empty($snC['geraete_json']) ? json_decode($snC['geraete_json'], true) : [];
|
||||
$isProGeraet = ($snC['pro_geraet'] === 1);
|
||||
|
||||
if (!$isProGeraet && !in_array($d, $allowedGeraete)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Determine number of runs for this program
|
||||
$anzRunsConfig = !empty($snC['anzahl_laeufe_json']) ? json_decode($snC['anzahl_laeufe_json'], true) : [];
|
||||
|
||||
$runs = $anzRunsConfig[$d][$programm_id] ?? $anzRunsConfig[$d]["all"] ?? $anzRunsConfig['default'] ?? 1;
|
||||
|
||||
if (isset($displayNoten) && array_key_exists($snC['id'], $displayNoten)) {
|
||||
$displayNoten[$snC['id']] = $runs;
|
||||
}
|
||||
|
||||
for ($r = 1; $r <= $runs; $r++) {
|
||||
$value = $indexedNotenDB[$d][$snC['id']][$r] ?? $snC['default_value'] ?? 0;
|
||||
$noten[$d][$r][$snC['id']] = number_format($value, $snC['nullstellen'] ?? 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$countBtn = 1;
|
||||
|
||||
if (isset($displayNoten)) {
|
||||
$countBtn = min($displayNoten);
|
||||
}
|
||||
|
||||
|
||||
$titel = $row['vorname'].' '.$row['name'].', '.$row['programm'];
|
||||
|
||||
if (!$all_disciplines) {
|
||||
|
||||
|
||||
$stmt = $mysqli->prepare("
|
||||
SELECT
|
||||
t.name,
|
||||
t.vorname,
|
||||
t.programm,
|
||||
t.id,
|
||||
agg.abteilung,
|
||||
agg.geraeteIndex,
|
||||
agg.startIndex
|
||||
FROM $db_tabelle_teilnehmende t
|
||||
LEFT JOIN (
|
||||
SELECT
|
||||
ta.turnerin_id,
|
||||
GROUP_CONCAT(DISTINCT a.name SEPARATOR ', ') AS abteilung,
|
||||
GROUP_CONCAT(DISTINCT g.start_index SEPARATOR ', ') AS geraeteIndex,
|
||||
ta.turnerin_index AS startIndex
|
||||
FROM $db_tabelle_teilnehmende_gruppen ta
|
||||
INNER JOIN $db_tabelle_gruppen a
|
||||
ON a.id = ta.abteilung_id
|
||||
LEFT JOIN $db_tabelle_disziplinen g
|
||||
ON g.id = ta.geraet_id
|
||||
GROUP BY ta.turnerin_id
|
||||
) agg ON agg.turnerin_id = t.id
|
||||
WHERE agg.abteilung = ? AND agg.geraeteIndex = ?
|
||||
ORDER BY t.id DESC
|
||||
");
|
||||
|
||||
|
||||
$bezahlt = 4;
|
||||
$bezahltoverride = 4;
|
||||
|
||||
$stmt->bind_param('ss', $row['abteilung'], $row['geraeteIndex']);
|
||||
|
||||
|
||||
$stmt->execute();
|
||||
|
||||
|
||||
$result = $stmt->get_result();
|
||||
$entries = $result->fetch_all(MYSQLI_ASSOC);
|
||||
|
||||
$stmt->close();
|
||||
|
||||
if (!$entries || !is_array($entries) || count($entries) < 1) {
|
||||
echo json_encode(['success' => false, 'message' => 'No DB Result for next Turnerin']);
|
||||
exit;
|
||||
}
|
||||
|
||||
|
||||
$maxstartindex = count($entries);
|
||||
|
||||
if ($maxstartindex < 1) {
|
||||
$maxstartindex = 1;
|
||||
}
|
||||
|
||||
$csti = (int)$row['startIndex'];
|
||||
$nsti = $csti + 1;
|
||||
|
||||
if ($nsti > $maxstartindex){
|
||||
$nsti -= $maxstartindex;
|
||||
}
|
||||
|
||||
$rohstartindex = intval($row['startIndex']);
|
||||
$varstartgeraet = intval($row['geraeteIndex']);
|
||||
|
||||
$aktsubabt = $_SESSION['currentsubabt'];
|
||||
|
||||
foreach ($disciplines as $index => $sdiscipline) {
|
||||
if (isset($sdiscipline) && $sdiscipline === $discipline) {
|
||||
$indexuser = $index;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
$calculedstartindex = $rohstartindex - $indexuser;
|
||||
|
||||
$calculedstartindex = $calculedstartindex >= 1 ? $calculedstartindex : $calculedstartindex + $maxstartindex;
|
||||
|
||||
|
||||
$nrow = null;
|
||||
|
||||
if ($calculedstartindex !== count($entries)){
|
||||
$nrow = null;
|
||||
|
||||
foreach ($entries as $entry) {
|
||||
if ($entry['startIndex'] == $nsti) {
|
||||
$nrow = $entry;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($nrow) {
|
||||
$nturnerin = [
|
||||
'name' => $nrow['vorname'].' '.$nrow['name'].', '.$nrow['programm'],
|
||||
'id' => $nrow['id']
|
||||
];
|
||||
} else {
|
||||
$nturnerin = [
|
||||
'name' => '--- nächste Gruppe ---',
|
||||
'id' => 0
|
||||
];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if ($isAdmin) {
|
||||
echo json_encode([
|
||||
'success' => true,
|
||||
'id' => $editId,
|
||||
'programm_id' => $programm_id,
|
||||
'titel' => $titel,
|
||||
'noten' => $noten,
|
||||
'countBtn' => $countBtn
|
||||
]);
|
||||
} else {
|
||||
echo json_encode([
|
||||
'success' => true,
|
||||
'id' => $editId,
|
||||
'programm_id' => $programm_id,
|
||||
'titel' => $titel,
|
||||
'noten' => $noten,
|
||||
'nturnerin' => $nturnerin,
|
||||
'countBtn' => $countBtn
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,489 @@
|
||||
<?php
|
||||
|
||||
use TCPDF;
|
||||
|
||||
if (!isset($baseDir)) {
|
||||
$baseDir = $_SERVER['DOCUMENT_ROOT'];
|
||||
}
|
||||
|
||||
require_once $baseDir . '/../scripts/session_functions.php';
|
||||
|
||||
ini_wkvs_session();
|
||||
|
||||
check_user_permission('kampfrichter');
|
||||
|
||||
verify_csrf();
|
||||
|
||||
if (!isset($baseDir)) {
|
||||
$baseDir = $_SERVER['DOCUMENT_ROOT'];
|
||||
}
|
||||
|
||||
$type = 'kr';
|
||||
$data = require $baseDir . '/../scripts/db/db-verbindung-script.php';
|
||||
|
||||
if ($data['success'] === false) {
|
||||
header('Content-Type: application/json');
|
||||
echo json_encode(['success' => false, 'message' => $data['message']]);
|
||||
exit;
|
||||
}
|
||||
|
||||
require $baseDir . '/../scripts/db/db-tables.php';
|
||||
require $baseDir . '/../scripts/db/db-functions.php';
|
||||
|
||||
$wkName = db_get_var($mysqli, "SELECT `value` FROM $db_tabelle_var WHERE `name` = ?", ['wkName']);
|
||||
|
||||
$wkName = ($wkName === null) ? 'Keinen Wettkampfname angegeben. Setzen unter: /intern/wk-leitung/einstellungen' : $wkName;
|
||||
|
||||
$normalFontSize = 11;
|
||||
$marginSide = 10;
|
||||
$marginTop = 10;
|
||||
$minMarginBottomTable = 20;
|
||||
$format = 'A4';
|
||||
$orientation = 'L';
|
||||
|
||||
$abt = intval($_POST['abteilungId'] ?? 1);
|
||||
|
||||
$now = trim($_POST['date'] ?? date('Y-m-d H:i:s'));
|
||||
|
||||
$geraete = db_select($mysqli, $db_tabelle_disziplinen, "*", '', [], "start_index ASC");
|
||||
|
||||
$IndexedGeraete = array_column($geraete, 'name', 'id');
|
||||
|
||||
$notenBezeichnungen = db_select($mysqli, $db_tabelle_wertungstypen, "`name`, `id`, `nullstellen`, `anzahl_laeufe_json`", '', [], "");
|
||||
|
||||
$IndexedNotenBezeichnungen = array_column($notenBezeichnungen, 'name', 'id');
|
||||
|
||||
$IndexedNotenNullstellen = array_column($notenBezeichnungen, 'nullstellen', 'id');
|
||||
|
||||
$IndexedNotenJsonGeraete = array_column($notenBezeichnungen, 'anzahl_laeufe_json', 'id');
|
||||
|
||||
$programme = db_select($mysqli, $db_tabelle_kategorien, "`programm`, `id`", '', [], "");
|
||||
|
||||
$indexedProgramme = array_column($programme, 'id', 'programm');
|
||||
|
||||
// Prepare SQL statement
|
||||
$stmt = $mysqli->prepare("
|
||||
SELECT
|
||||
t.id AS person_id,
|
||||
t.name,
|
||||
t.vorname,
|
||||
t.programm,
|
||||
t.verein,
|
||||
ab.id AS abteilung_id,
|
||||
tab.geraet_id AS start_geraet_id,
|
||||
tab.turnerin_index
|
||||
FROM $db_tabelle_teilnehmende_gruppen tab
|
||||
INNER JOIN $db_tabelle_teilnehmende t ON tab.turnerin_id = t.id
|
||||
INNER JOIN $db_tabelle_gruppen ab ON ab.id = tab.abteilung_id
|
||||
WHERE ab.id = ?
|
||||
ORDER BY t.id ASC
|
||||
");
|
||||
|
||||
$stmt->bind_param('i', $abt);
|
||||
$stmt->execute();
|
||||
|
||||
$result = $stmt->get_result();
|
||||
$personen = $result->fetch_all(MYSQLI_ASSOC);
|
||||
|
||||
$indexedPersonen = array_column($personen, null, 'person_id');
|
||||
|
||||
// Close statement
|
||||
$stmt->close();
|
||||
|
||||
// 1. Get the IDs from the first query results
|
||||
$personenIds = array_column($personen, 'person_id');
|
||||
|
||||
$current_wk_id = (int) db_get_variable($mysqli, $db_tabelle_var, ['current_wk_id']) ?: 0;
|
||||
|
||||
if (!empty($personenIds)) {
|
||||
$placeholders = implode(',', array_fill(0, count($personenIds), '?'));
|
||||
|
||||
$sqlNotenChanges = "SELECT * FROM $db_tabelle_wertungen_log WHERE person_id IN ($placeholders) AND `wk_id` = ?";
|
||||
$stmtNotenChanges = $mysqli->prepare($sqlNotenChanges);
|
||||
|
||||
$paramsArray = array_merge($personenIds, [$current_wk_id]);
|
||||
|
||||
$types = str_repeat('i', count($personenIds)) . 's';
|
||||
|
||||
$stmtNotenChanges->bind_param($types, ...$paramsArray);
|
||||
|
||||
$stmtNotenChanges->execute();
|
||||
$notenChangesResult = $stmtNotenChanges->get_result();
|
||||
$notenChangesEntries = $notenChangesResult->fetch_all(MYSQLI_ASSOC);
|
||||
|
||||
$stmtNotenChanges->close();
|
||||
} else {
|
||||
$notenChangesEntries = [];
|
||||
}
|
||||
|
||||
$kampfrichterIds = array_column($notenChangesEntries, 'edited_by');
|
||||
|
||||
if (!empty($kampfrichterIds)) {
|
||||
$placeholders = implode(',', array_fill(0, count($kampfrichterIds), '?'));
|
||||
|
||||
$sqlKampfrichter = "SELECT `id` AS `id_kampfrichter`, `name_person` AS `name_kampfrichter` FROM $db_tabelle_intern_benutzende WHERE id IN ($placeholders)";
|
||||
$stmtKampfrichter = $mysqli->prepare($sqlKampfrichter);
|
||||
|
||||
$types = str_repeat('i', count($kampfrichterIds));
|
||||
|
||||
$stmtKampfrichter->bind_param($types, ...$kampfrichterIds);
|
||||
|
||||
$stmtKampfrichter->execute();
|
||||
$kampfrichterResult = $stmtKampfrichter->get_result();
|
||||
$kampfrichter = $kampfrichterResult->fetch_all(MYSQLI_ASSOC);
|
||||
|
||||
$indexedKampfrichter = array_column($kampfrichter, 'name_kampfrichter', 'id_kampfrichter');
|
||||
|
||||
$stmtKampfrichter->close();
|
||||
} else {
|
||||
$indexedKampfrichter = [];
|
||||
}
|
||||
|
||||
$entriesArray = [];
|
||||
|
||||
|
||||
|
||||
foreach ($notenChangesEntries as $snce) {
|
||||
|
||||
$programmId = $indexedProgramme[$indexedPersonen[$snce['person_id']]['programm']] ?? 0;
|
||||
|
||||
$runs = json_decode($IndexedNotenJsonGeraete[$snce['note_bezeichnung_id']], true) ?? [];
|
||||
|
||||
$countRuns = (int) $runs[$snce['geraet_id']][$programmId] ?? (int) $runs['default'] ?? 1;
|
||||
|
||||
$notenTextRaw = $IndexedNotenBezeichnungen[$snce['note_bezeichnung_id']] ?? 'Unbekannter Notenname';
|
||||
|
||||
$notenText = ($countRuns > 1) ? $notenTextRaw . ' (R' . ($snce['run_number'] ?? 1 ). ')' : $notenTextRaw;
|
||||
|
||||
$nullstellen = (int) $IndexedNotenNullstellen[$snce['note_bezeichnung_id']] ?? 2;
|
||||
$value = ($snce['old_value'] !== null) ? number_format((float) $snce['old_value'], $nullstellen) . ' ' . json_decode('"\u2192"') . ' ' . number_format((float) $snce['new_value'], $nullstellen) : number_format((float) $snce['new_value'], $nullstellen);
|
||||
|
||||
$entriesArray[$snce['geraet_id']][$indexedPersonen[$snce['person_id']]['start_geraet_id']][] = [
|
||||
'name' => ($indexedPersonen[$snce['person_id']]['name'] ?? 'Unbekannter Nachname') . ', ' . ($indexedPersonen[$snce['person_id']]['vorname'] ?? 'Unbekannter Vorname'),
|
||||
'programm' => $indexedPersonen[$snce['person_id']]['programm'] ?? 'Unbekanntes Programm',
|
||||
'verein' => $indexedPersonen[$snce['person_id']]['verein'] ?? 'Unbekannter Verein',
|
||||
'note' => $notenText,
|
||||
'value' => $value,
|
||||
'kampfrichter' => $indexedKampfrichter[$snce['edited_by']] ?? 'Unbekannter Kampfrichter',
|
||||
'timestamp' => new DateTime($snce['timestamp'])->format('d.m.Y H:i:s') ?? '---'
|
||||
];
|
||||
}
|
||||
|
||||
// Load TCPDF
|
||||
require $baseDir . '/../composer/vendor/autoload.php';
|
||||
/*
|
||||
// Optional: load custom font
|
||||
$fontfile = $baseDir . '/wp-content/uploads/fonts/Inter-Regular.ttf'; // adjust path
|
||||
if (file_exists($fontfile)) {
|
||||
$fontname = TCPDF_FONTS::addTTFfont($fontfile, 'TrueTypeUnicode', '', 32);
|
||||
}
|
||||
*/
|
||||
class ProtokollPDF extends TCPDF
|
||||
{
|
||||
public $current_year;
|
||||
public $subAbt;
|
||||
public $abt;
|
||||
public $columns;
|
||||
public $discipline;
|
||||
public $wkName;
|
||||
public $marginSide;
|
||||
public $marginTop;
|
||||
public $pdfHeight;
|
||||
public $pdfWidth;
|
||||
public $headerType;
|
||||
public $now;
|
||||
// Page header
|
||||
|
||||
public $headerBottomY = 0;
|
||||
|
||||
|
||||
public function Header()
|
||||
{
|
||||
$this->SetFillColor(255, 255, 255);
|
||||
|
||||
$this->Rect(0, 0, $this->pdfWidth, $this->pdfHeight, 'F');
|
||||
|
||||
$arrayTitles = [];
|
||||
$image_file = $_SERVER['DOCUMENT_ROOT'] . '/intern/img/logo-normal.png';
|
||||
$this->SetY($this->marginTop);
|
||||
$this->SetX(($this->marginSide ?? 10));
|
||||
$this->SetFont('freesans', '', 20);
|
||||
|
||||
if ($this->headerType === 'bigHeader') {
|
||||
|
||||
$this->Cell(0, 0, 'Protokoll ' . $this->wkName . ' ' . $this->current_year, 0, 1, 'L', 0, '', 0, false, 'T', 'M');
|
||||
$preimageX = $this->GetX();
|
||||
$preimageY = $this->GetY();
|
||||
$this->Image($image_file, $this->pdfWidth - 10 - $this->marginSide, $this->marginTop, '', 10, 'png', '', 'T');
|
||||
|
||||
$this->SetY($preimageY + 5);
|
||||
$this->SetX($this->marginSide ?? 10); // Force back to left margin
|
||||
$this->SetFont('freesans', '', 11);
|
||||
$this->Cell(0, 6, 'Gereat: ' . $this->discipline, 0, 1, 'L');
|
||||
$this->Cell(0, 6, 'Abteilung: ' . $this->abt, 0, 1, 'L');
|
||||
$this->Cell(0, 6, 'Gruppe: ' . $this->subAbt, 0, 1, 'L');
|
||||
|
||||
$this->Ln(5);
|
||||
|
||||
} else {
|
||||
|
||||
$this->Cell(10, 0, 'Protokoll ' . $this->wkName . ' ' . $this->current_year, 0, 1, 'L', 0, '', 0, false, 'T', 'M');
|
||||
$this->SetFont('freesans', '', 11);
|
||||
$info = "Gerät: {$this->discipline} | Abt: {$this->abt} | Gruppe: {$this->subAbt}";
|
||||
$this->Cell(10, 6, $info, 0, 1, 'L'); // Align all info to the right while title is on the left
|
||||
|
||||
$this->Image($image_file, $this->pdfWidth - 10 - $this->marginSide, $this->marginTop, '', 10, 'png', '', 'T');
|
||||
|
||||
$this->Ln(18);
|
||||
}
|
||||
|
||||
$columns = $this->columns;
|
||||
$startY = $this->GetY();
|
||||
$this->SetFont('', 'B');
|
||||
|
||||
$this->SetX($this->marginSide ?? 10);
|
||||
|
||||
foreach ($columns as $col) {
|
||||
|
||||
$title = $col['header'];
|
||||
|
||||
if (($col['rotate'] ?? false)) {
|
||||
$x = $this->GetX();
|
||||
$y = $this->GetY() + 7;
|
||||
|
||||
$this->StartTransform();
|
||||
$this->Rotate(45, $x, $y);
|
||||
|
||||
$lineY = $startY + 7;
|
||||
if (($col['id'] ?? '') === 'gesamt') {
|
||||
$this->SetLineWidth(0.6);
|
||||
} else {
|
||||
$this->SetLineWidth(0.2);
|
||||
}
|
||||
|
||||
$this->Line($x, $lineY, $x + ($col['width_header'] ?? 0), $lineY);
|
||||
$this->SetLineWidth(0.2);
|
||||
|
||||
$this->Cell($col['width_header'] ?? 0, 7, $title ?? '', 0, 0, 'C');
|
||||
$this->StopTransform();
|
||||
$this->SetX($x + ($col['max_width'] ?? 0));
|
||||
} else {
|
||||
$this->Cell($col['max_width'] ?? 0, 7, $title ?? '', 0, 0, $col['align'] ?? 'L');
|
||||
}
|
||||
}
|
||||
|
||||
$this->Ln();
|
||||
$this->headerBottomY = $this->GetY();
|
||||
}
|
||||
|
||||
|
||||
// Page footer
|
||||
public function Footer()
|
||||
{
|
||||
$this->SetLineWidth(0.6);
|
||||
$this->Line($this->marginSide ?? 10, $this->headerBottomY, $this->pdfWidth - ($this->marginSide ?? 10), $this->headerBottomY);
|
||||
|
||||
$this->SetLineWidth(0.2);
|
||||
|
||||
$this->SetY(0);
|
||||
$this->SetX(0);
|
||||
|
||||
$this->SetFillColor(255, 255, 255); // white
|
||||
|
||||
$this->Cell(($this->marginSide ?? 10), $this->pdfHeight, '', 0, 0, 'L', true);
|
||||
|
||||
$this->SetY(0);
|
||||
$this->SetX($this->pdfWidth - ($this->marginSide ?? 10));
|
||||
|
||||
$this->Cell(($this->marginSide ?? 10), $this->pdfHeight, '', 0, 0, 'L', true);
|
||||
|
||||
$this->SetY(-15);
|
||||
$this->SetFont('freesans', 'I', 8);
|
||||
|
||||
// 1. Page Number - Centered
|
||||
$this->Cell(0, 10, 'Seite ' . $this->getAliasNumPage() . ' von ' . $this->getAliasNbPages(), 0, false, 'C');
|
||||
|
||||
// 2. Timestamp - Force to Left
|
||||
$this->SetX($this->getMargins()['left']); // Reset to left margin
|
||||
$this->Cell(0, 10, 'Zeitstempel: ' . $this->now, 0, false, 'L');
|
||||
|
||||
// 3. Host - Force to Right (Cell with width 0 and align 'R' handles this)
|
||||
$this->SetX($this->getMargins()['left']); // Reset again so 'R' alignment works from the start
|
||||
$this->Cell(0, 10, $_SERVER['HTTP_HOST'], 0, 0, 'R', false, 'https://'.$_SERVER['HTTP_HOST']);
|
||||
}
|
||||
}
|
||||
|
||||
$pdf = new ProtokollPDF($orientation, 'mm', $format, true, 'UTF-8', false);
|
||||
|
||||
$pdfHeight = $pdf->getPageHeight();
|
||||
$pdfWidth = $pdf->getPageWidth();
|
||||
|
||||
$pdf->current_year = $current_year;
|
||||
$pdf->wkName = $wkName;
|
||||
$pdf->abt = $abt;
|
||||
$pdf->marginSide = $marginSide;
|
||||
$pdf->marginTop = $marginTop;
|
||||
$pdf->pdfHeight = $pdfHeight;
|
||||
$pdf->pdfWidth = $pdfWidth;
|
||||
$pdf->now = $now;
|
||||
|
||||
$pdf->SetCreator(PDF_CREATOR);
|
||||
$pdf->SetAuthor($wkName);
|
||||
$pdf->SetTitle($wkName . "_Protokoll_" . $abt . "_" . $current_year . ".pdf");
|
||||
|
||||
$pdf->SetAutoPageBreak(FALSE);
|
||||
|
||||
|
||||
$pdf->SetFont('freesans', '', 11);
|
||||
|
||||
// Define columns dynamically
|
||||
$columns = [
|
||||
['id' => 'name', 'header' => 'Name Person', 'align' => 'L', 'flex' => true, 'type' => 'field', 'field' => 'name'],
|
||||
['id' => 'programm', 'header' => 'Programm', 'align' => 'L', 'flex' => true, 'type' => 'field', 'field' => 'programm'],
|
||||
['id' => 'verein', 'header' => 'Verein', 'align' => 'L', 'flex' => true, 'type' => 'field', 'field' => 'verein'],
|
||||
['id' => 'note', 'header' => 'Note', 'align' => 'C', 'flex' => false, 'type' => 'field', 'field' => 'note'],
|
||||
['id' => 'value', 'header' => 'Wert', 'align' => 'C', 'flex' => false, 'type' => 'field', 'field' => 'value'],
|
||||
['id' => 'kr', 'header' => 'Kampfrichter/in', 'align' => 'C', 'flex' => true, 'type' => 'field', 'field' => 'kampfrichter'],
|
||||
['id' => 'timestamp', 'header' => 'Zeitstempel', 'align' => 'C', 'flex' => false, 'type' => 'field', 'field' => 'timestamp'],
|
||||
];
|
||||
|
||||
|
||||
$padding = 4;
|
||||
|
||||
unset($col);
|
||||
|
||||
// 1. Calculate initial max widths based on headers
|
||||
foreach ($columns as &$col) {
|
||||
$col['width_header'] = $pdf->GetStringWidth($col['header']) + ($padding * 2);
|
||||
if ($col['type'] !== 'note') {
|
||||
$col['max_width'] = $col['width_header'];
|
||||
} else {
|
||||
$col['max_width'] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($entriesArray as $geratId => $singleGeraet) {
|
||||
|
||||
$pdf->discipline = $IndexedGeraete[$geratId] ?? 'Unbekanntes Gerät';
|
||||
|
||||
foreach ($singleGeraet as $geratIdStart => $singleStartGeraet) {
|
||||
|
||||
$pdf->subAbt = $geratIdStart;
|
||||
|
||||
$tcolumns = $columns;
|
||||
|
||||
foreach ($singleStartGeraet as $se) {
|
||||
foreach ($tcolumns as &$col) {
|
||||
$text = '';
|
||||
if (isset($se[$col['field']])) {
|
||||
$text = $se[$col['field']];
|
||||
}
|
||||
$width = $pdf->GetStringWidth($text) + ($padding * 2);
|
||||
if ($width > $col['max_width']) {
|
||||
$col['max_width'] = $width;
|
||||
}
|
||||
}
|
||||
unset($col);
|
||||
}
|
||||
|
||||
// 4. Distribute Flexible Widths
|
||||
$tablew = $pdfWidth - (2 * $marginSide); // total table width (A4 landscape in mm minus margins)
|
||||
$fixedWidth = 0;
|
||||
$flexCols = [];
|
||||
|
||||
foreach ($tcolumns as $col) {
|
||||
if ($col['flex'] ?? false) {
|
||||
$flexCols[] = $col['id'];
|
||||
$fixedWidth += $col['max_width'];
|
||||
} else {
|
||||
$fixedWidth += $col['max_width'];
|
||||
}
|
||||
}
|
||||
|
||||
$effTableWidth = $tablew - $fixedWidth;
|
||||
|
||||
if (!empty($flexCols) && $effTableWidth > 0) {
|
||||
$flexTotalInitial = 0;
|
||||
foreach ($tcolumns as $col) {
|
||||
if ($col['flex'] ?? false) $flexTotalInitial += $col['max_width'];
|
||||
}
|
||||
|
||||
foreach ($tcolumns as &$col) {
|
||||
if ($col['flex'] ?? false) {
|
||||
$col['max_width'] += ($col['max_width'] / $flexTotalInitial) * $effTableWidth;
|
||||
}
|
||||
}
|
||||
unset($col);
|
||||
}
|
||||
|
||||
$pdf->columns = $tcolumns;
|
||||
|
||||
$pdf->headerType = 'bigHeader';
|
||||
$pdf->AddPage();
|
||||
$pdf->headerType = '';
|
||||
|
||||
// After AddPage(), the header has been drawn
|
||||
$margin_top = $pdf->headerBottomY;
|
||||
|
||||
// Now adjust your margins if needed
|
||||
$pdf->SetMargins($marginSide, $margin_top, $marginSide); // +5 mm padding below header
|
||||
$pdf->SetY($margin_top); // Move cursor below header manually
|
||||
|
||||
$pdf->SetFont('', '');
|
||||
$rIndex = 0;
|
||||
|
||||
foreach ($singleStartGeraet as $r) {
|
||||
|
||||
$pdf->SetTextColor(0, 0, 0);
|
||||
|
||||
if ($rIndex % 2 == 0) {
|
||||
$pdf->SetFillColor(255, 255, 255);
|
||||
} else {
|
||||
$pdf->SetFillColor(240, 240, 240);
|
||||
}
|
||||
|
||||
$rowHeight = 10;
|
||||
|
||||
foreach ($tcolumns as $col) {
|
||||
|
||||
if ($pdf->getY() + $rowHeight > $pdfHeight - $minMarginBottomTable) {
|
||||
$pdf->addPage();
|
||||
$margin_top = $pdf->headerBottomY;
|
||||
$pdf->setY($margin_top);
|
||||
}
|
||||
|
||||
$customFontSize = (isset($col['font_size']) && $col['font_size'] != 0);
|
||||
|
||||
if ($customFontSize) {
|
||||
$pdf->SetFont('', '', $col['font_size']);
|
||||
}
|
||||
|
||||
$startX = $pdf->GetX();
|
||||
$startY = $pdf->GetY();
|
||||
|
||||
$text = strip_tags($r[$col['field']]);
|
||||
|
||||
if ($col['type'] === 'field') {
|
||||
$pdf->MultiCell($col['max_width'], $rowHeight, $text, 'B', $col['align'], true, 0, $startX, $startY, true, 0, false, true, $rowHeight, 'M');
|
||||
}
|
||||
|
||||
if ($customFontSize) {
|
||||
$pdf->SetFont('', '', $normalFontSize);
|
||||
}
|
||||
}
|
||||
|
||||
$pdf->SetY($startY + $rowHeight); // Move Y manually instead of Ln() to account for rowHeight
|
||||
$rIndex++;
|
||||
}
|
||||
$textanzEintaege = (count($singleStartGeraet) > 1) ? 'Einträge': 'Eintrag';
|
||||
|
||||
$pdf->SetFont('', '', 7);
|
||||
|
||||
$pdf->Cell(20, 6, count($singleStartGeraet).' '.$textanzEintaege, 0, 0, 'L');
|
||||
|
||||
$pdf->SetFont('', '', $normalFontSize);
|
||||
}
|
||||
}
|
||||
|
||||
$pdf->Output($wkName . "_Protokoll_" . $abt . "_" . $current_year . ".pdf", 'I');
|
||||
exit;
|
||||
@@ -0,0 +1,750 @@
|
||||
<?php
|
||||
|
||||
use TCPDF;
|
||||
|
||||
if (!isset($baseDir)) {
|
||||
$baseDir = $_SERVER['DOCUMENT_ROOT'];
|
||||
}
|
||||
|
||||
require_once $baseDir . '/../scripts/session_functions.php';
|
||||
|
||||
ini_wkvs_session();
|
||||
|
||||
check_user_permission('kampfrichter');
|
||||
|
||||
verify_csrf();
|
||||
|
||||
if (!isset($baseDir)) {
|
||||
$baseDir = $_SERVER['DOCUMENT_ROOT'];
|
||||
}
|
||||
|
||||
$type = 'kr';
|
||||
$data = require $baseDir . '/../scripts/db/db-verbindung-script.php';
|
||||
|
||||
if ($data['success'] === false) {
|
||||
header('Content-Type: application/json');
|
||||
echo json_encode(['success' => false, 'message' => $data['message']]);
|
||||
exit;
|
||||
}
|
||||
|
||||
require $baseDir . '/../scripts/db/db-tables.php';
|
||||
require $baseDir . '/../scripts/db/db-functions.php';
|
||||
|
||||
$wkName = db_get_var($mysqli, "SELECT `value` FROM $db_tabelle_var WHERE `name` = ?", ['wkName']);
|
||||
|
||||
$wkName = ($wkName === null) ? 'Keinen Wettkampfname angegeben. Setzen unter: /intern/wk-leitung/einstellungen' : $wkName;
|
||||
|
||||
$normalFontSize = 11;
|
||||
$marginSide = 10;
|
||||
$marginTop = 10;
|
||||
$minMarginBottomTable = 20;
|
||||
$format = 'A4';
|
||||
$orientation = 'L';
|
||||
|
||||
$programm = trim($_POST['prog'] ?? 'P6A');
|
||||
$buttontype = trim($_POST['type'] ?? 'downloadRangliste');
|
||||
|
||||
$allowedOperations = ['downloadRangliste', 'updateServerRangliste'];
|
||||
|
||||
if (!in_array($buttontype, $allowedOperations)) {
|
||||
header('Content-Type: application/json');
|
||||
echo json_encode(["success" => false, "message" => "Invalide Operation"]);
|
||||
exit;
|
||||
}
|
||||
|
||||
$upperprogramm = strtoupper($programm);
|
||||
|
||||
$stmt = $mysqli->prepare("SELECT `id`, `name` FROM $db_tabelle_disziplinen ORDER BY start_index ASC");
|
||||
|
||||
if (!$stmt->execute()) {
|
||||
http_response_code(400);
|
||||
exit;
|
||||
}
|
||||
|
||||
$result = $stmt->get_result();
|
||||
$geraete = $result->fetch_all(MYSQLI_ASSOC);
|
||||
$disciplines = array_map(
|
||||
'strtolower',
|
||||
array_column($geraete, 'name')
|
||||
);
|
||||
|
||||
$stmt->close();
|
||||
|
||||
// Determine current year
|
||||
$current_year = date('Y');
|
||||
$monat = date('n');
|
||||
if ($monat > 6) $current_year++;
|
||||
|
||||
// Prepare SQL statement
|
||||
$stmt = $mysqli->prepare("
|
||||
SELECT * FROM $db_tabelle_teilnehmende
|
||||
WHERE LOWER(programm) = LOWER(?)
|
||||
AND (bezahltoverride = ? OR (bezahlt = ? OR bezahltoverride = ?))
|
||||
ORDER BY rang ASC
|
||||
");
|
||||
$bezahlt1 = '4';
|
||||
$bezahlt2 = '4';
|
||||
$bezahlt3 = '0';
|
||||
$stmt->bind_param('ssss', $programm, $bezahlt1, $bezahlt2, $bezahlt3);
|
||||
$stmt->execute();
|
||||
|
||||
$result = $stmt->get_result();
|
||||
$personen = $result->fetch_all(MYSQLI_ASSOC);
|
||||
|
||||
|
||||
// Close statement
|
||||
$stmt->close();
|
||||
|
||||
$programmId = db_get_var($mysqli, "SELECT `id` FROM $db_tabelle_kategorien WHERE LOWER(`programm`) = LOWER(?)", [$programm]);
|
||||
$cache = require $baseDir . '/../scripts/cache/noten-config-calculating-cache.php';
|
||||
$ascArrayAnzahlLaeufeJSON = $cache['anzahl_laeufe_json'];
|
||||
|
||||
// 1. Get the IDs from the first query results
|
||||
$turnerinnenIds = array_column($personen, 'id');
|
||||
|
||||
$rangNote = intval(db_get_var($mysqli, "SELECT `value` FROM $db_tabelle_var WHERE `name` = ?", ['rangNote']));
|
||||
|
||||
if ($rangNote === 0) {
|
||||
header('Content-Type: application/json');
|
||||
echo json_encode(["success" => false, "message" => "Keine Note für Rangvergabe ausgewählt"]);
|
||||
http_response_code(400);
|
||||
exit;
|
||||
}
|
||||
|
||||
$current_wk_id = (int) db_get_variable($mysqli, $db_tabelle_var, ['current_wk_id']) ?: 0;
|
||||
|
||||
if (!empty($turnerinnenIds)) {
|
||||
// 2. Create a string of placeholders: ?,?,?
|
||||
$placeholders = implode(',', array_fill(0, count($turnerinnenIds), '?'));
|
||||
|
||||
// 3. Prepare the IN statement
|
||||
$sqlNoten = "SELECT * FROM $db_tabelle_wertungen WHERE person_id IN ($placeholders) AND `wk_id` = ?";
|
||||
$stmtNoten = $mysqli->prepare($sqlNoten);
|
||||
|
||||
// --- FIX STARTS HERE ---
|
||||
|
||||
// 1. Combine all values into one flat array for binding
|
||||
$paramsArray = array_merge($turnerinnenIds, [$current_wk_id]);
|
||||
|
||||
// 2. Build the types string
|
||||
// 'i' for every ID, plus 'i' (or 's') for the year
|
||||
$types = str_repeat('i', count($turnerinnenIds)) . 's';
|
||||
|
||||
// 3. Unpack the combined array into the bind_param function
|
||||
$stmtNoten->bind_param($types, ...$paramsArray);
|
||||
|
||||
// --- FIX ENDS HERE ---
|
||||
|
||||
$stmtNoten->execute();
|
||||
$notenResult = $stmtNoten->get_result();
|
||||
$notenEntries = $notenResult->fetch_all(MYSQLI_ASSOC);
|
||||
|
||||
$stmtNoten->close(); // Close inside the IF to avoid errors if IDs were empty
|
||||
} else {
|
||||
$notenEntries = [];
|
||||
}
|
||||
|
||||
$indexedNotenEntries = [];
|
||||
foreach ($notenEntries as $sn) {
|
||||
if (!isset($indexedNotenEntries[$sn['person_id']][$sn['note_bezeichnung_id']][$sn['geraet_id']])) {
|
||||
$indexedNotenEntries[$sn['person_id']][$sn['note_bezeichnung_id']][$sn['geraet_id']] = [];
|
||||
}
|
||||
$indexedNotenEntries[$sn['person_id']][$sn['note_bezeichnung_id']][$sn['geraet_id']][$sn['run_number']] = $sn['value'];
|
||||
}
|
||||
|
||||
$orderBestRang = db_get_var($mysqli, "SELECT `value` FROM $db_tabelle_var WHERE `name` = ?", ['orderBestRang']);
|
||||
|
||||
$okValuesOrderBestRang = ["ASC", "DESC"];
|
||||
|
||||
if (!in_array($orderBestRang, $okValuesOrderBestRang)) {
|
||||
header('Content-Type: application/json');
|
||||
echo json_encode(["success" => false, "message" => "Invalide Sortierung der Ränge"]);
|
||||
http_response_code(400);
|
||||
exit;
|
||||
}
|
||||
|
||||
$alleNoten = db_select($mysqli, $db_tabelle_wertungstypen, "id, default_value, nullstellen, pro_geraet, geraete_json, zeige_auf_rangliste, groesse_auf_rangliste, name", "zeige_auf_rangliste = ? OR id = ?", ['1', $rangNote]);
|
||||
|
||||
$displayedNoten = [];
|
||||
|
||||
$alleNotenIndexed = array_column($alleNoten, null, 'id');
|
||||
|
||||
foreach ($alleNotenIndexed as $key => $sN) {
|
||||
if (intval($sN['zeige_auf_rangliste']) === 1) {
|
||||
$displayedNoten[$key] = $sN;
|
||||
}
|
||||
}
|
||||
|
||||
$ascArrayDefaultValues = array_column($alleNoten, 'default_value', 'id');
|
||||
$ascArrayGeraeteJSON = array_column($alleNoten, 'geraete_json', 'id');
|
||||
|
||||
foreach ($ascArrayGeraeteJSON as $key => $saagj) {
|
||||
$ascArrayGeraeteJSON[$key] = json_decode($saagj, true) ?? [];
|
||||
}
|
||||
|
||||
// 1. Initialize the structure for every person
|
||||
$indexedNotenArray = [];
|
||||
$sortArray = [];
|
||||
|
||||
$notenGeraeteArray = array_merge($geraete, array(array("id" => 0)));
|
||||
|
||||
foreach ($personen as $sp) {
|
||||
$pId = $sp['id'];
|
||||
foreach ($displayedNoten as $an) {
|
||||
$nId = $an['id'];
|
||||
$isProGeraet = (intval($an['pro_geraet']) === 1);
|
||||
$allowedGeraete = $ascArrayGeraeteJSON[$nId] ?? [];
|
||||
|
||||
foreach ($notenGeraeteArray as $g) {
|
||||
$gId = $g['id'];
|
||||
|
||||
if ($isProGeraet) {
|
||||
if ($gId === 0) continue;
|
||||
} else {
|
||||
if (!in_array($gId, $allowedGeraete)) continue;
|
||||
}
|
||||
|
||||
$indexedNotenArray[$pId][$gId][$nId] = $indexedNotenEntries[$pId][$nId][$gId] ?? [$an['default_value']];
|
||||
}
|
||||
|
||||
if (intval($nId) === $rangNote) {
|
||||
$val = $indexedNotenArray[$pId][0][$nId] ?? [$an['default_value']];
|
||||
$sortArray[$pId] = is_array($val) ? end($val) : $val; // fallback to the last run for sorting if needed, or total should just be one run
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$wkWebpageDomain = db_get_var($mysqli, "SELECT `value` FROM $db_tabelle_var WHERE `name` = ?", ['linkWebseite']);
|
||||
|
||||
// Load TCPDF
|
||||
require $baseDir . '/../composer/vendor/autoload.php';
|
||||
|
||||
// Optional: load custom font
|
||||
$fontfile = $baseDir . '/wp-content/uploads/fonts/Inter-Regular.ttf'; // adjust path
|
||||
if (file_exists($fontfile)) {
|
||||
$fontname = TCPDF_FONTS::addTTFfont($fontfile, 'TrueTypeUnicode', '', 32);
|
||||
}
|
||||
|
||||
class RanglistePDF extends TCPDF
|
||||
{
|
||||
public $current_year;
|
||||
public $programm;
|
||||
public $upperprogramm;
|
||||
public $columns;
|
||||
public $disciplines;
|
||||
public $wkName;
|
||||
public $marginSide;
|
||||
public $marginTop;
|
||||
public $pdfHeight;
|
||||
public $pdfWidth;
|
||||
public $wkWebpageDomain;
|
||||
// Page header
|
||||
|
||||
public $headerBottomY = 0;
|
||||
|
||||
public function Header()
|
||||
{
|
||||
$this->SetFillColor(255, 255, 255);
|
||||
|
||||
$this->Rect(0, 0, $this->pdfWidth, $this->pdfHeight, 'F');
|
||||
|
||||
$arrayTitles = [];
|
||||
$image_file = $_SERVER['DOCUMENT_ROOT'] . '/intern/img/logo-normal.png';
|
||||
$this->SetY($this->marginTop);
|
||||
$this->SetX(($this->marginSide ?? 10));
|
||||
$this->SetFont('freesans', '', 20);
|
||||
$this->Cell(0, 0, 'Rangliste ' . $this->wkName . ' ' . $this->current_year, 0, 1, 'L', 0, '', 0, false, 'T', 'M');
|
||||
$preimageX = $this->GetX();
|
||||
$preimageY = $this->GetY();
|
||||
$this->Image($image_file, $this->pdfWidth - 10 - $this->marginSide, $this->marginTop, '', 10, 'png', '', 'T');
|
||||
|
||||
$this->SetY($preimageY);
|
||||
$this->SetX($this->marginSide ?? 10); // Force back to left margin
|
||||
$this->SetFont('freesans', '', 11);
|
||||
$this->Cell(0, 10, 'Programm: ' . $this->upperprogramm, 0, 1, 'L');
|
||||
|
||||
$this->Ln(5);
|
||||
|
||||
$columns = $this->columns;
|
||||
$startY = $this->GetY();
|
||||
$this->SetFont('', 'B');
|
||||
|
||||
$this->SetX($this->marginSide ?? 10);
|
||||
|
||||
foreach ($columns as $col) {
|
||||
$isDuplicate = in_array($col['header'], $arrayTitles);
|
||||
|
||||
$title = $isDuplicate ? '' : $col['header'];
|
||||
|
||||
if (!$isDuplicate) {
|
||||
$arrayTitles[] = $col['header'];
|
||||
}
|
||||
|
||||
if (($col['rotate'] ?? false) && !$isDuplicate) {
|
||||
$x = $this->GetX();
|
||||
$y = $this->GetY() + 7;
|
||||
|
||||
$this->StartTransform();
|
||||
$this->Rotate(45, $x, $y);
|
||||
|
||||
$lineY = $startY + 7;
|
||||
if (($col['id'] ?? '') === 'gesamt') {
|
||||
$this->SetLineWidth(0.6);
|
||||
} else {
|
||||
$this->SetLineWidth(0.2);
|
||||
}
|
||||
|
||||
$this->Line($x, $lineY, $x + ($col['width_header'] ?? 0), $lineY);
|
||||
$this->SetLineWidth(0.2);
|
||||
|
||||
$this->Cell($col['width_header'] ?? 0, 7, $title ?? '', 0, 0, 'C');
|
||||
$this->StopTransform();
|
||||
$this->SetX($x + ($col['max_width'] ?? 0));
|
||||
} else {
|
||||
$this->Cell($col['max_width'] ?? 0, 7, $title ?? '', 0, 0, $col['align'] ?? 'L');
|
||||
}
|
||||
}
|
||||
|
||||
$this->Ln();
|
||||
$this->headerBottomY = $this->GetY();
|
||||
}
|
||||
|
||||
|
||||
// Page footer
|
||||
public function Footer()
|
||||
{
|
||||
$this->SetLineWidth(0.6);
|
||||
$this->Line($this->marginSide ?? 10, $this->headerBottomY, $this->pdfWidth - ($this->marginSide ?? 10), $this->headerBottomY);
|
||||
|
||||
$this->SetLineWidth(0.2);
|
||||
|
||||
$this->SetY(0);
|
||||
$this->SetX(0);
|
||||
|
||||
$this->SetFillColor(255, 255, 255); // white
|
||||
|
||||
$this->Cell(($this->marginSide ?? 10), $this->pdfHeight, '', 0, 0, 'L', true);
|
||||
|
||||
$this->SetY(0);
|
||||
$this->SetX($this->pdfWidth - ($this->marginSide ?? 10));
|
||||
|
||||
$this->Cell(($this->marginSide ?? 10), $this->pdfHeight, '', 0, 0, 'L', true);
|
||||
|
||||
$this->SetY(-15);
|
||||
$this->SetFont('freesans', 'I', 8);
|
||||
$this->Cell(0, 10, 'Seite ' . $this->getAliasNumPage() . ' von ' . $this->getAliasNbPages(), 0, false, 'C', 0, '', 0, false, 'T', 'M');
|
||||
$this->SetFont('', '');
|
||||
$this->Cell(0, 10, ($this->wkWebpageDomain ?? $_SERVER['HTTP_HOST']), 0, 0, 'R', false, 'https://' . ($this->wkWebpageDomain ?? $_SERVER['HTTP_HOST']), 0, false, 'T', 'M');
|
||||
}
|
||||
}
|
||||
|
||||
$pdf = new RanglistePDF($orientation, 'mm', $format, true, 'UTF-8', false);
|
||||
|
||||
$pdfHeight = $pdf->getPageHeight();
|
||||
$pdfWidth = $pdf->getPageWidth();
|
||||
|
||||
$pdf->current_year = $current_year;
|
||||
$pdf->wkName = $wkName;
|
||||
$pdf->wkWebpageDomain = $wkWebpageDomain;
|
||||
$pdf->programm = $programm;
|
||||
$pdf->upperprogramm = $upperprogramm;
|
||||
$pdf->marginSide = $marginSide;
|
||||
$pdf->marginTop = $marginTop;
|
||||
$pdf->pdfHeight = $pdfHeight;
|
||||
$pdf->pdfWidth = $pdfWidth;
|
||||
|
||||
$pdf->SetCreator(PDF_CREATOR);
|
||||
$pdf->SetAuthor($wkName);
|
||||
$pdf->SetTitle($wkName . "_Ergebnisse_" . $programm . "_" . $current_year . ".pdf");
|
||||
|
||||
$pdf->SetAutoPageBreak(FALSE);
|
||||
|
||||
|
||||
$pdf->SetFont('freesans', '', 11);
|
||||
|
||||
// Define columns dynamically
|
||||
$columns = [
|
||||
['id' => 'rang', 'header' => 'Rang', 'align' => 'C', 'flex' => false, 'type' => 'rank'],
|
||||
['id' => 'name', 'header' => 'Name', 'align' => 'L', 'flex' => true, 'type' => 'field', 'field' => 'name'],
|
||||
['id' => 'vorname', 'header' => 'Vorname', 'align' => 'L', 'flex' => true, 'type' => 'field', 'field' => 'vorname'],
|
||||
['id' => 'geburtsdatum', 'header' => 'Jg.', 'align' => 'C', 'flex' => false, 'type' => 'year', 'field' => 'geburtsdatum'],
|
||||
['id' => 'verein', 'header' => 'Verein', 'align' => 'L', 'flex' => true, 'type' => 'field', 'field' => 'verein'],
|
||||
];
|
||||
|
||||
// Add notes dynamically per device
|
||||
foreach ($geraete as $g) {
|
||||
foreach ($displayedNoten as $noteDef) {
|
||||
$neni = $noteDef['id'];
|
||||
$isProGeraet = (intval($noteDef['pro_geraet']) === 1);
|
||||
$allowedGeraete = $ascArrayGeraeteJSON[$neni] ?? [];
|
||||
|
||||
if ($isProGeraet || in_array($g['id'], $allowedGeraete)) {
|
||||
$columns[] = [
|
||||
'id' => 'note_' . $g['id'] . '_' . $neni,
|
||||
'header' => $g['name'],
|
||||
'align' => 'C',
|
||||
'flex' => false,
|
||||
'rotate' => true,
|
||||
'type' => 'note',
|
||||
'geraet_id' => $g['id'],
|
||||
'note_bezeichnung_id' => $neni,
|
||||
'nullstellen' => $noteDef['nullstellen'] ?? 2,
|
||||
'font_size' => intval($noteDef['groesse_auf_rangliste']) ?? 0
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Add Gesamt (Total) column
|
||||
$columns[] = [
|
||||
'id' => 'gesamt',
|
||||
'header' => $alleNotenIndexed[$rangNote]['name'] ?? 'Total',
|
||||
'align' => 'C',
|
||||
'flex' => false,
|
||||
'rotate' => true,
|
||||
'type' => 'note',
|
||||
'geraet_id' => 0,
|
||||
'note_bezeichnung_id' => $rangNote,
|
||||
'nullstellen' => $alleNotenIndexed[$rangNote]['nullstellen'] ?? 2,
|
||||
'font_size' => intval($alleNotenIndexed[$rangNote]['groesse_auf_rangliste']) ?? 0
|
||||
];
|
||||
|
||||
|
||||
|
||||
$padding = 4;
|
||||
|
||||
unset($col);
|
||||
|
||||
// 1. Calculate initial max widths based on headers
|
||||
foreach ($columns as &$col) {
|
||||
$col['width_header'] = $pdf->GetStringWidth($col['header']) + ($padding * 2);
|
||||
if ($col['type'] !== 'note') {
|
||||
$col['max_width'] = $col['width_header'];
|
||||
} else {
|
||||
$col['max_width'] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// 2. Fill missing defaults and update max widths based on data
|
||||
foreach ($personen as $sp) {
|
||||
$pId = $sp['id'];
|
||||
foreach ($indexedNotenArray[$pId] as $sG => $currentNoten) {
|
||||
foreach ($displayedNoten as $noteDef) {
|
||||
$neni = $noteDef['id'];
|
||||
if (isset($currentNoten[$neni])) {
|
||||
$runs = $currentNoten[$neni];
|
||||
if (is_array($runs)) {
|
||||
$runsConfig = $ascArrayAnzahlLaeufeJSON[$neni] ?? [];
|
||||
$runsCount = $runsConfig[$sG][$programmId] ?? $runsConfig[$sG]['all'] ?? $runsConfig["default"] ?? 1;
|
||||
$defaultValue = $ascArrayDefaultValues[$neni] ?? 0;
|
||||
|
||||
for ($r = 1; $r <= $runsCount - 1; $r++) {
|
||||
if (!isset($runs[$r])) {
|
||||
$runs[$r] = $defaultValue;
|
||||
}
|
||||
}
|
||||
$indexedNotenArray[$pId][$sG][$neni] = $runs;
|
||||
|
||||
ksort($runs);
|
||||
$maxLenStr = "";
|
||||
foreach ($runs as $rVal) {
|
||||
$str = number_format((float)$rVal, $noteDef['nullstellen']);
|
||||
// Approximate max width by string length, GetStringWidth will do the real check later
|
||||
if (strlen($str) > strlen($maxLenStr)) {
|
||||
$maxLenStr = $str;
|
||||
}
|
||||
}
|
||||
$val = $maxLenStr;
|
||||
} else {
|
||||
$val = number_format((float)$runs, $noteDef['nullstellen']);
|
||||
}
|
||||
} else {
|
||||
// Logic for "Pro Gerät" vs "Specific/Total"
|
||||
$isProGeraet = (intval($noteDef['pro_geraet']) === 1);
|
||||
$allowedGeraete = $ascArrayGeraeteJSON[$neni] ?? [];
|
||||
|
||||
if ($isProGeraet) {
|
||||
if ($sG === 0) continue;
|
||||
} else {
|
||||
if (!in_array($sG, $allowedGeraete)) continue;
|
||||
}
|
||||
|
||||
$defaultValue = $ascArrayDefaultValues[$neni] ?? 0;
|
||||
|
||||
$runsConfig = $ascArrayAnzahlLaeufeJSON[$neni] ?? [];
|
||||
$runsCount = $runsConfig[$sG][$programmId] ?? $runsConfig[$sG]['all'] ?? $runsConfig["default"] ?? 1;
|
||||
|
||||
$valArray = [];
|
||||
$maxLenStr = "";
|
||||
for ($r = 1; $r <= $runsCount - 1; $r++) {
|
||||
$valArray[$r] = $defaultValue;
|
||||
$str = number_format((float)$defaultValue, $noteDef['nullstellen']);
|
||||
if (strlen($str) > strlen($maxLenStr)) {
|
||||
$maxLenStr = $str;
|
||||
}
|
||||
}
|
||||
|
||||
$val = $maxLenStr;
|
||||
$indexedNotenArray[$pId][$sG][$neni] = $valArray;
|
||||
|
||||
if ($neni === $rangNote && $sG === 0) {
|
||||
$sortArray[$pId] = $defaultValue;
|
||||
}
|
||||
}
|
||||
|
||||
// Update column width if this note is displayed
|
||||
foreach ($columns as &$col) {
|
||||
if ($col['type'] === 'note' && $col['geraet_id'] == $sG && $col['note_bezeichnung_id'] == $neni) {
|
||||
|
||||
$customFontSize = (isset($col['font_size']) && $col['font_size'] != 0);
|
||||
|
||||
$cpadding = $padding;
|
||||
|
||||
if ($customFontSize) {
|
||||
$pdf->SetFont('', '', $col['font_size']);
|
||||
$cpadding = ($col['font_size'] / $normalFontSize) * $padding;
|
||||
}
|
||||
|
||||
$width = $pdf->GetStringWidth($val) + ($cpadding * 2);
|
||||
if ($width > $col['max_width']) {
|
||||
$col['max_width'] = $width;
|
||||
}
|
||||
|
||||
if ($customFontSize) {
|
||||
$pdf->SetFont('', '', $normalFontSize);
|
||||
}
|
||||
}
|
||||
}
|
||||
unset($col);
|
||||
}
|
||||
}
|
||||
|
||||
// Also update widths for static fields
|
||||
foreach ($columns as &$col) {
|
||||
if ($col['type'] === 'field' || $col['type'] === 'year' || $col['type'] === 'rank') {
|
||||
$text = '';
|
||||
if ($col['type'] === 'rank') {
|
||||
$text = '999'; // Placeholder for rank width
|
||||
} elseif ($col['type'] === 'year') {
|
||||
$text = '0000';
|
||||
} elseif (isset($sp[$col['field']])) {
|
||||
$text = $sp[$col['field']];
|
||||
}
|
||||
$width = $pdf->GetStringWidth($text) + ($padding * 2);
|
||||
if ($width > $col['max_width']) {
|
||||
$col['max_width'] = $width;
|
||||
}
|
||||
}
|
||||
}
|
||||
unset($col);
|
||||
}
|
||||
|
||||
function calculateRanks(array $scoreArray, $direction = 'DESC') {
|
||||
// 1. Sort the scores while preserving keys
|
||||
if ($direction === 'DESC') {
|
||||
arsort($scoreArray); // High scores first
|
||||
} else {
|
||||
asort($scoreArray); // Low scores first
|
||||
}
|
||||
|
||||
$ranks = [];
|
||||
$currentRank = 0;
|
||||
$lastScore = null;
|
||||
$skipped = 0;
|
||||
|
||||
foreach ($scoreArray as $pId => $score) {
|
||||
if ($score !== $lastScore) {
|
||||
$currentRank += ($skipped + 1);
|
||||
$skipped = 0;
|
||||
} else {
|
||||
$skipped++;
|
||||
}
|
||||
|
||||
$ranks[$pId] = $currentRank;
|
||||
$lastScore = $score;
|
||||
}
|
||||
return $ranks;
|
||||
}
|
||||
|
||||
|
||||
// 3. Finalize Ranks
|
||||
$ranks = calculateRanks($sortArray, $orderBestRang);
|
||||
|
||||
// 4. Distribute Flexible Widths
|
||||
$tablew = $pdfWidth - (2 * $marginSide); // total table width (A4 landscape in mm minus margins)
|
||||
$fixedWidth = 0;
|
||||
$flexCols = [];
|
||||
|
||||
foreach ($columns as $col) {
|
||||
if ($col['flex'] ?? false) {
|
||||
$flexCols[] = $col['id'];
|
||||
$fixedWidth += $col['max_width'];
|
||||
} else {
|
||||
$fixedWidth += $col['max_width'];
|
||||
}
|
||||
}
|
||||
|
||||
$effTableWidth = $tablew - $fixedWidth;
|
||||
|
||||
|
||||
if (!empty($flexCols) && $effTableWidth > 0) {
|
||||
$flexTotalInitial = 0;
|
||||
foreach ($columns as $col) {
|
||||
if ($col['flex'] ?? false) $flexTotalInitial += $col['max_width'];
|
||||
}
|
||||
|
||||
foreach ($columns as &$col) {
|
||||
if ($col['flex'] ?? false) {
|
||||
$col['max_width'] += ($col['max_width'] / $flexTotalInitial) * $effTableWidth;
|
||||
}
|
||||
}
|
||||
unset($col);
|
||||
}
|
||||
|
||||
$pdf->columns = $columns;
|
||||
$pdf->disciplines = $disciplines;
|
||||
|
||||
$pdf->AddPage();
|
||||
|
||||
// After AddPage(), the header has been drawn
|
||||
$margin_top = $pdf->headerBottomY;
|
||||
|
||||
// Now adjust your margins if needed
|
||||
$pdf->SetMargins($marginSide, $margin_top, $marginSide); // +5 mm padding below header
|
||||
$pdf->SetY($margin_top); // Move cursor below header manually
|
||||
|
||||
$pdf->SetFont('', '');
|
||||
$rIndex = 0;
|
||||
|
||||
usort($personen, function($a, $b) use ($ranks) {
|
||||
$rankA = $ranks[$a['id']];
|
||||
$rankB = $ranks[$b['id']];
|
||||
|
||||
return $rankA <=> $rankB;
|
||||
});
|
||||
|
||||
foreach ($personen as $r) {
|
||||
|
||||
$pdf->SetTextColor(0, 0, 0);
|
||||
|
||||
$rang = $ranks[$r['id']];
|
||||
|
||||
if ($rang == 1) {
|
||||
$pdf->SetFillColor(255, 235, 128);
|
||||
} elseif($rang == 2) {
|
||||
$pdf->SetFillColor(224, 224, 224);
|
||||
} elseif($rang == 3) {
|
||||
$pdf->SetFillColor(230, 191, 153);
|
||||
} elseif ($rIndex % 2 == 0) {
|
||||
$pdf->SetFillColor(255, 255, 255); // white
|
||||
} else {
|
||||
$pdf->SetFillColor(240, 240, 240); // light gray
|
||||
}
|
||||
|
||||
|
||||
// Determine row height based on max runs
|
||||
$maxRuns = 1;
|
||||
foreach ($columns as $col) {
|
||||
if ($col['type'] === 'note') {
|
||||
$runs = $indexedNotenArray[$r['id']][$col['geraet_id']][$col['note_bezeichnung_id']] ?? [];
|
||||
if (is_array($runs) && count($runs) > $maxRuns) {
|
||||
$maxRuns = count($runs);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Base height is 8, add extra height for additional runs. Let's say 4mm per additional line.
|
||||
// But to keep it centered properly, we will use MultiCell with valign='M' (Middle).
|
||||
$rowHeight = max(8, $maxRuns * 5 + 3); // 5mm per line
|
||||
|
||||
if ($pdf->getY() + $rowHeight >= $pdfHeight - $minMarginBottomTable) {
|
||||
$pdf->addPage();
|
||||
$pdf->setX($marginSide);
|
||||
}
|
||||
|
||||
foreach ($columns as $col) {
|
||||
|
||||
$customFontSize = (isset($col['font_size']) && $col['font_size'] != 0);
|
||||
|
||||
if ($customFontSize) {
|
||||
$pdf->SetFont('', '', $col['font_size']);
|
||||
}
|
||||
|
||||
$startX = $pdf->GetX();
|
||||
$startY = $pdf->GetY();
|
||||
|
||||
if ($col['id'] === 'rang') {
|
||||
$pdf->SetFont('', 'B');
|
||||
$pdf->MultiCell($col['max_width'], $rowHeight, $rang, 'B', 'C', true, 0, $startX, $startY, true, 0, false, true, $rowHeight, 'M');
|
||||
$pdf->SetFont('', '');
|
||||
} elseif ($col['type'] === 'field') {
|
||||
$pdf->MultiCell($col['max_width'], $rowHeight, $r[$col['field']], 'B', $col['align'], true, 0, $startX, $startY, true, 0, false, true, $rowHeight, 'M');
|
||||
} elseif ($col['type'] === 'year') {
|
||||
$pdf->MultiCell($col['max_width'], $rowHeight, (new DateTime($r[$col['field']]))->format("Y"), 'B', $col['align'], true, 0, $startX, $startY, true, 0, false, true, $rowHeight, 'M');
|
||||
} elseif ($col['type'] === 'note') {
|
||||
$runs = $indexedNotenArray[$r['id']][$col['geraet_id']][$col['note_bezeichnung_id']] ?? [];
|
||||
if (!is_array($runs)) {
|
||||
$runs = [$runs];
|
||||
} else {
|
||||
ksort($runs);
|
||||
}
|
||||
|
||||
$numRuns = max(count($runs), 1);
|
||||
$lineHeight = $rowHeight / $numRuns;
|
||||
|
||||
$pdf->SetXY($startX, $startY);
|
||||
$pdf->Cell($col['max_width'], $rowHeight, '', 0, 0, '', true);
|
||||
|
||||
$runIndex = 0;
|
||||
foreach (array_values($runs) as $rnVal) {
|
||||
$formatted = number_format((float)$rnVal, $col['nullstellen'] ?? 0);
|
||||
$currentY = $startY + ($runIndex * $lineHeight);
|
||||
|
||||
$pdf->SetXY($startX, $currentY);
|
||||
|
||||
$pdf->Cell($col['max_width'], $lineHeight, $formatted, 0, 0, $col['align'], false);
|
||||
$runIndex++;
|
||||
}
|
||||
|
||||
// Draw the bottom border for the entire row height
|
||||
$pdf->Line($startX, $startY + $rowHeight, $startX + $col['max_width'], $startY + $rowHeight);
|
||||
|
||||
// Reset pointer for the next column
|
||||
$pdf->SetXY($startX + $col['max_width'], $startY);
|
||||
|
||||
if ($col['id'] === 'gesamt') {
|
||||
// Draw the heavy separator line on the left side of the "Gesamt" column
|
||||
$pdf->SetLineWidth(0.6);
|
||||
$pdf->Line($startX, $startY, $startX, $startY + $rowHeight);
|
||||
$pdf->SetLineWidth(0.2);
|
||||
}
|
||||
}
|
||||
|
||||
if ($customFontSize) {
|
||||
$pdf->SetFont('', '', $normalFontSize);
|
||||
}
|
||||
}
|
||||
|
||||
$pdf->SetY($startY + $rowHeight); // Move Y manually instead of Ln() to account for rowHeight
|
||||
$rIndex++;
|
||||
}
|
||||
|
||||
|
||||
|
||||
$pdf->SetFont('', '', 7);
|
||||
$textanzturnerinnen = (count($personen) > 1) ? 'Turnerinnen': 'Turnerin';
|
||||
$pdf->Cell(20, 6, count($personen).' '.$textanzturnerinnen, 0, 0, 'L');
|
||||
|
||||
if ($buttontype === 'downloadRangliste') {
|
||||
$pdf->Output($wkName . "_Ergebnisse_" . $programm . "_" . $current_year . ".pdf", 'I');
|
||||
exit;
|
||||
} elseif ($buttontype === 'updateServerRangliste') {
|
||||
$dir = $baseDir . '/files/ranglisten/';
|
||||
if (!file_exists($dir)) mkdir($dir, 0755, true);
|
||||
$localPath = $dir . str_replace("/", "", str_replace(" ", "_", $wkName)) . "_Ergebnisse_" . str_replace("/", "", $programm) . "_" . $current_year . ".pdf";
|
||||
if (file_exists($localPath)) unlink($localPath);
|
||||
$pdf->Output($localPath, 'F');
|
||||
header('Content-Type: application/json');
|
||||
echo json_encode(["success" => true, "message" => "PDF wurde aktualisiert"]);
|
||||
exit;
|
||||
}
|
||||
@@ -0,0 +1,125 @@
|
||||
<?php
|
||||
|
||||
if (!isset($baseDir)) {
|
||||
$baseDir = $_SERVER['DOCUMENT_ROOT'];
|
||||
}
|
||||
|
||||
require_once $baseDir . '/../scripts/session_functions.php';
|
||||
|
||||
ini_wkvs_session();
|
||||
|
||||
check_user_permission('kampfrichter');
|
||||
|
||||
verify_csrf();
|
||||
|
||||
$type = 'kr';
|
||||
|
||||
$data = require $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';
|
||||
|
||||
// ---------- Get and sanitize input ----------
|
||||
$personId = intval($_POST['personId'] ?? 0);
|
||||
$gereatId = intval($_POST['geraetId'] ?? 0);
|
||||
|
||||
if ($gereatId < 1) {
|
||||
echo json_encode(['success' => false, 'message' => 'Kein Gerät angegeben']);
|
||||
exit;
|
||||
}
|
||||
|
||||
if ($personId < 1) {
|
||||
echo json_encode(['success' => false, 'message' => 'Invalid ID']);
|
||||
exit;
|
||||
}
|
||||
|
||||
// ---------- Step 2: Get values from DB ----------
|
||||
|
||||
$sqlQuery = "SELECT
|
||||
paf.`audiofile_id`,
|
||||
af.`file_path`,
|
||||
af.`file_name`,
|
||||
tu.`name`,
|
||||
tu.`vorname`
|
||||
FROM $db_tabelle_teilnehmende_audiofiles paf
|
||||
INNER JOIN $db_tabelle_audiofiles af
|
||||
ON paf.`audiofile_id` = af.`id`
|
||||
LEFT JOIN $db_tabelle_teilnehmende tu
|
||||
ON paf.`person_id` = tu.`id`
|
||||
WHERE paf.`person_id` = ?
|
||||
AND paf.`geraet_id` = ?
|
||||
";
|
||||
|
||||
$stmt = $mysqli->prepare($sqlQuery);
|
||||
|
||||
$stmt->bind_param('ii', $personId, $gereatId);
|
||||
|
||||
$stmt->execute();
|
||||
|
||||
$result = $stmt->get_result();
|
||||
|
||||
$rows = $result->fetch_all(MYSQLI_ASSOC);
|
||||
|
||||
if (count($rows) !== 1 || !isset($rows[0]['file_path']) || $rows[0]['file_path'] === null) {
|
||||
echo json_encode(['success' => false, 'message' => 'Keine Musik']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$row = $rows[0];
|
||||
|
||||
$folder = realpath($baseDir . '/externe-geraete/json');
|
||||
if ($folder === false) {
|
||||
echo json_encode([
|
||||
'success' => false,
|
||||
'message' => 'Could not find displays folder.'
|
||||
]);
|
||||
exit;
|
||||
}
|
||||
|
||||
$filename = 'audio-id-'. $gereatId .'.json';
|
||||
$filepath = $folder . '/' . $filename;
|
||||
|
||||
if (!is_writable($folder)) {
|
||||
echo json_encode(['success' => false, 'message' => 'Folder not writable.']);
|
||||
exit;
|
||||
}
|
||||
|
||||
|
||||
if (!is_file($filepath)){
|
||||
file_put_contents($filepath, []);
|
||||
}
|
||||
|
||||
|
||||
$json = [
|
||||
"audio_path" => $row['file_path'],
|
||||
"audio_name" => $row['file_name'],
|
||||
"start" => true,
|
||||
"person" => [
|
||||
"name" => $row['name'],
|
||||
"vorname" => $row['vorname']
|
||||
]
|
||||
];
|
||||
|
||||
$jsonData = json_encode($json);
|
||||
|
||||
// Write file
|
||||
if (file_put_contents($filepath, $jsonData) === false) {
|
||||
echo json_encode([
|
||||
'success' => false,
|
||||
'message' => 'Failed to write JSON file'
|
||||
]);
|
||||
exit;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// ---------- Return JSON ----------
|
||||
echo json_encode([
|
||||
'success' => true,
|
||||
'message' => 'Audio JSON updated successfully'
|
||||
]);
|
||||
exit;
|
||||
@@ -0,0 +1,67 @@
|
||||
<?php
|
||||
header('Content-Type: application/json');
|
||||
|
||||
if (!isset($baseDir)) {
|
||||
$baseDir = $_SERVER['DOCUMENT_ROOT'];
|
||||
}
|
||||
|
||||
require_once $baseDir . '/../scripts/session_functions.php';
|
||||
|
||||
ini_wkvs_session();
|
||||
|
||||
check_user_permission('kampfrichter');
|
||||
|
||||
verify_csrf();
|
||||
|
||||
$gereatId = intval($_POST['geraetId'] ?? 0);
|
||||
|
||||
if ($gereatId < 1) {
|
||||
echo json_encode(['success' => false, 'message' => 'Kein Gerät angegeben']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$folder = realpath($baseDir . '/externe-geraete/json');
|
||||
if ($folder === false) {
|
||||
echo json_encode([
|
||||
'success' => false,
|
||||
'message' => 'Could not find displays folder.'
|
||||
]);
|
||||
exit;
|
||||
}
|
||||
|
||||
$filename = 'audio-id-'. $gereatId .'.json';
|
||||
$filepath = $folder . '/' . $filename;
|
||||
|
||||
if (!is_writable($folder)) {
|
||||
echo json_encode(['success' => false, 'message' => 'Folder not writable']);
|
||||
exit;
|
||||
}
|
||||
|
||||
if (!is_file($filepath)){
|
||||
file_put_contents($filepath, []);
|
||||
}
|
||||
|
||||
$json = [
|
||||
"start" => false
|
||||
];
|
||||
|
||||
$jsonData = json_encode($json);
|
||||
|
||||
// Write file
|
||||
if (file_put_contents($filepath, $jsonData) === false) {
|
||||
echo json_encode([
|
||||
'success' => false,
|
||||
'message' => 'Failed to write JSON file: ' . $filepath
|
||||
]);
|
||||
exit;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// ---------- Return JSON ----------
|
||||
echo json_encode([
|
||||
'success' => true,
|
||||
'message' => 'JSON updated successfully for '.$discipline,
|
||||
'disable_musik_button' => true
|
||||
]);
|
||||
exit;
|
||||
@@ -0,0 +1,315 @@
|
||||
<?php
|
||||
|
||||
if (!isset($baseDir)) {
|
||||
$baseDir = $_SERVER['DOCUMENT_ROOT'];
|
||||
}
|
||||
|
||||
require_once $baseDir . '/../scripts/session_functions.php';
|
||||
|
||||
ini_wkvs_session();
|
||||
|
||||
check_user_permission('kampfrichter');
|
||||
|
||||
verify_csrf();
|
||||
|
||||
$type = 'kr';
|
||||
|
||||
$data = require $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-functions.php';
|
||||
require $baseDir . '/../scripts/db/db-tables.php';
|
||||
|
||||
$person_id = isset($_POST['personId']) ? intval($_POST['personId']) : 0;
|
||||
$field_type_id = intval($_POST['fieldTypeId'] ?? 0);
|
||||
$gereat_id = intval($_POST['gereatId'] ?? 0);
|
||||
$jahr = isset($_POST['jahr']) ? intval($_POST['jahr']) : 0;
|
||||
$run_number = isset($_POST['run']) ? intval($_POST['run']) : 1;
|
||||
|
||||
if (!isset($_POST['value'])) {
|
||||
echo json_encode(['success' => false, 'message' => 'Kein Value angegeben']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$valueNoteUpdate = floatval($_POST['value']);
|
||||
|
||||
if ($person_id < 1) {
|
||||
echo json_encode(['success' => false, 'message' => 'Invalide Personen-ID']);
|
||||
exit;
|
||||
}
|
||||
|
||||
if ($jahr < 1) {
|
||||
echo json_encode(['success' => false, 'message' => 'Invalides Jahr']);
|
||||
exit;
|
||||
}
|
||||
|
||||
if ($gereat_id < 1) {
|
||||
echo json_encode(['success' => false, 'message' => 'Invalide Geraet-ID']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$geratExistiert = db_get_var($mysqli, "SELECT 1 FROM $db_tabelle_disziplinen WHERE id = ? LIMIT 1", [$gereat_id]);
|
||||
|
||||
if (!$geratExistiert) {
|
||||
echo json_encode(['success' => false, 'message' => 'Invalide Geraet-ID']);
|
||||
exit;
|
||||
}
|
||||
|
||||
if ($field_type_id < 1) {
|
||||
echo json_encode(['success' => false, 'message' => 'Invalide Notentyp-ID']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$noteConfig = db_select($mysqli, $db_tabelle_wertungstypen, "*", "id = ?", [$field_type_id]);
|
||||
|
||||
if (count($noteConfig) !== 1) {
|
||||
echo json_encode(['success' => false, 'message' => 'Invalide Notentyp-ID']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$singleNoteConfig = $noteConfig[0];
|
||||
|
||||
if ($singleNoteConfig['max_value'] !== null && $valueNoteUpdate > $singleNoteConfig['max_value']) {
|
||||
echo json_encode(['success' => false, 'message' => "Wert zu hoch (max " . $singleNoteConfig['max_value'].")"]);
|
||||
exit;
|
||||
}
|
||||
|
||||
if ($singleNoteConfig['min_value'] !== null && $valueNoteUpdate < $singleNoteConfig['min_value']){
|
||||
echo json_encode(['success' => false, 'message' => "Wert zu niedrig (min " . $singleNoteConfig['min_value'].")"]);
|
||||
exit;
|
||||
}
|
||||
|
||||
$current_wk_id = (int) db_get_variable($mysqli, $db_tabelle_var, ['current_wk_id']) ?: 0;
|
||||
|
||||
$oldNote = db_get_var($mysqli, "SELECT `value` FROM $db_tabelle_wertungen WHERE `person_id` = ? AND `note_bezeichnung_id` = ? AND `geraet_id` = ? AND `wk_id` = ? AND `run_number` = ?", [$person_id, $field_type_id, $gereat_id, $current_wk_id, $run_number]);
|
||||
|
||||
$sql = "INSERT INTO $db_tabelle_wertungen (`value`, `person_id`, `note_bezeichnung_id`, `geraet_id`, `wk_id`, `run_number`)
|
||||
VALUES (?, ?, ?, ?, ?, ?)
|
||||
ON DUPLICATE KEY UPDATE `value` = VALUES(`value`)";
|
||||
|
||||
$stmt = $mysqli->prepare($sql);
|
||||
|
||||
$stmt->bind_param("siiiii", $valueNoteUpdate, $person_id, $field_type_id, $gereat_id, $current_wk_id, $run_number);
|
||||
|
||||
$stmt->execute();
|
||||
|
||||
$stmt->close();
|
||||
|
||||
$userId = (int) $_SESSION['user_id_kampfrichter'];
|
||||
|
||||
$sql = "INSERT INTO $db_tabelle_wertungen_log (`new_value`, `old_value`, `person_id`, `note_bezeichnung_id`, `geraet_id`, `wk_id`, `run_number`, `edited_by`)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?)";
|
||||
|
||||
$stmt = $mysqli->prepare($sql);
|
||||
|
||||
$stmt->bind_param("ssiiiiii", $valueNoteUpdate, $oldNote, $person_id, $field_type_id, $gereat_id, $current_wk_id, $run_number, $userId);
|
||||
|
||||
$stmt->execute();
|
||||
|
||||
$stmt->close();
|
||||
|
||||
if ($singleNoteConfig['berechnung_json'] === null) {
|
||||
echo json_encode(['success' => true, 'message' => "Wert aktualisiert"]);
|
||||
exit;
|
||||
}
|
||||
|
||||
require $baseDir . "/../scripts/string-calculator/string-calculator-functions.php";
|
||||
|
||||
$updateNoten = [];
|
||||
|
||||
$notenRechner = new NotenRechner();
|
||||
|
||||
try {
|
||||
$abhaenigeRechnungen = json_decode($singleNoteConfig['berechnung_json']);
|
||||
} catch (Exception $e) {
|
||||
echo json_encode(['success' => true, 'message' => "Wert aktualisiert, fehler bei der Berechnung der weiteren Werte"]);
|
||||
exit;
|
||||
}
|
||||
|
||||
$geraete = db_select($mysqli, $db_tabelle_disziplinen, "id");
|
||||
|
||||
$programmName = db_get_var($mysqli, "SELECT `programm` FROM $db_tabelle_teilnehmende WHERE `id` = ?", [$person_id]);
|
||||
|
||||
$programmId = db_get_var($mysqli, "SELECT `id` FROM $db_tabelle_kategorien WHERE `programm` = ?", [$programmName]);
|
||||
|
||||
// We load the configuration native cached array
|
||||
$cache = require $baseDir . '/../scripts/cache/noten-config-calculating-cache.php';
|
||||
|
||||
$noten = db_select($mysqli, $db_tabelle_wertungen, "`value`, `note_bezeichnung_id`, `geraet_id`, `run_number`", "`person_id` = ? AND `wk_id` = ? AND `value` IS NOT NULL", [$person_id, $current_wk_id]);
|
||||
|
||||
$ascArrayDefaultValues = $cache['default_values'];
|
||||
$ascArrayProGeraet = $cache['pro_geraet'];
|
||||
$ascArrayGeraeteJSON = $cache['geraete_json'];
|
||||
$ascArrayAnzahlLaeufeJSON = $cache['anzahl_laeufe_json'];
|
||||
$ascArrayRechnungen = $cache['rechnungen'];
|
||||
$indexedNullstellen = $cache['nullstellen'];
|
||||
|
||||
$mRunFunctions = [];
|
||||
|
||||
foreach ($abhaenigeRechnungen as $saRechnung) {
|
||||
$sRechnung = $ascArrayRechnungen[$saRechnung[0]] ?? 0;
|
||||
//var_dump($sRechnung);
|
||||
$mRunCalc = $notenRechner->checkRunFunctions($sRechnung) ?? false;
|
||||
|
||||
if ($mRunCalc) {
|
||||
$mRunFunctions[] = $saRechnung[0];
|
||||
}
|
||||
}
|
||||
|
||||
$indexedNotenArray = [];
|
||||
|
||||
foreach ($geraete as $g) {
|
||||
$indexedNotenArray[$g['id']] = [];
|
||||
}
|
||||
|
||||
$indexedNotenArray[0] = [];
|
||||
|
||||
foreach ($noten as $sn) {
|
||||
$indexedNotenArray[$sn['geraet_id']][$sn['note_bezeichnung_id']][$sn['run_number']] = ["value" => $sn['value'], "type" => "note"];
|
||||
}
|
||||
|
||||
$requiredNoteIds = [];
|
||||
$requiredNoteIds[$field_type_id] = true;
|
||||
|
||||
foreach ($abhaenigeRechnungen as $saRechnung) {
|
||||
// Only load dependencies for the specifically connected calculations
|
||||
$sRechnungStr = $ascArrayRechnungen[$saRechnung[0]] ?? '';
|
||||
if ($sRechnungStr !== '') {
|
||||
$ids = $notenRechner->getBenoetigteIdsComplex($sRechnungStr);
|
||||
foreach ($ids as $idConfig) {
|
||||
$requiredNoteIds[(int)$idConfig['noteId']] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
$alleNotenIds = array_keys($requiredNoteIds);
|
||||
|
||||
if (count($mRunFunctions) > 0) {
|
||||
foreach ($indexedNotenArray as $sG => $siNA) {
|
||||
foreach ($alleNotenIds as $neni) {
|
||||
if (!isset($ascArrayDefaultValues[$neni])) continue;
|
||||
|
||||
$isProGeraet = (int)($ascArrayProGeraet[$neni] ?? 0);
|
||||
if ($isProGeraet === 1 && (int)$sG === 0) continue;
|
||||
|
||||
if ($isProGeraet !== 1) {
|
||||
$allowedGeraete = $ascArrayGeraeteJSON[$neni] ?? [];
|
||||
if (!is_array($allowedGeraete) || !in_array($sG, $allowedGeraete)) continue;
|
||||
}
|
||||
|
||||
$runs = $ascArrayAnzahlLaeufeJSON[$neni][$sG][$programmId] ?? $ascArrayAnzahlLaeufeJSON[$neni][$sG]['all'] ?? $ascArrayAnzahlLaeufeJSON[$neni]["default"] ?? 1;
|
||||
|
||||
for ($r = 1; $r <= $runs; $r++) {
|
||||
if (!isset($indexedNotenArray[$sG][$neni][$r])) {
|
||||
$indexedNotenArray[$sG][$neni][$r] = ["value" => $ascArrayDefaultValues[$neni], "type" => "default_value"];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
foreach ($indexedNotenArray as $sG => $siNA) {
|
||||
foreach ($alleNotenIds as $neni) {
|
||||
if (isset($indexedNotenArray[$sG][$neni][$run_number])) continue;
|
||||
if (!isset($ascArrayDefaultValues[$neni])) continue;
|
||||
|
||||
$isProGeraet = (int)($ascArrayProGeraet[$neni] ?? 0);
|
||||
if ($isProGeraet === 1 && (int)$sG === 0) continue;
|
||||
|
||||
if ($isProGeraet !== 1) {
|
||||
$allowedGeraete = $ascArrayGeraeteJSON[$neni] ?? [];
|
||||
if (!is_array($allowedGeraete) || !in_array($sG, $allowedGeraete)) continue;
|
||||
}
|
||||
|
||||
$indexedNotenArray[$sG][$neni][$run_number] = ["value" => $ascArrayDefaultValues[$neni], "type" => "default_value"];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// We only want to save the IDs that were actually recalculated
|
||||
$idsToSave = [];
|
||||
|
||||
foreach ($abhaenigeRechnungen as $sRechnung) {
|
||||
$targetNoteId = $sRechnung[0];
|
||||
$rechnungType = $sRechnung[1];
|
||||
$targetRun = $sRechnung[2][0] ?? 'A';
|
||||
|
||||
// 1. Initial Filter
|
||||
if ($rechnungType !== "A" && intval($rechnungType) !== $gereat_id) continue;
|
||||
|
||||
$rechnung = $ascArrayRechnungen[$targetNoteId] ?? null;
|
||||
if ($rechnung === null) {
|
||||
echo json_encode(['success' => true, 'message' => "Fehler: Rechnung $targetNoteId nicht gefunden"]);
|
||||
exit;
|
||||
}
|
||||
|
||||
// 2. Determine Target Device ID
|
||||
$isProGeraet = (intval($ascArrayProGeraet[$targetNoteId] ?? 0) === 1);
|
||||
$allowedGeraete = $ascArrayGeraeteJSON[$targetNoteId] ?? [];
|
||||
|
||||
if ($rechnungType === "A" || $isProGeraet || in_array($gereat_id, $allowedGeraete)) {
|
||||
$targetGeraetKey = $gereat_id;
|
||||
} else {
|
||||
$targetGeraetKey = 0;
|
||||
}
|
||||
|
||||
// 3. Calculation Logic
|
||||
$runsConfig = $ascArrayAnzahlLaeufeJSON[$targetNoteId] ?? [];
|
||||
$runs = $runsConfig[$targetGeraetKey][$programmId] ?? $runsConfig[$targetGeraetKey]["all"] ?? $runsConfig["default"] ?? 1;
|
||||
|
||||
$acrun = min($runs, $run_number);
|
||||
|
||||
if (in_array($targetNoteId, $mRunFunctions)) {
|
||||
$calcResult = $notenRechner->berechneStringComplexRun($rechnung, $indexedNotenArray, $targetGeraetKey, $programmId, $ascArrayAnzahlLaeufeJSON);
|
||||
} else {
|
||||
$calcResult = $notenRechner->berechneStringComplex($rechnung, $indexedNotenArray, $targetGeraetKey, $acrun);
|
||||
}
|
||||
|
||||
if (!($calcResult['success'] ?? false)) {
|
||||
echo json_encode(['success' => true, 'message' => "Rechenfehler in $targetNoteId: " . ($calcResult['value'] ?? '')]);
|
||||
exit;
|
||||
}
|
||||
|
||||
$acTargetRun = ($targetRun === "A") ? $acrun : intval($targetRun);
|
||||
|
||||
|
||||
// 4. Update State
|
||||
$val = $calcResult['value'];
|
||||
$indexedNotenArray[$targetGeraetKey][$targetNoteId][$acTargetRun] = ["value" => $val, "type" => "berechnet"];
|
||||
$updatedValues[$targetGeraetKey][$targetNoteId][$acTargetRun] = $val;
|
||||
}
|
||||
|
||||
// Prepare the statement once
|
||||
$sql = "INSERT INTO $db_tabelle_wertungen (`value`, `person_id`, `note_bezeichnung_id`, `geraet_id`, `wk_id`, `run_number`)
|
||||
VALUES (?, ?, ?, ?, ?, ?)
|
||||
ON DUPLICATE KEY UPDATE `value` = VALUES(`value`)";
|
||||
|
||||
$stmt = $mysqli->prepare($sql);
|
||||
$formatedNoten = [];
|
||||
|
||||
$mysqli->begin_transaction();
|
||||
|
||||
foreach ($updatedValues as $gereat => $notenArray) {
|
||||
foreach ($notenArray as $note => $runArray) {
|
||||
foreach ($runArray as $run => $value) {
|
||||
$stmt->bind_param("siiiii", $value, $person_id, $note, $gereat, $current_wk_id, $run);
|
||||
$stmt->execute();
|
||||
$formatedNoten[$gereat][$note][$run] = number_format($value ,$indexedNullstellen[$note] ?? 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$mysqli->commit();
|
||||
|
||||
$formatedNoten[$gereat_id][$field_type_id][$run_number] = number_format($valueNoteUpdate ,$indexedNullstellen[$field_type_id] ?? 2);
|
||||
|
||||
$stmt->close();
|
||||
$mysqli->close();
|
||||
|
||||
echo json_encode([
|
||||
'success' => true,
|
||||
'message' => "Wert aktualisiert, alle Berechnungen durchgeführt",
|
||||
"noten" => $formatedNoten
|
||||
]);
|
||||
@@ -0,0 +1,297 @@
|
||||
<?php
|
||||
header('Content-Type: application/json');
|
||||
|
||||
if (!isset($baseDir)) {
|
||||
$baseDir = $_SERVER['DOCUMENT_ROOT'];
|
||||
}
|
||||
|
||||
require_once $baseDir . '/../scripts/session_functions.php';
|
||||
|
||||
ini_wkvs_session();
|
||||
|
||||
check_user_permission('kampfrichter');
|
||||
|
||||
verify_csrf();
|
||||
|
||||
// ---------- Get and sanitize input ----------
|
||||
$id = intval($_POST['personId'] ?? 0);
|
||||
$initNoteRun = intval($_POST['run'] ?? 0);
|
||||
$geraetId = intval($_POST['geraetId'] ?? 0);
|
||||
$dataType = intval($_POST['dataType'] ?? 0);
|
||||
$jahr = isset($_POST['jahr']) ? preg_replace('/[^0-9]/', '', $_POST['jahr']) : '';
|
||||
$anfrageType = $_POST['type'] ?? '';
|
||||
|
||||
$allowedTypes = ["neu", "start", "result"];
|
||||
|
||||
if (!in_array($anfrageType, $allowedTypes)) {
|
||||
echo json_encode(['success' => false, 'message' => "Operation nicht gestattet."]);
|
||||
exit;
|
||||
}
|
||||
|
||||
if ($anfrageType !== "start" && ($id < 1 || intval($jahr) < 1)) {
|
||||
echo json_encode(['success' => false, 'message' => 'Personen ID ist nicht valide.']);
|
||||
exit;
|
||||
}
|
||||
|
||||
if ($geraetId < 1) {
|
||||
echo json_encode(['success' => false, 'message' => 'Invalid discipline']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$type = 'kr';
|
||||
|
||||
$data = require $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-functions.php';
|
||||
require $baseDir . '/../scripts/db/db-tables.php';
|
||||
|
||||
$stmt = $mysqli->prepare("SELECT `name` FROM $db_tabelle_disziplinen WHERE `id` = ? LIMIT 1");
|
||||
$stmt->bind_param("s", $geraetId);
|
||||
|
||||
if (!$stmt->execute()) {
|
||||
http_response_code(500);
|
||||
exit;
|
||||
}
|
||||
|
||||
$result = $stmt->get_result();
|
||||
|
||||
if ($result->num_rows === 0) {
|
||||
echo json_encode(['success' => false, 'message' => 'Invalid discipline']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$geraetData = $result->fetch_assoc();
|
||||
$geraetName = $geraetData['name'];
|
||||
|
||||
$stmt->close();
|
||||
|
||||
$folder = realpath($baseDir . '/externe-geraete/json');
|
||||
|
||||
if ($folder === false) {
|
||||
echo json_encode([
|
||||
'success' => false,
|
||||
'message' => 'Could not find displays folder.'
|
||||
]);
|
||||
exit;
|
||||
}
|
||||
|
||||
$filename = 'display-id-' . $geraetId . '.json';
|
||||
$filepath = $folder . '/' . $filename;
|
||||
|
||||
if (!is_writable($folder)) {
|
||||
echo json_encode(['success' => false, 'message' => 'Folder not writable']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$jsonString = file_get_contents($filepath);
|
||||
|
||||
// decode JSON, fallback to empty array if invalid
|
||||
$oldjson = json_decode($jsonString, true) ?? [];
|
||||
|
||||
switch ($anfrageType) {
|
||||
case "neu":
|
||||
$stmt = $mysqli->prepare("SELECT `id`, `name`, `vorname`, `programm`, `verein` FROM `$db_tabelle_teilnehmende` WHERE id = ? LIMIT 1");
|
||||
$stmt->bind_param("i", $id);
|
||||
$stmt->execute();
|
||||
|
||||
$result = $stmt->get_result();
|
||||
$rows = $result->fetch_all(MYSQLI_ASSOC);
|
||||
|
||||
if (!$rows || !is_array($rows) || count($rows) !== 1) {
|
||||
echo json_encode(['success' => false, 'message' => 'Row fetch failed']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$row = $rows[0];
|
||||
|
||||
|
||||
$data = ["noteLinks" => '',
|
||||
"noteRechts" => '',
|
||||
"id" => $id,
|
||||
"name" => $row['name'],
|
||||
"vorname" => $row['vorname'],
|
||||
"programm" => $row['programm'],
|
||||
"verein" => $row['verein'],
|
||||
"start" => false
|
||||
];
|
||||
|
||||
$arrayData = $data;
|
||||
break;
|
||||
case "start":
|
||||
if (!array_key_exists("id", $oldjson) || intval($oldjson["id"]) !== $id || !array_key_exists("start", $oldjson)) {
|
||||
echo json_encode(['success' => false, 'message' => 'Person nicht auf Display!']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$oldjson["start"] = (bool) $dataType;
|
||||
|
||||
$arrayData = $oldjson;
|
||||
break;
|
||||
case "result":
|
||||
// 1. Get IDs and filter out empty values
|
||||
$noteLinksId = db_get_variable($mysqli, $db_tabelle_var, ['displayIdNoteL']);
|
||||
$noteRechtsId = db_get_variable($mysqli, $db_tabelle_var, ['displayIdNoteR']);
|
||||
|
||||
$programm_id = db_get_var($mysqli, "SELECT p.`id` FROM $db_tabelle_teilnehmende t INNER JOIN $db_tabelle_kategorien p ON p.`programm` = t.`programm` WHERE t.`id` = ?", [$id]) ?? null;
|
||||
|
||||
$display_cache = require $baseDir . '/../scripts/cache/display-dependencies.php';
|
||||
|
||||
$this_display_cache = $display_cache[$programm_id][$geraetId][$initNoteRun];
|
||||
|
||||
$sql_where_values = $this_display_cache['values'];
|
||||
|
||||
$sql_where_string = $this_display_cache['SQL'];
|
||||
|
||||
$intersect_noten = $this_display_cache['intersect_noten'];
|
||||
|
||||
$rankLiveArray = [];
|
||||
|
||||
$current_wk_id = (int) db_get_variable($mysqli, $db_tabelle_var, ['current_wk_id']) ?: 0;
|
||||
|
||||
if (!empty($sql_where_values) && $sql_where_string !== '') {
|
||||
|
||||
$notenDB = db_select($mysqli, $db_tabelle_wertungen, '`value`, `note_bezeichnung_id`, `geraet_id`, `run_number`', "`person_id` = ? AND `wk_id` = ? AND ($sql_where_string)", array_merge([$id, $current_wk_id], $sql_where_values));
|
||||
|
||||
$indexedNotenDB = [];
|
||||
|
||||
foreach ($notenDB as $sn) {
|
||||
$indexedNotenDB[$sn['geraet_id']][$sn['note_bezeichnung_id']][$sn['run_number']] = $sn;
|
||||
}
|
||||
}
|
||||
|
||||
$mysqli->begin_transaction();
|
||||
|
||||
|
||||
try {
|
||||
$stmt = $mysqli->prepare("INSERT INTO $db_tabelle_wertungen (`person_id`, `note_bezeichnung_id`, `wk_id`, `geraet_id`, `run_number`, `is_public`, `public_value`) VALUES (?, ?, ?, ?, ?, 1, ?) ON DUPLICATE KEY UPDATE `public_value` = VALUES(`public_value`), `is_public` = 1");
|
||||
|
||||
foreach ($intersect_noten as $s_note) {
|
||||
$n_id = $s_note['n_id'];
|
||||
$g_id = $s_note['g_id'];
|
||||
$run = $s_note['r'];
|
||||
|
||||
$value = $indexedNotenDB[$g_id][$n_id][$run]['value'] ?? $notenConfig['default_values'][$n_id] ?? 0;
|
||||
$rankLiveArray[$g_id][$run][$n_id] = number_format($value, $notenConfig['nullstellen'][$n_id] ?? 2);
|
||||
|
||||
$stmt->bind_param("iiiiid", $id, $n_id, $current_wk_id, $g_id, $run, $value);
|
||||
|
||||
$stmt->execute();
|
||||
}
|
||||
|
||||
$mysqli->commit();
|
||||
$stmt->close();
|
||||
} catch (Exception $e) {
|
||||
$mysqli->rollback();
|
||||
echo json_encode(['success' => false, 'message' => 'DB Transaction failed Error: ' . $e->getMessage()]);
|
||||
exit;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// Create an array of IDs that actually exist
|
||||
$validIds = array_filter([$noteLinksId, $noteRechtsId]);
|
||||
|
||||
$noten = [];
|
||||
$notenConfig = [];
|
||||
|
||||
if (!empty($validIds)) {
|
||||
// 2. Fetch Noten (Only if we have IDs to look for)
|
||||
$placeholders = implode(',', array_fill(0, count($validIds), '?'));
|
||||
|
||||
$sqlNoten = "SELECT `value`, `note_bezeichnung_id` FROM $db_tabelle_wertungen
|
||||
WHERE person_id = ? AND `wk_id` = ? AND `geraet_id` = ? AND run_number = ?
|
||||
AND `note_bezeichnung_id` IN ($placeholders)";
|
||||
|
||||
$stmt = $mysqli->prepare($sqlNoten);
|
||||
// Combine standard params with our dynamic ID list
|
||||
$params = array_merge([$id, $current_wk_id, $geraetId, $initNoteRun], $validIds);
|
||||
$types = str_repeat('s', count($params));
|
||||
$stmt->bind_param($types, ...$params);
|
||||
$stmt->execute();
|
||||
$notenDB = $stmt->get_result()->fetch_all(MYSQLI_ASSOC);
|
||||
$noten = array_column($notenDB, 'value', 'note_bezeichnung_id');
|
||||
$stmt->close();
|
||||
|
||||
// 3. Fetch Config
|
||||
$sqlConfig = "SELECT `id`, `default_value`, `nullstellen`, `display_string`
|
||||
FROM $db_tabelle_wertungstypen WHERE `id` IN ($placeholders)";
|
||||
|
||||
$stmt = $mysqli->prepare($sqlConfig);
|
||||
$typesConfig = str_repeat('s', count($validIds));
|
||||
$stmt->bind_param($typesConfig, ...$validIds);
|
||||
$stmt->execute();
|
||||
$notenConfigDB = $stmt->get_result()->fetch_all(MYSQLI_ASSOC);
|
||||
$notenConfig = array_column($notenConfigDB, null, 'id');
|
||||
$stmt->close();
|
||||
}
|
||||
|
||||
// 4. Helper function to safely format the output without crashing
|
||||
$formatNote = function($id) use ($noten, $notenConfig) {
|
||||
if (!$id || !isset($notenConfig[$id])) {
|
||||
return ""; // Return empty string if ID is not set or not found in DB
|
||||
}
|
||||
|
||||
$conf = $notenConfig[$id];
|
||||
$val = $noten[$id] ?? $conf['default_value'] ?? 0;
|
||||
$prec = $conf['nullstellen'] ?? 2;
|
||||
|
||||
$display_schema = $conf['display_string'] ?? '${note}';
|
||||
|
||||
$formatted_note = number_format((float)$val, (int)$prec, '.', '');
|
||||
|
||||
$result = str_ireplace('${note}', $formatted_note, $display_schema);
|
||||
|
||||
if ($result === $display_schema) {
|
||||
return $formatted_note;
|
||||
}
|
||||
|
||||
return $result;
|
||||
};
|
||||
|
||||
// 5. Assign to JSON
|
||||
$oldjson["noteLinks"] = $formatNote($noteLinksId);
|
||||
$oldjson["noteRechts"] = $formatNote($noteRechtsId);
|
||||
|
||||
$arrayData = $oldjson;
|
||||
|
||||
break;
|
||||
default:
|
||||
http_response_code(400);
|
||||
exit;
|
||||
}
|
||||
|
||||
$jsonData = json_encode($arrayData);
|
||||
|
||||
// Write file
|
||||
if (file_put_contents($filepath, $jsonData) === false) {
|
||||
echo json_encode([
|
||||
'success' => false,
|
||||
'message' => 'Failed to write JSON file'
|
||||
]);
|
||||
exit;
|
||||
}
|
||||
|
||||
if ($anfrageType === "result") {
|
||||
echo json_encode([
|
||||
'success' => true,
|
||||
'message' => 'JSON updated successfully for ' . $geraetName,
|
||||
'data' => $arrayData,
|
||||
'rankLive' => $rankLiveArray,
|
||||
'nameGeraet' => strtolower($geraetName)
|
||||
]);
|
||||
} else {
|
||||
// ---------- Return JSON ----------
|
||||
echo json_encode([
|
||||
'success' => true,
|
||||
'message' => 'JSON updated successfully for ' . $geraetName,
|
||||
'data' => $arrayData,
|
||||
'nameGeraet' => strtolower($geraetName)
|
||||
]);
|
||||
}
|
||||
exit;
|
||||
@@ -0,0 +1,557 @@
|
||||
jQuery(document).ready(function($) {
|
||||
const csrf_token = window.CSDR_TOKEN;
|
||||
|
||||
const allowedRanglistenTypes = ['downloadRangliste', 'updateServerRangliste'];
|
||||
|
||||
$('.ranglisteExport').on('click', function() {
|
||||
const $button = $(this);
|
||||
const progId = $button.data('id');
|
||||
const fieldType = $button.data('field_type');
|
||||
|
||||
if (!allowedRanglistenTypes.includes(fieldType)) {
|
||||
displayMsg(0, "Dieser Button besitzt eine fehlerhafte Konfiguration");
|
||||
return;
|
||||
}
|
||||
|
||||
// Visual feedback (optional but recommended)
|
||||
$button.addClass('opacity50');
|
||||
|
||||
const url = '/intern/scripts/kampfrichter/ajax/ajax-neu_rangliste.php';
|
||||
|
||||
fetch(url, {
|
||||
method: 'POST',
|
||||
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
|
||||
body: new URLSearchParams({
|
||||
csrf_token,
|
||||
prog: progId,
|
||||
type: fieldType
|
||||
})
|
||||
})
|
||||
.then(res => {
|
||||
if (!res.ok) throw new Error('Network response was not ok');
|
||||
|
||||
// Return both the response and the blob/json promise
|
||||
// to keep the chain clean, or handle them based on fieldType here.
|
||||
if (fieldType === 'downloadRangliste') {
|
||||
return res.blob().then(blob => ({ type: 'blob', data: blob }));
|
||||
} else {
|
||||
return res.json().then(json => ({ type: 'json', data: json }));
|
||||
}
|
||||
})
|
||||
.then(result => {
|
||||
if (result.type === 'blob') {
|
||||
const url = window.URL.createObjectURL(result.data);
|
||||
const a = document.createElement('a');
|
||||
a.href = url;
|
||||
a.download = "Rangliste.pdf";
|
||||
document.body.appendChild(a);
|
||||
a.click();
|
||||
a.remove();
|
||||
window.URL.revokeObjectURL(url);
|
||||
displayMsg(1, "Rangliste wurde erfolgreich heuntergeladen.");
|
||||
} else if (result.type === 'json') {
|
||||
if (result.data.success) {
|
||||
const $container = $button.closest(".singleAbtDiv");
|
||||
$container.find(".uploadRanglisteText").addClass("hidden");
|
||||
$container.find(".updateRanglisteText").removeClass("hidden");
|
||||
$container.find(".rangliseOnlineSpan").removeClass("hidden");
|
||||
$container.find(".ranglisteDelete").removeClass("hidden");
|
||||
displayMsg(1, "Die Rangliste wurde auf dem Server aktualisiert.");
|
||||
} else {
|
||||
displayMsg(0, "Fehler beim Aktualiseren der Rangliste.");
|
||||
}
|
||||
}
|
||||
$button.removeClass('opacity50');
|
||||
})
|
||||
.catch(err => {
|
||||
displayMsg(0, "Error processing request:", err);
|
||||
console.error("Error processing request:", err);
|
||||
$button.removeClass('opacity50');
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
$('.ranglisteDelete').on('click', function() {
|
||||
const $button = $(this);
|
||||
const progId = $button.data('id');
|
||||
|
||||
// Visual feedback (optional but recommended)
|
||||
$button.addClass('opacity50');
|
||||
|
||||
const url = '/intern/scripts/kampfrichter/ajax/ajax-delete_rangliste.php';
|
||||
|
||||
fetch(url, {
|
||||
method: 'POST',
|
||||
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
|
||||
body: new URLSearchParams({
|
||||
csrf_token,
|
||||
prog: progId
|
||||
})
|
||||
})
|
||||
.then(res => {
|
||||
if (!res.ok) throw new Error('Network response was not ok');
|
||||
|
||||
|
||||
return res.json().then(json => ({ type: 'json', data: json }));
|
||||
|
||||
})
|
||||
.then(result => {
|
||||
if (result.data.success) {
|
||||
const $container = $button.closest(".singleAbtDiv");
|
||||
$container.find(".uploadRanglisteText").removeClass("hidden");
|
||||
$container.find(".updateRanglisteText").addClass("hidden");
|
||||
$container.find(".rangliseOnlineSpan").addClass("hidden");
|
||||
$container.find(".ranglisteDelete").addClass("hidden");
|
||||
displayMsg(1, "Die Rangliste wurde erfolgreich entfernt.");
|
||||
} else {
|
||||
displayMsg(0, "Fehler beim Löschen der Rangliste.");
|
||||
}
|
||||
$button.removeClass('opacity50');
|
||||
})
|
||||
.catch(err => {
|
||||
displayMsg(0, "Error processing request:", err);
|
||||
console.error("Error processing request:", err);
|
||||
$button.removeClass('opacity50');
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
$('.protokollExport').on('click', function() {
|
||||
const $button = $(this);
|
||||
const abteilungId = $button.data('abteilung-id');
|
||||
|
||||
|
||||
const now = new Date();
|
||||
|
||||
const formattedDate = new Intl.DateTimeFormat('en-CA', {
|
||||
year: 'numeric',
|
||||
month: '2-digit',
|
||||
day: '2-digit',
|
||||
hour: '2-digit',
|
||||
minute: '2-digit',
|
||||
second: '2-digit',
|
||||
hour12: false
|
||||
}).format(now).replace(/,/g, '');
|
||||
|
||||
const url = '/intern/scripts/kampfrichter/ajax/ajax-neu_protokoll.php';
|
||||
|
||||
fetch(url, {
|
||||
method: 'POST',
|
||||
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
|
||||
body: new URLSearchParams({
|
||||
csrf_token,
|
||||
abteilungId: abteilungId,
|
||||
date: formattedDate
|
||||
})
|
||||
})
|
||||
.then(res => {
|
||||
if (!res.ok) throw new Error('Network response was not ok');
|
||||
|
||||
return res.blob().then(blob => ({ type: 'blob', data: blob }));
|
||||
})
|
||||
.then(result => {
|
||||
if (result.type === 'blob') {
|
||||
const url = window.URL.createObjectURL(result.data);
|
||||
const a = document.createElement('a');
|
||||
a.href = url;
|
||||
a.download = "Protokoll.pdf";
|
||||
document.body.appendChild(a);
|
||||
a.click();
|
||||
a.remove();
|
||||
window.URL.revokeObjectURL(url);
|
||||
displayMsg(1, "Protokoll wurde erfolgreich heuntergeladen.");
|
||||
}
|
||||
})
|
||||
.catch(err => {
|
||||
displayMsg(0, "Error processing request:", err);
|
||||
console.error("Error processing request:", err);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
$('.protokollDeleteEntries').on('click', async function() {
|
||||
const $button = $(this);
|
||||
const abt = $button.data('abteilung-id');
|
||||
|
||||
if (!await displayConfirmImportant("Möchten Sie wirklich alle Protokolleinträge für diese Abteilung löschen? Diese Aktion kann nicht rückgängig gemacht werden.")) { return; }
|
||||
|
||||
const url = '/intern/scripts/kampfrichter/ajax/ajax-delete_protokoll_entries.php';
|
||||
|
||||
fetch(url, {
|
||||
method: 'POST',
|
||||
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
|
||||
body: new URLSearchParams({
|
||||
csrf_token,
|
||||
abteilungId: abt
|
||||
})
|
||||
})
|
||||
.then(res => {
|
||||
if (!res.ok) throw new Error('Network response was not ok');
|
||||
|
||||
|
||||
return res.json().then(json => ({ type: 'json', data: json }));
|
||||
|
||||
})
|
||||
.then(result => {
|
||||
if (result.data.success) {
|
||||
displayMsg(1, "Die Einträge wurden erfolgreich entfernt.");
|
||||
} else {
|
||||
displayMsg(0, "Fehler beim Löschen der Einträge.");
|
||||
}
|
||||
})
|
||||
.catch(err => {
|
||||
displayMsg(0, "Error processing request:", err);
|
||||
console.error("Error processing request:", err);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
let activeEdit = null;
|
||||
|
||||
$(document).on('click', '.editableValue', function () {
|
||||
const input = $(this);
|
||||
|
||||
// Already editing
|
||||
if (!input.prop('readonly')) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Close another active edit
|
||||
if (activeEdit && activeEdit.get(0) !== input.get(0)) {
|
||||
cancelEdit(activeEdit);
|
||||
}
|
||||
|
||||
input.data('original', input.val());
|
||||
input.prop('readonly', false).focus().select();
|
||||
|
||||
activeEdit = input;
|
||||
|
||||
input.on('keydown.edit', function (e) {
|
||||
if (e.key === 'Enter') {
|
||||
e.preventDefault();
|
||||
saveEdit(input);
|
||||
}
|
||||
|
||||
if (e.key === 'Escape') {
|
||||
e.preventDefault();
|
||||
cancelEdit(input);
|
||||
}
|
||||
});
|
||||
|
||||
input.on('blur.edit', function () {
|
||||
saveEdit(input);
|
||||
});
|
||||
});
|
||||
|
||||
function saveEdit(input) {
|
||||
const originalValue = input.data('original');
|
||||
const newValue = input.val();
|
||||
const type = input.data('type');
|
||||
const discipline = input.data('discipline');
|
||||
const dataId = input.data('id');
|
||||
|
||||
if (newValue === originalValue) {
|
||||
input.prop('readonly', true);
|
||||
cleanup(input);
|
||||
return;
|
||||
}
|
||||
|
||||
input.addClass('is-saving');
|
||||
|
||||
$.ajax({
|
||||
url: '/intern/scripts/kampfrichter/ajax/ajax-update_value_kampfrichter_admin.php',
|
||||
method: 'POST',
|
||||
data: {
|
||||
id: dataId,
|
||||
field_type: type,
|
||||
discipline: discipline,
|
||||
value: newValue
|
||||
},
|
||||
success: function () {
|
||||
input.prop('readonly', true);
|
||||
|
||||
const row = input.closest('td');
|
||||
if (row.length) {
|
||||
row.css(
|
||||
'background',
|
||||
'radial-gradient(circle at bottom right, #22c55e, transparent 55%)'
|
||||
);
|
||||
|
||||
setTimeout(() => row.css('background', ''), 2000);
|
||||
}
|
||||
|
||||
ws.send(JSON.stringify({
|
||||
type: "KAMPFRICHTER_UPDATE",
|
||||
payload: {
|
||||
discipline: discipline,
|
||||
id: dataId,
|
||||
val: newValue
|
||||
}
|
||||
}));
|
||||
},
|
||||
error: function () {
|
||||
input.val(originalValue).prop('readonly', true);
|
||||
alert('Speichern fehlgeschlagen');
|
||||
},
|
||||
complete: function () {
|
||||
input.removeClass('is-saving');
|
||||
cleanup(input);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function cancelEdit(input) {
|
||||
input.val(input.data('original')).prop('readonly', true);
|
||||
cleanup(input);
|
||||
}
|
||||
|
||||
function cleanup(input) {
|
||||
input.off('.edit');
|
||||
activeEdit = null;
|
||||
}
|
||||
|
||||
let rangNotenArray = JSON.parse(window.RANG_NOTEN_ARRAY) ?? [];
|
||||
|
||||
const rangNotenId = window.RANG_NOTE_ID ?? 0;
|
||||
|
||||
const rangSort = window.RANG_SORT ?? '';
|
||||
|
||||
const selecteddiscipline = window.FREIGABE;
|
||||
|
||||
ws.addEventListener("message", event => { // Use 'event' as it's more standard than 'blob'
|
||||
let msgOBJ;
|
||||
|
||||
try {
|
||||
msgOBJ = JSON.parse(event.data);
|
||||
} catch (error) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Ensure it's an UPDATE type (matches your sendToGroup logic)
|
||||
if (msgOBJ?.type === "UPDATE") {
|
||||
|
||||
const data = msgOBJ.payload;
|
||||
|
||||
// Check access rights
|
||||
if (selecteddiscipline === 'A') {
|
||||
const noten = data.noten;
|
||||
|
||||
|
||||
if (noten[0][rangNotenId][1] !== undefined && rangNotenArray[data.programmId][data.personId] !== undefined) {
|
||||
rangNotenArray[data.programmId][data.personId] = noten[0][rangNotenId][1];
|
||||
applyRanks(rankProgramm(rangNotenArray, data.programmId, rangSort), true);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
function rankProgramm(dataObj, programmId, order = 'DESC') {
|
||||
if (!dataObj[programmId]) {
|
||||
console.error(`ID ${programmId} not found in data.`);
|
||||
return [];
|
||||
}
|
||||
|
||||
const values = dataObj[programmId];
|
||||
|
||||
// 1. Transform and Sort
|
||||
const sorted = Object.entries(values)
|
||||
.map(([id, val]) => ({ id, val }))
|
||||
.sort((a, b) => {
|
||||
// 1. Handle null values first (Always push them to the bottom)
|
||||
if (a.val === null && b.val === null) return 0;
|
||||
if (a.val === null) return 1; // Move 'a' to a higher index (down)
|
||||
if (b.val === null) return -1; // Move 'b' to a higher index (down)
|
||||
|
||||
// 2. Normal sorting logic for valid numbers
|
||||
return order.toUpperCase() === 'ASC'
|
||||
? a.val - b.val
|
||||
: b.val - a.val;
|
||||
});
|
||||
|
||||
let lastVal = null;
|
||||
let lastRank = 0;
|
||||
|
||||
let sortedMap = [];
|
||||
|
||||
sortedMap[programmId] = sorted.map((item, index) => {
|
||||
// If current value is different from the last, update rank to current position
|
||||
if (item.val !== lastVal) {
|
||||
lastRank = index + 1;
|
||||
}
|
||||
|
||||
lastVal = item.val;
|
||||
|
||||
return {
|
||||
rang: lastRank,
|
||||
...item
|
||||
};
|
||||
});
|
||||
|
||||
return sortedMap;
|
||||
}
|
||||
|
||||
|
||||
function rankAll(dataObj, order = 'DESC') {
|
||||
return Object.fromEntries(
|
||||
Object.entries(dataObj).map(([groupKey, values]) => {
|
||||
const sorted = Object.entries(values)
|
||||
.map(([id, val]) => ({ id, val }))
|
||||
.sort((a, b) => {
|
||||
// 1. Handle null values first (Always push them to the bottom)
|
||||
if (a.val === null && b.val === null) return 0;
|
||||
if (a.val === null) return 1; // Move 'a' to a higher index (down)
|
||||
if (b.val === null) return -1; // Move 'b' to a higher index (down)
|
||||
|
||||
// 2. Normal sorting logic for valid numbers
|
||||
return order.toUpperCase() === 'ASC'
|
||||
? a.val - b.val
|
||||
: b.val - a.val;
|
||||
});
|
||||
|
||||
let lastVal = null;
|
||||
let lastRank = 0;
|
||||
|
||||
const ranked = sorted.map((item, index) => {
|
||||
if (item.val !== lastVal) {
|
||||
lastRank = index + 1;
|
||||
}
|
||||
lastVal = item.val;
|
||||
|
||||
return {
|
||||
rang: lastRank,
|
||||
...item
|
||||
};
|
||||
});
|
||||
|
||||
return [groupKey, ranked];
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
function applyRanks(array, sort = false) {
|
||||
for (const [key, entries] of Object.entries(array)) {
|
||||
const $tbody = $(`.customDisplayEditorTable tbody[data-programm-id="${key}"]`);
|
||||
|
||||
if ($tbody.length === 0) continue;
|
||||
|
||||
for (const [skey, entry] of Object.entries(entries)) {
|
||||
const $row = $tbody.find(`tr[data-person-id="${entry.id}"]:not(.notpaid)`);
|
||||
|
||||
if ($row.length === 0) continue;
|
||||
|
||||
$row.attr('data-sort-rank', entry.rang);
|
||||
|
||||
const $cell = $row.find('.rangField');
|
||||
|
||||
const points = parseFloat(rangNotenArray[key][entry.id]);
|
||||
|
||||
const text = !isNaN(points) ? entry.rang : '';
|
||||
|
||||
$cell.text(text);
|
||||
}
|
||||
|
||||
if (sort) {
|
||||
const rows = $tbody.find('tr').get();
|
||||
|
||||
rows.sort((a, b) => {
|
||||
const rankA = parseFloat($(a).attr('data-sort-rank')) || 999;
|
||||
const rankB = parseFloat($(b).attr('data-sort-rank')) || 999;
|
||||
return rankA - rankB;
|
||||
});
|
||||
|
||||
$.each(rows, (index, row) => {
|
||||
$tbody.append(row);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
applyRanks(rankAll(rangNotenArray, rangSort), true);
|
||||
|
||||
window.addEventListener('valueChanged', (e) => {
|
||||
// Use e.detail to get your object
|
||||
const { noten, programmId, personId } = e.detail;
|
||||
|
||||
if (noten[0][rangNotenId][1] !== undefined && rangNotenArray[programmId][personId] !== undefined) {
|
||||
rangNotenArray[programmId][personId] = noten[0][rangNotenId][1];
|
||||
applyRanks(rankProgramm(rangNotenArray, programmId, rangSort), true);
|
||||
}
|
||||
});
|
||||
|
||||
const $parent = $('.allAbtContainer');
|
||||
const $children = $parent.children('.shiftedGeraetTable');
|
||||
|
||||
$children.sort((a, b) => {
|
||||
const idA = parseFloat($(a).data('geraet-index'));
|
||||
const idB = parseFloat($(b).data('geraet-index'));
|
||||
|
||||
return idA - idB;
|
||||
});
|
||||
|
||||
$parent.append($children);
|
||||
|
||||
const wsMessage = window.WS_MESSAGE || '';
|
||||
|
||||
if (wsMessage !== '') {
|
||||
ws.addEventListener('open', () => {
|
||||
setTimeout(() => {
|
||||
ws.send(wsMessage);
|
||||
}, 300);
|
||||
});
|
||||
}
|
||||
|
||||
$('.deleteNotenAbt').on('click', async function () {
|
||||
if (!(await displayConfirmImportant('Alle Noten dieses Programmes wirklich löschen? Diese Aktion ist unumkehrbar!'))) return;
|
||||
|
||||
const $btn = $(this);
|
||||
|
||||
const programmId = parseInt($btn.data('programm-id') || 0);
|
||||
|
||||
$.ajax({
|
||||
url: '/intern/scripts/kampfrichter/ajax/ajax-delete-noten-turnerinnen.php',
|
||||
type: 'DELETE',
|
||||
data: {
|
||||
csrf_token,
|
||||
programmId
|
||||
},
|
||||
success: function (response) {
|
||||
if (response.success) {
|
||||
const $tbody = $btn.closest('.singleAbtDiv').find('tbody');
|
||||
|
||||
if ($tbody.length !== 1 || $tbody.data('programm-id') !== programmId) {
|
||||
location.reload();
|
||||
return;
|
||||
}
|
||||
|
||||
const $allValues = $tbody.find('.changebleValue:not(.emtyPlaceholder)');
|
||||
|
||||
$allValues.each((ind, el) => {
|
||||
$(el).text('-').addClass('emtyPlaceholder');
|
||||
updateDependentVisibility($(el));
|
||||
});
|
||||
|
||||
const $allRanks = $tbody.find('.rangField');
|
||||
|
||||
$allRanks.each((ind, el) => {
|
||||
$(el).text('');
|
||||
});
|
||||
|
||||
const $allRows = $tbody.find('tr');
|
||||
|
||||
$allRows.each((ind, el) => {
|
||||
$(el).attr('data-sort-rank', "0");
|
||||
rangNotenArray[programmId][$(el).attr('data-person-id')] = null;
|
||||
});
|
||||
|
||||
displayMsg(1, 'Noten gelöscht');
|
||||
|
||||
} else {
|
||||
displayMsg(0, response.message || 'Fehler beim Löschen');
|
||||
}
|
||||
},
|
||||
error: function () {
|
||||
displayMsg(0, 'Fehler beim Löschen');
|
||||
}
|
||||
})
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,856 @@
|
||||
document.addEventListener('keydown', function (e) {
|
||||
// Mac = Option, Windows/Linux = Alt
|
||||
const isOptionOrAlt = e.altKey || e.metaKey;
|
||||
|
||||
if (isOptionOrAlt && e.shiftKey && e.key.toLowerCase() === 'f') {
|
||||
toggleFullscreen();
|
||||
}
|
||||
|
||||
if (e.key === 'ArrowUp' || e.key === 'ArrowDown') {
|
||||
e.preventDefault();
|
||||
}
|
||||
});
|
||||
|
||||
function toggleFullscreen() {
|
||||
// If not in fullscreen → enter fullscreen
|
||||
if (!document.fullscreenElement) {
|
||||
document.documentElement.requestFullscreen()
|
||||
.catch(err => console.error("Fullscreen error:", err));
|
||||
}
|
||||
// If already fullscreen → exit fullscreen
|
||||
else {
|
||||
document.exitFullscreen();
|
||||
}
|
||||
}
|
||||
|
||||
let messagePosArray = [];
|
||||
const csrf_token = window.CSDR_TOKEN;
|
||||
|
||||
const text = document.getElementById('wsInfo');
|
||||
const rect = document.getElementById('wsInfoRectangle');
|
||||
|
||||
let ws;
|
||||
let firstConnect = true;
|
||||
let wsOpen = false;
|
||||
const RETRY_DELAY = 2000; // ms
|
||||
|
||||
const WSaccesstype = "kampfrichter";
|
||||
const WSaccess = window.FREIGABE;
|
||||
const WSaccessPermission = "W";
|
||||
|
||||
const urlAjaxNewWSToken = '/intern/scripts/ajax-create-ws-token.php';
|
||||
|
||||
async function fetchNewWSToken(accesstype, access, accessPermission) {
|
||||
try {
|
||||
const response = await fetch(urlAjaxNewWSToken, {
|
||||
method: "POST",
|
||||
headers: {
|
||||
'Content-Type': 'application/x-www-form-urlencoded',
|
||||
},
|
||||
body: new URLSearchParams({
|
||||
csrf_token,
|
||||
accesstype,
|
||||
access,
|
||||
accessPermission
|
||||
})
|
||||
});
|
||||
|
||||
if (response.status === 403) {
|
||||
console.warn("Please Re-Autenithicate. Reloading page...");
|
||||
location.reload();
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!response.ok) return null;
|
||||
|
||||
const data = await response.json();
|
||||
return data.success ? data.token : null;
|
||||
} catch (error) {
|
||||
console.error("Token fetch failed:", error);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
async function startWebSocket() {
|
||||
console.log("Attempting WebSocket connection...");
|
||||
|
||||
let token;
|
||||
if (firstConnect) {
|
||||
token = window.WS_ACCESS_TOKEN;
|
||||
} else {
|
||||
token = await fetchNewWSToken(WSaccesstype, WSaccess, WSaccessPermission);
|
||||
}
|
||||
|
||||
if (!token) {
|
||||
console.error("No valid token available. Retrying...");
|
||||
scheduleRetry();
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
ws = new WebSocket(`wss://${window.location.hostname}/ws/?access=token&token=${token}`);
|
||||
} catch (err) {
|
||||
console.error("Malformed WebSocket URL", err);
|
||||
scheduleRetry();
|
||||
return;
|
||||
}
|
||||
|
||||
ws.onopen = () => {
|
||||
console.log("WebSocket connected!");
|
||||
if (!firstConnect) {
|
||||
displayMsg(1, "Live Syncronisation wieder verfügbar");
|
||||
}
|
||||
firstConnect = true;
|
||||
wsOpen = true;
|
||||
|
||||
rect.innerHTML =
|
||||
'<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><circle cx="12" cy="12" r="10" fill="#28a745"></circle><path d="M7 12l3 3 7-7" stroke="white" stroke-width="2" fill="none" stroke-linecap="round" stroke-linejoin="round"></path></svg>';
|
||||
|
||||
requestAnimationFrame(() => {
|
||||
text.style.opacity = 1;
|
||||
});
|
||||
};
|
||||
|
||||
ws.onerror = (event) => {
|
||||
console.error("WebSocket error observed." + JSON.stringify(event));
|
||||
};
|
||||
|
||||
ws.onclose = (event) => {
|
||||
|
||||
if (firstConnect) {
|
||||
displayMsg(0, "Live Syncronisation verloren");
|
||||
console.log(event);
|
||||
}
|
||||
firstConnect = false;
|
||||
wsOpen = false;
|
||||
rect.innerHTML =
|
||||
'<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><circle cx="12" cy="12" r="10" fill="#dc3545"/><path d="M8 8l8 8M16 8l-8 8" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg>';
|
||||
|
||||
requestAnimationFrame(() => {
|
||||
text.style.opacity = 1;
|
||||
});
|
||||
|
||||
scheduleRetry();
|
||||
};
|
||||
}
|
||||
|
||||
function scheduleRetry() {
|
||||
console.log(`Retrying in ${RETRY_DELAY}ms...`);
|
||||
setTimeout(startWebSocket, RETRY_DELAY);
|
||||
}
|
||||
|
||||
// Start the initial connection attempt safely
|
||||
startWebSocket();
|
||||
|
||||
function updateRunButtons(targetCount, personId, $container) {
|
||||
|
||||
if (targetCount === 0) { return; }
|
||||
|
||||
const geraetId = $container.find('.submit-display-result').first().data('geraet-id') || "";
|
||||
|
||||
const currentCount = $container.find('.submit-display-result').length;
|
||||
|
||||
$container.find('.submit-display-result').removeClass('hidden');
|
||||
|
||||
if (targetCount > currentCount) {
|
||||
for (let i = currentCount + 1; i <= targetCount; i++) {
|
||||
const buttonHtml = `
|
||||
<input type="button" class="submit-display-result"
|
||||
data-person-id="${personId}"
|
||||
data-geraet-id="${geraetId}"
|
||||
data-run="${i}"
|
||||
value="Ergebnis anzeigen (Run ${i})">`;
|
||||
$container.append(buttonHtml);
|
||||
}
|
||||
$container.find('.submit-display-result[data-run="1"]').val('Ergebnis anzeigen (Run 1)');
|
||||
} else if (targetCount < currentCount) {
|
||||
for (let i = currentCount; i > targetCount; i--) {
|
||||
$container.find(`.submit-display-result[data-run="${i}"]`).remove();
|
||||
}
|
||||
if (targetCount === 1 && $container.find('.submit-display-result').length === 1) {
|
||||
$container.find('.submit-display-result').val('Ergebnis anzeigen');
|
||||
}
|
||||
}
|
||||
|
||||
$container.find('.submit-display-result').each(function() {
|
||||
$(this).attr('data-person-id', personId);
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
$.fn.updateCurrentEdit = function() {
|
||||
return this.each(function() {
|
||||
const $input = $(this);
|
||||
|
||||
const url = '/intern/scripts/kampfrichter/ajax/ajax-kampfrichter_currentedit.php';
|
||||
|
||||
if ($input.attr('data-person-id') === "0"){
|
||||
$('<form>', {
|
||||
action: '/intern/kampfrichter',
|
||||
method: 'post'
|
||||
})
|
||||
.append($('<input>', {
|
||||
type: 'hidden',
|
||||
name: 'next_subabt',
|
||||
value: 1
|
||||
}))
|
||||
.append($('<input>', {
|
||||
type: 'hidden',
|
||||
name: 'next_subabt_submit',
|
||||
value: '>'
|
||||
}))
|
||||
.append($('<input>', {
|
||||
type: 'hidden',
|
||||
name: 'csrf_token',
|
||||
value: csrf_token
|
||||
}))
|
||||
.appendTo('body')
|
||||
.submit();
|
||||
}
|
||||
|
||||
fetch(url, {
|
||||
method: 'POST',
|
||||
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
|
||||
body: new URLSearchParams({
|
||||
csrf_token,
|
||||
editId: $input.attr('data-person-id'),
|
||||
geraet: $input.attr('data-geraet-id') ?? null
|
||||
})
|
||||
})
|
||||
.then(res => res.json())
|
||||
.then(response => {
|
||||
if (response.success) {
|
||||
|
||||
$(".current-turnerin-name").css({
|
||||
'color': '#209200ff',
|
||||
'transition': 'all 0.3s ease-out'
|
||||
});
|
||||
|
||||
setTimeout(() => $(".current-turnerin-name").css({
|
||||
'color': ''
|
||||
}), 2000);
|
||||
|
||||
$(".div_edit_values_user").css("display", "flex");
|
||||
|
||||
$(".heading_fv_selturnerin")[0].scrollIntoView();
|
||||
|
||||
$(".current-turnerin-name").text(response.titel);
|
||||
|
||||
$(".fv_nextturnerin").text(response.nturnerin?.name ?? '');
|
||||
$(".fv_nextturnerin").val(response.nturnerin?.id ?? 0).attr('data-person-id', response.nturnerin?.id ?? 0);
|
||||
|
||||
$(".submit-display-turnerin").css("opacity", "1");
|
||||
$(".submit-display-start").css("opacity", "1");
|
||||
$(".submit-display-result").css("opacity", "1");
|
||||
|
||||
const $editAllDiv = $('.div_edit_values_all_gereate');
|
||||
const noten = response.noten;
|
||||
const personId = response.id;
|
||||
const programmId = response.programm_id;
|
||||
|
||||
$editAllDiv.find(`.submit-display-turnerin`).closest('.all_vaules_div').addClass('hidden');
|
||||
|
||||
// 1. Loop directly through the 'noten' object
|
||||
for (const [geraetId, disciplineData] of Object.entries(noten)) {
|
||||
|
||||
// Find the specific DOM wrapper for this Geraet using the outer div
|
||||
// Assuming your PHP renders the tables with the correct geraetId on the button
|
||||
const $disciplineWrapper = $editAllDiv.find(`.submit-display-turnerin[data-geraet-id="${geraetId}"]`).closest('.all_vaules_div');
|
||||
|
||||
if ($disciplineWrapper.length === 0) continue;
|
||||
|
||||
$disciplineWrapper.removeClass('hidden');
|
||||
|
||||
// --- UPDATE GENERAL BUTTONS FOR THIS GERAET ---
|
||||
$disciplineWrapper.find(".submit-display-turnerin, .submit-display-start").attr({
|
||||
'data-person-id': personId,
|
||||
'data-geraet-id': geraetId
|
||||
});
|
||||
|
||||
$disciplineWrapper.find(".submit-musik-start, .submit-musik-stopp").attr({
|
||||
'data-id': personId,
|
||||
'data-geraet': geraetId
|
||||
});
|
||||
|
||||
// 2. Identify master containers for this specific discipline
|
||||
const $masterContainer = $disciplineWrapper.find('.singleNotentable').first();
|
||||
const $displayresultDiv = $disciplineWrapper.find('.div-submit-display-result');
|
||||
|
||||
$masterContainer.find('.note-container').addClass('hidden');
|
||||
|
||||
// 3. CLEANUP: Remove previously generated runs and buttons
|
||||
$disciplineWrapper.find('.singleNotentable').not(':first').remove();
|
||||
$displayresultDiv.find('.submit-display-result').not(':first').remove();
|
||||
|
||||
const $originalResultBtn = $displayresultDiv.find('.submit-display-result').first();
|
||||
$displayresultDiv.find('.submit-display-result').addClass('hidden');
|
||||
const runKeys = Object.keys(disciplineData).sort((a, b) => a - b);
|
||||
const totalRuns = runKeys.length;
|
||||
|
||||
// 4. Process each Run in the data
|
||||
runKeys.forEach(runNum => {
|
||||
const runInt = parseInt(runNum);
|
||||
let $currentRunContainer;
|
||||
|
||||
if (runInt === 1) {
|
||||
$currentRunContainer = $masterContainer;
|
||||
} else {
|
||||
// CLONE the entire container for Run 2, 3, etc.
|
||||
$currentRunContainer = $masterContainer.clone();
|
||||
$currentRunContainer.addClass(`run-container-block run-${runNum}`);
|
||||
$currentRunContainer.insertAfter($disciplineWrapper.find('.singleNotentable').last());
|
||||
}
|
||||
|
||||
|
||||
|
||||
// 5. Update all Tables and Inputs inside this Run Container
|
||||
for (const [noteId, value] of Object.entries(disciplineData[runNum])) {
|
||||
const $table = $currentRunContainer.find(`.note-container[data-note-id="${noteId}"]`);
|
||||
$table.removeClass('hidden');
|
||||
|
||||
// Update Header to show Run Number
|
||||
if (runInt > 1) {
|
||||
const $header = $table.find('.note-name-header');
|
||||
if (!$header.find('.rm-tag').length) {
|
||||
$header.append(` <span class="rm-tag" style="font-size: 0.8em;">(R${runNum})</span>`);
|
||||
}
|
||||
}
|
||||
|
||||
// Update Input attributes and value
|
||||
const $input = $table.find('input');
|
||||
$input.attr({
|
||||
'data-run': runNum,
|
||||
'data-person-id': personId,
|
||||
'data-geraet-id': geraetId,
|
||||
'data-programm-id': programmId
|
||||
}).val(value ?? '');
|
||||
}
|
||||
|
||||
// 6. Remove tables cloned from Run 1 that don't exist in Run 2+
|
||||
if (runInt > 1) {
|
||||
$currentRunContainer.find('input[data-run="1"]').closest('.note-container').remove();
|
||||
}
|
||||
});
|
||||
|
||||
// Ensure the UI script tracking the buttons is updated last
|
||||
updateRunButtons(totalRuns, personId, $displayresultDiv);
|
||||
}
|
||||
|
||||
|
||||
|
||||
//$(".submit-display-result").attr('data-person-id', response.id);
|
||||
|
||||
} else {
|
||||
displayMsg(0, response.message);
|
||||
$input.css({
|
||||
'background-color': '#f8d7da',
|
||||
'color': '#fff',
|
||||
'transition': 'all 0.3s ease-out'
|
||||
});
|
||||
setTimeout(() => $input.css({
|
||||
'background-color': '',
|
||||
'color': ''
|
||||
}), 2000);
|
||||
}
|
||||
})
|
||||
.catch(err => {
|
||||
$input.css('background-color', '#f8d7da');
|
||||
console.error('AJAX fetch error:', err);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
function getRandomInt(max) {
|
||||
return Math.floor(Math.random() * max);
|
||||
}
|
||||
|
||||
jQuery(document).ready(function($) {
|
||||
|
||||
|
||||
$('.editTurnerin').on('click', function() {
|
||||
$(this).updateCurrentEdit();
|
||||
});
|
||||
|
||||
const $ajaxInputDiv = $('.div_edit_values_all_gereate');
|
||||
|
||||
|
||||
$ajaxInputDiv.on('change', '.ajax-input', function(e) {
|
||||
const $input = $(this);
|
||||
|
||||
const url = `/intern/scripts/kampfrichter/ajax/ajax-update_value_kampfrichter.php`;
|
||||
|
||||
personId = $input.attr('data-person-id');
|
||||
fieldTypeId = $input.attr('data-field-type-id');
|
||||
programmId = $input.attr('data-programm-id');
|
||||
gereatId = $input.attr('data-geraet-id');
|
||||
runNum = $input.attr('data-run') || 1;
|
||||
jahr = window.AKTUELLES_JAHR;
|
||||
value = $input.val();
|
||||
|
||||
fetch(url, {
|
||||
method: 'POST',
|
||||
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
|
||||
body: new URLSearchParams({
|
||||
csrf_token,
|
||||
personId: personId,
|
||||
fieldTypeId: fieldTypeId,
|
||||
gereatId: gereatId,
|
||||
run: runNum,
|
||||
jahr: jahr,
|
||||
value: value
|
||||
})
|
||||
})
|
||||
.then(res => res.json())
|
||||
.then(response => {
|
||||
|
||||
if (response.success) {
|
||||
|
||||
let objValues = [];
|
||||
|
||||
const rowId = $input.attr('data-id');
|
||||
|
||||
$input.css({"color": "#0e670d", "font-weight": "600"});
|
||||
|
||||
|
||||
setTimeout(() => $input.css({'color': '', "font-weight": ""}), 2000);
|
||||
|
||||
const noten = response.noten;
|
||||
|
||||
for (const [keyG, noteGroup] of Object.entries(noten)) {
|
||||
for (const [key, runGroup] of Object.entries(noteGroup)) {
|
||||
for (const [run, value] of Object.entries(runGroup)) {
|
||||
|
||||
const $elements = $(`.changebleValue[data-field-type-id="${key}"][data-geraet-id="${keyG}"][data-person-id="${personId}"][data-run="${run}"]`);
|
||||
|
||||
$elements.each((ind, el) => {
|
||||
const $el = $(el);
|
||||
|
||||
if ($el.is('input')) {
|
||||
$el.val(value ?? '');
|
||||
} else {
|
||||
const isNullable = ($el.attr('data-noten-nullable') ?? 'false') === 'true';
|
||||
const floatValZero = parseFloat(value.replace(",", ".").replace("'", "")) === 0.0;
|
||||
|
||||
let hasValue = false;
|
||||
|
||||
if (isNullable && floatValZero || value === '') {
|
||||
$el.text('-').addClass('emtyPlaceholder');
|
||||
} else {
|
||||
$el.text(value).removeClass('emtyPlaceholder');
|
||||
hasValue = true;
|
||||
}
|
||||
|
||||
updateDependentVisibility($el, hasValue);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (selecteddiscipline === 'A') {
|
||||
const event = new CustomEvent('valueChanged', {
|
||||
detail: {
|
||||
noten: noten,
|
||||
programmId: programmId,
|
||||
personId: personId
|
||||
}
|
||||
});
|
||||
|
||||
window.dispatchEvent(event);
|
||||
}
|
||||
|
||||
if (wsOpen) {
|
||||
ws.send(JSON.stringify({
|
||||
type: "KAMPFRICHTER_UPDATE",
|
||||
payload: {
|
||||
discipline: window.FREIGABE,
|
||||
gereatId: gereatId,
|
||||
personId: personId,
|
||||
programmId: programmId,
|
||||
jahr: jahr,
|
||||
noten: noten
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
} else {
|
||||
// Flash red on error
|
||||
$input.css({'color': '#ff6a76ff'});
|
||||
displayMsg(0, response.message || 'Unknown error');
|
||||
console.error(response.message || 'Unknown error');
|
||||
}
|
||||
})
|
||||
.catch(err => {
|
||||
$input.css({'color': '#670d0d'});
|
||||
console.error('AJAX fetch error:', err);
|
||||
});
|
||||
});
|
||||
|
||||
$('.submit-display-turnerin').on('click', function() {
|
||||
const $input = $(this);
|
||||
const geraetId = $input.attr('data-geraet-id');
|
||||
|
||||
// Build the URL with GET parameters safely
|
||||
const url = '/intern/scripts/kampfrichter/ajax/displays/ajax-display-functions.php';
|
||||
|
||||
fetch(url,{
|
||||
method: 'POST',
|
||||
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
|
||||
body: new URLSearchParams({
|
||||
csrf_token,
|
||||
personId: $input.attr('data-person-id'),
|
||||
geraetId,
|
||||
jahr: window.AKTUELLES_JAHR,
|
||||
type: "neu"
|
||||
})
|
||||
})
|
||||
.then(res => res.json())
|
||||
.then(response => {
|
||||
|
||||
if (response.success) {
|
||||
if (wsOpen) {
|
||||
ws.send(JSON.stringify({
|
||||
type: "UPDATE_SCORE",
|
||||
payload: {
|
||||
geraet: response.nameGeraet,
|
||||
geraetId,
|
||||
data: response.data
|
||||
}
|
||||
}));
|
||||
} else {
|
||||
displayMsg(2, 'Keine live Syncrosation, Verzögerungen');
|
||||
}
|
||||
displayMsg(1, 'Neue Person wird angezigt');
|
||||
|
||||
$input.css('opacity', 0.5);
|
||||
} else {
|
||||
displayMsg(0, response.message);
|
||||
}
|
||||
})
|
||||
.catch(err => {
|
||||
$input.css('background-color', '#f8d7da');
|
||||
displayMsg(0, 'AJAX fetch error:' + err);
|
||||
console.error('AJAX fetch error:', err);
|
||||
});
|
||||
});
|
||||
|
||||
$('.submit-display-start').on('click', function() {
|
||||
const $input = $(this);
|
||||
const geraetId = $input.attr('data-geraet-id');
|
||||
const personId = $input.attr('data-person-id')
|
||||
|
||||
const url = '/intern/scripts/kampfrichter/ajax/displays/ajax-display-functions.php';
|
||||
const dataType = $input.attr('data-type');
|
||||
|
||||
fetch(url,{
|
||||
method: 'POST',
|
||||
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
|
||||
body: new URLSearchParams({
|
||||
csrf_token,
|
||||
geraetId,
|
||||
personId,
|
||||
dataType: dataType,
|
||||
type: "start"
|
||||
})
|
||||
})
|
||||
.then(res => res.json())
|
||||
.then(response => {
|
||||
|
||||
if (response.success) {
|
||||
if (wsOpen) {
|
||||
ws.send(JSON.stringify({
|
||||
type: "UPDATE_SCORE",
|
||||
payload: {
|
||||
geraet: response.nameGeraet,
|
||||
geraetId,
|
||||
data: response.data
|
||||
}
|
||||
}));
|
||||
} else {
|
||||
displayMsg(2, 'Keine live Syncrosation, Verzögerungen');
|
||||
}
|
||||
|
||||
if (dataType == 1) {
|
||||
displayMsg(1, 'Start freigegeben');
|
||||
} else if (dataType == 0) {
|
||||
displayMsg(1, 'Startfreigabe entzogen');
|
||||
}
|
||||
|
||||
|
||||
} else {
|
||||
displayMsg(0, response.message);
|
||||
}
|
||||
})
|
||||
.catch(err => {
|
||||
$input.css('background-color', '#f8d7da');
|
||||
displayMsg(0, 'AJAX fetch error:' + err);
|
||||
console.error('AJAX fetch error:', err);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
$('.submit-musik-start').on('click', function() {
|
||||
const $input = $(this);
|
||||
const geraetId = $input.attr('data-geraet-id');
|
||||
|
||||
// Build the URL with GET parameters safely
|
||||
const url = `/intern/scripts/kampfrichter/ajax/ajax-update_kampfrichter_start_musik.php`;
|
||||
|
||||
fetch(url,{
|
||||
method: 'POST',
|
||||
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
|
||||
body: new URLSearchParams({
|
||||
csrf_token,
|
||||
personId: $input.attr('data-id'),
|
||||
geraetId
|
||||
})
|
||||
})
|
||||
.then(res => res.json())
|
||||
.then(response => {
|
||||
if (wsOpen) {
|
||||
ws.send(JSON.stringify({
|
||||
type: "AUDIO",
|
||||
payload: {
|
||||
audioDiscipline: geraetId
|
||||
}
|
||||
}));
|
||||
} else {
|
||||
displayMsg(2, 'Keine live Syncrosation, Verzögerungen');
|
||||
}
|
||||
|
||||
if (response.success) {
|
||||
displayMsg(1, 'Musik wird abgespielt werden');
|
||||
} else {
|
||||
displayMsg(0, 'Error: ' + response.message);
|
||||
}
|
||||
})
|
||||
.catch(err => {
|
||||
$input.css('background-color', '#f8d7da');
|
||||
displayMsg(0, 'AJAX fetch error:' + err);
|
||||
console.error('AJAX fetch error:', err);
|
||||
});
|
||||
});
|
||||
|
||||
$('.submit-musik-stopp').on('click', function() {
|
||||
const $input = $(this);
|
||||
const geraetId = $input.attr('data-geraet-id');
|
||||
|
||||
// Build the URL with GET parameters safely
|
||||
const url = `/intern/scripts/kampfrichter/ajax/ajax-update_kampfrichter_stopp_musik.php`;
|
||||
|
||||
fetch(url,{
|
||||
method: 'POST',
|
||||
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
|
||||
body: new URLSearchParams({
|
||||
csrf_token,
|
||||
geraetId
|
||||
})
|
||||
})
|
||||
.then(res => res.json())
|
||||
.then(response => {
|
||||
if (response.success) {
|
||||
if (wsOpen) {
|
||||
ws.send(JSON.stringify({
|
||||
type: "AUDIO",
|
||||
payload: {
|
||||
audioDiscipline: geraetId
|
||||
}
|
||||
}));
|
||||
} else {
|
||||
displayMsg(2, 'Keine live Syncrosation, Verzögerungen');
|
||||
}
|
||||
displayMsg(1, 'Musik wird gestoppt werden');
|
||||
} else {
|
||||
alert('Error: ' + response.message);
|
||||
}
|
||||
})
|
||||
.catch(err => {
|
||||
$input.css('background-color', '#f8d7da');
|
||||
displayMsg(0, 'AJAX fetch error:' + err);
|
||||
console.error('AJAX fetch error:', err);
|
||||
});
|
||||
});
|
||||
|
||||
$('.div-submit-display-result').on('click', '.submit-display-result', function() {
|
||||
$input = $(this);
|
||||
const geraetId = $input.attr('data-geraet-id');
|
||||
const personId = $input.attr('data-person-id');
|
||||
|
||||
// Build the URL with GET parameters safely
|
||||
const url = '/intern/scripts/kampfrichter/ajax/displays/ajax-display-functions.php';
|
||||
|
||||
fetch(url,{
|
||||
method: 'POST',
|
||||
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
|
||||
body: new URLSearchParams({
|
||||
csrf_token,
|
||||
personId,
|
||||
geraetId,
|
||||
run: $input.attr("data-run"),
|
||||
jahr: window.AKTUELLES_JAHR,
|
||||
type: "result"
|
||||
})
|
||||
})
|
||||
.then(res => res.json())
|
||||
.then(response => {
|
||||
|
||||
if (response.success) {
|
||||
if (wsOpen) {
|
||||
ws.send(JSON.stringify({
|
||||
type: "UPDATE_SCORE",
|
||||
payload: {
|
||||
geraetId,
|
||||
geraet: response.nameGeraet,
|
||||
data: response.data
|
||||
}
|
||||
}));
|
||||
ws.send(JSON.stringify({
|
||||
type: "UPDATE_RANKLIVE_SCORE",
|
||||
payload: {
|
||||
geraetId,
|
||||
personId,
|
||||
jahr: window.AKTUELLES_JAHR,
|
||||
rankLive: response.rankLive
|
||||
}
|
||||
}));
|
||||
} else {
|
||||
displayMsg(2, 'Keine live Syncrosation, Verzögerungen');
|
||||
}
|
||||
$input.css('opacity', 0.5);
|
||||
displayMsg(1, 'Resultat wird angezeigt');
|
||||
} else {
|
||||
alert('Error: ' + response.message);
|
||||
}
|
||||
})
|
||||
.catch(err => {
|
||||
$input.css('background-color', '#f8d7da');
|
||||
displayMsg(0, 'AJAX fetch error:' + err);
|
||||
console.error('AJAX fetch error:', err);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
function updateDependentVisibility($changedEl, hasValue = false) {
|
||||
const uid = $changedEl.attr('data-uid');
|
||||
if (uid === undefined || uid === null) return;
|
||||
|
||||
const $row = $changedEl.closest('tr');
|
||||
|
||||
if ($row.length !== 1) return;
|
||||
|
||||
const isVisible = $changedEl.hasClass('emtyPlaceholder');
|
||||
const doesExist = $changedEl.hasClass('nonExistentEl');
|
||||
|
||||
const $linkedEls = $row.find(`.singleValueSpan[data-linked-el-uid="${uid}"]`);
|
||||
|
||||
$linkedEls.each((ind, el) => {
|
||||
const $linkedEl = $(el);
|
||||
if (!hasValue) {
|
||||
hasValue = $linkedEl.hasClass('changebleValue') && $linkedEl.text().trim() !== '-';
|
||||
}
|
||||
|
||||
$linkedEl.toggleClass('emtyPlaceholder', (isVisible && !hasValue)).toggleClass('nonExistentEl', doesExist);
|
||||
|
||||
const linkedElUid = $linkedEl.data('linked-el-uid');
|
||||
|
||||
const $subLinkedEls = $row.find(`.singleValueSpan[data-linked-el-uid="${linkedElUid}"]`);
|
||||
|
||||
if ($subLinkedEls.length > 0) updateDependentVisibility($linkedEl);
|
||||
});
|
||||
}
|
||||
|
||||
function initConditionalVisibility() {
|
||||
const $table = $('table.customDisplayEditorTable');
|
||||
|
||||
const $rows = $table.find('tr');
|
||||
|
||||
$rows.each((ind, el) => {
|
||||
const $row = $(el);
|
||||
$row.find('.singleValueSpan[data-linked-el-uid]').each(function() {
|
||||
|
||||
const linkedUid = $(this).data('linked-el-uid');
|
||||
|
||||
const $linkedEl = $row.find(`.singleValueSpan[data-uid="${linkedUid}"]`);
|
||||
|
||||
if ($linkedEl.length === 1) {
|
||||
updateDependentVisibility($linkedEl);
|
||||
}
|
||||
});
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
initConditionalVisibility();
|
||||
initConditionalVisibility();
|
||||
|
||||
const selecteddiscipline = window.FREIGABE;
|
||||
|
||||
ws.addEventListener("message", event => { // Use 'event' as it's more standard than 'blob'
|
||||
let msgOBJ;
|
||||
|
||||
try {
|
||||
msgOBJ = JSON.parse(event.data);
|
||||
} catch (error) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Ensure it's an UPDATE type (matches your sendToGroup logic)
|
||||
if (msgOBJ?.type === "UPDATE") {
|
||||
const data = msgOBJ.payload;
|
||||
|
||||
// Check access rights
|
||||
if (data.discipline === selecteddiscipline.toLowerCase() || selecteddiscipline === 'A') {
|
||||
const noten = data.noten;
|
||||
|
||||
for (const [keyG, noteGroup] of Object.entries(noten)) {
|
||||
for (const [key, runGroup] of Object.entries(noteGroup)) {
|
||||
|
||||
for (const [run, value] of Object.entries(runGroup)) {
|
||||
|
||||
// Select all matching elements (inputs and spans)
|
||||
const $elements = $(`.changebleValue[data-field-type-id="${key}"][data-geraet-id="${keyG}"][data-person-id="${data.personId}"][data-run="${run}"]`);
|
||||
|
||||
$elements.each((ind, el) => {
|
||||
const $el = $(el);
|
||||
|
||||
if ($el.is('input')) {
|
||||
$el.val(value ?? '');
|
||||
|
||||
// Visual feedback: Flash color
|
||||
const nativeEl = $el[0];
|
||||
nativeEl.style.transition = 'color 0.3s';
|
||||
nativeEl.style.color = '#008e85';
|
||||
|
||||
setTimeout(() => {
|
||||
nativeEl.style.color = '';
|
||||
}, 1000);
|
||||
} else {
|
||||
const isNullable = ($el.attr('data-noten-nullable') ?? 'false') === 'true';
|
||||
const floatValZero = parseFloat(value.replace(",", ".").replace("'", "")) === 0.0;
|
||||
|
||||
let hasValue = false;
|
||||
|
||||
if (isNullable && floatValZero || value === '') {
|
||||
$el.text('-').addClass('emtyPlaceholder');
|
||||
} else {
|
||||
$el.text(value).removeClass('emtyPlaceholder');
|
||||
hasValue = true;
|
||||
}
|
||||
|
||||
updateDependentVisibility($el, hasValue);
|
||||
|
||||
$el.removeClass('updated');
|
||||
$el.addClass('updated');
|
||||
|
||||
setTimeout(() => {
|
||||
$el.removeClass('updated');
|
||||
}, 2000);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,185 @@
|
||||
<?php
|
||||
|
||||
use Dotenv\Dotenv;
|
||||
|
||||
header('Content-Type: application/json');
|
||||
|
||||
date_default_timezone_set('Europe/Zurich');
|
||||
|
||||
if (!isset($baseDir)) {
|
||||
$baseDir = $_SERVER['DOCUMENT_ROOT'];
|
||||
}
|
||||
|
||||
require_once $baseDir . '/../scripts/session_functions.php';
|
||||
|
||||
ini_wkvs_session();
|
||||
|
||||
check_user_permission('wk_leitung');
|
||||
|
||||
verify_csrf();
|
||||
|
||||
|
||||
require $baseDir . '/../scripts/db/db-functions.php';
|
||||
require $baseDir . '/../scripts/db/db-tables.php';
|
||||
|
||||
|
||||
|
||||
$type = 'wkl';
|
||||
|
||||
$dbconnection = require $baseDir . '/../scripts/db/db-verbindung-script.php';
|
||||
|
||||
if ($dbconnection['success'] !== true){
|
||||
echo json_encode(['success' => false, 'message' => 'Critical DB Error.']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$link_expires_at = $_POST['linkExpiresAt'] ?? '';
|
||||
|
||||
if ($link_expires_at === '' || strtotime($link_expires_at) === false) {
|
||||
echo json_encode(['success' => false, 'message' => 'Ungültiges Ablaufdatum']);
|
||||
http_response_code(400);
|
||||
exit;
|
||||
}
|
||||
|
||||
if (strtotime($link_expires_at) > strtotime('+8 days')) {
|
||||
echo json_encode(['success' => false, 'message' => 'Datum liegt zu weit in der Zukunft']);
|
||||
http_response_code(400);
|
||||
exit;
|
||||
}
|
||||
|
||||
if (strtotime($link_expires_at) < time()) {
|
||||
echo json_encode(['success' => false, 'message' => 'Datum liegt in der Vergangenheit']);
|
||||
http_response_code(400);
|
||||
exit;
|
||||
}
|
||||
|
||||
$editor_id = $_SESSION['user_id_wk_leitung'];
|
||||
|
||||
$plain = trim($_POST['password'] ?? null);
|
||||
|
||||
$username = trim($_POST['username'] ?? null);
|
||||
|
||||
$namePerson = htmlspecialchars(trim($_POST['namePerson'] ?? null));
|
||||
|
||||
$freigaben = $_POST['freigaben'] ?? [];
|
||||
$freigabenTrainer = $_POST['freigabenTrainer'] ?? [];
|
||||
$freigabenKampfrichter = $_POST['freigabenKampfrichter'] ?? [];
|
||||
|
||||
if (!is_array($freigaben)) {
|
||||
$freigaben = [];
|
||||
}
|
||||
if (!is_array($freigabenTrainer)) {
|
||||
$freigabenTrainer = [];
|
||||
}
|
||||
if (!is_array($freigabenKampfrichter)) {
|
||||
$freigabenKampfrichter = [];
|
||||
}
|
||||
|
||||
$array = [
|
||||
'types' => $freigaben,
|
||||
'freigabenTrainer' => $freigabenTrainer,
|
||||
'freigabenKampfrichter' => $freigabenKampfrichter
|
||||
];
|
||||
|
||||
// Store as proper JSON string
|
||||
$freigabe_store = json_encode($array);
|
||||
|
||||
$hash = null;
|
||||
$cipher_store = null;
|
||||
|
||||
if ($plain != null) {
|
||||
// Hash for login
|
||||
$hash = password_hash($plain, PASSWORD_ARGON2ID);
|
||||
|
||||
|
||||
require $baseDir . '/../composer/vendor/autoload.php';
|
||||
|
||||
$envFile = realpath($baseDir . '/../config/.env.pw-encryption-key');
|
||||
|
||||
if ($envFile === false) {
|
||||
http_response_code(500);
|
||||
echo json_encode([
|
||||
'success' => false,
|
||||
'message' => "Environment file not found"
|
||||
]);
|
||||
exit;
|
||||
}
|
||||
|
||||
try {
|
||||
$envDir = dirname($envFile);
|
||||
|
||||
$dotenv = Dotenv::createImmutable($envDir, '.env.pw-encryption-key');
|
||||
|
||||
$dotenv->load();
|
||||
} catch (Throwable $e) {
|
||||
http_response_code(500);
|
||||
echo json_encode([
|
||||
'success' => false,
|
||||
'message' => "Dotenv error"
|
||||
]);
|
||||
}
|
||||
|
||||
// Encrypt for display
|
||||
$iv_length = openssl_cipher_iv_length('aes-256-cbc');
|
||||
$iv = random_bytes($iv_length);
|
||||
$encrypted = openssl_encrypt($plain, 'aes-256-cbc', $_ENV['PW_ENCRYPTION_KEY'], 0, $iv);
|
||||
$cipher_store = base64_encode($iv . $encrypted);
|
||||
}
|
||||
|
||||
$created_at = date('Y-m-d H:i:s');
|
||||
$updated_at = $created_at;
|
||||
|
||||
|
||||
$stmt = $mysqli->prepare(
|
||||
"INSERT INTO {$db_tabelle_intern_benutzende}
|
||||
(username, name_person, password_hash, password_cipher, freigabe, created_at, updated_at, edited_by)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?)"
|
||||
);
|
||||
|
||||
$stmt->bind_param(
|
||||
"sssssssi",
|
||||
$username,
|
||||
$namePerson,
|
||||
$hash,
|
||||
$cipher_store,
|
||||
$freigabe_store,
|
||||
$created_at,
|
||||
$updated_at,
|
||||
$editor_id
|
||||
);
|
||||
|
||||
$updated = $stmt->execute();
|
||||
|
||||
if (!$updated) {
|
||||
echo json_encode(['success' => false, 'message' => 'DB Error']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$new_id = $mysqli->insert_id;
|
||||
|
||||
db_delete($mysqli, $db_tabelle_einmal_links, ['user_id' => $new_id]);
|
||||
|
||||
$typeOp = "create_profile";
|
||||
|
||||
$stmt = $mysqli->prepare("INSERT INTO $db_tabelle_einmal_links (user_id, `type`, `expires_at`) VALUES (?, ?, ?)");
|
||||
$stmt->bind_param("iss", $new_id, $typeOp, $link_expires_at);
|
||||
|
||||
|
||||
if (!$stmt->execute()) {
|
||||
echo json_encode(['success' => false, 'message' => 'Failed to create OTL record']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$row_id = $stmt->insert_id;
|
||||
|
||||
$stmt->close();
|
||||
|
||||
// Now fetch the auto-generated URL
|
||||
$url = db_get_var($mysqli, "SELECT url FROM $db_tabelle_einmal_links WHERE id = ? LIMIT 1", [$row_id]);
|
||||
|
||||
if (!$url) {
|
||||
echo json_encode(['success' => false, 'message' => 'Could not fetch generated URL']);
|
||||
exit;
|
||||
}
|
||||
|
||||
echo json_encode(['success' => true, 'url' => $url, 'expiresAt' => $link_expires_at]);
|
||||
@@ -0,0 +1,72 @@
|
||||
<?php
|
||||
header('Content-Type: application/json');
|
||||
|
||||
if (!isset($baseDir)) {
|
||||
$baseDir = $_SERVER['DOCUMENT_ROOT'];
|
||||
}
|
||||
|
||||
require_once $baseDir . '/../scripts/session_functions.php';
|
||||
|
||||
ini_wkvs_session();
|
||||
|
||||
check_user_permission('wk_leitung');
|
||||
|
||||
verify_csrf();
|
||||
|
||||
require $baseDir . '/../scripts/db/db-functions.php';
|
||||
require $baseDir . '/../scripts/db/db-tables.php';
|
||||
|
||||
date_default_timezone_set('Europe/Zurich');
|
||||
|
||||
$type = 'wkl';
|
||||
|
||||
$dbconnection = require $baseDir . '/../scripts/db/db-verbindung-script.php';
|
||||
|
||||
if ($dbconnection['success'] !== true){
|
||||
echo 'Critical DB Error.';
|
||||
exit;
|
||||
}
|
||||
|
||||
$id = intval($_POST['user_id'] ?? 0);
|
||||
$typeOp = trim($_POST['type'] ?? '');
|
||||
|
||||
$allowedTypesOp = ['login', 'pwreset'];
|
||||
|
||||
if (!in_array($typeOp, $allowedTypesOp)) {
|
||||
echo json_encode(['success' => false, 'message' => 'Operation nicht gestattet']);
|
||||
exit;
|
||||
}
|
||||
|
||||
if ($id <= 0) {
|
||||
echo json_encode(['success' => false, 'message' => 'No valid ID']);
|
||||
exit;
|
||||
}
|
||||
|
||||
// Delete old OTL links for this user (recommended)
|
||||
db_delete($mysqli, $db_tabelle_einmal_links, ['user_id' => $id]);
|
||||
|
||||
$timestamp_one_day = strtotime('+1 days');
|
||||
|
||||
$link_expires_at = date("Y-m-d H:i:s", $timestamp_one_day);
|
||||
|
||||
$stmt = $mysqli->prepare("INSERT INTO $db_tabelle_einmal_links (user_id, `type`, `expires_at`) VALUES (?, ?, ?)");
|
||||
$stmt->bind_param("iss", $id, $typeOp, $link_expires_at);
|
||||
|
||||
|
||||
if (!$stmt->execute()) {
|
||||
echo json_encode(['success' => false, 'message' => 'Failed to create OTL record']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$row_id = $stmt->insert_id;
|
||||
|
||||
$stmt->close();
|
||||
|
||||
$url = db_get_var($mysqli, "SELECT url FROM $db_tabelle_einmal_links WHERE id = ? LIMIT 1", [$row_id]);
|
||||
|
||||
if (!$url) {
|
||||
echo json_encode(['success' => false, 'message' => 'Could not fetch generated URL']);
|
||||
exit;
|
||||
}
|
||||
|
||||
echo json_encode(['success' => true, 'url' => $url, 'expiresAt' => $link_expires_at]);
|
||||
@@ -0,0 +1,40 @@
|
||||
<?php
|
||||
header('Content-Type: application/json');
|
||||
|
||||
if (!isset($baseDir)) {
|
||||
$baseDir = $_SERVER['DOCUMENT_ROOT'];
|
||||
}
|
||||
|
||||
require_once $baseDir . '/../scripts/session_functions.php';
|
||||
|
||||
ini_wkvs_session();
|
||||
|
||||
check_user_permission('wk_leitung');
|
||||
|
||||
verify_csrf();
|
||||
|
||||
require $baseDir . '/../scripts/db/db-functions.php';
|
||||
require $baseDir . '/../scripts/db/db-tables.php';
|
||||
|
||||
|
||||
$type = 'wkl';
|
||||
|
||||
$dbconnection = require $baseDir . '/../scripts/db/db-verbindung-script.php';
|
||||
|
||||
if ($dbconnection['success'] !== true){
|
||||
echo json_encode(['success' => false, 'message' => 'Critical DB Error.']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$id = intval($_POST['field_id'] ?? 0);
|
||||
if ($id <= 0) {
|
||||
echo json_encode(['success' => false, 'message' => 'Invalid Input.']);
|
||||
exit;
|
||||
}
|
||||
|
||||
db_delete($mysqli, $db_tabelle_intern_benutzende, ['id' => $id]);
|
||||
db_delete($mysqli, $db_tabelle_einmal_links, ['user_id' => $id]);
|
||||
|
||||
echo json_encode(['success' => true, 'message' => "Benutzer $id erfolgreich gelöscht.", 'id' => $id]);
|
||||
exit;
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
<?php
|
||||
header('Content-Type: application/json');
|
||||
|
||||
if (!isset($baseDir)) {
|
||||
$baseDir = $_SERVER['DOCUMENT_ROOT'];
|
||||
}
|
||||
|
||||
require_once $baseDir . '/../scripts/session_functions.php';
|
||||
|
||||
ini_wkvs_session();
|
||||
|
||||
check_user_permission('wk_leitung');
|
||||
|
||||
require_once $baseDir . '/../scripts/delete_request_type_functions.php';
|
||||
|
||||
parse_input_to_delete();
|
||||
|
||||
verify_delete_csrf($_DELETE);
|
||||
|
||||
$id = (int) ($_DELETE['id'] ?? 0);
|
||||
|
||||
if ($id <= 0) {
|
||||
echo json_encode(['success' => false, 'message' => 'No valid ID']);
|
||||
}
|
||||
|
||||
require $baseDir . '/../scripts/db/db-functions.php';
|
||||
require $baseDir . '/../scripts/db/db-tables.php';
|
||||
|
||||
|
||||
$type = 'wkl';
|
||||
|
||||
$dbconnection = require $baseDir . '/../scripts/db/db-verbindung-script.php';
|
||||
|
||||
if ($dbconnection['success'] !== true){
|
||||
echo 'Critical DB Error.';
|
||||
exit;
|
||||
}
|
||||
|
||||
$entrys = db_select($mysqli, $db_tabelle_vereine, "1", '`id` = ?', [$id]);
|
||||
|
||||
if (count($entrys) < 1) {
|
||||
echo json_encode(['success' => true, 'message' => 'Verein bereits gelöscht']);
|
||||
http_response_code(410);
|
||||
exit;
|
||||
}
|
||||
|
||||
db_delete($mysqli, $db_tabelle_vereine, ['id' => $id]);
|
||||
|
||||
echo json_encode(['success' => true, 'message' => 'Verein gelöscht']);
|
||||
http_response_code(200);
|
||||
@@ -0,0 +1,84 @@
|
||||
<?php
|
||||
header('Content-Type: application/json');
|
||||
|
||||
if (!isset($baseDir)) {
|
||||
$baseDir = $_SERVER['DOCUMENT_ROOT'];
|
||||
}
|
||||
|
||||
require_once $baseDir . '/../scripts/session_functions.php';
|
||||
|
||||
ini_wkvs_session();
|
||||
|
||||
check_user_permission('wk_leitung');
|
||||
|
||||
verify_csrf();
|
||||
|
||||
$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';
|
||||
|
||||
$value = isset($_POST['value']) ? preg_replace('/[^a-zA-Z0-9\s\-"]/u', '', $_POST['value']) : '';
|
||||
|
||||
if (!$value || $value === ''){
|
||||
echo json_encode(['success' => false, 'message' => 'No input']);
|
||||
exit;
|
||||
}
|
||||
|
||||
|
||||
// ---------- Step 2: Get values from DB ----------
|
||||
|
||||
|
||||
$stmt = $mysqli->prepare("INSERT INTO `$db_tabelle_kategorien` (programm) VALUES (?)");
|
||||
if (!$stmt) {
|
||||
echo json_encode(['success' => false, 'message' => 'Critical DB ERROR']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$stmt->bind_param("s", $value);
|
||||
$success = $stmt->execute();
|
||||
$stmt->close();
|
||||
|
||||
if (!$success) {
|
||||
echo json_encode(['success' => false, 'message' => 'Insert failed']);
|
||||
exit;
|
||||
}
|
||||
|
||||
// Fetch all rows
|
||||
$query2 = "SELECT * FROM `$db_tabelle_kategorien` ORDER BY programm ASC";
|
||||
$programme = $mysqli->query($query2);
|
||||
|
||||
if (!$programme) {
|
||||
echo json_encode(['success' => false, 'message' => 'Select failed']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$output = [];
|
||||
while ($entry = $programme->fetch_assoc()) {
|
||||
$output[] = [
|
||||
'id' => $entry['id'],
|
||||
'programm' => $entry['programm'],
|
||||
'aktiv' => intval($entry['aktiv']),
|
||||
'preis' => floatval($entry['preis']),
|
||||
'orderIndex' => intval($entry['order_index'])
|
||||
];
|
||||
}
|
||||
|
||||
require_once $baseDir . '/../scripts/cache/cache-creators/regenerate-display-dependencies-cache.php';
|
||||
|
||||
generateIntersectCache($mysqli, $baseDir);
|
||||
|
||||
// Return JSON
|
||||
echo json_encode([
|
||||
'success' => true,
|
||||
'output' => $output,
|
||||
'message' => $value.' hinzugefügt'
|
||||
]);
|
||||
exit;
|
||||
@@ -0,0 +1,60 @@
|
||||
<?php
|
||||
header('Content-Type: application/json');
|
||||
|
||||
if (!isset($baseDir)) {
|
||||
$baseDir = $_SERVER['DOCUMENT_ROOT'];
|
||||
}
|
||||
|
||||
require_once $baseDir . '/../scripts/session_functions.php';
|
||||
|
||||
ini_wkvs_session();
|
||||
|
||||
check_user_permission('wk_leitung');
|
||||
|
||||
require_once $baseDir . '/../scripts/delete_request_type_functions.php';
|
||||
|
||||
parse_input_to_delete();
|
||||
|
||||
verify_delete_csrf($_DELETE);
|
||||
|
||||
$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';
|
||||
|
||||
$id = (int) ($_DELETE['id'] ?? 0);
|
||||
|
||||
if ($id < 1) {
|
||||
echo json_encode(['success' => false, 'message' => 'Invalid ID']);
|
||||
http_response_code(400);
|
||||
exit;
|
||||
}
|
||||
|
||||
$entrys = db_select($mysqli, $db_tabelle_kategorien, "programm", '`id` = ?', [$id]);
|
||||
|
||||
if (count($entrys) !== 1) {
|
||||
echo json_encode(['success' => true, 'message' => 'Alters-/ Leistungsklasse bereits gelöscht']);
|
||||
http_response_code(410);
|
||||
exit;
|
||||
}
|
||||
|
||||
$bezeichnung = $entrys[0]['programm'];
|
||||
|
||||
|
||||
db_delete($mysqli, $db_tabelle_kategorien, ['id' => $id]);
|
||||
|
||||
require_once $baseDir . '/../scripts/cache/cache-creators/regenerate-display-dependencies-cache.php';
|
||||
|
||||
generateIntersectCache($mysqli, $baseDir);
|
||||
|
||||
|
||||
echo json_encode(['success' => true, 'message' => $bezeichnung.' gelöscht']);
|
||||
http_response_code(200);
|
||||
exit;
|
||||
@@ -0,0 +1,193 @@
|
||||
<?php
|
||||
|
||||
use Dotenv\Dotenv;
|
||||
|
||||
ini_set('display_errors', 1);
|
||||
|
||||
header('Content-Type: application/json');
|
||||
|
||||
if (!isset($baseDir)) {
|
||||
$baseDir = $_SERVER['DOCUMENT_ROOT'];
|
||||
}
|
||||
|
||||
require_once $baseDir . '/../scripts/session_functions.php';
|
||||
|
||||
ini_wkvs_session();
|
||||
|
||||
check_user_permission('wk_leitung');
|
||||
|
||||
verify_csrf();
|
||||
|
||||
require $baseDir . '/../scripts/db/db-functions.php';
|
||||
require $baseDir . '/../scripts/db/db-tables.php';
|
||||
|
||||
$type = 'wkl';
|
||||
|
||||
$dbconnection = require $baseDir . '/../scripts/db/db-verbindung-script.php';
|
||||
|
||||
if ($dbconnection['success'] !== true){
|
||||
echo json_encode(['success' => false, 'message' => 'Critical DB Error.']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$allowed_update_types = ['all', 'no_password', 'new_user'];
|
||||
|
||||
$update_type = $_POST['updateType'] ?? '';
|
||||
|
||||
if (!in_array($update_type, $allowed_update_types)) {
|
||||
echo json_encode(['success' => false, 'message' => 'Unbekannte Aktion']);
|
||||
http_response_code(400);
|
||||
exit;
|
||||
}
|
||||
|
||||
$editor_id = (int) $_SESSION['user_id_wk_leitung'];
|
||||
|
||||
if ($update_type === 'new_user') {
|
||||
$stmt = $mysqli->prepare(
|
||||
"INSERT INTO {$db_tabelle_intern_benutzende}
|
||||
(created_at, updated_at, edited_by, login_active)
|
||||
VALUES (?, ?, ?, ?)"
|
||||
);
|
||||
|
||||
$loginActive = 1;
|
||||
|
||||
$created_at = date('Y-m-d H:i:s');
|
||||
$updated_at = $created_at;
|
||||
|
||||
$stmt->bind_param(
|
||||
"ssis",
|
||||
$created_at,
|
||||
$updated_at,
|
||||
$editor_id,
|
||||
$loginActive
|
||||
);
|
||||
|
||||
$updated = $stmt->execute();
|
||||
|
||||
$new_id = $mysqli->insert_id;
|
||||
echo json_encode(['success' => true, 'message' => 'Neuer Benutzer wurde erfolgreich erstellt', 'id' => $new_id]);
|
||||
http_response_code(200);
|
||||
exit;
|
||||
}
|
||||
|
||||
$id = (int) ($_POST['personId'] ?? 0);
|
||||
|
||||
if ($id < 1 && $update_type !== 'new_user') {
|
||||
echo json_encode(['success' => false, 'message' => 'Die angegebene ID ist nicht valide']);
|
||||
http_response_code(400);
|
||||
exit;
|
||||
}
|
||||
|
||||
$plain_password = trim($_POST['password'] ?? '');
|
||||
|
||||
if ($plain_password === '' && $update_type !== 'no_password') {
|
||||
echo json_encode(['success' => false, 'message' => 'Kein Passwort angegeben']);
|
||||
http_response_code(422);
|
||||
exit;
|
||||
}
|
||||
|
||||
if ($update_type !== 'no_password' && strlen($plain_password) < 6) {
|
||||
echo json_encode(['success' => false, 'message' => 'Das Passwort muss mindestens 6 Zeichen enthalten']);
|
||||
http_response_code(400);
|
||||
exit;
|
||||
}
|
||||
|
||||
$username = htmlspecialchars(trim($_POST['username'] ?? ''));
|
||||
|
||||
if ($username === '') {
|
||||
echo json_encode(['success' => false, 'message' => 'Keinen Benutzernamen angegeben']);
|
||||
http_response_code(422);
|
||||
exit;
|
||||
}
|
||||
|
||||
$namePerson = htmlspecialchars(trim($_POST['namePerson'] ?? ''));
|
||||
|
||||
$freigaben = $_POST['freigaben'] ?? [];
|
||||
$freigabenTrainer = $_POST['freigabenTrainer'] ?? [];
|
||||
$freigabenKampfrichter = $_POST['freigabenKampfrichter'] ?? [];
|
||||
|
||||
if (!is_array($freigaben)) {
|
||||
$freigaben = [];
|
||||
}
|
||||
if (!is_array($freigabenTrainer)) {
|
||||
$freigabenTrainer = [];
|
||||
}
|
||||
if (!is_array($freigabenKampfrichter)) {
|
||||
$freigabenKampfrichter = [];
|
||||
}
|
||||
|
||||
$array = [
|
||||
'types' => $freigaben,
|
||||
'freigabenTrainer' => $freigabenTrainer,
|
||||
'freigabenKampfrichter' => $freigabenKampfrichter
|
||||
];
|
||||
|
||||
// Store as proper JSON string
|
||||
$freigabe_store = json_encode($array);
|
||||
|
||||
if ($update_type !== 'no_password') {
|
||||
$hash = password_hash($plain_password, PASSWORD_ARGON2ID);
|
||||
|
||||
|
||||
require $baseDir . '/../composer/vendor/autoload.php';
|
||||
|
||||
$envFile = realpath($baseDir . '/../config/.env.pw-encryption-key');
|
||||
|
||||
if ($envFile === false) {
|
||||
http_response_code(500);
|
||||
echo json_encode([
|
||||
'success' => false,
|
||||
'message' => "Environment file not found"
|
||||
]);
|
||||
exit;
|
||||
}
|
||||
|
||||
try {
|
||||
$envDir = dirname($envFile);
|
||||
|
||||
$dotenv = Dotenv::createImmutable($envDir, '.env.pw-encryption-key');
|
||||
|
||||
$dotenv->load();
|
||||
} catch (Throwable $e) {
|
||||
http_response_code(500);
|
||||
echo json_encode([
|
||||
'success' => false,
|
||||
'message' => "Dotenv error"
|
||||
]);
|
||||
}
|
||||
|
||||
$iv_length = openssl_cipher_iv_length('aes-256-cbc');
|
||||
$iv = random_bytes($iv_length);
|
||||
$encrypted = openssl_encrypt($plain_password, 'aes-256-cbc', $_ENV['PW_ENCRYPTION_KEY'], 0, $iv);
|
||||
$cipher_store = base64_encode($iv . $encrypted);
|
||||
}
|
||||
|
||||
if ($update_type === 'no_password') {
|
||||
$updated = db_update($mysqli, $db_tabelle_intern_benutzende, [
|
||||
'username' => $username,
|
||||
'name_person' => $namePerson,
|
||||
'freigabe' => $freigabe_store,
|
||||
'updated_at' => date('Y-m-d H:i:s'),
|
||||
'edited_by' => $editor_id
|
||||
], ['id' => $id]);
|
||||
} else {
|
||||
$updated = db_update($mysqli, $db_tabelle_intern_benutzende, [
|
||||
'password_hash' => $hash,
|
||||
'password_cipher' => $cipher_store,
|
||||
'username' => $username,
|
||||
'name_person' => $namePerson,
|
||||
'freigabe' => $freigabe_store,
|
||||
'updated_at' => date('Y-m-d H:i:s'),
|
||||
'edited_by' => $editor_id
|
||||
], ['id' => $id]);
|
||||
}
|
||||
|
||||
if ($updated === false) {
|
||||
echo json_encode(['success' => false, 'message' => 'DB Error']);
|
||||
http_response_code(500);
|
||||
exit;
|
||||
}
|
||||
|
||||
echo json_encode(['success' => true, 'message' => $username.' wurde erfolgreich aktualisiert.']);
|
||||
http_response_code(200);
|
||||
exit;
|
||||
@@ -0,0 +1,69 @@
|
||||
<?php
|
||||
header('Content-Type: application/json');
|
||||
|
||||
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();
|
||||
|
||||
$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';
|
||||
|
||||
// ---------- Get and sanitize input ----------
|
||||
$id = isset($_POST['id']) ? intval($_POST['id']) : 0;
|
||||
$value = isset($_POST['value']) ? floatval($_POST['value']) : 0;
|
||||
$type = isset($_POST['type']) ? $_POST['type'] : '';
|
||||
|
||||
$allowedTypes = ['preis', 'order_index', 'aktiv'];
|
||||
if (!in_array($type, $allowedTypes, true)) {
|
||||
echo json_encode(['success' => false, 'message' => 'Invalid type']);
|
||||
http_response_code(400);
|
||||
exit;
|
||||
}
|
||||
|
||||
if ($id < 0) {
|
||||
echo json_encode(['success' => false, 'message' => 'Invalid ID']);
|
||||
exit;
|
||||
}
|
||||
|
||||
// ---------- Step 2: Get values from DB ----------
|
||||
|
||||
|
||||
$query = "UPDATE `$db_tabelle_kategorien` SET $type = '$value' WHERE id = $id";
|
||||
$result = $mysqli->query($query);
|
||||
|
||||
if (!$result) {
|
||||
echo json_encode(['success' => false, 'message' => 'Update failed']);
|
||||
exit;
|
||||
}
|
||||
|
||||
if ($type === 'aktiv') {
|
||||
require_once $baseDir . '/../scripts/cache/cache-creators/regenerate-display-dependencies-cache.php';
|
||||
|
||||
generateIntersectCache($mysqli, $baseDir);
|
||||
}
|
||||
|
||||
// ---------- Return JSON ----------
|
||||
echo json_encode([
|
||||
'success' => true,
|
||||
'message' => 'Aktualisiert'
|
||||
]);
|
||||
exit;
|
||||
@@ -0,0 +1,67 @@
|
||||
<?php
|
||||
|
||||
header('Content-Type: application/json');
|
||||
|
||||
if (!isset($baseDir)) {
|
||||
$baseDir = $_SERVER['DOCUMENT_ROOT'];
|
||||
}
|
||||
|
||||
require_once $baseDir . '/../scripts/session_functions.php';
|
||||
|
||||
ini_wkvs_session();
|
||||
|
||||
check_user_permission('wk_leitung');
|
||||
|
||||
verify_csrf();
|
||||
|
||||
require $baseDir . '/../scripts/db/db-functions.php';
|
||||
require $baseDir . '/../scripts/db/db-tables.php';
|
||||
|
||||
|
||||
$type = 'wkl';
|
||||
|
||||
$dbconnection = require $baseDir . '/../scripts/db/db-verbindung-script.php';
|
||||
|
||||
if ($dbconnection['success'] !== true){
|
||||
echo json_encode(['success' => false, 'message' => 'Critical DB Error.']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$id = intval($_POST['field_id']) ?? '';
|
||||
$verein = htmlspecialchars(trim($_POST['verein'] ?? ''));
|
||||
|
||||
if (!isset($id) || !is_int($id) || !isset($verein)){
|
||||
echo json_encode(['success' => false, 'message' => 'Invalid Input.']);
|
||||
exit;
|
||||
}
|
||||
|
||||
if ($id > 0) {
|
||||
$updated = db_update($mysqli, $db_tabelle_vereine, [
|
||||
'verein' => $verein,
|
||||
], ['id' => $id]);
|
||||
} else {
|
||||
$stmt = $mysqli->prepare(
|
||||
"INSERT INTO {$db_tabelle_vereine}
|
||||
(verein)
|
||||
VALUES (?)"
|
||||
);
|
||||
|
||||
$stmt->bind_param(
|
||||
"s",
|
||||
$verein
|
||||
);
|
||||
|
||||
$updated = $stmt->execute();
|
||||
}
|
||||
|
||||
if ($updated !== false) {
|
||||
if ($id == 0) { // new user
|
||||
$new_id = $mysqli->insert_id;
|
||||
|
||||
echo json_encode(['success' => true, 'message' => $verein.' wurde erfolgreich erstellt.', 'id' => $new_id]);
|
||||
} else {
|
||||
echo json_encode(['success' => true, 'message' => $verein.' wurde erfolgreich aktualisiert.']);
|
||||
}
|
||||
} else {
|
||||
echo json_encode(['success' => false, 'message' => 'DB Error']);
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
<?php
|
||||
header('Content-Type: application/json');
|
||||
|
||||
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();
|
||||
|
||||
$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';
|
||||
|
||||
$slug = $_POST['slug'] ?? '';
|
||||
|
||||
$allowed_slugs = ['rankLive-overview', 'rankLive-geraet', 'kampfrichter-admin', 'kampfrichter-geraet', 'rangliste'];
|
||||
|
||||
if (!in_array($slug, $allowed_slugs)){
|
||||
echo json_encode(['success' => false, 'message' => 'Invalid Type']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$_SESSION['current_ranklive_slug'] = $slug;
|
||||
|
||||
$db_res = db_select($mysqli, $db_tabelle_tabellen_konfiguration, '`json`', '`type_slug` = ?', [$slug], '', 1);
|
||||
|
||||
$res = $db_res[0]['json'] ?? '';
|
||||
|
||||
// Return JSON
|
||||
echo json_encode([
|
||||
'success' => true,
|
||||
'data' => $res,
|
||||
'message' => 'gespeichert'
|
||||
]);
|
||||
exit;
|
||||
@@ -0,0 +1,148 @@
|
||||
<?php
|
||||
header('Content-Type: application/json');
|
||||
|
||||
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();
|
||||
|
||||
$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';
|
||||
|
||||
$json = $_POST['json'] ?? '';
|
||||
|
||||
$slug = $_POST['slug'] ?? '';
|
||||
|
||||
$allowed_slugs = ['rankLive-overview' => 'all', 'rankLive-geraet' => 'geraet', 'kampfrichter-admin' => 'all', 'kampfrichter-geraet' => 'geraet', 'rangliste' => 'all'];
|
||||
|
||||
if (!array_key_exists($slug, $allowed_slugs)){
|
||||
echo json_encode(['success' => false, 'message' => 'Invalid Type']);
|
||||
exit;
|
||||
}
|
||||
|
||||
if (!$json || $json === ''){
|
||||
echo json_encode(['success' => false, 'message' => 'No input']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$array = json_decode($json, true) ?? [];
|
||||
|
||||
$body = $array['body'];
|
||||
|
||||
$all_noten = [];
|
||||
|
||||
function extractNotenData(array $array): array {
|
||||
$result = [];
|
||||
|
||||
// Check if the current array is a 'notenData' object itself
|
||||
if (isset($array['type']) && $array['type'] === 'notenData') {
|
||||
return [$array];
|
||||
}
|
||||
|
||||
// Otherwise, loop through the elements to go deeper
|
||||
foreach ($array as $value) {
|
||||
if (is_array($value)) {
|
||||
// Recursively extract from the sub-array and merge into our result list
|
||||
$result = array_merge($result, extractNotenData($value));
|
||||
}
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
function extractNotenGeraetData(array $array): array {
|
||||
$result = [];
|
||||
|
||||
// Check if the current array is a 'notenData' object itself
|
||||
if (isset($array['type']) && $array['type'] === 'notenGeraetData') {
|
||||
return [$array];
|
||||
}
|
||||
|
||||
// Otherwise, loop through the elements to go deeper
|
||||
foreach ($array as $value) {
|
||||
if (is_array($value)) {
|
||||
// Recursively extract from the sub-array and merge into our result list
|
||||
$result = array_merge($result, extractNotenGeraetData($value));
|
||||
}
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
$all_noten = ($allowed_slugs[$slug] === 'all') ? extractNotenData($body) : extractNotenGeraetData($body);
|
||||
|
||||
$all_noten_export = [];
|
||||
|
||||
foreach ($all_noten as $single_note) {
|
||||
$all_noten_export[] = [
|
||||
'g_id' => $single_note['geraet-id'] ?? 'A',
|
||||
'n_id' => $single_note['field-type-id'],
|
||||
'r' => $single_note['run']
|
||||
];
|
||||
}
|
||||
|
||||
function unique_matrix($matrix) {
|
||||
$matrixAux = $matrix;
|
||||
|
||||
foreach($matrix as $key => $subMatrix) {
|
||||
unset($matrixAux[$key]);
|
||||
|
||||
foreach($matrixAux as $subMatrixAux) {
|
||||
if($subMatrix === $subMatrixAux) {
|
||||
unset($matrix[$key]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $matrix;
|
||||
}
|
||||
|
||||
$all_noten_json = json_encode(unique_matrix($all_noten_export) ?? []) ?? '';
|
||||
|
||||
$user_id = (int) $_SESSION['user_id_wk_leitung'] ?? 0;
|
||||
|
||||
$stmt = $mysqli->prepare("INSERT INTO `$db_tabelle_tabellen_konfiguration` (`json`, `all_noten_json`, `type_slug`, `created_by`, `updated_by`) VALUES (?, ?, ?, ?, ?) ON DUPLICATE KEY UPDATE `json` = VALUES(`json`), `all_noten_json` = VAlUES(`all_noten_json`), `updated_by` = VALUES(`updated_by`)");
|
||||
|
||||
if (!$stmt) {
|
||||
echo json_encode(['success' => false, 'message' => 'Critical DB ERROR']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$stmt->bind_param("sssii", $json, $all_noten_json, $slug, $user_id, $user_id);
|
||||
$success = $stmt->execute();
|
||||
$stmt->close();
|
||||
|
||||
if (!$success) {
|
||||
echo json_encode(['success' => false, 'message' => 'Insert failed']);
|
||||
exit;
|
||||
}
|
||||
|
||||
if (str_contains($slug, 'rankLive')) {
|
||||
require_once $baseDir . '/../scripts/cache/cache-creators/regenerate-display-dependencies-cache.php';
|
||||
generateIntersectCache($mysqli, $baseDir);
|
||||
}
|
||||
|
||||
// Return JSON
|
||||
echo json_encode([
|
||||
'success' => true,
|
||||
'message' => 'gespeichert'
|
||||
]);
|
||||
exit;
|
||||
@@ -0,0 +1,82 @@
|
||||
<?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();
|
||||
|
||||
$tableJSONVersion = '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';
|
||||
|
||||
$slug = $_POST['slug'] ?? '';
|
||||
|
||||
$allowed_slugs = [
|
||||
'rankLive-overview' => 'RankLive Overview',
|
||||
'rankLive-geraet' => 'RankLive einzelnes Gerät',
|
||||
'kampfrichter-admin' => 'Kampfrichter Admin (alle Geräte)',
|
||||
'kampfrichter-geraet' => 'Kampfrichter einzelnes Gerät' //, 'rangliste' => 'all'
|
||||
];
|
||||
|
||||
if (!array_key_exists($slug, $allowed_slugs)){
|
||||
http_response_code(400);
|
||||
echo json_encode(['success' => false, 'message' => 'Invalid Type']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$json = db_get_var($mysqli, "SELECT `json` FROM $db_tabelle_tabellen_konfiguration WHERE `type_slug` = ?", [$slug]) ?: '';
|
||||
|
||||
try {
|
||||
$json_array = json_decode($json, true) ?? [];
|
||||
} catch (Exception $e) {
|
||||
http_response_code(500);
|
||||
echo json_encode(['success' => false, 'message' => 'Error parsing JSON']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$wk_name = db_get_var($mysqli, "SELECT `value` FROM $db_tabelle_var WHERE `name` = ?", ['wkName']);
|
||||
|
||||
$exportData = [
|
||||
'metadata' => [
|
||||
'erstellt_am' => date("d.m.Y H:i"),
|
||||
'ersteller' => $_SERVER['HTTP_HOST'],
|
||||
'erstellt_mit' => 'WKVS Auto-Export',
|
||||
'wkvs_json_table_version' => '1.0.0',
|
||||
'titel' => 'WKVS Table für ' . $allowed_slugs[$slug] . ' ' . $wk_name . ' (V 1.0.0)'
|
||||
],
|
||||
'data' => $json_array,
|
||||
'type' => $slug
|
||||
];
|
||||
|
||||
$jsonOutput = json_encode($exportData, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);
|
||||
|
||||
// 6. Force Browser File Download
|
||||
$fileName = 'WKVS-table-config-' . date('Y-m-d_H-i') . '-' . $slug . '.conf.wkvs';
|
||||
|
||||
header('Content-Type: application/json; charset=utf-8');
|
||||
header('Content-Disposition: attachment; filename="' . $fileName . '"');
|
||||
header('Expires: 0');
|
||||
header('Cache-Control: must-revalidate');
|
||||
header('Pragma: public');
|
||||
header('Content-Length: ' . strlen($jsonOutput));
|
||||
|
||||
echo $jsonOutput;
|
||||
exit;
|
||||
@@ -0,0 +1,193 @@
|
||||
<?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;
|
||||
}
|
||||
|
||||
$tableJSONVersion = '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';
|
||||
|
||||
$slug = $_POST['slug'] ?? '';
|
||||
|
||||
$allowed_slugs = ['rankLive-overview' => 'all', 'rankLive-geraet' => 'geraet', 'kampfrichter-admin' => 'Kampfrichter Admin (alle Geräte)', 'kampfrichter-geraet' => 'geraet', 'rangliste' => 'all'];
|
||||
|
||||
if (!array_key_exists($slug, $allowed_slugs)){
|
||||
http_response_code(400);
|
||||
echo json_encode(['success' => false, 'message' => 'Invalid Type']);
|
||||
exit;
|
||||
}
|
||||
|
||||
|
||||
$tmpPath = $_FILES['configFile']['tmp_name'];
|
||||
$originalName = $_FILES['configFile']['name'];
|
||||
$extension = strtolower(pathinfo($originalName, PATHINFO_EXTENSION));
|
||||
|
||||
$allowedExt = ['json', 'wkvs'];
|
||||
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;
|
||||
}
|
||||
|
||||
$JSONcontent = file_get_contents($tmpPath);
|
||||
|
||||
$content = json_decode($JSONcontent, true);
|
||||
if (json_last_error() !== JSON_ERROR_NONE) {
|
||||
die("Invalid JSON layout.");
|
||||
}
|
||||
|
||||
if (!isset($content['metadata']['wkvs_json_table_version']) || $content['metadata']['wkvs_json_table_version'] !== $tableJSONVersion) {
|
||||
echo json_encode(['success' => false, 'message' => 'Inkompatible Datei-Version. (V ' . $tableJSONVersion . ' 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['data']) || !is_array($content['data'])) {
|
||||
echo json_encode(['success' => false, 'message' => 'Ungültige JSON-Struktur']);
|
||||
unlink($destination);
|
||||
http_response_code(422);
|
||||
exit;
|
||||
}
|
||||
|
||||
$body = $content['data']['body'];
|
||||
|
||||
$all_noten = [];
|
||||
|
||||
function extractNotenData(array $array): array {
|
||||
$result = [];
|
||||
|
||||
// Check if the current array is a 'notenData' object itself
|
||||
if (isset($array['type']) && $array['type'] === 'notenData') {
|
||||
return [$array];
|
||||
}
|
||||
|
||||
// Otherwise, loop through the elements to go deeper
|
||||
foreach ($array as $value) {
|
||||
if (is_array($value)) {
|
||||
// Recursively extract from the sub-array and merge into our result list
|
||||
$result = array_merge($result, extractNotenData($value));
|
||||
}
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
function extractNotenGeraetData(array $array): array {
|
||||
$result = [];
|
||||
|
||||
// Check if the current array is a 'notenData' object itself
|
||||
if (isset($array['type']) && $array['type'] === 'notenGeraetData') {
|
||||
return [$array];
|
||||
}
|
||||
|
||||
// Otherwise, loop through the elements to go deeper
|
||||
foreach ($array as $value) {
|
||||
if (is_array($value)) {
|
||||
// Recursively extract from the sub-array and merge into our result list
|
||||
$result = array_merge($result, extractNotenGeraetData($value));
|
||||
}
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
$all_noten = ($allowed_slugs[$slug] === 'all') ? extractNotenData($body) : extractNotenGeraetData($body);
|
||||
|
||||
$all_noten_export = [];
|
||||
|
||||
foreach ($all_noten as $single_note) {
|
||||
$all_noten_export[] = [
|
||||
'g_id' => $single_note['geraet-id'] ?? 'A',
|
||||
'n_id' => $single_note['field-type-id'],
|
||||
'r' => $single_note['run']
|
||||
];
|
||||
}
|
||||
|
||||
function unique_matrix($matrix) {
|
||||
$matrixAux = $matrix;
|
||||
|
||||
foreach($matrix as $key => $subMatrix) {
|
||||
unset($matrixAux[$key]);
|
||||
|
||||
foreach($matrixAux as $subMatrixAux) {
|
||||
if($subMatrix === $subMatrixAux) {
|
||||
unset($matrix[$key]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $matrix;
|
||||
}
|
||||
|
||||
$all_noten_json = json_encode(unique_matrix($all_noten_export) ?? []) ?? '';
|
||||
|
||||
$user_id = (int) $_SESSION['user_id_wk_leitung'] ?? 0;
|
||||
|
||||
$stmt = $mysqli->prepare("INSERT INTO `$db_tabelle_tabellen_konfiguration` (`json`, `all_noten_json`, `type_slug`, `created_by`, `updated_by`) VALUES (?, ?, ?, ?, ?) ON DUPLICATE KEY UPDATE `json` = VALUES(`json`), `all_noten_json` = VAlUES(`all_noten_json`), `updated_by` = VALUES(`updated_by`)");
|
||||
|
||||
if (!$stmt) {
|
||||
echo json_encode(['success' => false, 'message' => 'Critical DB ERROR']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$json = json_encode($content['data']);
|
||||
|
||||
$stmt->bind_param("sssii", $json, $all_noten_json, $slug, $user_id, $user_id);
|
||||
$success = $stmt->execute();
|
||||
$stmt->close();
|
||||
|
||||
if (!$success) {
|
||||
echo json_encode(['success' => false, 'message' => 'Insert failed']);
|
||||
exit;
|
||||
}
|
||||
|
||||
if (str_contains($slug, 'rankLive')) {
|
||||
require_once $baseDir . '/../scripts/cache/cache-creators/regenerate-display-dependencies-cache.php';
|
||||
generateIntersectCache($mysqli, $baseDir);
|
||||
}
|
||||
|
||||
// Return JSON
|
||||
echo json_encode([
|
||||
'success' => true,
|
||||
'message' => 'gespeichert'
|
||||
]);
|
||||
exit;
|
||||
@@ -0,0 +1,366 @@
|
||||
<?php
|
||||
|
||||
use TCPDF;
|
||||
|
||||
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($baseDir)) {
|
||||
$baseDir = $_SERVER['DOCUMENT_ROOT'];
|
||||
}
|
||||
|
||||
$type = 'kr';
|
||||
$data = require $baseDir . '/../scripts/db/db-verbindung-script.php';
|
||||
|
||||
if ($data['success'] === false) {
|
||||
header('Content-Type: application/json');
|
||||
echo json_encode(['success' => false, 'message' => $data['message']]);
|
||||
exit;
|
||||
}
|
||||
|
||||
require $baseDir . '/../scripts/db/db-tables.php';
|
||||
require $baseDir . '/../scripts/db/db-functions.php';
|
||||
|
||||
$wkName = db_get_var($mysqli, "SELECT `value` FROM $db_tabelle_var WHERE `name` = ?", ['wkName']);
|
||||
|
||||
$wkName = ($wkName === null) ? 'Keinen Wettkampfname angegeben. Setzen unter: /intern/wk-leitung/einstellungen' : $wkName;
|
||||
|
||||
$normalFontSize = 11;
|
||||
$marginSide = 10;
|
||||
$marginTop = 10;
|
||||
$minMarginBottomTable = 20;
|
||||
$format = 'A4';
|
||||
$orientation = 'L';
|
||||
|
||||
$svgs = [
|
||||
'1' => '<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M6 2h12v2a6 6 0 0 1-6 6 6 6 0 0 1-6-6V2zm0 20h12v-2a6 6 0 0 0-6-6 6 6 0 0 0-6 6v2zm6-10c1.657 0 3-1.343 3-3H9c0 1.657 1.343 3 3 3z" fill="#0073aa"/></svg>',
|
||||
'2' => '<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><circle cx="12" cy="12" r="10" fill="#28a745"/><path d="M7 12l3 3 7-7" stroke="white" stroke-width="2" fill="none" stroke-linecap="round" stroke-linejoin="round"/></svg>',
|
||||
'3' => '<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><circle cx="12" cy="12" r="10" fill="#dc3545"/><path d="M8 8l8 8M16 8l-8 8" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg>'
|
||||
];
|
||||
|
||||
$now = trim($_POST['date'] ?? date('Y-m-d H:i:s'));
|
||||
|
||||
$logEntries = db_select($mysqli, $db_tabelle_verbuchte_startgebueren_log, "*");
|
||||
|
||||
$personen = db_select($mysqli, $db_tabelle_intern_benutzende, "`id`, `name_person`, `username`");
|
||||
|
||||
$indexedPersonen = array_column($personen, null, 'id');
|
||||
|
||||
$entriesArray = [];
|
||||
|
||||
foreach ($logEntries as $slE) {
|
||||
|
||||
// $value = ($slE['old_order_status'] !== null) ? ($svgs[$slE['old_order_status']] ?? $slE['old_order_status']) . ' ' . json_decode('"\u2192"') . ' ' . ($svgs[$slE['new_order_status'] ?? ''] ?? $slE['new_order_status'] ?? '') : ($svgs[$slE['new_order_status'] ?? ''] ?? $slE['new_order_status'] ?? '');
|
||||
|
||||
$valueArray = [
|
||||
1 => $svgs[$slE['old_order_status'] ?? ''] ?? '',
|
||||
2 => isset($svgs[$slE['old_order_status']]),
|
||||
3 => $svgs[$slE['new_order_status'] ?? ''] ?? '',
|
||||
4 => isset($svgs[$slE['new_order_status']])
|
||||
];
|
||||
|
||||
$entriesArray[] = [
|
||||
'order_id' => $slE['order_id'] ?? '',
|
||||
'value' => $valueArray,
|
||||
'edited_by' => $indexedPersonen[$slE['edited_by']]['name_person'] ?? 'Unbekannter User',
|
||||
'timestamp' => new DateTime($slE['edited_at'])->format('d.m.Y H:i:s') ?? '---'
|
||||
];
|
||||
}
|
||||
|
||||
// Load TCPDF
|
||||
require $baseDir . '/../composer/vendor/autoload.php';
|
||||
|
||||
class ProtokollPDF extends TCPDF
|
||||
{
|
||||
public $columns;
|
||||
public $wkName;
|
||||
public $marginSide;
|
||||
public $marginTop;
|
||||
public $pdfHeight;
|
||||
public $pdfWidth;
|
||||
public $headerType;
|
||||
public $now;
|
||||
// Page header
|
||||
|
||||
public $headerBottomY = 0;
|
||||
|
||||
|
||||
public function Header()
|
||||
{
|
||||
$this->SetFillColor(255, 255, 255);
|
||||
|
||||
$this->Rect(0, 0, $this->pdfWidth, $this->pdfHeight, 'F');
|
||||
|
||||
$arrayTitles = [];
|
||||
$image_file = $_SERVER['DOCUMENT_ROOT'] . '/intern/img/logo-normal.png';
|
||||
$this->SetY($this->marginTop);
|
||||
$this->SetX(($this->marginSide ?? 10));
|
||||
$this->SetFont('freesans', '', 20);
|
||||
|
||||
$this->Cell(0, 0, 'Protokoll Rechnungen ' . $this->wkName, 0, 1, 'L', 0, '', 0, false, 'T', 'M');
|
||||
$preimageX = $this->GetX();
|
||||
$preimageY = $this->GetY();
|
||||
$this->Image($image_file, $this->pdfWidth - 10 - $this->marginSide, $this->marginTop, '', 10, 'png', '', 'T');
|
||||
|
||||
$this->SetY($preimageY + 5);
|
||||
$this->SetX($this->marginSide ?? 10); // Force back to left margin
|
||||
$this->SetFont('freesans', '', 11);
|
||||
|
||||
$this->Ln(5);
|
||||
|
||||
$columns = $this->columns;
|
||||
$startY = $this->GetY();
|
||||
$this->SetFont('', 'B');
|
||||
|
||||
$this->SetX($this->marginSide ?? 10);
|
||||
|
||||
foreach ($columns as $col) {
|
||||
|
||||
$title = $col['header'];
|
||||
|
||||
if (($col['rotate'] ?? false)) {
|
||||
$x = $this->GetX();
|
||||
$y = $this->GetY() + 7;
|
||||
|
||||
$this->StartTransform();
|
||||
$this->Rotate(45, $x, $y);
|
||||
|
||||
$lineY = $startY + 7;
|
||||
if (($col['id'] ?? '') === 'gesamt') {
|
||||
$this->SetLineWidth(0.6);
|
||||
} else {
|
||||
$this->SetLineWidth(0.2);
|
||||
}
|
||||
|
||||
$this->Line($x, $lineY, $x + ($col['width_header'] ?? 0), $lineY);
|
||||
$this->SetLineWidth(0.2);
|
||||
|
||||
$this->Cell($col['width_header'] ?? 0, 7, $title ?? '', 0, 0, 'C');
|
||||
$this->StopTransform();
|
||||
$this->SetX($x + ($col['max_width'] ?? 0));
|
||||
} else {
|
||||
$this->Cell($col['max_width'] ?? 0, 7, $title ?? '', 0, 0, $col['align'] ?? 'L');
|
||||
}
|
||||
}
|
||||
|
||||
$this->Ln();
|
||||
$this->headerBottomY = $this->GetY();
|
||||
}
|
||||
|
||||
|
||||
// Page footer
|
||||
public function Footer()
|
||||
{
|
||||
$this->SetLineWidth(0.6);
|
||||
$this->Line($this->marginSide ?? 10, $this->headerBottomY, $this->pdfWidth - ($this->marginSide ?? 10), $this->headerBottomY);
|
||||
|
||||
$this->SetLineWidth(0.2);
|
||||
|
||||
$this->SetY(0);
|
||||
$this->SetX(0);
|
||||
|
||||
$this->SetFillColor(255, 255, 255); // white
|
||||
|
||||
$this->Cell(($this->marginSide ?? 10), $this->pdfHeight, '', 0, 0, 'L', true);
|
||||
|
||||
$this->SetY(0);
|
||||
$this->SetX($this->pdfWidth - ($this->marginSide ?? 10));
|
||||
|
||||
$this->Cell(($this->marginSide ?? 10), $this->pdfHeight, '', 0, 0, 'L', true);
|
||||
|
||||
$this->SetY(-15);
|
||||
$this->SetFont('freesans', 'I', 8);
|
||||
|
||||
// 1. Page Number - Centered
|
||||
$this->Cell(0, 10, 'Seite ' . $this->getAliasNumPage() . ' von ' . $this->getAliasNbPages(), 0, false, 'C');
|
||||
|
||||
// 2. Timestamp - Force to Left
|
||||
$this->SetX($this->getMargins()['left']); // Reset to left margin
|
||||
$this->Cell(0, 10, 'Zeitstempel: ' . $this->now, 0, false, 'L');
|
||||
|
||||
// 3. Host - Force to Right (Cell with width 0 and align 'R' handles this)
|
||||
$this->SetX($this->getMargins()['left']); // Reset again so 'R' alignment works from the start
|
||||
$this->Cell(0, 10, $_SERVER['HTTP_HOST'], 0, 0, 'R', false, 'https://'.$_SERVER['HTTP_HOST']);
|
||||
}
|
||||
}
|
||||
|
||||
$pdf = new ProtokollPDF($orientation, 'mm', $format, true, 'UTF-8', false);
|
||||
|
||||
$pdfHeight = $pdf->getPageHeight();
|
||||
$pdfWidth = $pdf->getPageWidth();
|
||||
|
||||
$pdf->wkName = $wkName;
|
||||
$pdf->marginSide = $marginSide;
|
||||
$pdf->marginTop = $marginTop;
|
||||
$pdf->pdfHeight = $pdfHeight;
|
||||
$pdf->pdfWidth = $pdfWidth;
|
||||
$pdf->now = $now;
|
||||
|
||||
$pdf->SetCreator(PDF_CREATOR);
|
||||
$pdf->SetAuthor($wkName);
|
||||
$pdf->SetTitle($wkName . "_Protokoll.pdf");
|
||||
|
||||
$pdf->SetAutoPageBreak(FALSE);
|
||||
|
||||
|
||||
$pdf->SetFont('freesans', '', 11);
|
||||
|
||||
// Define columns dynamically
|
||||
$columns = [
|
||||
['id' => 'order_id', 'header' => 'Rechnungsnummer', 'align' => 'L', 'flex' => true, 'type' => 'link', 'field' => 'order_id'],
|
||||
['id' => 'value', 'header' => 'Änderung', 'align' => 'L', 'flex' => true, 'type' => 'value', 'field' => 'value'],
|
||||
['id' => 'edited_by', 'header' => 'Geändert durch', 'align' => 'C', 'flex' => true, 'type' => 'field', 'field' => 'edited_by'],
|
||||
['id' => 'timestamp', 'header' => 'Zeitstempel', 'align' => 'C', 'flex' => true, 'type' => 'field', 'field' => 'timestamp'],
|
||||
];
|
||||
|
||||
|
||||
$padding = 4;
|
||||
|
||||
// 1. Calculate initial max widths based on headers
|
||||
foreach ($columns as &$col) {
|
||||
$col['width_header'] = $pdf->GetStringWidth($col['header']) + ($padding * 2);
|
||||
if ($col['type'] !== 'note') {
|
||||
$col['max_width'] = $col['width_header'];
|
||||
} else {
|
||||
$col['max_width'] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
unset($col);
|
||||
|
||||
foreach ($entriesArray as $row) {
|
||||
foreach ($columns as $col) {
|
||||
$text = '';
|
||||
if ($col['type'] !== 'value') {
|
||||
if (isset($row[$col['field']])) {
|
||||
$text = $row[$col['field']];
|
||||
}
|
||||
$width = $pdf->GetStringWidth($text) + ($padding * 2);
|
||||
if ($width > $col['max_width']) {
|
||||
$col['max_width'] = $width;
|
||||
}
|
||||
} else {
|
||||
if (40 > $col['max_width']) {
|
||||
$col['max_width'] = 40;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$fixedWidth = 0;
|
||||
|
||||
foreach ($columns as $col) {
|
||||
if ($col['flex'] ?? false) {
|
||||
$flexCols[] = $col['id'];
|
||||
$fixedWidth += $col['max_width'];
|
||||
} else {
|
||||
$fixedWidth += $col['max_width'];
|
||||
}
|
||||
}
|
||||
|
||||
$tablew = $pdfWidth - (2 * $marginSide);
|
||||
|
||||
$effTableWidth = $tablew - $fixedWidth;
|
||||
|
||||
if (!empty($flexCols) && $effTableWidth > 0) {
|
||||
$flexTotalInitial = 0;
|
||||
foreach ($columns as $col) {
|
||||
if ($col['flex'] ?? false) $flexTotalInitial += $col['max_width'];
|
||||
}
|
||||
|
||||
foreach ($columns as &$col) {
|
||||
if ($col['flex'] ?? false) {
|
||||
$col['max_width'] += ($col['max_width'] / $flexTotalInitial) * $effTableWidth;
|
||||
}
|
||||
}
|
||||
unset($col);
|
||||
}
|
||||
|
||||
$pdf->columns = $columns;
|
||||
|
||||
$pdf->AddPage();
|
||||
$margin_top = $pdf->headerBottomY;
|
||||
|
||||
$pdf->SetMargins($marginSide, $margin_top, $marginSide); // +5 mm padding below header
|
||||
$pdf->SetY($margin_top); // Move cursor below header manually
|
||||
|
||||
$pdf->SetFont('', '');
|
||||
|
||||
foreach ($entriesArray as $row) {
|
||||
|
||||
$rowHeight = 10;
|
||||
|
||||
foreach ($columns as $col) {
|
||||
|
||||
$pdf->setFillColor(255, 255, 255);
|
||||
|
||||
if ($pdf->getY() + $rowHeight > $pdfHeight - $minMarginBottomTable) {
|
||||
$pdf->addPage();
|
||||
$margin_top = $pdf->headerBottomY;
|
||||
$pdf->setY($margin_top);
|
||||
}
|
||||
|
||||
$customFontSize = (isset($col['font_size']) && $col['font_size'] != 0);
|
||||
|
||||
if ($customFontSize) {
|
||||
$pdf->SetFont('', '', $col['font_size']);
|
||||
}
|
||||
|
||||
$startX = $pdf->GetX();
|
||||
$startY = $pdf->GetY();
|
||||
|
||||
if ($col['type'] === 'field') {
|
||||
$text = $row[$col['field']] ?? '';
|
||||
|
||||
$pdf->MultiCell($col['max_width'], $rowHeight, $text, 'B', $col['align'], true, 0, $startX, $startY, true, 0, false, true, $rowHeight, 'M');
|
||||
} elseif ($col['type'] === 'value') {
|
||||
$pdf->MultiCell($col['max_width'], $rowHeight, '', 'B', $col['align'], true, 0, $startX, $startY, true, 0, false, true, $rowHeight, 'M');
|
||||
|
||||
$valuesArrary = $row[$col['field']];
|
||||
|
||||
if (isset($valuesArrary[1]) && isset($valuesArrary[2]) && $valuesArrary[2]) {
|
||||
$pdf->ImageSVG('@' . $valuesArrary[1], $startX, $startY + 2, $rowHeight - 4, $rowHeight - 4);
|
||||
$pdf->MultiCell(10, $rowHeight, json_decode('"\u2192"'), '', 'C', false, 0, $startX + $rowHeight - 4, $startY, true, 0, false, true, $rowHeight, 'M');
|
||||
}
|
||||
|
||||
if (isset($valuesArrary[3]) && isset($valuesArrary[3]) && $valuesArrary[4]) {
|
||||
$pdf->ImageSVG('@' . $valuesArrary[3], $startX + $rowHeight - 4 + 10, $startY + 2, $rowHeight - 4, $rowHeight - 4);
|
||||
}
|
||||
|
||||
$pdf->SetX($startX + $col['max_width']);
|
||||
|
||||
} elseif ($col['type'] === 'link') {
|
||||
$text = $row[$col['field']] ?? '';
|
||||
|
||||
$pdf->MultiCell($col['max_width'], $rowHeight, $text, 'B', $col['align'], true, 0, $startX, $startY, true, 0, false, true, $rowHeight, 'M');
|
||||
|
||||
$pdf->Link($startX, $startY, $col['max_width'], $rowHeight, 'https://'.$_SERVER['HTTP_HOST'].'/intern/wk-leitung/rechnungen-viewer?order_id='.$text);
|
||||
}
|
||||
|
||||
if ($customFontSize) {
|
||||
$pdf->SetFont('', '', $normalFontSize);
|
||||
}
|
||||
}
|
||||
|
||||
$pdf->SetY($startY + $rowHeight);
|
||||
}
|
||||
$textanzEintaege = (count($entriesArray) > 1) ? 'Einträge': 'Eintrag';
|
||||
|
||||
$pdf->SetFont('', '', 7);
|
||||
|
||||
$pdf->Cell(20, 6, count($entriesArray).' '.$textanzEintaege, 0, 0, 'L');
|
||||
|
||||
$pdf->SetFont('', '', $normalFontSize);
|
||||
|
||||
|
||||
$pdf->Output($wkName . "_Protokoll_Rechnungen.pdf", 'I');
|
||||
exit;
|
||||
@@ -0,0 +1,112 @@
|
||||
<?php
|
||||
header('Content-Type: application/json');
|
||||
|
||||
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();
|
||||
|
||||
$allowedActions = ['payEntrys' => 2, 'deleteEntrys' => 3];
|
||||
|
||||
$requestedAction = trim($_POST['action'] ?? '');
|
||||
|
||||
if (!array_key_exists($requestedAction, $allowedActions)) {
|
||||
echo json_encode(['success' => false, 'message' => 'Invalid Action']);
|
||||
http_response_code(400);
|
||||
exit;
|
||||
}
|
||||
|
||||
$actionValue = $allowedActions[$requestedAction];
|
||||
|
||||
$user = $_SESSION['user_id_wk_leitung'] ?? 0;
|
||||
|
||||
$type = 'wkl';
|
||||
|
||||
$data = include $baseDir . '/../scripts/db/db-verbindung-script.php';
|
||||
|
||||
if ($data['success'] === false){
|
||||
echo json_encode(['success' => false, 'message' => $data['message']]);
|
||||
http_response_code(500);
|
||||
exit;
|
||||
}
|
||||
|
||||
require $baseDir . '/../scripts/db/db-tables.php';
|
||||
require $baseDir . '/../scripts/db/db-functions.php';
|
||||
|
||||
if (!isset($_POST['ids']) || !is_array($_POST['ids']) || count($_POST['ids']) < 1) {
|
||||
echo json_encode(['success' => false, 'message' => 'Keine Id angegeben']);
|
||||
http_response_code(422);
|
||||
exit;
|
||||
}
|
||||
|
||||
$ids = $_POST['ids'];
|
||||
|
||||
// Validate: all IDs must be integers
|
||||
$ids = array_filter($ids, fn($id) => ctype_digit(strval($id)));
|
||||
|
||||
if (count($ids) === 0) {
|
||||
echo json_encode(['success' => false, 'message' => 'Kein gültiger Input']);
|
||||
http_response_code(422);
|
||||
exit;
|
||||
}
|
||||
|
||||
// Build placeholders for prepared statement
|
||||
$placeholders = implode(',', array_fill(0, count($ids), '?'));
|
||||
|
||||
$affectedRows = db_select($mysqli, $db_tabelle_verbuchte_startgebueren, "order_status, order_id, `item_ids`, `used_verein_konten`", "order_id IN ($placeholders)", $ids);
|
||||
|
||||
$mysqli->begin_transaction();
|
||||
|
||||
require $baseDir . '/../scripts/rechnungen/rechnungs-functions.php';
|
||||
|
||||
try {
|
||||
$stmt = $mysqli->prepare("INSERT INTO $db_tabelle_verbuchte_startgebueren_log (`old_order_status`, `new_order_status`, `order_id`, `edited_by`) VALUES (?, ?, ?, ?)");
|
||||
foreach ($affectedRows as $row) {
|
||||
$stmt->bind_param("ssss", $row['order_status'], $actionValue, $row['order_id'], $user);
|
||||
$stmt->execute();
|
||||
update_teilnehmende($row['item_ids'], $row['order_status'], $actionValue);
|
||||
update_konten_vereine($row['used_verein_konten'], $row['order_status'], $actionValue);
|
||||
}
|
||||
|
||||
// Prepare the SQL statement
|
||||
$sql = "UPDATE $db_tabelle_verbuchte_startgebueren SET order_status = ? WHERE order_id IN ($placeholders)";
|
||||
$stmt = $mysqli->prepare($sql);
|
||||
|
||||
if (!$stmt) {
|
||||
echo json_encode(['success' => false, 'message' => 'Fehler beim Vorbereiten der Abfrage']);
|
||||
http_response_code(500);
|
||||
exit;
|
||||
}
|
||||
|
||||
$params = array_merge([$actionValue], $ids);
|
||||
|
||||
$types = 's' . str_repeat('i', count($ids));
|
||||
$stmt->bind_param($types, ...$params);
|
||||
|
||||
if (!$stmt->execute()) {
|
||||
echo json_encode(['success' => false, 'message' => 'Fehler beim Löschen']);
|
||||
http_response_code(500);
|
||||
exit;
|
||||
}
|
||||
|
||||
$stmt->close();
|
||||
|
||||
$mysqli->commit();
|
||||
} catch (Exception $e) {
|
||||
$mysqli->rollback();
|
||||
exit;
|
||||
}
|
||||
$mysqli->close();
|
||||
|
||||
echo json_encode(['success' => true, 'message' => 'Bestellungen erfolgreich gelöscht']);
|
||||
http_response_code(200);
|
||||
exit;
|
||||
@@ -0,0 +1,87 @@
|
||||
<?php
|
||||
header('Content-Type: application/json');
|
||||
|
||||
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();
|
||||
|
||||
$type = 'wkl';
|
||||
|
||||
$data = include $baseDir . '/../scripts/db/db-verbindung-script.php';
|
||||
|
||||
if ($data['success'] === false){
|
||||
echo json_encode(['success' => false, 'message' => $data['message']]);
|
||||
http_response_code(500);
|
||||
exit;
|
||||
}
|
||||
|
||||
require $baseDir . '/../scripts/db/db-tables.php';
|
||||
require $baseDir . '/../scripts/db/db-functions.php';
|
||||
|
||||
if (!isset($_POST['scor']) || empty($_POST['scor']) || $_POST['scor'] === '') {
|
||||
echo json_encode(['success' => false, 'message' => 'Keine Referenz angegeben']);
|
||||
http_response_code(422);
|
||||
exit;
|
||||
}
|
||||
|
||||
$user = $_SESSION['user_id_wk_leitung'] ?? 0;
|
||||
|
||||
$scorFullStr = strval($_POST['scor'] ?? '');
|
||||
|
||||
$scor = intval(substr($scorFullStr, 2));
|
||||
|
||||
$stmt = $mysqli->prepare(
|
||||
"SELECT 1 FROM $db_tabelle_verbuchte_startgebueren WHERE order_id = ? LIMIT 1"
|
||||
);
|
||||
|
||||
$stmt->bind_param('i', $scor);
|
||||
$stmt->execute();
|
||||
$stmt->store_result();
|
||||
|
||||
if ($stmt->num_rows !== 1) {
|
||||
echo json_encode(['success' => false, 'message' => 'Invalide Referenz']);
|
||||
http_response_code(403);
|
||||
exit;
|
||||
}
|
||||
|
||||
$stmt->close();
|
||||
|
||||
require $baseDir . '/../scripts/rechnungen/rechnungs-functions.php';
|
||||
|
||||
$affectedRow = db_select($mysqli, $db_tabelle_verbuchte_startgebueren, "`order_status`, `order_id`, `item_ids`, `used_verein_konten`", "order_id = ?", [$scor]);
|
||||
try {
|
||||
$stmt = $mysqli->prepare("INSERT INTO $db_tabelle_verbuchte_startgebueren_log (`old_order_status`, `new_order_status`, `order_id`, `edited_by`) VALUES (?, 2, ?, ?)");
|
||||
foreach ($affectedRow as $row) {
|
||||
$stmt->bind_param("sss", $row['order_status'], $row['order_id'], $user);
|
||||
$stmt->execute();
|
||||
update_teilnehmende($row['item_ids'], $row['order_status'], 2);
|
||||
update_konten_vereine($row['used_verein_konten'], $row['order_status'], 2);
|
||||
}
|
||||
|
||||
$sql = "UPDATE $db_tabelle_verbuchte_startgebueren SET order_status = 2 WHERE order_id = ?";
|
||||
|
||||
$nstmt = $mysqli->prepare($sql);
|
||||
|
||||
$nstmt->bind_param('i', $scor);
|
||||
|
||||
$mysqli->commit();
|
||||
} catch (Exception $e) {
|
||||
$mysqli->rollback();
|
||||
exit;
|
||||
}
|
||||
|
||||
$mysqli->close();
|
||||
|
||||
echo json_encode(['success' => true, 'message' => 'Rechnung wurde aktualisiert']);
|
||||
http_response_code(200);
|
||||
exit;
|
||||
@@ -0,0 +1,86 @@
|
||||
<?php
|
||||
header('Content-Type: application/json');
|
||||
|
||||
|
||||
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();
|
||||
|
||||
require $baseDir . '/../scripts/db/db-functions.php';
|
||||
require $baseDir . '/../scripts/db/db-tables.php';
|
||||
|
||||
|
||||
$type = 'wkl';
|
||||
$dbconnection = require $baseDir . '/../scripts/db/db-verbindung-script.php';
|
||||
|
||||
if ($dbconnection['success'] !== true){
|
||||
echo json_encode(['success' => false, 'message' => 'Critical DB Error.']);
|
||||
exit;
|
||||
}
|
||||
|
||||
|
||||
$action = $_POST['action'] ?? '';
|
||||
|
||||
if ($action === 'update') {
|
||||
$abt_id = intval($_POST['abt'] ?? 0);
|
||||
$field = $_POST['type'] ?? '';
|
||||
$type_id = intval($_POST['type_id'] ?? 0);
|
||||
|
||||
$value = $_POST['value'] ?? '';
|
||||
|
||||
if (!preg_match('/^\d{2}:\d{2}$/', $value)) {
|
||||
echo json_encode(['success' => false, 'message' => 'Invalid parameters.']);
|
||||
http_response_code(400);
|
||||
exit;
|
||||
}
|
||||
|
||||
$allowedFields = ['start', 'end'];
|
||||
if (
|
||||
$abt_id > 0 &&
|
||||
$type_id > 0 &&
|
||||
db_check_var($mysqli, $db_tabelle_gruppen, 'id = ?', [$abt_id]) &&
|
||||
db_check_var($mysqli, $db_tabelle_zeitplan_types, 'id = ?', [$type_id]) &&
|
||||
($field === 'start' || ($field === 'end' && db_check_var($mysqli, $db_tabelle_zeitplan_types, 'id = ? AND has_endtime = ?', [$type_id, 1])))
|
||||
) {
|
||||
|
||||
$stmt = $mysqli->prepare("INSERT INTO $db_tabelle_gruppen_zeiten (`abt_id`, `zeitplan_id`, `" . $field . "_time`) VALUES (?, ?, ?) ON DUPLICATE KEY UPDATE `" . $field . "_time` = VALUES(`" . $field . "_time`)");
|
||||
|
||||
$stmt->bind_param("iis", $abt_id, $type_id, $value);
|
||||
|
||||
$stmt->execute();
|
||||
|
||||
$stmt->close();
|
||||
|
||||
echo json_encode(['success' => true]);
|
||||
} else {
|
||||
echo json_encode(['success' => false, 'message' => 'Invalid parameters.']);
|
||||
http_response_code(400);
|
||||
exit;
|
||||
}
|
||||
|
||||
} elseif ($action === 'delete') {
|
||||
$abt_id = intval($_POST['abt'] ?? 0);
|
||||
$type_id = intval($_POST['type_id'] ?? 0);
|
||||
|
||||
if ($type_id > 0 && $abt_id > 0) {
|
||||
db_delete($mysqli, $db_tabelle_gruppen_zeiten, ['abt_id' => $abt_id, 'zeitplan_id' => $type_id]);
|
||||
echo json_encode(['success' => true]);
|
||||
} else {
|
||||
echo json_encode(['success' => false, 'message' => 'Invalid ID.']);
|
||||
http_response_code(400);
|
||||
exit;
|
||||
}
|
||||
|
||||
} else {
|
||||
echo json_encode(['success' => false, 'message' => 'Action not found.']);
|
||||
}
|
||||
@@ -0,0 +1,183 @@
|
||||
<?php
|
||||
|
||||
ini_set('display_errors', 1);
|
||||
ini_set('display_startup_errors', 1);
|
||||
// Show all errors except deprecation notices (these come from vendor libraries
|
||||
// that aren't yet typed for newer PHP versions). Long-term fix: update
|
||||
// dependencies to versions compatible with your PHP runtime.
|
||||
error_reporting(E_ALL & ~E_DEPRECATED & ~E_USER_DEPRECATED);
|
||||
|
||||
if (!isset($baseDir)) {
|
||||
$baseDir = $_SERVER['DOCUMENT_ROOT'];
|
||||
}
|
||||
|
||||
require_once $baseDir . '/../scripts/session_functions.php';
|
||||
|
||||
ini_wkvs_session();
|
||||
|
||||
check_user_permission('wk_leitung');
|
||||
|
||||
verify_csrf();
|
||||
|
||||
$allowed_operations = ['overrite', 'add'];
|
||||
|
||||
if (!isset($_POST['operation']) || !in_array($_POST['operation'], $allowed_operations, true)) {
|
||||
http_response_code(400);
|
||||
echo 'Invalid operation.';
|
||||
exit;
|
||||
}
|
||||
|
||||
$operation = $_POST['operation'];
|
||||
|
||||
$type = 'wkl';
|
||||
|
||||
$dbconnection = require $baseDir . '/../scripts/db/db-verbindung-script.php';
|
||||
|
||||
if ($dbconnection['success'] !== true){
|
||||
echo 'Critical DB Error.';
|
||||
exit;
|
||||
}
|
||||
|
||||
require $baseDir . '/../scripts/db/db-functions.php';
|
||||
require $baseDir . '/../scripts/db/db-tables.php';
|
||||
|
||||
$allGeraete = db_select($mysqli, $db_tabelle_disziplinen, "id, name, start_index", "", [], "start_index ASC");
|
||||
$allAbt = db_select($mysqli, $db_tabelle_gruppen, "name, id, order_index", "", [], "order_index ASC");
|
||||
|
||||
$indexded_order_index_abt = array_column($allAbt, null, 'order_index');
|
||||
|
||||
$maxTurnerinnenGruppe = 8;
|
||||
|
||||
$allTurnerinnen = db_select($mysqli, $db_tabelle_teilnehmende, "id, programm, verein, name" , "", [], "programm ASC");
|
||||
|
||||
$grouped = [];
|
||||
|
||||
foreach ($allTurnerinnen as $t) {
|
||||
$grouped[strtolower($t['programm'])][$t['verein']][] = $t;
|
||||
}
|
||||
|
||||
function getMinKey(array $array): string|int {
|
||||
return array_search(min($array), $array, true);
|
||||
}
|
||||
|
||||
function arrayRiegeneiteilung($allturnerinnen, $maxTurnerinnenGruppe, $allGeraete) {
|
||||
$indabt = 1;
|
||||
$arrayAutoRiegeneinteilung = [];
|
||||
foreach ($allturnerinnen as $prog => $vereine) {
|
||||
// ABTEILUNG BERECHNEN
|
||||
$countturterinnenprog = 0;
|
||||
foreach ($vereine as $verein => $turnerinnen) {
|
||||
foreach ($turnerinnen as $ind => $turnerin) {
|
||||
$countturterinnenprog++;
|
||||
$abt = intdiv($countturterinnenprog, $maxTurnerinnenGruppe * count($allGeraete)) + $indabt;
|
||||
$allturnerinnen[$prog][$verein][$ind]['abt'] = $abt;
|
||||
$arrayAbt[$abt][$verein][] = $turnerin;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
$indabt += intdiv($countturterinnenprog - 1, $maxTurnerinnenGruppe * count($allGeraete)) + 1;
|
||||
}
|
||||
|
||||
foreach ($arrayAbt as $abt => $vereine) {
|
||||
|
||||
// AUSGLEICHEN DER GRUPPEN
|
||||
$arrayAbt = [];
|
||||
$arrayGruppen = [];
|
||||
foreach ($allGeraete as $geraet) {
|
||||
$arrayGruppen[$geraet['id']] = 0;
|
||||
}
|
||||
|
||||
$turnerinnenCount = 0;
|
||||
|
||||
foreach ($vereine as $verein => $turnerinnen) {
|
||||
$turnerinnenCount += count($turnerinnen);
|
||||
}
|
||||
|
||||
foreach ($vereine as $verein => $turnerinnen) {
|
||||
|
||||
if (count($turnerinnen) > $maxTurnerinnenGruppe || count($turnerinnen) > $turnerinnenCount / count($allGeraete)) {
|
||||
|
||||
if (count($turnerinnen) > $turnerinnenCount / count($allGeraete)) {
|
||||
$maxTurnerinnenGruppeTemp = ceil($turnerinnenCount / count($allGeraete));
|
||||
} else {
|
||||
$maxTurnerinnenGruppeTemp = $maxTurnerinnenGruppe;
|
||||
}
|
||||
// AUFTEILEN IN MEHRERE GRUPPEN
|
||||
$chunks = array_chunk($turnerinnen, $maxTurnerinnenGruppeTemp);
|
||||
foreach ($chunks as $chunk) {
|
||||
|
||||
$minKey = getMinKey($arrayGruppen);
|
||||
|
||||
$arrayGruppen[$minKey] += count($chunk);
|
||||
|
||||
foreach ($chunk as $ind =>$turnerin) {
|
||||
$arrayAutoRiegeneinteilung[$abt][$minKey][] = $turnerin;
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
$minKey = getMinKey($arrayGruppen);
|
||||
|
||||
$arrayGruppen[$minKey] += count($turnerinnen);
|
||||
|
||||
foreach ($turnerinnen as $ind =>$turnerin) {
|
||||
$arrayAutoRiegeneinteilung[$abt][$minKey][] = $turnerin;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
foreach ($arrayAutoRiegeneinteilung as $indAbt => $abt) {
|
||||
foreach ($abt as $indGeraet => $geraet) {
|
||||
foreach ($geraet as $indTurnerin => $turnerin) {
|
||||
$arrayAutoRiegeneinteilung[$indAbt][$indGeraet][$indTurnerin]['turnerin_index'] = $indTurnerin + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return $arrayAutoRiegeneinteilung;
|
||||
}
|
||||
|
||||
$arrayAutoRiegeneinteilung = arrayRiegeneiteilung($grouped, $maxTurnerinnenGruppe, $allGeraete);
|
||||
|
||||
if ($operation === 'overrite') {
|
||||
$stmt = $mysqli->prepare("DELETE FROM $db_tabelle_gruppen");
|
||||
$stmt->execute();
|
||||
$stmt->close();
|
||||
}
|
||||
|
||||
$stmt = $mysqli->prepare("DELETE FROM $db_tabelle_teilnehmende_gruppen");
|
||||
$stmt->execute();
|
||||
$stmt->close();
|
||||
|
||||
|
||||
|
||||
foreach ($arrayAutoRiegeneinteilung as $indAbt => $abt) {
|
||||
|
||||
if ($operation === 'overrite' || !isset($indexded_order_index_abt[$indAbt])) {
|
||||
$var_name = "Abteilung $indAbt";
|
||||
|
||||
$stmt = $mysqli->prepare("INSERT INTO $db_tabelle_gruppen (`name`, `order_index`) VALUES (?, ?)");
|
||||
$stmt->bind_param("si", $var_name, $indAbt);
|
||||
$stmt->execute();
|
||||
$idAbt = $stmt->insert_id;
|
||||
$stmt->close();
|
||||
} else {
|
||||
$idAbt = $indexded_order_index_abt[$indAbt]['id'];
|
||||
}
|
||||
|
||||
foreach ($abt as $indGeraet => $geraet) {
|
||||
foreach ($geraet as $indTurnerin => $turnerin) {
|
||||
$stmt = $mysqli->prepare("INSERT INTO $db_tabelle_teilnehmende_gruppen (turnerin_id, abteilung_id, geraet_id, turnerin_index) VALUES (?, ?, ?, ?)");
|
||||
$stmt->bind_param("ssss", $turnerin['id'], $idAbt, $indGeraet, $turnerin['turnerin_index']);
|
||||
$stmt->execute();
|
||||
$stmt->close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return http_response_code(200);
|
||||
@@ -0,0 +1,44 @@
|
||||
<?php
|
||||
|
||||
$baseDir = $_SERVER['DOCUMENT_ROOT'];
|
||||
|
||||
require_once $baseDir . '/../scripts/session_functions.php';
|
||||
|
||||
ini_wkvs_session();
|
||||
|
||||
check_user_permission('wk_leitung');
|
||||
|
||||
verify_csrf();
|
||||
|
||||
// Validate input
|
||||
if (!isset($_POST['abt']) || !ctype_digit($_POST['abt']) || !isset($_POST['newName'])) {
|
||||
http_response_code(406);
|
||||
exit;
|
||||
}
|
||||
|
||||
$abtInput = (int) $_POST['abt'];
|
||||
$new_name = trim($_POST['newName']);
|
||||
|
||||
$type = 'wkl';
|
||||
|
||||
$dbconnection = require $baseDir . '/../scripts/db/db-verbindung-script.php';
|
||||
|
||||
if ($dbconnection['success'] !== true){
|
||||
echo 'Critical DB Error.';
|
||||
exit;
|
||||
}
|
||||
|
||||
require $baseDir . '/../scripts/db/db-functions.php';
|
||||
require $baseDir . '/../scripts/db/db-tables.php';
|
||||
|
||||
|
||||
db_update(
|
||||
$mysqli,
|
||||
$db_tabelle_gruppen,
|
||||
['name' => $new_name],
|
||||
['id' => $abtInput]
|
||||
);
|
||||
|
||||
http_response_code(200);
|
||||
echo json_encode(['success' => true]);
|
||||
exit;
|
||||
@@ -0,0 +1,68 @@
|
||||
<?php
|
||||
|
||||
ini_set('display_errors', 1);
|
||||
ini_set('display_startup_errors', 1);
|
||||
// Show all errors except deprecation notices (these come from vendor libraries
|
||||
// that aren't yet typed for newer PHP versions). Long-term fix: update
|
||||
// dependencies to versions compatible with your PHP runtime.
|
||||
error_reporting(E_ALL & ~E_DEPRECATED & ~E_USER_DEPRECATED);
|
||||
|
||||
if (!isset($baseDir)) {
|
||||
$baseDir = $_SERVER['DOCUMENT_ROOT'];
|
||||
}
|
||||
|
||||
require_once $baseDir . '/../scripts/session_functions.php';
|
||||
|
||||
ini_wkvs_session();
|
||||
|
||||
check_user_permission('wk_leitung');
|
||||
|
||||
verify_csrf();
|
||||
|
||||
// Validate input
|
||||
if (!isset($_POST['anz_abt']) || !ctype_digit($_POST['anz_abt'])) {
|
||||
http_response_code(406);
|
||||
exit;
|
||||
}
|
||||
|
||||
$anz_abt = (int) $_POST['anz_abt'];
|
||||
|
||||
$type = 'wkl';
|
||||
|
||||
$dbconnection = require $baseDir . '/../scripts/db/db-verbindung-script.php';
|
||||
|
||||
if ($dbconnection['success'] !== true){
|
||||
echo 'Critical DB Error.';
|
||||
exit;
|
||||
}
|
||||
|
||||
require $baseDir . '/../scripts/db/db-functions.php';
|
||||
require $baseDir . '/../scripts/db/db-tables.php';
|
||||
|
||||
// Fetch existing Abteilungen
|
||||
$abts = db_select($mysqli, $db_tabelle_gruppen, '*');
|
||||
|
||||
// Delete excess Abteilungen
|
||||
foreach ($abts as $dbabt) {
|
||||
if ((int) $dbabt['order_index'] > $anz_abt) {
|
||||
db_delete($mysqli, $db_tabelle_gruppen, ['id' => $dbabt['id']]);
|
||||
}
|
||||
}
|
||||
|
||||
// Build lookup of existing names
|
||||
$existing = array_map('intval', array_column($abts, 'order_index'));
|
||||
|
||||
// Insert missing Abteilungen
|
||||
$stmt = $mysqli->prepare("INSERT INTO $db_tabelle_gruppen (`name`, `order_index`) VALUES (?, ?)");
|
||||
|
||||
for ($i = 1; $i <= $anz_abt; $i++) {
|
||||
if (!in_array($i, $existing, true)) {
|
||||
$var_name = "Abteilung $i";
|
||||
$stmt->bind_param('si', $var_name, $i);
|
||||
$stmt->execute();
|
||||
}
|
||||
}
|
||||
|
||||
$stmt->close();
|
||||
|
||||
http_response_code(201);
|
||||
@@ -0,0 +1,67 @@
|
||||
<?php
|
||||
|
||||
$baseDir = $_SERVER['DOCUMENT_ROOT'];
|
||||
|
||||
require_once $baseDir . '/../scripts/session_functions.php';
|
||||
|
||||
ini_wkvs_session();
|
||||
|
||||
check_user_permission('wk_leitung');
|
||||
|
||||
verify_csrf();
|
||||
|
||||
// Validate input
|
||||
if (!isset($_POST['abt']) || !ctype_digit($_POST['abt']) || !isset($_POST['newOrderIndex'])) {
|
||||
http_response_code(406);
|
||||
exit;
|
||||
}
|
||||
|
||||
$abtInput = (int) $_POST['abt'];
|
||||
$newOrderIndex_input = (int) $_POST['newOrderIndex'];
|
||||
|
||||
$type = 'wkl';
|
||||
|
||||
$dbconnection = require $baseDir . '/../scripts/db/db-verbindung-script.php';
|
||||
|
||||
if ($dbconnection['success'] !== true){
|
||||
echo 'Critical DB Error.';
|
||||
exit;
|
||||
}
|
||||
|
||||
require $baseDir . '/../scripts/db/db-functions.php';
|
||||
require $baseDir . '/../scripts/db/db-tables.php';
|
||||
|
||||
$allAbts = db_select($mysqli, $db_tabelle_gruppen, 'id', 'id != ? ORDER BY order_index ASC', [$abtInput]);
|
||||
$ids = array_column($allAbts, 'id');
|
||||
|
||||
$targetIndex = max(0, $newOrderIndex_input - 1);
|
||||
|
||||
array_splice($ids, $targetIndex, 0, $abtInput);
|
||||
|
||||
$mysqli->begin_transaction();
|
||||
|
||||
$one_based_indexes = [];
|
||||
|
||||
try {
|
||||
foreach ($ids as $zeroBasedIndex => $abtId) {
|
||||
$newIndex = $zeroBasedIndex + 1;
|
||||
db_update(
|
||||
$mysqli,
|
||||
$db_tabelle_gruppen,
|
||||
['order_index' => $newIndex],
|
||||
['id' => $abtId]
|
||||
);
|
||||
$one_based_indexes[$abtId] = $newIndex;
|
||||
}
|
||||
|
||||
$mysqli->commit();
|
||||
} catch (Exception $e) {
|
||||
$mysqli->rollback();
|
||||
http_response_code(500);
|
||||
echo json_encode(['success' => false, 'error' => $e->getMessage()]);
|
||||
exit;
|
||||
}
|
||||
|
||||
http_response_code(200);
|
||||
echo json_encode(['success' => true, 'newIndexes' => $one_based_indexes]);
|
||||
exit;
|
||||
@@ -0,0 +1,68 @@
|
||||
<?php
|
||||
|
||||
ini_set('display_errors', 1);
|
||||
ini_set('display_startup_errors', 1);
|
||||
// Show all errors except deprecation notices (these come from vendor libraries
|
||||
// that aren't yet typed for newer PHP versions). Long-term fix: update
|
||||
// dependencies to versions compatible with your PHP runtime.
|
||||
error_reporting(E_ALL & ~E_DEPRECATED & ~E_USER_DEPRECATED);
|
||||
|
||||
|
||||
if (!isset($baseDir)) {
|
||||
$baseDir = $_SERVER['DOCUMENT_ROOT'];
|
||||
}
|
||||
|
||||
require_once $baseDir . '/../scripts/session_functions.php';
|
||||
|
||||
ini_wkvs_session();
|
||||
|
||||
check_user_permission('wk_leitung');
|
||||
|
||||
verify_csrf();
|
||||
|
||||
// Validate input
|
||||
if (!isset($_POST['abtId']) || !ctype_digit($_POST['abtId'])) {
|
||||
http_response_code(406);
|
||||
exit;
|
||||
}
|
||||
|
||||
$abtInputId = (int) $_POST['abtId'];
|
||||
|
||||
$type = 'wkl';
|
||||
|
||||
$dbconnection = require $baseDir . '/../scripts/db/db-verbindung-script.php';
|
||||
|
||||
if ($dbconnection['success'] !== true){
|
||||
echo 'Critical DB Error.';
|
||||
exit;
|
||||
}
|
||||
|
||||
require $baseDir . '/../scripts/db/db-functions.php';
|
||||
require $baseDir . '/../scripts/db/db-tables.php';
|
||||
|
||||
// Fetch existing Abteilungen ordered by order_index
|
||||
$abts = db_select($mysqli, $db_tabelle_gruppen, '*', '', [], 'order_index ASC');
|
||||
|
||||
$indexed_abts = array_column($abts, null, 'id');
|
||||
|
||||
$deleteIndex = $indexed_abts[$abtInputId]['order_index'] ?? null;
|
||||
|
||||
if ($deleteIndex === null) {
|
||||
http_response_code(406);
|
||||
exit;
|
||||
}
|
||||
|
||||
// Delete selected row
|
||||
db_delete($mysqli, $db_tabelle_gruppen, ['id' => $abtInputId]);
|
||||
|
||||
// Reindex subsequent rows
|
||||
for ($i = $deleteIndex + 1; $i < count($abts); $i++) {
|
||||
db_update(
|
||||
$mysqli,
|
||||
$db_tabelle_gruppen,
|
||||
['order_index' => (int)$abts[$i]['order_index'] - 1],
|
||||
['id' => (int)$abts[$i]['id']]
|
||||
);
|
||||
}
|
||||
|
||||
http_response_code(201);
|
||||
@@ -0,0 +1,161 @@
|
||||
<?php
|
||||
|
||||
ini_set("display_errors", 1);
|
||||
ini_set("display_startup_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();
|
||||
|
||||
$type = 'wkl';
|
||||
|
||||
$dbconnection = require $baseDir . '/../scripts/db/db-verbindung-script.php';
|
||||
|
||||
if ($dbconnection['success'] !== true) {
|
||||
echo 'Critical DB Error.';
|
||||
exit;
|
||||
}
|
||||
|
||||
require $baseDir . '/../scripts/db/db-tables.php';
|
||||
require $baseDir . '/../scripts/db/db-functions.php';
|
||||
|
||||
$turnerin_ids = $_POST['turnerin_ids'] ?? [];
|
||||
$neu_abteilung_id = intval($_POST['neuAbteilungId'] ?? 0);
|
||||
$neu_geraet_id = intval($_POST['neuGeraetId'] ?? 0);
|
||||
$alt_abteilung_id = intval($_POST['altAbteilungId'] ?? 0);
|
||||
$alt_geraet_id = intval($_POST['altGeraetId'] ?? 0);
|
||||
$neu_first_index = intval($_POST['neuFirstIndex'] ?? 0);
|
||||
|
||||
// Resolve Abteilung ID
|
||||
if ($neu_abteilung_id < 1) {
|
||||
http_response_code(400);
|
||||
echo json_encode(['success' => false, 'message' => 'Keine Abteilungs ID angegeben.']);
|
||||
exit;
|
||||
} else {
|
||||
$stmt = $mysqli->prepare("SELECT 1 FROM $db_tabelle_gruppen WHERE id = ?");
|
||||
$stmt->bind_param("i", $neu_abteilung_id);
|
||||
$stmt->execute();
|
||||
if (!$stmt->get_result()->fetch_assoc()) {
|
||||
http_response_code(400);
|
||||
echo json_encode(['success' => false, 'message' => 'Invalide Abteilungs ID angegeben.']);
|
||||
exit;
|
||||
}
|
||||
$stmt->close();
|
||||
}
|
||||
|
||||
// Resolve Gerät ID
|
||||
if ($neu_geraet_id < 1) {
|
||||
http_response_code(400);
|
||||
echo json_encode(['success' => false, 'message' => 'Keine neue Geräte ID angegeben.']);
|
||||
exit;
|
||||
} else {
|
||||
$stmt = $mysqli->prepare("SELECT 1 FROM $db_tabelle_disziplinen WHERE id = ?");
|
||||
$stmt->bind_param("i", $neu_geraet_id);
|
||||
$stmt->execute();
|
||||
if (!$stmt->get_result()->fetch_assoc()) {
|
||||
http_response_code(400);
|
||||
echo json_encode(['success' => false, 'message' => 'Invalide Geräte ID angegeben.']);
|
||||
exit;
|
||||
}
|
||||
$stmt->close();
|
||||
}
|
||||
|
||||
function arrayshift($v) {
|
||||
return intval($v) + 1;
|
||||
}
|
||||
|
||||
$array_ids = array_map('intval', $turnerin_ids);
|
||||
|
||||
$mysqli->begin_transaction();
|
||||
|
||||
try {
|
||||
// 1. Move/Upsert the specific gymnasts into the new group
|
||||
$stmt = $mysqli->prepare("
|
||||
INSERT INTO $db_tabelle_teilnehmende_gruppen (turnerin_id, abteilung_id, geraet_id)
|
||||
VALUES (?, ?, ?)
|
||||
ON DUPLICATE KEY UPDATE abteilung_id = VALUES(abteilung_id), geraet_id = VALUES(geraet_id)
|
||||
");
|
||||
|
||||
foreach ($array_ids as $id) {
|
||||
$stmt->bind_param("iii", $id, $neu_abteilung_id, $neu_geraet_id);
|
||||
$stmt->execute();
|
||||
}
|
||||
$stmt->close();
|
||||
|
||||
// 2. Reorder the old group to fill any gaps left by the moved gymnasts
|
||||
|
||||
if ($alt_abteilung_id !== 0 && $alt_geraet_id !== 0 && ($alt_abteilung_id !== $neu_abteilung_id || $alt_geraet_id !== $neu_geraet_id)) {
|
||||
$old_group_rows_zero_based = db_select($mysqli, $db_tabelle_teilnehmende_gruppen, "turnerin_id",
|
||||
"abteilung_id = ? AND geraet_id = ?", [$alt_abteilung_id, $alt_geraet_id], "turnerin_index ASC");
|
||||
|
||||
$updOld = $mysqli->prepare("UPDATE $db_tabelle_teilnehmende_gruppen SET `turnerin_index` = ? WHERE `turnerin_id` = ?");
|
||||
|
||||
$old_group_rows = [];
|
||||
|
||||
foreach ($old_group_rows_zero_based as $i => $row) {
|
||||
$new_idx = $i + 1; // Start indexing at 1
|
||||
$updOld->bind_param("ii", $new_idx, $row['turnerin_id']);
|
||||
$updOld->execute();
|
||||
$old_group_rows[$row['turnerin_id']] = $new_idx;
|
||||
}
|
||||
$updOld->close();
|
||||
}
|
||||
|
||||
// 3. Fetch all gymnasts now in this group to determine final order
|
||||
// Order by start_index so we preserve the existing relative order of gymnasts already there
|
||||
$rows = db_select(
|
||||
$mysqli,
|
||||
$db_tabelle_teilnehmende_gruppen,
|
||||
"turnerin_id",
|
||||
"abteilung_id = ? AND geraet_id = ?",
|
||||
[$neu_abteilung_id, $neu_geraet_id],
|
||||
"turnerin_index ASC"
|
||||
);
|
||||
|
||||
$current_ids = array_column($rows, 'turnerin_id');
|
||||
|
||||
// 4. Reconstruct the order: [Remaining ones before index] -> [Prioritized] -> [Remaining ones after index]
|
||||
$remaining_ids = array_values(array_diff($current_ids, $array_ids));
|
||||
|
||||
$final_order_zero_based = [];
|
||||
// Adjust index to 0-based for array manipulation
|
||||
$target_pos = max(0, $neu_first_index - 1);
|
||||
|
||||
// Splice the prioritized IDs into the remaining list at the target position
|
||||
array_splice($remaining_ids, $target_pos, 0, $array_ids);
|
||||
$final_order_zero_based = $remaining_ids;
|
||||
|
||||
$final_order = [];
|
||||
|
||||
// 5. Update the database with the new continuous indices
|
||||
$updStmt = $mysqli->prepare("UPDATE $db_tabelle_teilnehmende_gruppen SET `turnerin_index` = ? WHERE `turnerin_id` = ?");
|
||||
|
||||
foreach ($final_order_zero_based as $array_index => $t_id) {
|
||||
$actual_index = $array_index + 1;
|
||||
$updStmt->bind_param("ii", $actual_index, $t_id);
|
||||
$updStmt->execute();
|
||||
$final_order[$t_id] = $actual_index;
|
||||
}
|
||||
$updStmt->close();
|
||||
|
||||
$mysqli->commit();
|
||||
http_response_code(200);
|
||||
echo json_encode([
|
||||
'success' => true,
|
||||
'old_new_start_indexes' => $old_group_rows ?? null,
|
||||
'new_new_start_indexes' => $final_order
|
||||
]);
|
||||
|
||||
} catch (Throwable $e) {
|
||||
$mysqli->rollback();
|
||||
http_response_code(500);
|
||||
echo json_encode(['success' => false]);
|
||||
}
|
||||
@@ -0,0 +1,188 @@
|
||||
<?php
|
||||
|
||||
use Shuchkin\SimpleXLSX;
|
||||
|
||||
header('Content-Type: application/json');
|
||||
|
||||
if (!isset($baseDir))
|
||||
$baseDir = $_SERVER['DOCUMENT_ROOT'];
|
||||
|
||||
require_once $baseDir . '/../scripts/session_functions.php';
|
||||
|
||||
ini_wkvs_session();
|
||||
|
||||
check_user_permission('trainer');
|
||||
|
||||
verify_csrf();
|
||||
|
||||
require $baseDir . '/../scripts/db/db-functions.php';
|
||||
require $baseDir . '/../scripts/db/db-tables.php';
|
||||
|
||||
require $baseDir . '/../composer/vendor/autoload.php';
|
||||
|
||||
$type = 'tr';
|
||||
|
||||
$dbconnection = require $baseDir . '/../scripts/db/db-verbindung-script.php';
|
||||
|
||||
if ($dbconnection['success'] !== true) {
|
||||
echo 'Critical DB Error.';
|
||||
exit;
|
||||
}
|
||||
|
||||
if ($_FILES['xlsx_file']['error'] !== UPLOAD_ERR_OK) {
|
||||
echo json_encode(['success' => false, 'message' => 'Fehler beim Datei-Upload']);
|
||||
http_response_code(400);
|
||||
exit;
|
||||
}
|
||||
|
||||
$tmpName = $_FILES['xlsx_file']['tmp_name'];
|
||||
|
||||
if (!class_exists('Shuchkin\\SimpleXLSX')) {
|
||||
echo json_encode(['success' => false, 'message' => 'Fehler beim Laden des Plugins']);
|
||||
http_response_code(400);
|
||||
exit;
|
||||
}
|
||||
|
||||
$xlsx = SimpleXLSX::parse($tmpName);
|
||||
|
||||
$rows = $xlsx->rows();
|
||||
|
||||
$vereine_rows = db_select($mysqli, $db_tabelle_vereine, 'verein', '', [], 'verein ASC');
|
||||
$vereine = array_column($vereine_rows, 'verein');
|
||||
|
||||
if (count($rows) < 2) {
|
||||
echo json_encode(['success' => false, 'message' => 'Die Excel-Datei muss mindestens einen Eintrag enthalten']);
|
||||
http_response_code(400);
|
||||
exit;
|
||||
}
|
||||
|
||||
$selectedverein = $_SESSION['selectedFreigabeTrainer'] ?? '';
|
||||
|
||||
$isAdmin = $selectedverein === "admin";
|
||||
|
||||
$columnMap = [
|
||||
'Nachname' => 'name',
|
||||
'Vorname' => 'vorname',
|
||||
'Geburtsdatum' => 'geburtsdatum',
|
||||
'Programm' => 'programm'
|
||||
];
|
||||
|
||||
if ($isAdmin) {
|
||||
$columnMap['Verein'] = 'verein';
|
||||
}
|
||||
|
||||
$header_row = false;
|
||||
|
||||
foreach ($rows as $row_index => $row) {
|
||||
$formated_row = array_map('trim', $row);
|
||||
|
||||
$columnIndexes = [];
|
||||
|
||||
$column_not_found = false;
|
||||
|
||||
foreach ($columnMap as $excelHeader => $dbColumn) {
|
||||
$index = array_search($excelHeader, $formated_row);
|
||||
if ($index === false) {
|
||||
$column_not_found = true;
|
||||
break;
|
||||
}
|
||||
$columnIndexes[$dbColumn] = $index;
|
||||
}
|
||||
|
||||
if ($column_not_found) {
|
||||
continue;
|
||||
} else {
|
||||
$header_row = $row_index;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!$header_row) {
|
||||
echo json_encode(['success' => false, 'message' => 'Es wurde keine vollständige Header-Zeile gefunden']);
|
||||
http_response_code(400);
|
||||
exit;
|
||||
}
|
||||
|
||||
for ($i = 0; $i <= (max($header_row, 1)); $i++) {
|
||||
unset($rows[$i]);
|
||||
}
|
||||
|
||||
$programme_db = db_select($mysqli, $db_tabelle_kategorien, 'programm', 'aktiv = ?', [1], 'programm ASC');
|
||||
|
||||
$programme = array_column($programme_db, 'programm');
|
||||
|
||||
$mysqli->begin_transaction();
|
||||
|
||||
$columns = ['name', 'vorname', 'geburtsdatum', 'programm', 'verein'];
|
||||
|
||||
$set = implode(', ', array_map(fn($col) => "$col = ?", $columns));
|
||||
|
||||
$sql = "INSERT INTO $db_tabelle_teilnehmende SET $set";
|
||||
|
||||
$stmt = $mysqli->prepare($sql);
|
||||
|
||||
$types = str_repeat('s', count($columns));
|
||||
|
||||
try {
|
||||
foreach ($rows as $row) {
|
||||
if (!array_filter($row))
|
||||
continue;
|
||||
|
||||
$data = [];
|
||||
foreach ($columnIndexes as $dbCol => $excel_column_index) {
|
||||
$data[$dbCol] = isset($row[$excel_column_index]) ? trim($row[$excel_column_index]) : null;
|
||||
}
|
||||
|
||||
if (!$isAdmin) {
|
||||
$data['verein'] = $selectedverein;
|
||||
} else {
|
||||
if (!in_array($data['verein'], $vereine)) {
|
||||
echo json_encode(['success' => false, 'message' => $data['verein'] . " existiert nicht im System"]);
|
||||
http_response_code(400);
|
||||
exit;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
$raw = trim($data['geburtsdatum']);
|
||||
|
||||
$temp = DateTime::createFromFormat('d.m.Y', $raw);
|
||||
|
||||
if ($temp && $temp->format('d.m.Y') === $raw) {
|
||||
$data['geburtsdatum'] = $temp->format('Y-m-d');
|
||||
} else {
|
||||
$data['geburtsdatum'] = substr($raw, 0, 10);
|
||||
}
|
||||
|
||||
|
||||
if (is_array($programme) && !(in_array($data['programm'], $programme))) {
|
||||
echo json_encode(['success' => false, 'message' => "Programm '{$data['programm']}' nicht valide bei " . $personEinzahl . " " . $data['name'] . " " . $data['vorname']]);
|
||||
http_response_code(400);
|
||||
exit;
|
||||
}
|
||||
|
||||
$values = array_values($data);
|
||||
|
||||
$stmt->bind_param($types, ...$values);
|
||||
|
||||
if (!$stmt->execute()) {
|
||||
echo json_encode(['success' => false, 'message' => "Fehler beim Einfügen eines Datensatzes"]);
|
||||
http_response_code(400);
|
||||
exit;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
$stmt->close();
|
||||
|
||||
$mysqli->commit();
|
||||
} catch (Exception $e) {
|
||||
$mysqli->rollback();
|
||||
echo json_encode(['success' => false, 'message' => "Fehler beim Einfügen der Datensätze"]);
|
||||
http_response_code(400);
|
||||
exit;
|
||||
}
|
||||
|
||||
echo json_encode(['success' => true, 'message' => count($rows) . " Datensätze importiert"]);
|
||||
http_response_code(200);
|
||||
exit;
|
||||
@@ -0,0 +1,201 @@
|
||||
<?php
|
||||
|
||||
if (!isset($baseDir)) $baseDir = $_SERVER['DOCUMENT_ROOT'];
|
||||
|
||||
require_once $baseDir . '/../scripts/session_functions.php';
|
||||
|
||||
ini_wkvs_session();
|
||||
|
||||
check_user_permission('trainer');
|
||||
|
||||
verify_csrf();
|
||||
|
||||
ini_set('display_errors', 1);
|
||||
|
||||
$type = 'tr';
|
||||
|
||||
$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';
|
||||
|
||||
$ids = isset($_POST['ids']) ? htmlspecialchars(strip_tags(trim($_POST['ids'])), ENT_QUOTES) : '';
|
||||
$user = intval($_SESSION['user_id_trainer']);
|
||||
|
||||
|
||||
$arrayids = array_filter(array_map('trim', explode(',', $ids)));
|
||||
|
||||
if (!$arrayids || !is_array($arrayids) || count($arrayids) === 0) {
|
||||
http_response_code(422);
|
||||
exit;
|
||||
}
|
||||
|
||||
if ($user <= 0) {
|
||||
http_response_code(422);
|
||||
exit;
|
||||
}
|
||||
|
||||
$placeholders = [];
|
||||
$values = [];
|
||||
$types = '';
|
||||
|
||||
foreach ($arrayids as $id) {
|
||||
if ($id <= 0) {
|
||||
http_response_code(422);
|
||||
exit;
|
||||
}
|
||||
|
||||
$sql = "SELECT bezahlt FROM $db_tabelle_teilnehmende WHERE id = ?";
|
||||
|
||||
$checkstmt = $mysqli->prepare($sql);
|
||||
$checkstmt->bind_param("i", $id);
|
||||
if (!$checkstmt->execute()) {
|
||||
http_response_code(500);
|
||||
exit;
|
||||
}
|
||||
|
||||
$checkstmt->bind_result($bezahlt);
|
||||
|
||||
$checkstmt->fetch();
|
||||
|
||||
$checkstmt->close();
|
||||
|
||||
$sql2 = "SELECT COUNT(*) FROM $db_tabelle_warenkorb_startgebueren WHERE user_id = ? AND item_id = ?";
|
||||
|
||||
$checkstmt2 = $mysqli->prepare($sql2);
|
||||
$checkstmt2->bind_param("ii", $user, $id);
|
||||
|
||||
if (!$checkstmt2->execute()) {
|
||||
http_response_code(500);
|
||||
exit;
|
||||
}
|
||||
|
||||
// Bind the result
|
||||
$checkstmt2->bind_result($countProd);
|
||||
$checkstmt2->fetch(); // fetch into $countProd
|
||||
|
||||
$checkstmt2->close();
|
||||
|
||||
if (isset($bezahlt) && in_array($bezahlt, [1,2]) && $countProd === 0) {
|
||||
$placeholders[] = '(?, ?)';
|
||||
$types .= 'ii';
|
||||
$values[] = $user;
|
||||
$values[] = $id;
|
||||
}
|
||||
}
|
||||
|
||||
if ($values === [] || $placeholders === [] || $types === '') {
|
||||
http_response_code(406);
|
||||
exit;
|
||||
}
|
||||
|
||||
$sql = "INSERT INTO `$db_tabelle_warenkorb_startgebueren` (user_id, item_id) VALUES " . implode(',', $placeholders);
|
||||
|
||||
$stmt = $mysqli->prepare($sql);
|
||||
|
||||
$stmt->bind_param($types, ...$values);
|
||||
|
||||
$success = $stmt->execute();
|
||||
|
||||
$stmt->close();
|
||||
|
||||
if (!$success) {
|
||||
http_response_code(500);
|
||||
exit;
|
||||
}
|
||||
|
||||
// Prepare statements once
|
||||
$sSql = "SELECT `name`, `vorname`, `programm`, `betrag_bezahlt`, `verein`
|
||||
FROM $db_tabelle_teilnehmende
|
||||
WHERE id = ?";
|
||||
|
||||
$kats = db_select($mysqli, $db_tabelle_kategorien, '`preis`, `programm`');
|
||||
|
||||
$indexed_kat_preise = array_column($kats, 'preis', 'programm');
|
||||
|
||||
$vereine = db_select($mysqli, $db_tabelle_vereine, '`verein`, `konto`, `id`');
|
||||
|
||||
$indexed_vereine_kontos = array_column($vereine, 'konto', 'verein');
|
||||
|
||||
$indexed_vereine = array_column($vereine, 'id', 'verein');
|
||||
|
||||
$sStmt = $mysqli->prepare($sSql);
|
||||
|
||||
$id = null;
|
||||
|
||||
$sStmt->bind_param("i", $id);
|
||||
|
||||
$array_response_gebueren = [];
|
||||
$array_response_abzuege = [];
|
||||
|
||||
$array_vereine = [];
|
||||
|
||||
foreach ($arrayids as $id) {
|
||||
|
||||
// --- Turnerinnen ---
|
||||
|
||||
if (!$sStmt->execute()) {
|
||||
http_response_code(500);
|
||||
exit;
|
||||
}
|
||||
|
||||
$row = $sStmt->get_result()->fetch_assoc();
|
||||
|
||||
if (!$row || !isset($row['programm'])) {
|
||||
http_response_code(500);
|
||||
exit;
|
||||
}
|
||||
|
||||
$kat = $row['programm'];
|
||||
|
||||
if (!isset($indexed_kat_preise[$kat])) {
|
||||
echo json_encode(['success' => false, 'message' => 'Der Preis einer Kat ist nicht definiert. Kat: '. $kat ]);
|
||||
http_response_code(500);
|
||||
exit;
|
||||
}
|
||||
|
||||
$betrag_bezahlt = (float) $row['betrag_bezahlt'] ?? 0;
|
||||
|
||||
$preis = ((float) $indexed_kat_preise[$kat]) - $betrag_bezahlt;
|
||||
|
||||
$array_vereine[$row['verein']] ??= 0.00;
|
||||
|
||||
$array_vereine[$row['verein']] += $preis;
|
||||
|
||||
$formated_preis = number_format($preis, 2, '.', "'");
|
||||
|
||||
// --- Build response ---
|
||||
$array_response_gebueren[$id] = [
|
||||
'turnerinName' => $row['name'],
|
||||
'turnerinVorname' => $row['vorname'],
|
||||
'programm' => $row['programm'],
|
||||
'preis' => $preis,
|
||||
'verein' => $row['verein'],
|
||||
'formated_preis' => $formated_preis,
|
||||
'appendix' => ($betrag_bezahlt !== 0.00) ? ' (Red.)' : ''
|
||||
];
|
||||
}
|
||||
|
||||
foreach ($array_vereine as $verein => $betrag) {
|
||||
$array_response_abzuege[$verein]['betrag'] = $betrag;
|
||||
$array_response_abzuege[$verein]['max'] = $indexed_vereine_kontos[$verein] ?? 0;
|
||||
$array_response_abzuege[$verein]['vereinId'] = $indexed_vereine[$verein];
|
||||
}
|
||||
|
||||
// Close statements once
|
||||
$sStmt->close();
|
||||
|
||||
|
||||
http_response_code(200);
|
||||
echo json_encode([
|
||||
'success' => true,
|
||||
'message' => 'Zum Warenkorb hinzugefügt',
|
||||
'arrayGebueren' => $array_response_gebueren,
|
||||
'arrayAbzuege' => $array_response_abzuege
|
||||
]);
|
||||
exit;
|
||||
@@ -0,0 +1,91 @@
|
||||
<?php
|
||||
|
||||
header('Content-Type: application/json');
|
||||
|
||||
if (!isset($baseDir))
|
||||
$baseDir = $_SERVER['DOCUMENT_ROOT'];
|
||||
|
||||
require_once $baseDir . '/../scripts/session_functions.php';
|
||||
|
||||
ini_wkvs_session();
|
||||
|
||||
check_user_permission('trainer');
|
||||
|
||||
verify_csrf();
|
||||
|
||||
require $baseDir . '/../scripts/db/db-functions.php';
|
||||
require $baseDir . '/../scripts/db/db-tables.php';
|
||||
|
||||
$type = 'tr';
|
||||
|
||||
$dbconnection = require $baseDir . '/../scripts/db/db-verbindung-script.php';
|
||||
|
||||
if ($dbconnection['success'] !== true) {
|
||||
echo 'Critical DB Error.';
|
||||
exit;
|
||||
}
|
||||
|
||||
$personen_ids_json = $_POST['personen_ids'] ?? '';
|
||||
|
||||
$personen_ids = json_decode($personen_ids_json) ?? [];
|
||||
|
||||
$personen_ids = !is_array($personen_ids) ? array(intval($personen_ids)) : array_map('intval', $personen_ids);
|
||||
|
||||
if (count($personen_ids) < 1) {
|
||||
echo json_encode(['success' => false, 'message' => "Keine Personen angegeben"]);
|
||||
http_response_code(422);
|
||||
exit;
|
||||
}
|
||||
|
||||
$userid = intval($_SESSION['user_id_trainer'] ?? 0);
|
||||
$arrayfreigaben = [];
|
||||
|
||||
if ($userid > 0) {
|
||||
$freigabe_json = db_get_var($mysqli, "SELECT freigabe FROM $db_tabelle_intern_benutzende WHERE id = ?", [$userid]);
|
||||
|
||||
if (is_string($freigabe_json) && $freigabe_json !== '') {
|
||||
$arrayfreigaben = json_decode($freigabe_json, true) ?: [];
|
||||
|
||||
$arrayfreigaben = $arrayfreigaben['freigabenTrainer'] ?? [];
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($arrayfreigaben)) {
|
||||
$selectedverein = $_SESSION['selectedFreigabeTrainer'] ?? '';
|
||||
|
||||
if (!in_array($selectedverein, $arrayfreigaben)) {
|
||||
$selectedverein = $arrayfreigaben[0];
|
||||
$_SESSION['selectedFreigabeTrainer'] = $selectedverein;
|
||||
}
|
||||
}
|
||||
|
||||
$isAdmin = $selectedverein === "admin";
|
||||
|
||||
$mysqli->begin_transaction();
|
||||
|
||||
try {
|
||||
if (!$isAdmin) {
|
||||
$stmt = $mysqli->prepare("DELETE FROM $db_tabelle_teilnehmende WHERE `id` = ? AND `verein` = ?");
|
||||
foreach ($personen_ids as $s_id) {
|
||||
$stmt->bind_param("is", $s_id, $selectedverein);
|
||||
$stmt->execute();
|
||||
}
|
||||
} else {
|
||||
$stmt = $mysqli->prepare("DELETE FROM $db_tabelle_teilnehmende WHERE `id` = ?");
|
||||
foreach ($personen_ids as $s_id) {
|
||||
$stmt->bind_param("i", $s_id);
|
||||
$stmt->execute();
|
||||
}
|
||||
}
|
||||
$stmt->close();
|
||||
$mysqli->commit();
|
||||
} catch (Exception $e) {
|
||||
$mysqli->rollback();
|
||||
echo json_encode(['success' => false, 'message' => "Datenbankfehler beim Löschen"]);
|
||||
http_response_code(500);
|
||||
exit;
|
||||
}
|
||||
|
||||
echo json_encode(['success' => true, 'message' => count($personen_ids) . " Datensätze gelöscht"]);
|
||||
http_response_code(200);
|
||||
exit;
|
||||
@@ -0,0 +1,670 @@
|
||||
<?php
|
||||
|
||||
use Sprain\SwissQrBill\PaymentPart\Output\DisplayOptions;
|
||||
use Sprain\SwissQrBill\PaymentPart\Output\TcPdfOutput\TcPdfOutput;
|
||||
use TCPDF;
|
||||
use Sprain\SwissQrBill as QrBill;
|
||||
|
||||
header('Content-Type: application/json');
|
||||
|
||||
ini_set('display_errors', 1);
|
||||
ini_set('display_startup_errors', 1);
|
||||
error_reporting(E_ALL);
|
||||
|
||||
if (!isset($baseDir)) $baseDir = $_SERVER['DOCUMENT_ROOT'];
|
||||
|
||||
require_once $baseDir . '/../scripts/session_functions.php';
|
||||
|
||||
ini_wkvs_session();
|
||||
|
||||
check_user_permission('trainer');
|
||||
|
||||
verify_csrf();
|
||||
|
||||
if (!isset($_POST['name']) || !isset($_POST['vorname']) || !isset($_POST['strasse']) || !isset($_POST['plz']) || !isset($_POST['ort'])) {
|
||||
http_response_code(400);
|
||||
echo json_encode(['success' => false, 'message' => 'Daten für die Rechnungserstellung fehlen.']);
|
||||
exit;
|
||||
}
|
||||
|
||||
|
||||
function generateInvoiceNumber() : int {
|
||||
return random_int(10000000, 99999999);
|
||||
}
|
||||
|
||||
$orderType = 'Startgebühr';
|
||||
|
||||
function createInvoice(mysqli $conn, $db_tabelle_verbuchte_startgebueren, $orderType, $userId, $jsonIds, $used_verein_konten, $order_status): int
|
||||
{
|
||||
$maxRetries = 25;
|
||||
|
||||
for ($i = 0; $i < $maxRetries; $i++) {
|
||||
|
||||
$invoiceNumber = generateInvoiceNumber();
|
||||
|
||||
|
||||
$stmt = $conn->prepare(
|
||||
"INSERT INTO `$db_tabelle_verbuchte_startgebueren` (order_id, order_type, user_id, item_ids, used_verein_konten, order_status)
|
||||
VALUES (?, ?, ?, ?, ?, ?)"
|
||||
);
|
||||
|
||||
$stmt->bind_param(
|
||||
"isissi",
|
||||
$invoiceNumber, $orderType, $userId, $jsonIds, $used_verein_konten, $order_status
|
||||
);
|
||||
|
||||
if ($stmt->execute()) {
|
||||
return $invoiceNumber;
|
||||
}
|
||||
|
||||
// Duplicate key error → retry
|
||||
if ($conn->errno !== 1062) {
|
||||
throw new RuntimeException(
|
||||
"Database error ({$conn->errno}): {$conn->error}"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
throw new RuntimeException('Failed to generate unique invoice number');
|
||||
}
|
||||
|
||||
$userId = $_SESSION['user_id_trainer'];
|
||||
|
||||
$type = 'tr';
|
||||
|
||||
$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 . '/../composer/vendor/autoload.php';
|
||||
|
||||
$sql = "SELECT
|
||||
bi.id AS basket_id,
|
||||
bi.item_id,
|
||||
p.programm AS programm_name,
|
||||
p.preis,
|
||||
bi.id,
|
||||
t.betrag_bezahlt
|
||||
FROM $db_tabelle_warenkorb_startgebueren bi
|
||||
LEFT JOIN $db_tabelle_teilnehmende t ON bi.item_id = t.id
|
||||
LEFT JOIN $db_tabelle_kategorien p ON p.programm = t.programm
|
||||
WHERE bi.user_id = ?";
|
||||
|
||||
$stmt = $mysqli->prepare($sql);
|
||||
$stmt->bind_param("i", $userId);
|
||||
$stmt->execute();
|
||||
$result = $stmt->get_result();
|
||||
$rows = $result->fetch_all(MYSQLI_ASSOC);
|
||||
|
||||
if (!$rows || count($rows) < 1) {
|
||||
http_response_code(422);
|
||||
exit;
|
||||
}
|
||||
|
||||
$used_konten_json = $_POST['usedKonten'] ?? '{}';
|
||||
|
||||
$used_konten = json_decode($used_konten_json, true) ?? [];
|
||||
|
||||
$konten_save = [];
|
||||
|
||||
if (count($used_konten) > 0) {
|
||||
$db_konten = db_select($mysqli, $db_tabelle_vereine, '`verein`, `konto`');
|
||||
$indexed_konten = array_column($db_konten, 'konto', 'verein');
|
||||
|
||||
$db_user_permissions = db_get_var($mysqli, "SELECT `freigabe` FROM $db_tabelle_intern_benutzende WHERE `id` = ?", [$userId]);
|
||||
|
||||
$array_permissions = json_decode($db_user_permissions ?? '', true) ?? [];
|
||||
|
||||
$trainer_permissions = $array_permissions['freigabenTrainer'] ?? [];
|
||||
|
||||
foreach ($used_konten as $verein => $betrag) {
|
||||
if (!isset($indexed_konten[$verein])) {
|
||||
http_response_code(400);
|
||||
echo json_encode(['success' => false, 'message' => 'Invalider Verein ' . htmlspecialchars($verein)]);
|
||||
exit;
|
||||
} elseif (!isset($trainer_permissions[$verein]) && !in_array('admin', $trainer_permissions)) {
|
||||
http_response_code(403);
|
||||
echo json_encode(['success' => false, 'message' => 'Keine Berechtigung auf den Zugriff des Kontos des Vereins ' . htmlspecialchars($verein)]);
|
||||
exit;
|
||||
} elseif ((float) $indexed_konten[$verein] < (float) $betrag) {
|
||||
http_response_code(403);
|
||||
echo json_encode(['success' => false, 'message' => 'Der Abzug des Vereins ' . htmlspecialchars($verein) . ' übersteigt das Guthaben dieses Vereins.']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$konten_save[$verein] = (float) $betrag;
|
||||
}
|
||||
}
|
||||
|
||||
$used_verein_konten = json_encode($konten_save);
|
||||
|
||||
$preis = 0;
|
||||
|
||||
$ids = [];
|
||||
|
||||
foreach ($rows as $r) {
|
||||
$r_preis = max(floatval($r['preis']) - floatval($r['betrag_bezahlt']), 0);
|
||||
$preis += $r_preis;
|
||||
$ids[$r['item_id']] = $r_preis;
|
||||
}
|
||||
|
||||
$preis = min($preis - array_sum($konten_save), 0);
|
||||
|
||||
$jsonIds = json_encode($ids);
|
||||
|
||||
$all_teilnehmende_ids = array_keys($ids);
|
||||
|
||||
if (json_last_error() !== JSON_ERROR_NONE) {
|
||||
http_response_code(400);
|
||||
echo json_encode(['success' => false, 'message' => 'Invalid JSON']);
|
||||
exit;
|
||||
}
|
||||
|
||||
// --- Check for existing open order ---
|
||||
$order_id = db_get_var($mysqli, "SELECT order_id FROM `$db_tabelle_verbuchte_startgebueren` WHERE user_id = ? AND order_status = 0 LIMIT 1", [$userId]);
|
||||
|
||||
$orderId = null;
|
||||
|
||||
if ($order_id === null) {
|
||||
// --- INSERT new order ---
|
||||
$stmt->close();
|
||||
|
||||
$order_status = 0;
|
||||
|
||||
$new_id = createInvoice($mysqli, $db_tabelle_verbuchte_startgebueren, $orderType, $userId, $jsonIds, $used_verein_konten, $order_status);
|
||||
|
||||
$orderId = $new_id;
|
||||
} else {
|
||||
// --- UPDATE existing order ---
|
||||
$stmt->close();
|
||||
|
||||
$orderId = $order_id;
|
||||
|
||||
$sql = "
|
||||
UPDATE `$db_tabelle_verbuchte_startgebueren`
|
||||
SET item_ids = ?, used_verein_konten = ?
|
||||
WHERE order_id = ?
|
||||
";
|
||||
|
||||
$stmt = $mysqli->prepare($sql);
|
||||
$stmt->bind_param("ssi", $jsonIds, $used_verein_konten, $order_id);
|
||||
$stmt->execute();
|
||||
}
|
||||
|
||||
$keys = [
|
||||
'wkName', 'rechnungenName', 'rechnungenVorname', 'rechnungenStrasse',
|
||||
'rechnungenHausnummer', 'rechnungenPostleitzahl', 'rechnungenOrt',
|
||||
'rechnungenIBAN', 'linkWebseite', 'rechnungenPostversand', 'rechnungenPostversandKosten'
|
||||
];
|
||||
|
||||
$placeholders = implode(',', array_fill(0, count($keys), '?'));
|
||||
|
||||
$stmt = $mysqli->prepare("SELECT `name`, `value` FROM $db_tabelle_var WHERE `name` IN ($placeholders)");
|
||||
$stmt->bind_param(str_repeat('s', count($keys)), ...$keys);
|
||||
$stmt->execute();
|
||||
|
||||
|
||||
$variables = array_column($stmt->get_result()->fetch_all(MYSQLI_ASSOC), 'value', 'name');
|
||||
|
||||
$kats = db_select($mysqli, $db_tabelle_kategorien, '`programm`, `preis`');
|
||||
|
||||
$indexed_kats_preis = array_column($kats, 'preis', 'programm');
|
||||
|
||||
$current_wk_id = (int) db_get_variable($mysqli, $db_tabelle_var, ['current_wk_id']) ?: 0;
|
||||
|
||||
$current_wk_name = db_get_var($mysqli, "SELECT `name` FROM $db_tabelle_wettkaempfe WHERE `id` = ? LIMIT 1", [$current_wk_id]) ?: ($wkName . ' ' . $current_year);
|
||||
class MYPDF extends TCPDF
|
||||
{
|
||||
public $columns;
|
||||
public $headerBottomY = 0;
|
||||
public $firstPageDone = false; // track first page
|
||||
public $abzuegeHeader = false; // track first page
|
||||
public $printfooter;
|
||||
|
||||
public function Header()
|
||||
{
|
||||
// Logo always
|
||||
$image_file = $_SERVER['DOCUMENT_ROOT'] . '/intern/img/logo-normal.png';
|
||||
$this->Image($image_file, 180, 15, 15);
|
||||
|
||||
// Table header only for subsequent pages
|
||||
if ($this->abzuegeHeader) {
|
||||
// Use same top margin as table
|
||||
$this->SetY(35); // or another fixed Y
|
||||
$this->SetX(15);
|
||||
$this->SetFont('GoogleSansFlex-Regular', '', 11);
|
||||
$this->setCellPaddings(2, 0, 2, 0);
|
||||
$this->Cell($this->columns['name']['max_width'] + $this->columns['programm']['max_width'] + $this->columns['verein']['max_width'], 10, 'Beschreibung', 0, 0, 'L');
|
||||
$this->Cell($this->columns['preis']['max_width'], 10, 'Abzug', 0, 0, 'C');
|
||||
$this->Ln();
|
||||
$this->headerBottomY = $this->GetY();
|
||||
$this->SetLineWidth(0.6);
|
||||
$this->Line(15, $this->GetY(), 210 - 15, $this->GetY());
|
||||
$this->SetLineWidth(0.2);
|
||||
} elseif ($this->firstPageDone && !empty($this->columns)) {
|
||||
// Use same top margin as table
|
||||
$this->SetY(35); // or another fixed Y
|
||||
$this->SetX(15);
|
||||
$this->SetFont('GoogleSansFlex-Regular', '', 11);
|
||||
$this->setCellPaddings(2, 0, 2, 0);
|
||||
foreach ($this->columns as $c) {
|
||||
$this->Cell($c['max_width'], 10, $c['header'], 0, 0, 'L');
|
||||
}
|
||||
$this->Ln();
|
||||
$this->headerBottomY = $this->GetY();
|
||||
$this->SetLineWidth(0.6);
|
||||
$this->Line(15, $this->GetY(), 210 - 15, $this->GetY());
|
||||
$this->SetLineWidth(0.2);
|
||||
}
|
||||
}
|
||||
|
||||
public function Footer()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// --- Create PDF ---
|
||||
$pdf = new MYPDF('P', 'mm', 'A4', true, 'UTF-8', false);
|
||||
$pdf->current_year = (date('n') > 6) ? date('Y') + 1 : date('Y');
|
||||
|
||||
$pdf->wkp_name = trim(($variables['rechnungenVorname'] ?? '') . ' ' . ($variables['rechnungenName'] ?? ''));
|
||||
$pdf->wkp_adresse = trim(($variables['rechnungenStrasse'] ?? '') . ' ' . ($variables['rechnungenHausnummer'] ?? ''));
|
||||
$pdf->wkp_plz_ort = trim(($variables['rechnungenPostleitzahl'] ?? '') . ' ' . ($variables['rechnungenOrt'] ?? ''));
|
||||
$pdf->wkp_url = $variables['linkWebseite'] ?? '';
|
||||
$pdf->wk_name = $variables['wkName'] ?? '';
|
||||
|
||||
$pdf->pers_name = trim(($_POST['vorname'] ?? '') . ' ' . ($_POST['name'] ?? ''));
|
||||
$pdf->pers_adresse = trim(($_POST['strasse'] ?? '') . ' ' . ($_POST['hausnummer'] ?? ''));
|
||||
$pdf->pers_plz_ort = trim(($_POST['plz'] ?? '') . ' ' . ($_POST['ort'] ?? ''));
|
||||
|
||||
$pdf->printfooter = true;
|
||||
$pdf->current_wk_name = $current_wk_name;
|
||||
|
||||
// Mark first page done so Header() prints table headers on subsequent pages
|
||||
$pdf->firstPageDone = false;
|
||||
|
||||
$pdf->setCellPaddings(2, 0, 2, 0);
|
||||
|
||||
$pdf->SetMargins(15, 35, 15);
|
||||
|
||||
// Fonts
|
||||
$pdf->AddFont('GoogleSansFlex9pt-Bold', '', $_SERVER['DOCUMENT_ROOT'] . '/../private-files/tcpdf-fonts/googlesansflex_9ptb.php');
|
||||
$pdf->AddFont('GoogleSansFlex-Regular', '', $_SERVER['DOCUMENT_ROOT'] . '/../private-files/tcpdf-fonts/gsf.php');
|
||||
|
||||
$pdf->SetCreator(PDF_CREATOR);
|
||||
$pdf->SetAuthor('WKVS');
|
||||
$pdf->SetAutoPageBreak(TRUE, 10);
|
||||
|
||||
$pdf->SetFont('GoogleSansFlex-Regular', '', 11);
|
||||
|
||||
// --- Add a page ---
|
||||
$pdf->AddPage();
|
||||
|
||||
// --- Sender block (left) ---
|
||||
$pdf->SetX(15);
|
||||
$pdf->Cell(0, 0, $pdf->wkp_name, 0, 1);
|
||||
$pdf->Cell(0, 0, $pdf->wkp_adresse, 0, 1);
|
||||
$pdf->Cell(0, 0, $pdf->wkp_plz_ort, 0, 1);
|
||||
$pdf->Ln(7);
|
||||
$pdf->Cell(0, 0, $pdf->wkp_url, 0, 1);
|
||||
|
||||
// --- Recipient block (right / window) ---
|
||||
$x = 110; // X coordinate for right window
|
||||
$y = 50; // Y coordinate
|
||||
$w = 80; // Width of recipient block
|
||||
|
||||
$address = implode("\n", [
|
||||
$pdf->pers_name,
|
||||
$pdf->pers_adresse,
|
||||
$pdf->pers_plz_ort
|
||||
]);
|
||||
|
||||
$pdf->MultiCell($w, 5, $address, 0, 'L', false, 1, $x, $y, true);
|
||||
|
||||
date_default_timezone_set('UTC');
|
||||
|
||||
// --- Invoice title ---
|
||||
$pdf->Ln(20); // space below recipient
|
||||
$pdf->SetFont('GoogleSansFlex9pt-Bold', '', 15);
|
||||
$pdf->Cell(0, 10, 'Startgebührenrechnung ' . $pdf->current_wk_name, 0, 1, 'L');
|
||||
$pdf->SetFont('GoogleSansFlex-Regular', '', 10);
|
||||
$pdf->Cell(0, 9, "Rechnungsnummer: " . $orderId, 0, 1, 'L');
|
||||
$pdf->SetFont('GoogleSansFlex-Regular', '', 7);
|
||||
$pdf->Cell(0, 0, "Ausstellungsdatum: " . date("d.m.y"), 0, 1, 'L');
|
||||
|
||||
$pdf->Ln(10); // space below title
|
||||
|
||||
$pdf->SetFont('GoogleSansFlex9pt-Bold', '', 13);
|
||||
|
||||
//$turnerinnnenIds = [];
|
||||
|
||||
$placeholders = implode(', ', array_fill(0, count($all_teilnehmende_ids), '?'));
|
||||
|
||||
$all_teilnehmende = db_select($mysqli, $db_tabelle_teilnehmende, '`id`, name, vorname, programm, verein, `betrag_bezahlt`', "id IN ($placeholders)", $all_teilnehmende_ids);
|
||||
|
||||
$all_teilnehmende_indexed = array_column($all_teilnehmende, null, 'id');
|
||||
|
||||
$columns = ['name' => ['header' => 'Name'],
|
||||
'programm' => ['header' => 'Programm'],
|
||||
'verein' => ['header' => 'Verein'],
|
||||
'preis' => ['header' => 'Startgebühr']];
|
||||
|
||||
foreach ($columns as $key => $column){
|
||||
$columns[$key]['max_width'] = $pdf->GetStringWidth($column['header']);
|
||||
}
|
||||
|
||||
$totalPreis = 0.00;
|
||||
|
||||
$dbdata = [];
|
||||
|
||||
foreach ($ids as $singleid => $s_preis){
|
||||
|
||||
if (!isset($all_teilnehmende_indexed[$singleid])) continue;
|
||||
|
||||
$row = &$all_teilnehmende_indexed[$singleid];
|
||||
|
||||
if (count($row) !== 6) continue;
|
||||
|
||||
$float_preis = (float) $s_preis;
|
||||
|
||||
$formated_preis = number_format($float_preis, 2, '.', "'");
|
||||
|
||||
$totalPreis += $float_preis;
|
||||
|
||||
$row['formated_preis'] = $formated_preis;
|
||||
|
||||
$programm = $row['programm'] ?? '';
|
||||
$kosten_kat_normal = (float) ($indexed_kats_preis[$programm] ?? 0.00);
|
||||
|
||||
$preis_text = $float_preis !== $kosten_kat_normal ? 'Die Startgebühren dieser Person wurden reduziert, da diese Person bereits CHF ' . number_format($row['betrag_bezahlt'], 2, '.', "'") . ' an Startgebühren zahlte' : '';
|
||||
|
||||
$row['preis_text'] = $preis_text;
|
||||
|
||||
$pdf->SetFont('', '', 10);
|
||||
$text = 'Startgebühr '. ($row['name'] ?? '') .' '. ($row['vorname'] ?? '');
|
||||
|
||||
$text_width = $pdf->GetStringWidth($text);
|
||||
$kat_width = $pdf->GetStringWidth($row['programm'] ?? '');
|
||||
$verein_width = $pdf->GetStringWidth($row['verein'] ?? '');
|
||||
$preis_width = $pdf->GetStringWidth('CHF '. $formated_preis);
|
||||
|
||||
$columns['name']['max_width'] = max($columns['name']['max_width'] ?? 0, $text_width);
|
||||
$columns['programm']['max_width'] = max($columns['programm']['max_width'] ?? 0, $kat_width);
|
||||
$columns['verein']['max_width'] = max($columns['verein']['max_width'] ?? 0, $verein_width);
|
||||
$columns['preis']['max_width'] = max($columns['preis']['max_width'] ?? 0, $preis_width);
|
||||
}
|
||||
|
||||
unset($row);
|
||||
|
||||
|
||||
foreach ($columns as $key => $column){
|
||||
$columns[$key]['max_width'] += 2; // Add some padding
|
||||
}
|
||||
|
||||
$maxWidth = 210 - 30; // A4 width minus margins
|
||||
$totalColumnWidth = 0;
|
||||
foreach ($columns as $column){
|
||||
$totalColumnWidth += $column['max_width'];
|
||||
}
|
||||
|
||||
if ($totalColumnWidth < $maxWidth){
|
||||
$scalingFactor = $maxWidth / $totalColumnWidth;
|
||||
foreach ($columns as $key => $column){
|
||||
$columns[$key]['max_width'] = $column['max_width'] * $scalingFactor;
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($columns as $c) {
|
||||
$pdf->Cell($c['max_width'], 10, $c['header'], 0, 0, 'L');
|
||||
}
|
||||
$pdf->Ln();
|
||||
|
||||
$pdf->SetLineWidth(0.6);
|
||||
$pdf->Line(15, $pdf->GetY(), 210 - 15, $pdf->GetY());
|
||||
$pdf->SetLineWidth(0.2);
|
||||
|
||||
$pdf->headerBottomY = $pdf->GetY();
|
||||
|
||||
// --- Set top margin for table below title ---
|
||||
|
||||
// Mark first page done so Header() prints table headers on subsequent pages
|
||||
$pdf->firstPageDone = true;
|
||||
|
||||
$pdf->SetFont('GoogleSansFlex-Regular', '', 11);
|
||||
|
||||
$pdf->columns = $columns;
|
||||
|
||||
$margin_top = $pdf->headerBottomY;
|
||||
|
||||
$pdf->SetMargins(15, 45, 15); // +5 mm padding below header
|
||||
$pdf->SetY($margin_top); // Move cursor below header manually
|
||||
|
||||
foreach ($all_teilnehmende_indexed as $s_id => $row){
|
||||
$pdf->SetFont('', '', 10);
|
||||
|
||||
$text = 'Startgebühr '. ($row['name'] ?? '') .' '. ($row['vorname'] ?? '');
|
||||
|
||||
$pdf->Cell($columns['name']['max_width'], 10, $text, 0, 0, 'L');
|
||||
$pdf->Cell($columns['programm']['max_width'], 10, $row['programm'] ?? '', 0, 0, 'L');
|
||||
$pdf->Cell($columns['verein']['max_width'], 10, $row['verein'] ?? '', 0, 0, 'L');
|
||||
|
||||
$pdf->SetFillColor(100, 100, 100);
|
||||
|
||||
$formated_preis = $row['formated_preis'] ?? '';
|
||||
|
||||
$pdf->Cell($columns['preis']['max_width'], 10, 'CHF ' . $formated_preis, 0, 1, 'C');
|
||||
|
||||
if ($row['preis_text'] !== '') {
|
||||
$pdf->SetY($pdf->getY() - 3);
|
||||
$pdf->SetFont('', '', 6);
|
||||
$pdf->Cell(195, 6, $row['preis_text'], 0, 1, 'L');
|
||||
$pdf->SetFont('', '', 10);
|
||||
}
|
||||
|
||||
$pdf->SetDrawColor(100, 100, 100);
|
||||
$pdf->Line(15, $pdf->getY(), 210 - 15, $pdf->getY());
|
||||
$pdf->SetDrawColor(0, 0, 0);
|
||||
}
|
||||
|
||||
if ($variables['rechnungenPostversand'] && isset($_POST['postversand'])) {
|
||||
$pdf->SetFont('', '', 10);
|
||||
|
||||
$text = 'Postversand der Rechnung';
|
||||
$pdf->Cell($columns['name']['max_width'], 10, $text, 0, 0, 'L');
|
||||
$pdf->Cell($columns['programm']['max_width'], 10, '', 0, 0, 'L');
|
||||
$pdf->Cell($columns['verein']['max_width'], 10, '', 0, 0, 'L');
|
||||
|
||||
$pdf->SetFillColor(100, 100, 100);
|
||||
|
||||
$pdf->Cell($columns['preis']['max_width'], 10, 'CHF '. number_format(floatval($variables['rechnungenPostversandKosten'] ?? 0), 2, ".", "'"), 0, 1, 'C');
|
||||
|
||||
$pdf->SetDrawColor(100, 100, 100);
|
||||
$pdf->Line(15, $pdf->getY(), 210 - 15, $pdf->getY());
|
||||
$pdf->SetDrawColor(0, 0, 0);
|
||||
|
||||
$totalPreis += floatval($variables['rechnungenPostversandKosten'] ?? 0);
|
||||
}
|
||||
|
||||
if (count($konten_save) > 0) {
|
||||
$pdf->Ln(8);
|
||||
$pdf->SetFont('GoogleSansFlex9pt-Bold', '', 10);
|
||||
$pdf->Cell(0, 10, 'Abzüge (Vereinsguthaben)', 0, 1, 'L');
|
||||
$pdf->SetFont('GoogleSansFlex-Regular', '', 10);
|
||||
|
||||
$pdf->SetFont('GoogleSansFlex9pt-Bold', '', 11);
|
||||
$pdf->Cell($columns['name']['max_width'] + $columns['programm']['max_width'] + $columns['verein']['max_width'], 10, 'Beschreibung', 0, 0, 'L');
|
||||
$pdf->Cell($columns['preis']['max_width'], 10, 'Abzug', 0, 0, 'C');
|
||||
$pdf->Ln();
|
||||
$pdf->SetLineWidth(0.6);
|
||||
$pdf->Line(15, $pdf->GetY(), 210 - 15, $pdf->GetY());
|
||||
$pdf->SetLineWidth(0.2);
|
||||
|
||||
$pdf->abzuegeHeader = true;
|
||||
|
||||
foreach ($konten_save as $verein => $betrag) {
|
||||
$pdf->SetFont('', '', 10);
|
||||
|
||||
$text = 'Guthaben '. $verein;
|
||||
|
||||
$pdf->Cell($columns['name']['max_width'] + $columns['programm']['max_width'] + $columns['verein']['max_width'], 10, $text, 0, 0, 'L');
|
||||
$pdf->SetFillColor(100, 100, 100);
|
||||
|
||||
$formated_preis = number_format(floatval($betrag ?? 0), 2, ".", "'");
|
||||
|
||||
$pdf->Cell($columns['preis']['max_width'], 10, '- CHF ' . $formated_preis, 0, 1, 'C');
|
||||
|
||||
$pdf->SetDrawColor(100, 100, 100);
|
||||
$pdf->Line(15, $pdf->getY(), 210 - 15, $pdf->getY());
|
||||
$pdf->SetDrawColor(0, 0, 0);
|
||||
|
||||
$totalPreis -= (float) $betrag;
|
||||
}
|
||||
|
||||
$pdf->abzuegeHeader = false;
|
||||
}
|
||||
|
||||
$pdf->Ln(3);
|
||||
$pdf->SetFont('GoogleSansFlex9pt-Bold', '', 10);
|
||||
$pdf->Cell(100, 10, "Gesamt:", 0, 0, 'L');
|
||||
$pdf->SetX($columns['name']['max_width'] + $columns['programm']['max_width'] + $columns['verein']['max_width'] + 15);
|
||||
$pdf->Cell($columns['preis']['max_width'], 10, 'CHF ' . number_format($totalPreis, 2, ".", "'"), 0, 1, 'C');
|
||||
$pdf->SetFont('GoogleSansFlex-Regular', '', 10);
|
||||
|
||||
$cent_total_preis = (int) round($totalPreis * 100);
|
||||
|
||||
$rechnung_is_null = $cent_total_preis === 0;
|
||||
|
||||
if ($rechnung_is_null) {
|
||||
$pdf->Ln(10);
|
||||
$pdf->SetTextColor(90, 103, 39);
|
||||
$pdf->MultiCell(0, 8, 'Diese Rechnung wurde als bezahlt eingetragen, da der Betrag CHF 0.00 beträgt', 0, 'L');
|
||||
$pdf->SetTextColor(0, 0, 0);
|
||||
} else {
|
||||
$qrBill = QrBill\QrBill::create();
|
||||
|
||||
$qrBill->setCreditor(
|
||||
QrBill\DataGroup\Element\StructuredAddress::createWithStreet(
|
||||
$pdf->wkp_name,
|
||||
trim($variables['rechnungenStrasse'] ?? ''),
|
||||
trim($variables['rechnungenHausnummer'] ?? ''),
|
||||
trim($variables['rechnungenPostleitzahl'] ?? ''),
|
||||
trim($variables['rechnungenOrt'] ?? ''),
|
||||
'CH'
|
||||
)
|
||||
);
|
||||
|
||||
$iban = strtoupper(str_replace(' ', '', (string)($variables['rechnungenIBAN'] ?? '')));
|
||||
|
||||
$qrBill->setCreditorInformation(
|
||||
QrBill\DataGroup\Element\CreditorInformation::create($iban)
|
||||
);
|
||||
|
||||
// Add debtor information
|
||||
// Who has to pay the invoice? This part is optional.
|
||||
$qrBill->setUltimateDebtor(
|
||||
QrBill\DataGroup\Element\StructuredAddress::createWithStreet(
|
||||
$_POST['vorname'] . ' ' . $_POST['name'],
|
||||
$_POST['strasse'],
|
||||
$_POST['hausnummer'],
|
||||
$_POST['plz'],
|
||||
$_POST['ort'],
|
||||
'CH'
|
||||
)
|
||||
);
|
||||
|
||||
// Add payment amount information
|
||||
// What amount is to be paid?
|
||||
$qrBill->setPaymentAmountInformation(
|
||||
QrBill\DataGroup\Element\PaymentAmountInformation::create(
|
||||
'CHF',
|
||||
$totalPreis
|
||||
)
|
||||
);
|
||||
|
||||
// Add payment reference
|
||||
// This is what you will need to identify incoming payments.
|
||||
$qrBill->setPaymentReference(
|
||||
QrBill\DataGroup\Element\PaymentReference::create(
|
||||
QrBill\DataGroup\Element\PaymentReference::TYPE_SCOR,
|
||||
QrBill\Reference\RfCreditorReferenceGenerator::generate($orderId)
|
||||
)
|
||||
);
|
||||
|
||||
$referenz = "Startgebührenrechnung ". $pdf->wkp_name;
|
||||
|
||||
// Optionally, add some human-readable information about what the bill is for.
|
||||
$qrBill->setAdditionalInformation(
|
||||
QrBill\DataGroup\Element\AdditionalInformation::create(
|
||||
$referenz
|
||||
)
|
||||
);
|
||||
|
||||
// 3. Create a full payment part for TcPDF
|
||||
$output = new TcPdfOutput($qrBill, 'de', $pdf);
|
||||
|
||||
// 4. Optional, set layout options
|
||||
if (class_exists(DisplayOptions::class)) {
|
||||
$displayOptions = new DisplayOptions();
|
||||
$displayOptions
|
||||
->setPrintable(false) // true to remove lines for printing on a perforated stationery
|
||||
->setDisplayTextDownArrows(false) // true to show arrows next to separation text, if shown
|
||||
->setDisplayScissors(false) // true to show scissors instead of separation text
|
||||
->setPositionScissorsAtBottom(false) // true to place scissors at the bottom, if shown
|
||||
;
|
||||
|
||||
// 5. Generate the output, applying display options when supported
|
||||
if (method_exists($output, 'setDisplayOptions')) {
|
||||
$output->setDisplayOptions($displayOptions);
|
||||
}
|
||||
}
|
||||
|
||||
if ($pdf->getY() > 297 - 120) {
|
||||
$pdf->firstPageDone = false;
|
||||
$pdf->printfooter = false;
|
||||
$pdf->addPage();
|
||||
}
|
||||
$output->getPaymentPart();
|
||||
}
|
||||
|
||||
$filename = 'Rechnung Startgebuehren '.$current_wk_name.' '.date('YmdHis').'.pdf';
|
||||
|
||||
$pdf->SetTitle($filename);
|
||||
|
||||
$savePath = $baseDir . '/../private-files/rechnungen/' . $orderId . '.pdf';
|
||||
|
||||
// Save PDF to disk
|
||||
$pdf->Output($savePath, 'F');
|
||||
|
||||
$orderStatus = $rechnung_is_null ? 2 : 1 ;
|
||||
|
||||
$sql = "UPDATE $db_tabelle_verbuchte_startgebueren SET order_status = ?, `preis` = ? WHERE order_id = ?";
|
||||
|
||||
$stmt = $mysqli->prepare($sql);
|
||||
$stmt->bind_param("idi", $orderStatus, $totalPreis, $orderId);
|
||||
$stmt->execute();
|
||||
$stmt->close();
|
||||
|
||||
require $baseDir . '/../scripts/rechnungen/rechnungs-functions.php';
|
||||
|
||||
update_teilnehmende($ids, 0, $orderStatus, true);
|
||||
update_konten_vereine($konten_save, 0, $orderStatus, true);
|
||||
|
||||
// 2. DELETE basket items
|
||||
db_delete($mysqli, $db_tabelle_warenkorb_startgebueren, ['user_id' => intval($userId)]);
|
||||
|
||||
$mysqli->close();
|
||||
|
||||
// Send headers manually
|
||||
header('Content-Type: application/pdf');
|
||||
header('Content-Disposition: attachment; filename="' . $dirFileName . '"');
|
||||
header('Content-Length: ' . filesize($savePath));
|
||||
|
||||
// Send file contents
|
||||
readfile($savePath);
|
||||
exit;
|
||||
@@ -0,0 +1,61 @@
|
||||
<?php
|
||||
header('Content-Type: application/json');
|
||||
|
||||
if (!isset($baseDir)) $baseDir = $_SERVER['DOCUMENT_ROOT'];
|
||||
|
||||
require_once $baseDir . '/../scripts/session_functions.php';
|
||||
|
||||
ini_wkvs_session();
|
||||
|
||||
check_user_permission('trainer');
|
||||
|
||||
verify_csrf();
|
||||
|
||||
|
||||
$type = 'tr';
|
||||
|
||||
$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';
|
||||
|
||||
// --- Get input ---
|
||||
$id = isset($_POST['id']) ? intval($_POST['id']) : 0;
|
||||
$userId = intval($_SESSION['user_id_trainer']);
|
||||
|
||||
// --- Validate inputs ---
|
||||
if ($id < 1) {
|
||||
http_response_code(422);
|
||||
echo json_encode(["success" => false, "message" => "Nicht valide id"]);
|
||||
exit;
|
||||
}
|
||||
|
||||
$verein = db_get_var($mysqli, "SELECT `verein` FROM $db_tabelle_teilnehmende WHERE `id` = ?", [$id]);
|
||||
|
||||
if ($verein === null) {
|
||||
http_response_code(400);
|
||||
echo json_encode(["success" => false, "message" => "Person hat keinen Verein"]);
|
||||
exit;
|
||||
}
|
||||
|
||||
$verein_konto = db_get_var($mysqli, "SELECT `konto` FROM $db_tabelle_vereine WHERE `verein` = ?", [$verein]) ?: 0.00;
|
||||
|
||||
// --- Check for existing open order ---
|
||||
$sql = "DELETE FROM $db_tabelle_warenkorb_startgebueren WHERE user_id = ? AND item_id = ?";
|
||||
$stmt = $mysqli->prepare($sql);
|
||||
$stmt->bind_param("ii", $userId, $id);
|
||||
|
||||
if (!$stmt->execute()) {
|
||||
http_response_code(500);
|
||||
exit;
|
||||
}
|
||||
|
||||
http_response_code(200);
|
||||
echo json_encode(["success" => true, "message" => "Startgebühr entfernt", "verein" => $verein, "vereinKonto" => $verein_konto]);
|
||||
exit;
|
||||
?>
|
||||
@@ -0,0 +1,202 @@
|
||||
<?php
|
||||
|
||||
header('Content-Type: application/json');
|
||||
|
||||
|
||||
if (!isset($baseDir))
|
||||
$baseDir = $_SERVER['DOCUMENT_ROOT'];
|
||||
|
||||
require_once $baseDir . '/../scripts/session_functions.php';
|
||||
|
||||
ini_wkvs_session();
|
||||
|
||||
check_user_permission('trainer');
|
||||
|
||||
verify_csrf();
|
||||
|
||||
$personen_ids_json = $_POST['personen_ids'] ?? '';
|
||||
|
||||
$personen_ids = json_decode($personen_ids_json) ?? [];
|
||||
|
||||
$personen_ids = !is_array($personen_ids) ? array(intval($personen_ids)) : array_map('intval', $personen_ids);
|
||||
|
||||
if (count($personen_ids) < 1) {
|
||||
echo json_encode(['success' => false, 'message' => "Keine Personen angegeben"]);
|
||||
http_response_code(400);
|
||||
exit;
|
||||
}
|
||||
|
||||
$neu_kat_id = (int) $_POST['kat_id'] ?? 0;
|
||||
|
||||
if ($neu_kat_id < 1) {
|
||||
echo json_encode(['success' => false, 'message' => "Keine neue Kategorie angegeben"]);
|
||||
http_response_code(400);
|
||||
exit;
|
||||
}
|
||||
|
||||
require $baseDir . '/../scripts/db/db-functions.php';
|
||||
require $baseDir . '/../scripts/db/db-tables.php';
|
||||
|
||||
$type = 'tr';
|
||||
|
||||
$dbconnection = require $baseDir . '/../scripts/db/db-verbindung-script.php';
|
||||
|
||||
if ($dbconnection['success'] !== true) {
|
||||
echo 'Critical DB Error.';
|
||||
exit;
|
||||
}
|
||||
|
||||
$all_kats = db_select($mysqli, $db_tabelle_kategorien, "`id`, `programm`, `preis`");
|
||||
|
||||
$all_kats_id_indexed = array_column($all_kats, null, 'id');
|
||||
|
||||
$preise_kats = array_column($all_kats, 'preis', 'programm');
|
||||
|
||||
if (!isset($all_kats_id_indexed[$neu_kat_id])) {
|
||||
echo json_encode(['success' => false, 'message' => "Nicht valide Kategorie"]);
|
||||
http_response_code(400);
|
||||
exit;
|
||||
}
|
||||
|
||||
$new_kat_name = $all_kats_id_indexed[$neu_kat_id]['programm'];
|
||||
$new_kat_preis = $all_kats_id_indexed[$neu_kat_id]['preis'];
|
||||
$vereine_plus_array = [];
|
||||
|
||||
function get_kat_price_diff(array $old_data, string $new_kat): array {
|
||||
global $preise_kats;
|
||||
global $vereine_plus_array;
|
||||
|
||||
$return_array = [];
|
||||
|
||||
$old_kat = $old_data['programm'] ?? '';
|
||||
$verein = $old_data['verein'] ?? '';
|
||||
$bezahlt = (int) ($old_data['bezahlt'] ?? 1);
|
||||
|
||||
var_dump(!isset($preise_kats[$new_kat]), !in_array($bezahlt, [2, 4], true), $old_kat === $new_kat, $old_kat === '', $old_kat, $new_kat);
|
||||
|
||||
if ($old_kat === '' || $old_kat === $new_kat || !in_array($bezahlt, [2, 4], true) || !isset($preise_kats[$new_kat])) {
|
||||
return $return_array;
|
||||
}
|
||||
|
||||
$betrag_bezahlt = (float) ($old_data['betrag_bezahlt'] ?? 0.00);
|
||||
$new_kat_preis = (float) $preise_kats[$new_kat];
|
||||
|
||||
if ($new_kat_preis > $betrag_bezahlt) {
|
||||
$return_array['bezahlt'] = ($betrag_bezahlt === 0.00) ? 1 : 2;
|
||||
} elseif ($new_kat_preis < $betrag_bezahlt) {
|
||||
$return_array['bezahlt'] = 4;
|
||||
$return_array['betrag_bezahlt'] = $betrag_bezahlt - $new_kat_preis;
|
||||
$vereine_plus_array[$verein] = ((float) ($vereine_plus_array[$verein] ?? 0.00)) + $betrag_bezahlt - $new_kat_preis;
|
||||
} else {
|
||||
$return_array['bezahlt'] = 4;
|
||||
}
|
||||
|
||||
return $return_array;
|
||||
}
|
||||
|
||||
function update_verein_balances(array $vereine_plus_array_funct) {
|
||||
global $mysqli;
|
||||
global $db_tabelle_vereine;
|
||||
|
||||
if (empty($vereine_plus_array_funct)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$stmt = $mysqli->prepare("UPDATE $db_tabelle_vereine SET `konto` = `konto` + ? WHERE `verein` = ?");
|
||||
|
||||
if ($stmt) {
|
||||
foreach ($vereine_plus_array_funct as $verein => $betrag) {
|
||||
if ($betrag <= 0.00) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$stmt->bind_param("ds", $betrag, $verein);
|
||||
$stmt->execute();
|
||||
}
|
||||
$stmt->close();
|
||||
}
|
||||
}
|
||||
|
||||
function remove_from_basket(array $ids_array = []) : bool {
|
||||
global $mysqli;
|
||||
global $db_tabelle_warenkorb_startgebueren;
|
||||
|
||||
if (empty($ids_array)) return true;
|
||||
|
||||
$tplaceholders = implode(", ", array_fill(0, count($ids_array), "?"));
|
||||
|
||||
$stmt = $mysqli->prepare("DELETE FROM $db_tabelle_warenkorb_startgebueren WHERE `item_id` IN ($tplaceholders)");
|
||||
$stmt->bind_param(str_repeat('i', count($ids_array)), ...$ids_array);
|
||||
$ret = $stmt->execute();
|
||||
$stmt->close();
|
||||
|
||||
return $ret;
|
||||
}
|
||||
|
||||
// 4. Data Processing & Transaction Block
|
||||
$placeholders = implode(", ", array_fill(0, count($personen_ids), "?"));
|
||||
$entries = db_select($mysqli, $db_tabelle_teilnehmende, "`id`, `programm`, `bezahlt`, `betrag_bezahlt`, `verein`", "`id` IN ($placeholders)", $personen_ids);
|
||||
|
||||
$mysqli->begin_transaction();
|
||||
|
||||
try {
|
||||
|
||||
$stmtbez = $mysqli->prepare("UPDATE $db_tabelle_teilnehmende SET `bezahlt` = ?, `programm` = ? WHERE `id` = ?");
|
||||
$stmtbezbet = $mysqli->prepare("UPDATE $db_tabelle_teilnehmende SET `bezahlt` = ?, `programm` = ?, `betrag_bezahlt` = ? WHERE `id` = ?");
|
||||
$stmtnorm = $mysqli->prepare("UPDATE $db_tabelle_teilnehmende SET `programm` = ? WHERE `id` = ?");
|
||||
|
||||
$status_update_bez = null;
|
||||
$current_id_bez = null;
|
||||
$stmtbez->bind_param("isi", $status_update_bez, $new_kat_name, $current_id_bez);
|
||||
|
||||
$status_update_bet_bez = null;
|
||||
$current_id_bet_bez = null;
|
||||
$betrag_bezahlt = null;
|
||||
$stmtbezbet->bind_param("isdi", $status_update_bet_bez, $new_kat_name, $betrag_bezahlt, $current_id_bet_bez);
|
||||
|
||||
$current_id_norm = null;
|
||||
$stmtnorm->bind_param("si", $new_kat_name, $current_id_norm);
|
||||
|
||||
foreach ($entries as $s_entry) {
|
||||
$res = get_kat_price_diff($s_entry, $new_kat_name);
|
||||
|
||||
if (count($res) < 1) {
|
||||
$current_id_norm = $s_entry['id'];
|
||||
$stmtnorm->execute();
|
||||
} elseif (isset($res['betrag_bezahlt'])){
|
||||
$status_update_bet_bez = $res['bezahlt'];
|
||||
$current_id_bet_bez = $s_entry['id'];
|
||||
$betrag_bezahlt = $res['betrag_bezahlt'];
|
||||
$stmtbezbet->execute();
|
||||
} else {
|
||||
$status_update_bez = $res['bezahlt'];
|
||||
$current_id_bez = $s_entry['id'];
|
||||
$stmtbez->execute();
|
||||
}
|
||||
}
|
||||
|
||||
$stmtnorm->close();
|
||||
$stmtbez->close();
|
||||
|
||||
remove_from_basket($personen_ids);
|
||||
|
||||
var_dump($vereine_plus_array);
|
||||
|
||||
update_verein_balances($vereine_plus_array);
|
||||
|
||||
$mysqli->commit();
|
||||
|
||||
// Fix #1: Added explicit echo for output tracking
|
||||
http_response_code(200);
|
||||
echo json_encode(['success' => true, 'message' => "Kategorie erfolgreich geändert"]);
|
||||
exit;
|
||||
|
||||
} catch (Exception $e) {
|
||||
// Rollback instantly if anything fails
|
||||
$mysqli->rollback();
|
||||
|
||||
// Fix #1 & #3: Proper error output formatting
|
||||
http_response_code(500);
|
||||
echo json_encode(['success' => false, 'message' => "Datenbankfehler"]);
|
||||
exit;
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
<?php
|
||||
header('Content-Type: application/json');
|
||||
|
||||
|
||||
if (!isset($baseDir)) $baseDir = $_SERVER['DOCUMENT_ROOT'];
|
||||
|
||||
require_once $baseDir . '/../scripts/session_functions.php';
|
||||
|
||||
ini_wkvs_session();
|
||||
|
||||
check_user_permission('trainer');
|
||||
|
||||
verify_csrf();
|
||||
|
||||
$audiofileId = intval($_POST['musicId'] ?? 0);
|
||||
$personId = intval($_POST['turnerinId'] ?? 0);
|
||||
$geraetId = intval($_POST['geraetId'] ?? 0);
|
||||
|
||||
if ($audiofileId < 1 || $personId < 1 || $geraetId < 1) {
|
||||
echo json_encode(['success' => false, 'message' => 'Ungültige Eingabe.']);
|
||||
http_response_code(400);
|
||||
exit;
|
||||
}
|
||||
|
||||
$type = 'tr';
|
||||
|
||||
$data = include $baseDir . '/../scripts/db/db-verbindung-script.php';
|
||||
|
||||
if ($data['success'] === false){
|
||||
echo json_encode(['success' => false, 'message' => $data['message']]);
|
||||
http_response_code(500);
|
||||
exit;
|
||||
}
|
||||
|
||||
require $baseDir . '/../scripts/db/db-tables.php';
|
||||
|
||||
$sql = "INSERT INTO $db_tabelle_teilnehmende_audiofiles (`person_id`, `geraet_id`, `audiofile_id`) VALUES (?, ?, ?) ON DUPLICATE KEY UPDATE `audiofile_id` = VALUES(`audiofile_id`)";
|
||||
|
||||
$stmt = $mysqli->prepare($sql);
|
||||
$stmt->bind_param("iii", $personId, $geraetId, $audiofileId);
|
||||
|
||||
if (!$stmt->execute()) {
|
||||
http_response_code(500);
|
||||
exit;
|
||||
}
|
||||
|
||||
$stmt->close();
|
||||
|
||||
$sql = "SELECT name, vorname FROM $db_tabelle_teilnehmende WHERE id = ?";
|
||||
|
||||
$stmt = $mysqli->prepare($sql);
|
||||
$stmt->bind_param("s", $turnerinId);
|
||||
|
||||
if (!$stmt->execute()) {
|
||||
http_response_code(500);
|
||||
exit;
|
||||
}
|
||||
|
||||
$result = $stmt->get_result();
|
||||
$rows = $result->fetch_all(MYSQLI_ASSOC);
|
||||
|
||||
$stmt->close();
|
||||
|
||||
$_SESSION['form_message_type'] = 1;
|
||||
|
||||
if (!isset($rows) || !is_array($rows) || count($rows) !== 1) {
|
||||
$_SESSION['form_message'] = 'Musik aktualisiert';
|
||||
} else {
|
||||
$_SESSION['form_message'] = 'Musik für '.$rows[0]['name'].' '.$rows[0]['vorname'].' aktualisiert';
|
||||
}
|
||||
|
||||
$mysqli->close();
|
||||
|
||||
echo json_encode(['success' => true]);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
<?php
|
||||
|
||||
if (!isset($baseDir)) $baseDir = $_SERVER['DOCUMENT_ROOT'];
|
||||
|
||||
require_once $baseDir . '/../scripts/session_functions.php';
|
||||
|
||||
ini_wkvs_session();
|
||||
|
||||
check_user_permission('trainer');
|
||||
|
||||
verify_csrf();
|
||||
|
||||
if (!isset($_POST['oldMusicId'])) {
|
||||
echo json_encode(['success' => false]);
|
||||
http_response_code(422);
|
||||
exit;
|
||||
}
|
||||
|
||||
$oldMusicId = intval($_POST['oldMusicId']);
|
||||
|
||||
if ($oldMusicId < 1) {
|
||||
echo json_encode(['success' => true]);
|
||||
http_response_code(202);
|
||||
exit;
|
||||
}
|
||||
|
||||
$type = 'tr';
|
||||
|
||||
$data = include $baseDir . '/../scripts/db/db-verbindung-script.php';
|
||||
|
||||
if ($data['success'] === false){
|
||||
echo json_encode(['success' => false, 'message' => $data['message']]);
|
||||
http_response_code(500);
|
||||
exit;
|
||||
}
|
||||
|
||||
require $baseDir . '/../scripts/db/db-tables.php';
|
||||
|
||||
$sql = "DELETE $db_tabelle_audiofiles WHERE id = ?";
|
||||
|
||||
$stmt = $mysqli->prepare($sql);
|
||||
$stmt->bind_param("i", $oldMusicId);
|
||||
|
||||
if (!$stmt->execute()) {
|
||||
http_response_code(500);
|
||||
exit;
|
||||
}
|
||||
|
||||
$stmt->close();
|
||||
$mysqli->close();
|
||||
|
||||
echo json_encode(['success' => true]);
|
||||
http_response_code(200);
|
||||
exit;
|
||||
@@ -0,0 +1,85 @@
|
||||
<?php
|
||||
header('Content-Type: application/json');
|
||||
|
||||
if (!isset($baseDir)) {
|
||||
$baseDir = $_SERVER['DOCUMENT_ROOT'];
|
||||
}
|
||||
|
||||
require_once $baseDir . '/../scripts/session_functions.php';
|
||||
|
||||
ini_wkvs_session();
|
||||
|
||||
check_user_permission('wk_leitung');
|
||||
|
||||
verify_csrf();
|
||||
|
||||
$name = trim($_POST['name'] ?? '');
|
||||
$slug = trim($_POST['slug'] ?? '');
|
||||
|
||||
if ($name === '') {
|
||||
http_response_code(400);
|
||||
echo json_encode(['success' => false, 'message' => 'Name ist leer']);
|
||||
exit;
|
||||
}
|
||||
|
||||
if ($slug === ''){
|
||||
http_response_code(400);
|
||||
echo json_encode(['success' => false, 'message' => 'Slug ist leer']);
|
||||
exit;
|
||||
}
|
||||
|
||||
if (preg_match('/\s/', $slug)) {
|
||||
http_response_code(400);
|
||||
echo json_encode(['success' => false, 'message' => 'Der Slug darf keine Leerzeichen enthalten']);
|
||||
exit;
|
||||
}
|
||||
|
||||
// Optional: Ensure the slug only contains lowercase letters, numbers, and hyphens
|
||||
if (!preg_match('/^[a-z0-9-]+$/', $slug)) {
|
||||
http_response_code(400);
|
||||
echo json_encode(['success' => false, 'message' => 'Der Slug darf nur Kleinbuchstaben, Zahlen und Bindestriche enthaltenn']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$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';
|
||||
|
||||
$stmt = $mysqli->prepare("INSERT INTO $db_tabelle_wettkaempfe (`name`, `slug`) VALUES (?, ?)");
|
||||
|
||||
$stmt->bind_param("ss", $name, $slug);
|
||||
|
||||
try {
|
||||
$stmt->execute();
|
||||
} catch (mysqli_sql_exception $e) {
|
||||
|
||||
if ($e->getCode() === 1062) {
|
||||
http_response_code(400);
|
||||
echo json_encode(['success' => false, 'message' => 'Dieser Slug existiert bereits']);
|
||||
exit;
|
||||
}
|
||||
|
||||
http_response_code(500);
|
||||
echo json_encode(['success' => false, 'message' => 'Ein Datenbankfehler ist aufgetreten']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$stmt->close();
|
||||
|
||||
$insert_id = $mysqli->insert_id;
|
||||
|
||||
// Return JSON
|
||||
echo json_encode([
|
||||
'success' => true,
|
||||
'message' => 'Wettkampf hinzugefügt',
|
||||
'id' => $insert_id
|
||||
]);
|
||||
exit;
|
||||
@@ -0,0 +1,50 @@
|
||||
<?php
|
||||
header('Content-Type: application/json');
|
||||
|
||||
if (!isset($baseDir)) {
|
||||
$baseDir = $_SERVER['DOCUMENT_ROOT'];
|
||||
}
|
||||
|
||||
require_once $baseDir . '/../scripts/session_functions.php';
|
||||
|
||||
ini_wkvs_session();
|
||||
|
||||
check_user_permission('wk_leitung');
|
||||
|
||||
require_once $baseDir . '/../scripts/delete_request_type_functions.php';
|
||||
|
||||
parse_input_to_delete();
|
||||
|
||||
verify_delete_csrf($_DELETE);
|
||||
|
||||
$id = (int) ($_DELETE['id'] ?? 0);
|
||||
|
||||
if ($id <= 0) {
|
||||
echo json_encode(['success' => false, 'message' => 'No valid ID']);
|
||||
}
|
||||
|
||||
require $baseDir . '/../scripts/db/db-functions.php';
|
||||
require $baseDir . '/../scripts/db/db-tables.php';
|
||||
|
||||
|
||||
$type = 'wkl';
|
||||
|
||||
$dbconnection = require $baseDir . '/../scripts/db/db-verbindung-script.php';
|
||||
|
||||
if ($dbconnection['success'] !== true){
|
||||
echo 'Critical DB Error.';
|
||||
exit;
|
||||
}
|
||||
|
||||
$entrys = db_select($mysqli, $db_tabelle_wettkaempfe, "1", '`id` = ?', [$id]);
|
||||
|
||||
if (count($entrys) < 1) {
|
||||
echo json_encode(['success' => true, 'message' => 'Wettkampf bereits gelöscht']);
|
||||
http_response_code(410);
|
||||
exit;
|
||||
}
|
||||
|
||||
db_delete($mysqli, $db_tabelle_wettkaempfe, ['id' => $id]);
|
||||
|
||||
echo json_encode(['success' => true, 'message' => 'Wettkampf gelöscht']);
|
||||
http_response_code(200);
|
||||
@@ -0,0 +1,62 @@
|
||||
<?php
|
||||
header('Content-Type: application/json');
|
||||
|
||||
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();
|
||||
|
||||
|
||||
$id = (int) $_POST['id'] ?? 0;
|
||||
|
||||
if ($id < 1) {
|
||||
echo json_encode(['success' => false, 'message' => 'Nicht valide ID']);
|
||||
http_response_code(400);
|
||||
exit;
|
||||
}
|
||||
|
||||
require $baseDir . '/../scripts/db/db-functions.php';
|
||||
require $baseDir . '/../scripts/db/db-tables.php';
|
||||
|
||||
$type = 'wkl';
|
||||
|
||||
$dbconnection = require $baseDir . '/../scripts/db/db-verbindung-script.php';
|
||||
|
||||
$id_row = db_select($mysqli, $db_tabelle_wettkaempfe, "1", "`id` = ?", [$id]);
|
||||
|
||||
if (count($id_row) !== 1) {
|
||||
echo json_encode(['success' => false, 'message' => 'Diese ID existiert nicht']);
|
||||
http_response_code(400);
|
||||
exit;
|
||||
}
|
||||
|
||||
$stmt = $mysqli->prepare("INSERT INTO $db_tabelle_var (`name`, `value`) VALUES ('current_wk_id', ?) ON DUPLICATE KEY UPDATE `value` = VALUES(`value`)");
|
||||
|
||||
$stmt->bind_param("i", $id);
|
||||
|
||||
try {
|
||||
$stmt->execute();
|
||||
} catch (mysqli_sql_exception $e) {
|
||||
|
||||
echo json_encode(['success' => false, 'message' => 'Ein Datenbankfehler ist aufgetreten']);
|
||||
http_response_code(500);
|
||||
exit;
|
||||
}
|
||||
|
||||
$stmt->close();
|
||||
|
||||
// Return JSON
|
||||
echo json_encode([
|
||||
'success' => true,
|
||||
'message' => 'Wert geändert'
|
||||
]);
|
||||
exit;
|
||||
@@ -0,0 +1,106 @@
|
||||
<?php
|
||||
header('Content-Type: application/json');
|
||||
|
||||
if (!isset($baseDir)) {
|
||||
$baseDir = $_SERVER['DOCUMENT_ROOT'];
|
||||
}
|
||||
|
||||
require_once $baseDir . '/../scripts/session_functions.php';
|
||||
|
||||
ini_wkvs_session();
|
||||
|
||||
check_user_permission('wk_leitung');
|
||||
|
||||
verify_csrf();
|
||||
|
||||
|
||||
$id = (int) $_POST['id'] ?? 0;
|
||||
$field_name = trim($_POST['inputType'] ?? '');
|
||||
$value = trim($_POST['value'] ?? '');
|
||||
|
||||
$allowed_field_names = ['name', 'slug'];
|
||||
|
||||
if (!in_array($field_name, $allowed_field_names)) {
|
||||
echo json_encode(['success' => false, 'message' => 'Nicht valides Feld']);
|
||||
http_response_code(400);
|
||||
exit;
|
||||
}
|
||||
|
||||
if ($id < 1) {
|
||||
echo json_encode(['success' => false, 'message' => 'Nicht valide ID']);
|
||||
http_response_code(400);
|
||||
exit;
|
||||
}
|
||||
|
||||
if ($value === '') {
|
||||
echo json_encode(['success' => false, 'message' => 'Inhalt ist leer']);
|
||||
http_response_code(400);
|
||||
exit;
|
||||
}
|
||||
|
||||
if ($field_name === 'slug'){
|
||||
if (preg_match('/\s/', $slug)) {
|
||||
echo json_encode(['success' => false, 'message' => 'Der Slug darf keine Leerzeichen enthalten']);
|
||||
http_response_code(400);
|
||||
exit;
|
||||
}
|
||||
|
||||
// Optional: Ensure the slug only contains lowercase letters, numbers, and hyphens
|
||||
if (!preg_match('/^[a-z0-9-]+$/', $slug)) {
|
||||
echo json_encode(['success' => false, 'message' => 'Der Slug darf nur Kleinbuchstaben, Zahlen und Bindestriche enthaltenn']);
|
||||
http_response_code(400);
|
||||
exit;
|
||||
}
|
||||
}
|
||||
|
||||
require $baseDir . '/../scripts/db/db-functions.php';
|
||||
require $baseDir . '/../scripts/db/db-tables.php';
|
||||
|
||||
$type = 'wkl';
|
||||
|
||||
$dbconnection = require $baseDir . '/../scripts/db/db-verbindung-script.php';
|
||||
|
||||
$id_row = db_select($mysqli, $db_tabelle_wettkaempfe, "1", "`id` = ?", [$id]);
|
||||
|
||||
if (count($id_row) !== 1) {
|
||||
echo json_encode(['success' => false, 'message' => 'Diese ID existiert nicht']);
|
||||
http_response_code(400);
|
||||
exit;
|
||||
}
|
||||
|
||||
$stmt = $mysqli->prepare("UPDATE $db_tabelle_wettkaempfe SET `$field_name` = ? WHERE `id` = ?");
|
||||
|
||||
$stmt->bind_param("si", $value, $id);
|
||||
|
||||
try {
|
||||
$stmt->execute();
|
||||
} catch (mysqli_sql_exception $e) {
|
||||
|
||||
// Error 1062: Duplicate entry
|
||||
if ($e->getCode() === 1062) {
|
||||
echo json_encode(['success' => false, 'message' => 'Dieser Slug existiert bereits']);
|
||||
http_response_code(400);
|
||||
exit;
|
||||
}
|
||||
|
||||
// Error 1054: Unknown column (e.g., $field_name doesn't exist)
|
||||
if ($e->getCode() === 1054) {
|
||||
echo json_encode(['success' => false, 'message' => "Das Feld '$field_name' existiert nicht"]);
|
||||
http_response_code(400);
|
||||
exit;
|
||||
}
|
||||
|
||||
// Fallback for other database errors
|
||||
echo json_encode(['success' => false, 'message' => 'Ein Datenbankfehler ist aufgetreten']);
|
||||
http_response_code(500);
|
||||
exit;
|
||||
}
|
||||
|
||||
$stmt->close();
|
||||
|
||||
// Return JSON
|
||||
echo json_encode([
|
||||
'success' => true,
|
||||
'message' => 'Wert geändert'
|
||||
]);
|
||||
exit;
|
||||
Reference in New Issue
Block a user