Überarbeitete Version der 1. Version. Es bestehen noch grosse Feher in einzelnen Skripten.

This commit is contained in:
Fabio Herzig
2026-04-18 23:45:17 +02:00
parent a51fd9dbeb
commit 3731183654
85 changed files with 2965 additions and 3371 deletions

View File

@@ -1,16 +0,0 @@
<?php
function csrf_token() {
if (session_status() === PHP_SESSION_NONE) session_start();
if (empty($_SESSION['csrf_token'])) {
$_SESSION['csrf_token'] = bin2hex(random_bytes(64));
}
return $_SESSION['csrf_token'];
}
function verify_csrf() {
if (!isset($_POST['csrf_token']) ||
!hash_equals($_SESSION['csrf_token'], $_POST['csrf_token'])) {
return false;
}
return true;
}

View File

@@ -2,24 +2,6 @@
use Dotenv\Dotenv;
if (!isset($token)){
http_response_code(403);
echo json_encode([
'success' => false,
'message' => 'security check failed: ERROR 01'
]);
exit;
}
if ($token !== 'QQa2UMbEYW8oOL7wz9DjtqECVCikSZsDuSdmzxiadEXFsKyujEUyQOW1AYMD2OqU8VXxClIRweRuWLzvBrZpPYL41e89Rs96tM7Lq1KpjA5E2mg2UfgvztheGRV'){
http_response_code(403);
echo json_encode([
'success' => false,
'message' => 'security check failed: ERROR 02'
]);
exit;
}
require __DIR__ . '/../../composer/vendor/autoload.php';
$envFile = realpath(__DIR__ . '/../../config/.env.db-guest');

View File

@@ -2,7 +2,9 @@
use Dotenv\Dotenv;
if(session_status() !== PHP_SESSION_ACTIVE) session_start();
require_once __DIR__ . '/../session_functions.php';
ini_wkvs_session();
if (!isset($type)){
return [
@@ -12,22 +14,13 @@ if (!isset($type)){
}
if ($type === 'kr'){
if (empty($_SESSION['access_granted_kampfrichter']) || $_SESSION['access_granted_kampfrichter'] !== true || empty($_SESSION['passcodekampfrichter_id']) || $_SESSION['passcodekampfrichter_id'] < 1) {
http_response_code(403);
exit;
}
check_user_permission('kampfrichter');
} elseif ($type === 'tr'){
if (empty($_SESSION['access_granted_trainer']) || $_SESSION['access_granted_trainer'] !== true || empty($_SESSION['passcodetrainer_id']) || $_SESSION['passcodetrainer_id'] < 1) {
http_response_code(403);
exit;
}
check_user_permission('trainer');
} elseif ($type === 'wkl') {
if (empty($_SESSION['access_granted_wk_leitung']) || $_SESSION['access_granted_wk_leitung'] !== true || empty($_SESSION['passcodewk_leitung_id']) || intval($_SESSION['passcodewk_leitung_id']) < 1 ) {
http_response_code(403);
exit;
}
check_user_permission('wk_leitung');
} elseif ($type === 'otl') {
if (empty($_SESSION['set_new_password_id_user']) || empty($_SESSION['set_new_password_granted']) || $_SESSION['set_new_password_granted'] !== true || $_SESSION['set_new_password_id_user'] < 1 ) {
if (empty($_SESSION['access_granted_db_otl']) || $_SESSION['access_granted_db_otl'] !== true) {
http_response_code(403);
exit;
}

View File

@@ -1,12 +1,6 @@
<?php
if ( empty($_SESSION['access_granted_kampfrichter']) || $_SESSION['access_granted_kampfrichter'] !== true || empty($_SESSION['passcodekampfrichter_id']) || intval($_SESSION['passcodekampfrichter_id']) < 1 ) {
http_response_code(403);
exit;
}
// ========== Access control setup ==========
$userid = intval($_SESSION['passcodekampfrichter_id'] ?? 0);
$userid = intval($_SESSION['user_id_kampfrichter'] ?? 0);
$arrayfreigaben = [];
if ($userid > 0) {

View File

@@ -1,277 +1,11 @@
<?php
if ( empty($_SESSION['access_granted_kampfrichter']) || $_SESSION['access_granted_kampfrichter'] !== true || empty($_SESSION['passcodekampfrichter_id']) || intval($_SESSION['passcodekampfrichter_id']) < 1 ) {
http_response_code(403);
exit;
}
// ========== Form handling logic ==========
$form_message = $_SESSION['form_message'] ?? '';
unset($_SESSION['form_message']);
// Handle recalculate all scores action
if ($selecteduser === 'admin' && isset($_POST['recalculate_scores'])) {
if (!verify_csrf()) {
$form_message = 'Sicherheitsproblem bei der Neuberechnung.';
} else {
$disciplines = ['sprung', 'barren', 'balken', 'boden'];
// Build column list
$columns = implode(', ', array_map(fn ($d) => "`note $d`", $disciplines));
$columns_array = array_merge(
['id', 'programm'],
array_map(fn($d) => "note $d", $disciplines)
);
$all_rows = db_select($mysqli, $tableTurnerinnen, $columns_array, 'bezahlt = ? OR bezahltoverride = ?', ['2', '5']);
$success = 0;
// Step 1: Calculate gesamtpunktzahl and update per row
foreach ($all_rows as $row) {
$sum = 0;
foreach ($disciplines as $discipline) {
$value = $row["note $discipline"];
if (is_numeric($value)) {
$sum += floatval($value);
}
}
db_update($mysqli, $tableTurnerinnen, ['gesamtpunktzahl' => $sum], ['id' => $row['id']]);
$success++;
}
// Step 2: Re-fetch rows grouped by programm with updated gesamtpunktzahl
$all_programms = db_get_col($mysqli, "SELECT DISTINCT programm FROM ".$tableTurnerinnen);
foreach ($all_programms as $programm) {
$group = db_select($mysqli, $tableTurnerinnen, ['id', 'gesamtpunktzahl', 'note sprung', 'note barren', 'note balken', 'note boden', 'geburtsdatum'], 'programm = ? AND (bezahlt = ? OR bezahltoverride = ?)', [$programm, '2', '5']);
usort($group, function ($a, $b) {
$scoreA = floatval($a['gesamtpunktzahl']);
$scoreB = floatval($b['gesamtpunktzahl']);
if ($scoreA !== $scoreB) return $scoreB <=> $scoreA;
// Only for top 3 tie-breaking
$scoresA = [
floatval($a['note sprung']),
floatval($a['note barren']),
floatval($a['note balken']),
floatval($a['note boden']),
];
$scoresB = [
floatval($b['note sprung']),
floatval($b['note barren']),
floatval($b['note balken']),
floatval($b['note boden']),
];
rsort($scoresA);
rsort($scoresB);
$sumTop3A = $scoresA[0] + $scoresA[1] + $scoresA[2];
$sumTop3B = $scoresB[0] + $scoresB[1] + $scoresB[2];
if (abs($sumTop3A - $sumTop3B) > 0.001) return $sumTop3B <=> $sumTop3A;
$sumTop2A = $scoresA[0] + $scoresA[1];
$sumTop2B = $scoresB[0] + $scoresB[1];
if (abs($sumTop2A - $sumTop2B) > 0.001) return $sumTop2B <=> $sumTop2A;
if (abs($scoresA[0] - $scoresB[0]) > 0.001) return $scoresB[0] <=> $scoresA[0];
// Younger participant ranks higher in case of full tie
$dateA = strtotime($a['geburtsdatum']);
$dateB = strtotime($b['geburtsdatum']);
return $dateB <=> $dateA; // later birthdate = younger = better
});
// Step 2: Assign ranks
$ranked = [];
$current_rank = 1;
$i = 0;
while ($i < count($group)) {
$current = $group[$i];
$tie_group = [$current];
$j = $i + 1;
while ($j < count($group)) {
$next = $group[$j];
// Tie logic
if ($current_rank <= 3) {
// Top 3: full tie-breaking
$is_tie =
round(floatval($current['gesamtpunktzahl']), 3) === round(floatval($next['gesamtpunktzahl']), 3) &&
round(floatval($current['note sprung']), 3) === round(floatval($next['note sprung']), 3) &&
round(floatval($current['note barren']), 3) === round(floatval($next['note barren']), 3) &&
round(floatval($current['note balken']), 3) === round(floatval($next['note balken']), 3) &&
round(floatval($current['note boden']), 3) === round(floatval($next['note boden']), 3) &&
$current['geburtsdatum'] === $next['geburtsdatum'];
} else {
// Ranks > 3: only check gesamtpunktzahl
$is_tie = round(floatval($current['gesamtpunktzahl']), 3) === round(floatval($next['gesamtpunktzahl']), 3);
}
if ($is_tie) {
$tie_group[] = $next;
$j++;
} else {
break;
}
}
// Assign the same rank for all ties in ranks > 3
foreach ($tie_group as $entry) {
$ranked[] = [
'id' => $entry['id'],
'rang' => $current_rank
];
}
$i += count($tie_group);
$current_rank += count($tie_group);
}
// Step 3: Write all ranks to DB
foreach ($ranked as $r) {
db_update($mysqli, $tableTurnerinnen, ['rang' => $r['rang']], ['id' => $r['id']]);
}
}
$_SESSION['form_message'] =
$success . ' Einträge wurden aktualisiert und neu gerankt.';
header("Location: ". $_SERVER['REQUEST_URI']);
exit;
}
}
if ($selecteduser === 'admin' && isset($_POST['reset_scores'])) {
if (!verify_csrf()) {
$form_message = 'Sicherheitsproblem bei der Neuberechnung.';
} else {
$all_rows = db_select($mysqli, $tableTurnerinnen, 'id');
$success = 0;
foreach ($all_rows as $row) {
db_update($mysqli, $tableTurnerinnen, ['gesamtpunktzahl' => 0, 'rang' => 0], ['id' => $row['id']]);
$success++;
}
$_SESSION['form_message'] = '<div class="success">' . $success . ' Einträge wurden zurückgesetzt.</div>';
header("Location: ". $_SERVER['REQUEST_URI']);
exit;
}
}
// === EDIT MODE: Load existing data if edit_id is present in URL ===
$edit_row = null;
if (isset($_GET['edit_id']) && is_numeric($_GET['edit_id']) && !isset($_POST['submit_turnerinnen_form'])) {
$edit_id = intval($_GET['edit_id']);
$edit_row = db_select($mysqli, $tableTurnerinnen, '*', 'id = ?', [$edit_id]);
foreach ($disciplines as $discipline) {
if ($selecteduser === ucfirst($discipline) || $selecteduser === 'admin') {
$_POST["d-note_{$discipline}"] = $edit_row["d-note {$discipline}"] ??
'';
$_POST["note_{$discipline}"] = $edit_row["note {$discipline}"] ?? '';
}
}
if ($selecteduser === 'admin') {
$gesamt = 0;
foreach ($disciplines as $discipline) {
if (isset($edit_row[0]["note {$discipline}"]) && is_numeric($edit_row[0]["note {$discipline}"])) {
$gesamt += floatval($edit_row[0]["note {$discipline}"]);
}
}
$_POST["gesamtpunktzahl"] = $gesamt;
$rang = isset($_POST['rang']) ? intval($_POST['rang']) : 0; // Safely get and cast to int
$data_to_insert["rang"] = $rang;
$data_formats[] = '%d';
}
$_POST['edit_id'] = $edit_id;
}
if (isset($_POST['submit_turnerinnen_form'])) {
// Check nonce
if (!verify_csrf()) {
$form_message = 'Sicherheitsproblem: Ungültige Formularübermittlung.';
} else {
foreach ($disciplines as $discipline) {
if ($selecteduser === ucfirst($discipline) || $selecteduser === 'admin') {
${"d_note_$discipline"} = floatval($_POST["d-note_{$discipline}"]);
${"note_$discipline"} = floatval($_POST["note_{$discipline}"]);
// Add to data array
$data_to_insert["d-note $discipline"] = ${"d_note_$discipline"};
$data_to_insert["note $discipline"] = ${"note_$discipline"};
$data_formats[] = '%f'; // float format for d-note
$data_formats[] = '%f';
// float format for note
}
}
if ($selecteduser === 'admin') {
$gesamtpunktzahl = isset($_POST['gesamtpunktzahl']) ?
intval($_POST['gesamtpunktzahl']) : 0; // Safely get and cast to int
$data_to_insert["gesamtpunktzahl"] = $gesamtpunktzahl;
$data_formats[] = '%f';
// CORRECTED LINE: Get 'rang' from $_POST
$rang = isset($_POST['rang']) ?
intval($_POST['rang']) : 0; // Safely get and cast to int
$data_to_insert["rang"] = $rang;
$data_formats[] = '%d';
}
// Check if we are editing an existing entry
$is_editing = isset($_POST['edit_id']) && is_numeric($_POST['edit_id']) && $_POST['edit_id'] > 0;
if ($is_editing) {
$edit_id = intval($_POST['edit_id']);
$updated = db_update($mysqli, $tableTurnerinnen, $data_to_insert, ['id' => $edit_id]);
if ($updated === false) {
$form_message = 'Fehler beim Aktualisieren des Eintrags.';
} else if ($updated === 0) {
$form_message = 'Keine Änderungen vorgenommen.';
} else {
$_SESSION['form_message'] = 'Eintrag erfolgreich aktualisiert!';
$_POST = [];
$parsed = parse_url($_SERVER['REQUEST_URI']);
if (!isset($parsed['query'])) {
return $url;
}
parse_str($parsed['query'], $query);
unset($query[$param]); // remove the parameter
$base = $parsed['path'] ?? '';
$new_query = http_build_query($query);
$url = $new_query ? $base . '?' . $new_query : $base;
header("Location: ". $url);
exit;
}
}
}
}
if ((isset($_POST['prev_abt'])) && !empty($_POST['prev_abt_submit'])) {
verify_csrf();
$value = $aktabt;
if ($value > 1){
$value -= 1;
@@ -285,10 +19,11 @@ if ((isset($_POST['prev_abt'])) && !empty($_POST['prev_abt_submit'])) {
$stmt->close();
}
header("Location: /intern/kampfrichter");
exit;
exit;
}
if ((isset($_POST['next_abt'])) && !empty($_POST['next_abt_submit'])) {
verify_csrf();
$value = $aktabt;
$maxvalue = db_get_var($mysqli, "SELECT name FROM $tableAbt ORDER BY name DESC LIMIT 1");
@@ -322,6 +57,7 @@ if ($_SESSION['last_abt'] !== $aktabt){
}
if ((isset($_POST['prev_subabt'])) && !empty($_POST['prev_subabt_submit'])) {
verify_csrf();
$value = $_SESSION['currentsubabt'];
if ($value > 1){
$_SESSION['currentsubabt']--;
@@ -333,6 +69,7 @@ if ((isset($_POST['prev_subabt'])) && !empty($_POST['prev_subabt_submit'])) {
}
if ((isset($_POST['next_subabt'])) && !empty($_POST['next_subabt_submit'])) {
verify_csrf();
$value = $_SESSION['currentsubabt'];
if ($value < $maxsubabt){
$_SESSION['currentsubabt']++;
@@ -343,7 +80,8 @@ if ((isset($_POST['next_subabt'])) && !empty($_POST['next_subabt_submit'])) {
exit;
}
if ( isset($_POST['togle_advanced_mode_admin']) && !empty($_POST['togle_advanced_mode_admin_submit']) ) {
if ( isset($_POST['togle_advanced_mode_admin']) && !empty($_POST['togle_advanced_mode_admin_submit']) && !empty($_POST['csrf_token'])) {
verify_csrf();
$current_value = $focus_view_admin;
$new_value = !$current_value;
@@ -351,31 +89,4 @@ if ( isset($_POST['togle_advanced_mode_admin']) && !empty($_POST['togle_advanced
header("Location: /intern/kampfrichter");
exit;
}
if ((isset($_POST['upload_remove_pdf_for_programm'])) && !empty($_POST['programm_remove_export'])) {
$current_year = date('Y');
$monat = date('n');
if ($monat > 6) $current_year++;
$programm = trim($_POST['programm_remove_export']);
$dir = $_SERVER['DOCUMENT_ROOT'] . '/wp-content/ergebnisse';
if (!file_exists($dir)) {
mkdir($dir, 0755, true);
}
$localPath = $_SERVER['DOCUMENT_ROOT'] . "/wp-content/ergebnisse/KTBB_Ergebnisse_" . $programm . "_" . $current_year . ".pdf";
// --- ADDED CODE START ---
// Check if the file already exists and delete it
if (file_exists($localPath)) {
unlink($localPath);
}
// --- ADDED CODE END ---
$_SESSION['form_message'] = 'PDF wurde gelöscht';
header("Location: ". $_SERVER['REQUEST_URI']);
}

View File

@@ -1,8 +1,8 @@
<?php
if (session_status() !== PHP_SESSION_ACTIVE) {
session_start();
}
require_once __DIR__ . '/../session_functions.php';
ini_wkvs_session();
if (!isset($error)) {
$error = '';
@@ -24,8 +24,6 @@ if ($_SESSION['lockout_time_'. $logintype] > time()) {
$error = "Zu viele fehlgeschlagene Anmeldeversuche. Bitte warte $minutes Minute(n).";
} elseif (isset($_POST[$logintype.'_login_submit'])) {
$token = "QQa2UMbEYW8oOL7wz9DjtqECVCikSZsDuSdmzxiadEXFsKyujEUyQOW1AYMD2OqU8VXxClIRweRuWLzvBrZpPYL41e89Rs96tM7Lq1KpjA5E2mg2UfgvztheGRV";
require __DIR__ .'/../db/db-verbindung-script-guest.php';
require __DIR__ . "/../db/db-tables.php";
@@ -35,8 +33,9 @@ if ($_SESSION['lockout_time_'. $logintype] > time()) {
$password = trim($_POST['access_passcode']);
// Prepare statement
$stmt = $guest->prepare("SELECT * FROM $tableInternUsers WHERE username = ? LIMIT 1");
$stmt->bind_param("s", $username);
$stmt = $guest->prepare("SELECT * FROM $tableInternUsers WHERE username = ? AND login_active = ? LIMIT 1");
$loginActive = 1;
$stmt->bind_param("ss", $username, $loginActive);
$stmt->execute();
$result = $stmt->get_result();
$user = $result->fetch_assoc();
@@ -60,7 +59,7 @@ if ($_SESSION['lockout_time_'. $logintype] > time()) {
if (password_verify($password, $user['password_hash']) && in_array($logintype, $freigabe_values)) {
foreach ($freigabe_values as $freigabe) {
$_SESSION['access_granted_'. $freigabe] = true;
$_SESSION['passcode'. $freigabe .'_id'] = $user['id'];
$_SESSION['user_id_'. $freigabe] = $user['id'];
$_SESSION['lockout_time_'. $freigabe] = 0;
$_SESSION['login_attempts_'. $freigabe] = 0;
}

View File

@@ -0,0 +1,104 @@
<?php
function deleteSession() {
$_SESSION = array();
if (ini_get("session.use_cookies")) {
$params = session_get_cookie_params();
setcookie(session_name(), '', time() - 42000,
$params["path"], $params["domain"],
$params["secure"], $params["httponly"]
);
}
session_destroy();
}
function ini_wkvs_session(bool $set_csrf = false, bool $regenerate = false) {
if (session_status() === PHP_SESSION_NONE) {
session_name('wkvs_cookie');
session_set_cookie_params([
'lifetime' => 0,
'path' => '/',
'domain' => '',
'secure' => true,
'httponly' => true,
'samesite' => 'Lax',
]);
session_start();
}
if ($regenerate) {
session_regenerate_id(true);
}
if ($set_csrf && !isset($_SESSION['csrf_token'])) {
$_SESSION['csrf_token'] = bin2hex(random_bytes(64));
}
}
function verify_csrf() {
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$token = $_POST['csrf_token'] ?? '';
if (!hash_equals($_SESSION['csrf_token'], $token)) {
http_response_code(403);
die("Access Denied: Invalid CSRF Token.");
}
} else {
http_response_code(403);
die("Access Denied: Invalid Request Type.");
}
}
$allowedUserTypes = ['trainer', 'kampfrichter', 'wk_leitung'];
function check_user_permission(string $type, bool $return = false) {
global $allowedUserTypes;
if (!in_array($type, $allowedUserTypes, true)) {
if ($return) {
return false;
} else {
http_response_code(403);
die("Invalid User Type Configuration");
}
}
$accessKey = "access_granted_{$type}";
$idKey = "user_id_{$type}";
$hasAccess = ($_SESSION[$accessKey] ?? false) === true;
$hasValidId = isset($_SESSION[$idKey]) && intval($_SESSION[$idKey]) > 0;
if (!$hasAccess || !$hasValidId) {
if ($return) {
return false;
} else {
http_response_code(403);
die("Access Denied");
}
}
if ($return) {
return true;
}
}
function check_multiple_allowed_permissions(array $types) {
$authorized = false;
foreach ($types as $type) {
if (check_user_permission($type, true)) {
$authorized = true;
break;
}
}
if (!$authorized) {
http_response_code(403);
die("Access Denied");
}
}

View File

@@ -13,9 +13,14 @@ use ChrisKonnertz\StringCalc\StringCalc;
class NotenRechner {
private $Rfunctions = ["MAXR", "MINR", "AVGR", "SUMR"];
private $RfunctionsSan = [];
public function __construct(
private StringCalc $rechner = new StringCalc()
) {}
) {
$this->RfunctionsSan = implode('|', array_map('preg_quote', $this->Rfunctions));
}
/*
Es wird ein Array mit allen Notentypen pro Gerät, Jahr und Person erwartet, so dass noten_bezeichnung_id als Key verwendet werden kann:
@@ -95,7 +100,7 @@ class NotenRechner {
}
}
private function insertValuesComplex(string $schemaRaw, array $valuesArray, int $currentId)
private function insertValuesComplex(string $schemaRaw, array $valuesArray, int $currentId, int $runNumber)
{
$schema = $this->santinzeString($schemaRaw);
$idsNeededArray = $this->getBenoetigteIdsComplex($schemaRaw);
@@ -104,7 +109,6 @@ class NotenRechner {
foreach ($idsNeededArray as $sina) {
$noteId = $sina['noteId'];
$geraetIdSearch = ($sina['geraetId'] === 'A') ? $currentId : $sina['geraetId'];
$runNumber = $sina['run'] ?? 1;
if (!isset($valuesArray[$geraetIdSearch][$noteId][$runNumber])) {
return ['success' => false, 'value' => "Fehlende Daten für Gerät $geraetIdSearch, Note $noteId, Lauf $runNumber"];
@@ -112,15 +116,13 @@ class NotenRechner {
}
try {
$returnStr = preg_replace_callback('/\{(\d+)(?:\[(\w*)\])?(?:\[(\d+)\])?\}/', function($m) use ($valuesArray, $currentId) {
$returnStr = preg_replace_callback('/\{(\d+)(?:\[(\w*)\])?(?:\[(\d+)\])?\}/', function($m) use ($valuesArray, $currentId, $runNumber) {
$noteId = $m[1];
// Get value inside brackets, default to 'S' if none exists
$rawGeraet = $m[2] ?? 'S';
$geraetId = ($rawGeraet === 'S' || $rawGeraet === '') ? $currentId : $rawGeraet;
$runNumber = isset($m[3]) ? (int)$m[3] : 1;
// Return value from [Device][Note][Run]
return $valuesArray[$geraetId][$noteId][$runNumber] ?? 0;
@@ -160,16 +162,120 @@ class NotenRechner {
return $this->calculate($rechnungArray['value']);
}
public function berechneStringComplex(string $schemaRaw, array $valuesArray = [], int $geraetId = 0) {
public function berechneStringComplex(string $schemaRaw, array $valuesArray = [], int $geraetId = 0, int $run_number = 0) {
if ($schemaRaw === '') { return ['success' => false, 'value' => 'Leeres Schema']; }
if ($geraetId === 0) { return ['success' => false, 'value' => 'Keine Geraet Id angegeben.']; }
if ($run_number === 0) { return ['success' => false, 'value' => 'Keine Run_Number angegeben.']; }
$rechnungArray = $this->insertValuesComplex($schemaRaw, $valuesArray, $geraetId);
$rechnungArray = $this->insertValuesComplex($schemaRaw, $valuesArray, $geraetId, $run_number);
if (!isset($rechnungArray['success']) || !isset($rechnungArray['value']) || !$rechnungArray['success']) {
return ['success' => false, 'value' => $rechnungArray['value'] ?? 'Fehler beim Einsetzen der Werte oder Werte fehlen'];
return ['success' => false, 'value' => $rechnungArray['value'] . " RECHNUNG: " . $schemaRaw ?? 'Fehler beim Einsetzen der Werte oder Werte fehlen'];
}
return $this->calculate($rechnungArray['value']);
}
public function berechneStringComplexRun(string $schemaRaw, array $valuesArray = [], int $geraetId = 0, int $programm = 0, array $arrayRuns = []) {
if ($schemaRaw === '') { return ['success' => false, 'value' => 'Leeres Schema']; }
if ($geraetId === 0) { return ['success' => false, 'value' => 'Keine Geraet Id angegeben.']; }
if ($programm === 0) { return ['success' => false, 'value' => 'Kein Programm angegeben.']; }
if ($arrayRuns === []) { return ['success' => false, 'value' => 'Leeres Array Runs Noten.']; }
$rechnung = $this->insertRunValues($schemaRaw, $valuesArray, $geraetId, $programm, $arrayRuns);
if (!isset($rechnung) || $rechnung === '') {
return ['success' => false, 'value' => 'Fehler beim Einsetzen der Werte oder Werte fehlen'];
}
return $this->calculate($rechnung);
}
private function insertRunValues($schema, $valuesArray, $currentId, $programm, $arrayRuns) {
$pattern = '/(?P<fn_name>' . $this->RfunctionsSan . ')\((?P<content>(?:(?R)|[^()])*)\)/';
return preg_replace_callback($pattern, function($m) use ($valuesArray, $currentId, $programm, $arrayRuns) {
$name = $m['fn_name'];
$content = $m['content'];
// Resolve inner nested functions first
$content = $this->insertRunValues($content, $valuesArray, $currentId, $programm, $arrayRuns);
if (!in_array($name, $this->Rfunctions)) {
return $m[0];
}
$parts = [];
$ids = $this->getBenoetigteIdsComplex($content);
$runCount = 0;
foreach ($ids as $sid) {
$geraetId = ($sid['geraetId'] === 'A') ? $currentId : $sid['geraetId'];
$runCountN = $arrayRuns[$sid['noteId']][$geraetId][$programm] ?? $arrayRuns["default"] ?? 1;
//var_dump($arrayRuns[$sid['noteId']][$geraetId][$programm]);
if ($runCount !== $runCountN && $runCount !== 0) { return; }
$runCount = $runCountN;
}
$string = "";
switch ($name) {
case "AVGR":
case "SUMR":
for ($r = 1; $r <= $runCount; $r++) {
$res = $this->insertValuesComplex($content, $valuesArray, $currentId, $r);
// FIXED: Only bail if success is false
if (!$res['success']) {
return "0"; // Or handle error as needed
}
$parts[] = "(" . $res['value'] . ")";
}
$innerMath = implode(" + ", $parts);
$string = ($name === "AVGR") ? "(($innerMath) / $runCount)" : "($innerMath)";
//var_dump($string);
break;
case "MAXR":
case "MINR":
$arrayRunValues = [];
for ($r = 1; $r <= $runCount; $r++) {
$res = $this->berechneStringComplex($content, $valuesArray, $currentId, $r);
// FIXED: Access the ['value'] key of the returned array
if ($res['success']) {
$arrayRunValues[] = floatval($res['value']);
} else {
$arrayRunValues[] = 0;
}
}
// Safety check for empty arrays to prevent max() errors
if (empty($arrayRunValues)) return "0";
$string = ($name === "MAXR") ? max($arrayRunValues) : min($arrayRunValues);
break;
}
return (string)$string;
}, $schema);
}
public function checkRunFunctions(string $schemaRaw) {
if ($schemaRaw === '') {
return ['success' => false, 'value' => 'Leeres Schema'];
}
$schema = $this->santinzeString($schemaRaw);
$pattern = '/(?P<fn_name>' . $this->RfunctionsSan . ')\((?:(?R)|[^()])*+\)/';
return (bool) preg_match($pattern, $schema);
}
}

View File

@@ -1,16 +1,12 @@
<?php
require $baseDir . '/../composer/vendor/autoload.php';
use Shuchkin\SimpleXLSX;
if (isset($_POST['apply_bulk_action']) ) {
if (!verify_csrf()) {
$_SESSION['form_message'] = 'Sicherheitsüberprüfung fehlgeschlagen.';
$_SESSION['form_message_type'] = 0;
} elseif ( empty($_POST['turnerin_ids']) || !is_array($_POST['turnerin_ids']) ) {
verify_csrf();
if ( empty($_POST['turnerin_ids']) || !is_array($_POST['turnerin_ids']) ) {
$_SESSION['form_message'] = 'Keine Turnerinnen für die Aktion ausgewählt.';
$_SESSION['form_message_type'] = 0;
} elseif (!isset($_POST['bulk_action_programm']) && !isset($_POST['bulk_action_bezahlt'])) {
@@ -93,7 +89,8 @@ if (isset($_POST['apply_bulk_action']) ) {
exit;
}
if (isset($_POST['delete_id']) && verify_csrf()) {
if (isset($_POST['delete_id'])) {
verify_csrf();
$delete_id = intval($_POST['delete_id']);
$stmt = $mysqli->prepare("DELETE FROM $tableTurnerinnen where id = ?");
@@ -113,6 +110,7 @@ if (isset($_POST['delete_id']) && verify_csrf()) {
}
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_FILES['xlsx_file'])) {
verify_csrf();
if ($_FILES['xlsx_file']['error'] === UPLOAD_ERR_OK) {
@@ -240,54 +238,6 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_FILES['xlsx_file'])) {
}
if (!empty($_FILES['music_file']['name']) && isset($_POST['music_id'])) {
echo 'ja';
$edit_id = (int) $_POST['music_id'];
$uploadedFile = $_FILES['music_file'];
// Validate actual MIME type
$finfo = finfo_open(FILEINFO_MIME_TYPE);
$mimeType = finfo_file($finfo, $uploadedFile['tmp_name']);
finfo_close($finfo);
$allowedTypes = ['audio/mpeg', 'audio/wav', 'audio/ogg'];
if (!in_array($mimeType, $allowedTypes, true)) {
die('Invalid file type.');
}
// Fetch and remove old file
$stmt = $mysqli->prepare("SELECT bodenmusik FROM $tableTurnerinnen WHERE id = ?");
$stmt->bind_param("i", $edit_id);
$stmt->execute();
$stmt->bind_result($oldurl);
$stmt->fetch();
$stmt->close();
if (!empty($oldurl) && is_file($oldurl)) unlink($oldurl);
// Ensure upload directory exists
$uploadDir = $baseDir . '/wk-musik-boden/';
if (!is_dir($uploadDir)) mkdir($uploadDir, 0755, true);
// Clean file name
$cleanName = preg_replace("/[^a-zA-Z0-9-_\.]/", "_", $uploadedFile['name']);
$filename = uniqid('music_', true) . '_' . $cleanName;
$targetPath = $uploadDir . $filename;
if (move_uploaded_file($uploadedFile['tmp_name'], $targetPath)) {
$stmt = $mysqli->prepare("UPDATE $tableTurnerinnen SET bodenmusik = ? WHERE id = ?");
$stmt->bind_param("si", $targetPath, $edit_id);
if (!$stmt->execute()) echo 'DB error: ' . $stmt->error;
$stmt->close();
} else {
die('Failed to move uploaded file.');
}
header('Location: ' . $_SERVER['REQUEST_URI']);
exit;
}
$edit_row = null;
if ($access_granted_trainer && isset($_GET['edit_id']) && is_numeric($_GET['edit_id']) && !isset($_POST['submit_turnerinnen_form'])) {
$edit_id = intval($_GET['edit_id']);
@@ -319,121 +269,117 @@ if ($access_granted_trainer && isset($_GET['edit_id']) && is_numeric($_GET['edit
// === INSERT/UPDATE Handler ===
if ( $access_granted_trainer && isset($_POST['submit_turnerinnen_form']) ) {
// Check nonce
if ( !verify_csrf() ) {
$_SESSION['form_message'] = 'Sicherheitsproblem: Ungültige Formularübermittlung.';
verify_csrf();
$name = htmlspecialchars( $_POST['nachname'] );
$vorname = htmlspecialchars( $_POST['vorname'] );
$geburtsdatum = trim($_POST['geburtsdatum'] );
$programm = htmlspecialchars( $_POST['programm'] );
if ($selectedverein !== 'admin'){
$verein = $selectedverein;
} else {$verein = htmlspecialchars( $_POST['verein'] ); $bezahlt = htmlspecialchars( $_POST['bezahlt'] ); }
if ( empty($name) || empty($vorname) || empty($geburtsdatum) || empty($programm)) {
$_SESSION['form_message'] = 'Bitte füllen Sie alle erforderlichen Felder aus.';
$_SESSION['form_message_type'] = 0;
} else {
$name = htmlspecialchars( $_POST['nachname'] );
$vorname = htmlspecialchars( $_POST['vorname'] );
$geburtsdatum = trim($_POST['geburtsdatum'] );
$programm = htmlspecialchars( $_POST['programm'] );
if ($selectedverein !== 'admin'){
$verein = $selectedverein;
} else {$verein = htmlspecialchars( $_POST['verein'] ); $bezahlt = htmlspecialchars( $_POST['bezahlt'] ); }
if ( empty($name) || empty($vorname) || empty($geburtsdatum) || empty($programm)) {
$_SESSION['form_message'] = 'Bitte füllen Sie alle erforderlichen Felder aus.';
$_SESSION['form_message_type'] = 0;
$data_to_insert = [];
$data_to_insert = array(
'name' => $name,
'vorname' => $vorname,
'geburtsdatum' => $geburtsdatum,
'programm' => $programm,
'verein' => $verein,
);
$data_formats = array('%s', '%s', '%s', '%s', '%s');
if ($selectedverein === 'admin') {
$data_to_insert['bezahltoverride'] = $bezahlt;
$data_formats[] = '%d';
}
print_r($data_to_insert);
// Check if we are editing an existing entry
$is_editing = isset($_POST['edit_id']) && is_numeric($_POST['edit_id']) && $_POST['edit_id'] > 0;
if ($is_editing) {
$edit_id = intval($_POST['edit_id']);
$entries = db_select($mysqli, $tableTurnerinnen, '*', 'id = ?', [$edit_id], 'rang ASC');
$entry = $entries[0]; // since you're fetching by ID, this should return exactly one row
$columns = array_keys($data_to_insert);
$set = implode(
', ',
array_map(fn($col) => "$col = ?", $columns)
);
$sql = "UPDATE $tableTurnerinnen SET $set WHERE id = ?";
var_dump($sql);
$stmt = $mysqli->prepare($sql);
$types = str_repeat('s', count($data_to_insert)) . 'i';
$values = array_values($data_to_insert);
$values[] = $edit_id;
$stmt->bind_param($types, ...$values);
$updated = $stmt->execute();
$stmt->close();
if ($updated === false) {
error_log('DB Update Error: ' . $wpdb->last_error);
$_SESSION['form_message'] = 'Fehler beim Aktualisieren des Eintrags.';
$_SESSION['form_message_type'] = 0;
} else if ($updated === 0) {
$_SESSION['form_message'] = 'Keine Änderungen vorgenommen.';
$_SESSION['form_message_type'] = 0;
} else {
$_SESSION['form_message'] = 'Eintrag erfolgreich aktualisiert!';
$_SESSION['form_message_type'] = 1;
$_POST = [];
header('Location: ' . strtok($_SERVER['REQUEST_URI'], '?'));
exit;
}
} else {
$data_to_insert = [];
$data_to_insert = array(
'name' => $name,
'vorname' => $vorname,
'geburtsdatum' => $geburtsdatum,
'programm' => $programm,
'verein' => $verein,
$columns = array_keys($data_to_insert);
$set = implode(
', ',
array_map(fn($col) => "$col = ?", $columns)
);
$data_formats = array('%s', '%s', '%s', '%s', '%s');
$sql = "INSERT INTO $tableTurnerinnen SET $set";
if ($selectedverein === 'admin') {
$data_to_insert['bezahltoverride'] = $bezahlt;
$data_formats[] = '%d';
}
$stmt = $mysqli->prepare($sql);
print_r($data_to_insert);
$types = str_repeat('s', count($data_to_insert));
$values = array_values($data_to_insert);
$stmt->bind_param($types, ...$values);
$inserted = $stmt->execute();
$stmt->close();
// Check if we are editing an existing entry
$is_editing = isset($_POST['edit_id']) && is_numeric($_POST['edit_id']) && $_POST['edit_id'] > 0;
if ($is_editing) {
$edit_id = intval($_POST['edit_id']);
$entries = db_select($mysqli, $tableTurnerinnen, '*', 'id = ?', [$edit_id], 'rang ASC');
$entry = $entries[0]; // since you're fetching by ID, this should return exactly one row
$columns = array_keys($data_to_insert);
$set = implode(
', ',
array_map(fn($col) => "$col = ?", $columns)
);
$sql = "UPDATE $tableTurnerinnen SET $set WHERE id = ?";
var_dump($sql);
$stmt = $mysqli->prepare($sql);
$types = str_repeat('s', count($data_to_insert)) . 'i';
$values = array_values($data_to_insert);
$values[] = $edit_id;
$stmt->bind_param($types, ...$values);
$updated = $stmt->execute();
$stmt->close();
if ($updated === false) {
error_log('DB Update Error: ' . $wpdb->last_error);
$_SESSION['form_message'] = 'Fehler beim Aktualisieren des Eintrags.';
$_SESSION['form_message_type'] = 0;
} else if ($updated === 0) {
$_SESSION['form_message'] = 'Keine Änderungen vorgenommen.';
$_SESSION['form_message_type'] = 0;
} else {
$_SESSION['form_message'] = 'Eintrag erfolgreich aktualisiert!';
$_SESSION['form_message_type'] = 1;
$_POST = [];
header('Location: ' . strtok($_SERVER['REQUEST_URI'], '?'));
exit;
}
if ( $inserted ) {
$_SESSION['form_message'] = 'Daten erfolgreich gespeichert!';
$_SESSION['form_message_type'] = 1;
header('Location: ' . strtok($_SERVER['REQUEST_URI'], '?'));
exit;
} else {
$columns = array_keys($data_to_insert);
$set = implode(
', ',
array_map(fn($col) => "$col = ?", $columns)
);
$sql = "INSERT INTO $tableTurnerinnen SET $set";
$stmt = $mysqli->prepare($sql);
$types = str_repeat('s', count($data_to_insert));
$values = array_values($data_to_insert);
$stmt->bind_param($types, ...$values);
$inserted = $stmt->execute();
$stmt->close();
if ( $inserted ) {
$_SESSION['form_message'] = 'Daten erfolgreich gespeichert!';
$_SESSION['form_message_type'] = 1;
header('Location: ' . strtok($_SERVER['REQUEST_URI'], '?'));
exit;
} else {
$_SESSION['form_message'] = 'Fehler beim Speichern der Daten. Bitte versuchen Sie es später erneut.';
$_SESSION['form_message_type'] = 0;
}
$_SESSION['form_message'] = 'Fehler beim Speichern der Daten. Bitte versuchen Sie es später erneut.';
$_SESSION['form_message_type'] = 0;
}
}
}