WKVS v 1.0.0
This commit is contained in:
@@ -0,0 +1,206 @@
|
||||
<?php
|
||||
function generateIntersectCache($mysqli, $baseDir) {
|
||||
global $db_tabelle_kategorien;
|
||||
global $db_tabelle_disziplinen;
|
||||
global $db_tabelle_wertungstypen;
|
||||
global $db_tabelle_tabellen_konfiguration;
|
||||
global $db_tabelle_var;
|
||||
|
||||
// 1. Fetch all unique IDs you need to loop through
|
||||
$all_programms = array_column(db_select($mysqli, $db_tabelle_kategorien, '`id`', '`aktiv` = ?', [1]) ?? [], 'id');
|
||||
$all_geraete = array_column(db_select($mysqli, $db_tabelle_disziplinen, 'id') ?? [], 'id');
|
||||
|
||||
// 2. Fetch the static DB configs ONCE before starting the massive loop
|
||||
$rang_note_id = db_get_variable($mysqli, $db_tabelle_var, ['rangNote']);
|
||||
|
||||
$json_geraet = db_get_var($mysqli, "SELECT `all_noten_json` FROM $db_tabelle_tabellen_konfiguration WHERE `type_slug` = ?", ["rankLive-geraet"]) ?: '';
|
||||
$json_overview = db_get_var($mysqli, "SELECT `all_noten_json` FROM $db_tabelle_tabellen_konfiguration WHERE `type_slug` = ?", ["rankLive-overview"]) ?: '';
|
||||
$noten_rank_live_geraet = json_decode($json_geraet, true) ?? [];
|
||||
$noten_rank_live_overview = json_decode($json_overview, true) ?? [];
|
||||
|
||||
$notenConfig_db = db_select($mysqli, $db_tabelle_wertungstypen, '`berechnung_json`, `id`, `type`, `anzahl_laeufe_json`');
|
||||
$noten_config = array_column($notenConfig_db, null, 'id');
|
||||
$following_config_array = array_column($notenConfig_db, 'berechnung_json', 'id');
|
||||
$all_inputs_noten_ids = array_filter(array_column($notenConfig_db, 'type', 'id'), fn($type) => $type === 'input');
|
||||
|
||||
$masterCache = [];
|
||||
|
||||
// 2. Extract ALL possible unique IDs dynamically from your JSON configurations
|
||||
$max_runs = 1; // Default fallback to at least 1 run
|
||||
|
||||
foreach ($noten_config as $n_id => $data) {
|
||||
$config = json_decode($data['anzahl_laeufe_json'], true);
|
||||
foreach ($config as $geraetKey => $value) {
|
||||
if ($geraetKey === 'default') {
|
||||
$max_runs = max($max_runs, (int)$value);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (is_array($value)) {
|
||||
foreach ($value as $progKey => $runsCount) {
|
||||
$max_runs = max($max_runs, (int)$runsCount);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure we have array lists instead of associative maps
|
||||
$all_programms = array_values($all_programms);
|
||||
$all_geraete = array_values($all_geraete);
|
||||
|
||||
// Generate standard run sequences (e.g., if max_runs is 2, creates [1, 2])
|
||||
$all_runs = range(1, $max_runs);
|
||||
|
||||
$masterCache = [];
|
||||
|
||||
// 3. The Grand Loop
|
||||
foreach ($all_programms as $programm_id) {
|
||||
|
||||
foreach ($all_geraete as $geraetId) {
|
||||
foreach ($all_runs as $initNoteRun) {
|
||||
|
||||
$all_needed_noten = [];
|
||||
|
||||
foreach ($noten_rank_live_geraet as $ind => $s_note) {
|
||||
|
||||
$n_id = $s_note['n_id'];
|
||||
|
||||
$anzahl_laeufe_json = $noten_config[$n_id]['anzahl_laeufe_json'] ?? '';
|
||||
|
||||
$anzahl_laeufe = json_decode($anzahl_laeufe_json, true);
|
||||
|
||||
$g_id = ($s_note['g_id'] === 'A') ? (int) $geraetId : (int) $s_note['g_id'];
|
||||
|
||||
$run = (int) $s_note['r'];
|
||||
|
||||
$runs = $anzahl_laeufe[$g_id][(int) $programm_id] ?? $anzahl_laeufe[$g_id]['all'] ?? $anzahl_laeufe['default'] ?? 0;
|
||||
|
||||
if (((int) $runs) < $run) {
|
||||
unset($noten_rank_live_geraet[$ind]);
|
||||
continue;
|
||||
}
|
||||
|
||||
$key = "$n_id|$g_id|$run";
|
||||
|
||||
if (!isset($all_needed_noten[$key])) {
|
||||
$all_needed_noten[$key] = [
|
||||
"r" => $run,
|
||||
"g_id" => $g_id,
|
||||
"n_id" => $n_id
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($noten_rank_live_overview as $s_note) {
|
||||
|
||||
$n_id = $s_note['n_id'];
|
||||
$g_id = $s_note['g_id'];
|
||||
$run = $s_note['r'];
|
||||
|
||||
$key = "$n_id|$g_id|$run";
|
||||
|
||||
if (!isset($all_needed_noten[$key])) {
|
||||
$all_needed_noten[$key] = [
|
||||
"r" => $run,
|
||||
"g_id" => $g_id,
|
||||
"n_id" => $n_id
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
$all_updating_noten = [];
|
||||
|
||||
foreach ($following_config_array as $this_note_id => $s_note_abhaenige_rechnungen_json) {
|
||||
$s_note_abhaenige_rechnungen = json_decode($s_note_abhaenige_rechnungen_json ?? '') ?? [];
|
||||
foreach ($s_note_abhaenige_rechnungen as $s_rechnung) {
|
||||
$this_note_geraet_id = $s_rechnung[1];
|
||||
|
||||
if ($this_note_geraet_id !== 'A' && (int) $this_note_geraet_id !== (int) $geraetId) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$target_note_id = $s_rechnung[0];
|
||||
$target_run_raw = $s_rechnung[2][0] ?? 'A';
|
||||
$target_geraet_id_raw = $s_rechnung[2][1] ?? 'A';
|
||||
|
||||
$target_run = ($target_run_raw === 'A') ? $initNoteRun : (int) $target_run_raw;
|
||||
$target_geraet_id = ($target_geraet_id_raw === 'A') ? $geraetId : (int) $target_geraet_id_raw;
|
||||
|
||||
$key = "$target_note_id|$target_geraet_id|$target_run";
|
||||
|
||||
if (!isset($all_updating_noten[$key])) {
|
||||
$all_updating_noten[$key] = [
|
||||
"r" => $target_run,
|
||||
"g_id" => $target_geraet_id,
|
||||
"n_id" => $target_note_id
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($all_inputs_noten_ids as $n_id => $_) {
|
||||
|
||||
$anzahl_laeufe_json = $noten_config[$n_id]['anzahl_laeufe_json'] ?? '';
|
||||
|
||||
$anzahl_laeufe = json_decode($anzahl_laeufe_json, true);
|
||||
|
||||
$runs = $anzahl_laeufe[$geraetId][(int) $programm_id] ?? $anzahl_laeufe[$geraetId]['all'] ?? $anzahl_laeufe['default'] ?? 0;
|
||||
|
||||
if ($initNoteRun > $runs) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$key = "$n_id|$geraetId|$initNoteRun";
|
||||
|
||||
if (!isset($all_updating_noten[$key])) {
|
||||
$all_updating_noten[$key] = [
|
||||
"r" => $initNoteRun,
|
||||
"g_id" => $geraetId,
|
||||
"n_id" => $n_id
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
$intersect_noten = array_intersect_key($all_updating_noten, $all_needed_noten);
|
||||
|
||||
$key = "$rang_note_id|0|1";
|
||||
|
||||
if (!isset($all_updating_noten[$key])) {
|
||||
$all_updating_noten[$key] = [
|
||||
"r" => 1,
|
||||
"g_id" => 0,
|
||||
"n_id" => $rang_note_id
|
||||
];
|
||||
}
|
||||
|
||||
$sql_where_array = [];
|
||||
$sql_where_values = [];
|
||||
|
||||
$i = 1;
|
||||
|
||||
foreach ($intersect_noten as $s_note) {
|
||||
$sql_where_values[] = $s_note['n_id'];
|
||||
$sql_where_values[] = $s_note['g_id'];
|
||||
$sql_where_values[] = $s_note['r'];
|
||||
|
||||
$sql_where_array[] = '(`note_bezeichnung_id` = ? AND `geraet_id` = ? AND `run_number` = ?)';
|
||||
}
|
||||
|
||||
$sql_where_string = '';
|
||||
|
||||
if (!empty($sql_where_values)) {
|
||||
$sql_where_string = implode(' OR ', $sql_where_array);
|
||||
}
|
||||
|
||||
|
||||
if (!empty($intersect_noten)) {
|
||||
$masterCache[$programm_id][$geraetId][$initNoteRun] = ["SQL" => $sql_where_string, "values" => $sql_where_values, "intersect_noten" => $intersect_noten];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 4. Save to file
|
||||
$fileContent = "<?php\nreturn " . var_export($masterCache, true) . ";";
|
||||
file_put_contents($baseDir . '/../scripts/cache/display-dependencies.php', $fileContent);
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
<?php
|
||||
function regenerate_noten_cache($mysqli, $db_tabelle_wertungstypen, $baseDir) {
|
||||
if (!function_exists('db_select')) require $baseDir . '/../scripts/db/db-functions.php';
|
||||
|
||||
$notenRechnerCache = new NotenRechner();
|
||||
|
||||
$all = db_select($mysqli, $db_tabelle_wertungstypen, "id, default_value, pro_geraet, geraete_json, anzahl_laeufe_json, berechnung, nullstellen, zeige_in_rank_live, display_string");
|
||||
|
||||
$ascArrayDefaultValues = array_column($all, 'default_value', 'id');
|
||||
$ascArrayProGeraet = array_column($all, 'pro_geraet', 'id');
|
||||
$ascArrayRechnungen = array_column($all, 'berechnung', 'id');
|
||||
$indexedNullstellen = array_column($all, 'nullstellen', 'id');
|
||||
$ascPrefixDisplay = array_column($all, 'display_string', 'id');
|
||||
|
||||
$ascArrayGeraeteJSON = array_column($all, 'geraete_json', 'id');
|
||||
foreach ($ascArrayGeraeteJSON as $key => $val) {
|
||||
$ascArrayGeraeteJSON[$key] = json_decode((string)$val, true);
|
||||
}
|
||||
|
||||
$ascArrayAnzahlLaeufeJSON = array_column($all, 'anzahl_laeufe_json', 'id');
|
||||
foreach ($ascArrayAnzahlLaeufeJSON as $key => $val) {
|
||||
$ascArrayAnzahlLaeufeJSON[$key] = json_decode((string)$val, true) ?? [];
|
||||
}
|
||||
|
||||
$export = "<?php\n\nreturn [\n";
|
||||
$export .= " 'default_values' => " . var_export($ascArrayDefaultValues, true) . ",\n";
|
||||
$export .= " 'pro_geraet' => " . var_export($ascArrayProGeraet, true) . ",\n";
|
||||
$export .= " 'geraete_json' => " . var_export($ascArrayGeraeteJSON, true) . ",\n";
|
||||
$export .= " 'anzahl_laeufe_json' => " . var_export($ascArrayAnzahlLaeufeJSON, true) . ",\n";
|
||||
$export .= " 'rechnungen' => " . var_export($ascArrayRechnungen, true) . ",\n";
|
||||
$export .= " 'nullstellen' => " . var_export($indexedNullstellen, true) . "\n";
|
||||
$export .= " ];\n";
|
||||
|
||||
file_put_contents($baseDir . '/../scripts/cache/noten-config-calculating-cache.php', $export);
|
||||
|
||||
$ascArrayStoreRuns = [];
|
||||
$ascArrayStoreGeraete = [];
|
||||
|
||||
foreach ($ascArrayRechnungen as $id => $calc) {
|
||||
$res = $notenRechnerCache->getStoreGeraetRun($calc);
|
||||
$ascArrayStoreRuns[$id] = $res['run_num'] ?? 'A';
|
||||
$ascArrayStoreGeraete[$id] = $res['geraet_id'] ?? 'A';
|
||||
}
|
||||
|
||||
$exportDisplay = "<?php\n\nreturn [\n";
|
||||
$exportDisplay .= " 'default_values' => " . var_export($ascArrayDefaultValues, true) . ",\n";
|
||||
$exportDisplay .= " 'pro_geraet' => " . var_export($ascArrayProGeraet, true) . ",\n";
|
||||
$exportDisplay .= " 'geraete_json' => " . var_export($ascArrayGeraeteJSON, true) . ",\n";
|
||||
$exportDisplay .= " 'anzahl_laeufe_json' => " . var_export($ascArrayAnzahlLaeufeJSON, true) . ",\n";
|
||||
$exportDisplay .= " 'nullstellen' => " . var_export($indexedNullstellen, true) . ",\n";
|
||||
$exportDisplay .= " 'display_string' => " . var_export($ascPrefixDisplay, true) . ",\n";
|
||||
$exportDisplay .= " 'store_run' => " . var_export($ascArrayStoreRuns, true) . ",\n";
|
||||
$exportDisplay .= " 'store_geraet' => " . var_export($ascArrayStoreGeraete, true) . "\n";
|
||||
$exportDisplay .= "];\n";
|
||||
|
||||
file_put_contents($baseDir . '/../scripts/cache/noten-config-display-cache.php', $exportDisplay);
|
||||
}
|
||||
+661
@@ -0,0 +1,661 @@
|
||||
<?php
|
||||
return array (
|
||||
4 =>
|
||||
array (
|
||||
1 =>
|
||||
array (
|
||||
1 =>
|
||||
array (
|
||||
'SQL' => '(`note_bezeichnung_id` = ? AND `geraet_id` = ? AND `run_number` = ?) OR (`note_bezeichnung_id` = ? AND `geraet_id` = ? AND `run_number` = ?) OR (`note_bezeichnung_id` = ? AND `geraet_id` = ? AND `run_number` = ?) OR (`note_bezeichnung_id` = ? AND `geraet_id` = ? AND `run_number` = ?)',
|
||||
'values' =>
|
||||
array (
|
||||
0 => 60,
|
||||
1 => 1,
|
||||
2 => 1,
|
||||
3 => 70,
|
||||
4 => 1,
|
||||
5 => 1,
|
||||
6 => 80,
|
||||
7 => 0,
|
||||
8 => 1,
|
||||
9 => 40,
|
||||
10 => 1,
|
||||
11 => 1,
|
||||
),
|
||||
'intersect_noten' =>
|
||||
array (
|
||||
'60|1|1' =>
|
||||
array (
|
||||
'r' => 1,
|
||||
'g_id' => 1,
|
||||
'n_id' => 60,
|
||||
),
|
||||
'70|1|1' =>
|
||||
array (
|
||||
'r' => 1,
|
||||
'g_id' => 1,
|
||||
'n_id' => 70,
|
||||
),
|
||||
'80|0|1' =>
|
||||
array (
|
||||
'r' => 1,
|
||||
'g_id' => 0,
|
||||
'n_id' => 80,
|
||||
),
|
||||
'40|1|1' =>
|
||||
array (
|
||||
'r' => 1,
|
||||
'g_id' => 1,
|
||||
'n_id' => 40,
|
||||
),
|
||||
),
|
||||
),
|
||||
2 =>
|
||||
array (
|
||||
'SQL' => '(`note_bezeichnung_id` = ? AND `geraet_id` = ? AND `run_number` = ?) OR (`note_bezeichnung_id` = ? AND `geraet_id` = ? AND `run_number` = ?) OR (`note_bezeichnung_id` = ? AND `geraet_id` = ? AND `run_number` = ?) OR (`note_bezeichnung_id` = ? AND `geraet_id` = ? AND `run_number` = ?)',
|
||||
'values' =>
|
||||
array (
|
||||
0 => 60,
|
||||
1 => 1,
|
||||
2 => 2,
|
||||
3 => 70,
|
||||
4 => 1,
|
||||
5 => 1,
|
||||
6 => 80,
|
||||
7 => 0,
|
||||
8 => 1,
|
||||
9 => 40,
|
||||
10 => 1,
|
||||
11 => 2,
|
||||
),
|
||||
'intersect_noten' =>
|
||||
array (
|
||||
'60|1|2' =>
|
||||
array (
|
||||
'r' => 2,
|
||||
'g_id' => 1,
|
||||
'n_id' => 60,
|
||||
),
|
||||
'70|1|1' =>
|
||||
array (
|
||||
'r' => 1,
|
||||
'g_id' => 1,
|
||||
'n_id' => 70,
|
||||
),
|
||||
'80|0|1' =>
|
||||
array (
|
||||
'r' => 1,
|
||||
'g_id' => 0,
|
||||
'n_id' => 80,
|
||||
),
|
||||
'40|1|2' =>
|
||||
array (
|
||||
'r' => 2,
|
||||
'g_id' => 1,
|
||||
'n_id' => 40,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
2 =>
|
||||
array (
|
||||
1 =>
|
||||
array (
|
||||
'SQL' => '(`note_bezeichnung_id` = ? AND `geraet_id` = ? AND `run_number` = ?) OR (`note_bezeichnung_id` = ? AND `geraet_id` = ? AND `run_number` = ?) OR (`note_bezeichnung_id` = ? AND `geraet_id` = ? AND `run_number` = ?) OR (`note_bezeichnung_id` = ? AND `geraet_id` = ? AND `run_number` = ?)',
|
||||
'values' =>
|
||||
array (
|
||||
0 => 60,
|
||||
1 => 2,
|
||||
2 => 1,
|
||||
3 => 70,
|
||||
4 => 2,
|
||||
5 => 1,
|
||||
6 => 80,
|
||||
7 => 0,
|
||||
8 => 1,
|
||||
9 => 40,
|
||||
10 => 2,
|
||||
11 => 1,
|
||||
),
|
||||
'intersect_noten' =>
|
||||
array (
|
||||
'60|2|1' =>
|
||||
array (
|
||||
'r' => 1,
|
||||
'g_id' => 2,
|
||||
'n_id' => 60,
|
||||
),
|
||||
'70|2|1' =>
|
||||
array (
|
||||
'r' => 1,
|
||||
'g_id' => 2,
|
||||
'n_id' => 70,
|
||||
),
|
||||
'80|0|1' =>
|
||||
array (
|
||||
'r' => 1,
|
||||
'g_id' => 0,
|
||||
'n_id' => 80,
|
||||
),
|
||||
'40|2|1' =>
|
||||
array (
|
||||
'r' => 1,
|
||||
'g_id' => 2,
|
||||
'n_id' => 40,
|
||||
),
|
||||
),
|
||||
),
|
||||
2 =>
|
||||
array (
|
||||
'SQL' => '(`note_bezeichnung_id` = ? AND `geraet_id` = ? AND `run_number` = ?) OR (`note_bezeichnung_id` = ? AND `geraet_id` = ? AND `run_number` = ?)',
|
||||
'values' =>
|
||||
array (
|
||||
0 => 70,
|
||||
1 => 2,
|
||||
2 => 1,
|
||||
3 => 80,
|
||||
4 => 0,
|
||||
5 => 1,
|
||||
),
|
||||
'intersect_noten' =>
|
||||
array (
|
||||
'70|2|1' =>
|
||||
array (
|
||||
'r' => 1,
|
||||
'g_id' => 2,
|
||||
'n_id' => 70,
|
||||
),
|
||||
'80|0|1' =>
|
||||
array (
|
||||
'r' => 1,
|
||||
'g_id' => 0,
|
||||
'n_id' => 80,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
3 =>
|
||||
array (
|
||||
1 =>
|
||||
array (
|
||||
'SQL' => '(`note_bezeichnung_id` = ? AND `geraet_id` = ? AND `run_number` = ?) OR (`note_bezeichnung_id` = ? AND `geraet_id` = ? AND `run_number` = ?) OR (`note_bezeichnung_id` = ? AND `geraet_id` = ? AND `run_number` = ?) OR (`note_bezeichnung_id` = ? AND `geraet_id` = ? AND `run_number` = ?)',
|
||||
'values' =>
|
||||
array (
|
||||
0 => 60,
|
||||
1 => 3,
|
||||
2 => 1,
|
||||
3 => 70,
|
||||
4 => 3,
|
||||
5 => 1,
|
||||
6 => 80,
|
||||
7 => 0,
|
||||
8 => 1,
|
||||
9 => 40,
|
||||
10 => 3,
|
||||
11 => 1,
|
||||
),
|
||||
'intersect_noten' =>
|
||||
array (
|
||||
'60|3|1' =>
|
||||
array (
|
||||
'r' => 1,
|
||||
'g_id' => 3,
|
||||
'n_id' => 60,
|
||||
),
|
||||
'70|3|1' =>
|
||||
array (
|
||||
'r' => 1,
|
||||
'g_id' => 3,
|
||||
'n_id' => 70,
|
||||
),
|
||||
'80|0|1' =>
|
||||
array (
|
||||
'r' => 1,
|
||||
'g_id' => 0,
|
||||
'n_id' => 80,
|
||||
),
|
||||
'40|3|1' =>
|
||||
array (
|
||||
'r' => 1,
|
||||
'g_id' => 3,
|
||||
'n_id' => 40,
|
||||
),
|
||||
),
|
||||
),
|
||||
2 =>
|
||||
array (
|
||||
'SQL' => '(`note_bezeichnung_id` = ? AND `geraet_id` = ? AND `run_number` = ?) OR (`note_bezeichnung_id` = ? AND `geraet_id` = ? AND `run_number` = ?)',
|
||||
'values' =>
|
||||
array (
|
||||
0 => 70,
|
||||
1 => 3,
|
||||
2 => 1,
|
||||
3 => 80,
|
||||
4 => 0,
|
||||
5 => 1,
|
||||
),
|
||||
'intersect_noten' =>
|
||||
array (
|
||||
'70|3|1' =>
|
||||
array (
|
||||
'r' => 1,
|
||||
'g_id' => 3,
|
||||
'n_id' => 70,
|
||||
),
|
||||
'80|0|1' =>
|
||||
array (
|
||||
'r' => 1,
|
||||
'g_id' => 0,
|
||||
'n_id' => 80,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
4 =>
|
||||
array (
|
||||
1 =>
|
||||
array (
|
||||
'SQL' => '(`note_bezeichnung_id` = ? AND `geraet_id` = ? AND `run_number` = ?) OR (`note_bezeichnung_id` = ? AND `geraet_id` = ? AND `run_number` = ?) OR (`note_bezeichnung_id` = ? AND `geraet_id` = ? AND `run_number` = ?) OR (`note_bezeichnung_id` = ? AND `geraet_id` = ? AND `run_number` = ?)',
|
||||
'values' =>
|
||||
array (
|
||||
0 => 60,
|
||||
1 => 4,
|
||||
2 => 1,
|
||||
3 => 70,
|
||||
4 => 4,
|
||||
5 => 1,
|
||||
6 => 80,
|
||||
7 => 0,
|
||||
8 => 1,
|
||||
9 => 40,
|
||||
10 => 4,
|
||||
11 => 1,
|
||||
),
|
||||
'intersect_noten' =>
|
||||
array (
|
||||
'60|4|1' =>
|
||||
array (
|
||||
'r' => 1,
|
||||
'g_id' => 4,
|
||||
'n_id' => 60,
|
||||
),
|
||||
'70|4|1' =>
|
||||
array (
|
||||
'r' => 1,
|
||||
'g_id' => 4,
|
||||
'n_id' => 70,
|
||||
),
|
||||
'80|0|1' =>
|
||||
array (
|
||||
'r' => 1,
|
||||
'g_id' => 0,
|
||||
'n_id' => 80,
|
||||
),
|
||||
'40|4|1' =>
|
||||
array (
|
||||
'r' => 1,
|
||||
'g_id' => 4,
|
||||
'n_id' => 40,
|
||||
),
|
||||
),
|
||||
),
|
||||
2 =>
|
||||
array (
|
||||
'SQL' => '(`note_bezeichnung_id` = ? AND `geraet_id` = ? AND `run_number` = ?) OR (`note_bezeichnung_id` = ? AND `geraet_id` = ? AND `run_number` = ?)',
|
||||
'values' =>
|
||||
array (
|
||||
0 => 70,
|
||||
1 => 4,
|
||||
2 => 1,
|
||||
3 => 80,
|
||||
4 => 0,
|
||||
5 => 1,
|
||||
),
|
||||
'intersect_noten' =>
|
||||
array (
|
||||
'70|4|1' =>
|
||||
array (
|
||||
'r' => 1,
|
||||
'g_id' => 4,
|
||||
'n_id' => 70,
|
||||
),
|
||||
'80|0|1' =>
|
||||
array (
|
||||
'r' => 1,
|
||||
'g_id' => 0,
|
||||
'n_id' => 80,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
13 =>
|
||||
array (
|
||||
1 =>
|
||||
array (
|
||||
1 =>
|
||||
array (
|
||||
'SQL' => '(`note_bezeichnung_id` = ? AND `geraet_id` = ? AND `run_number` = ?) OR (`note_bezeichnung_id` = ? AND `geraet_id` = ? AND `run_number` = ?) OR (`note_bezeichnung_id` = ? AND `geraet_id` = ? AND `run_number` = ?) OR (`note_bezeichnung_id` = ? AND `geraet_id` = ? AND `run_number` = ?)',
|
||||
'values' =>
|
||||
array (
|
||||
0 => 60,
|
||||
1 => 1,
|
||||
2 => 1,
|
||||
3 => 70,
|
||||
4 => 1,
|
||||
5 => 1,
|
||||
6 => 80,
|
||||
7 => 0,
|
||||
8 => 1,
|
||||
9 => 40,
|
||||
10 => 1,
|
||||
11 => 1,
|
||||
),
|
||||
'intersect_noten' =>
|
||||
array (
|
||||
'60|1|1' =>
|
||||
array (
|
||||
'r' => 1,
|
||||
'g_id' => 1,
|
||||
'n_id' => 60,
|
||||
),
|
||||
'70|1|1' =>
|
||||
array (
|
||||
'r' => 1,
|
||||
'g_id' => 1,
|
||||
'n_id' => 70,
|
||||
),
|
||||
'80|0|1' =>
|
||||
array (
|
||||
'r' => 1,
|
||||
'g_id' => 0,
|
||||
'n_id' => 80,
|
||||
),
|
||||
'40|1|1' =>
|
||||
array (
|
||||
'r' => 1,
|
||||
'g_id' => 1,
|
||||
'n_id' => 40,
|
||||
),
|
||||
),
|
||||
),
|
||||
2 =>
|
||||
array (
|
||||
'SQL' => '(`note_bezeichnung_id` = ? AND `geraet_id` = ? AND `run_number` = ?) OR (`note_bezeichnung_id` = ? AND `geraet_id` = ? AND `run_number` = ?) OR (`note_bezeichnung_id` = ? AND `geraet_id` = ? AND `run_number` = ?) OR (`note_bezeichnung_id` = ? AND `geraet_id` = ? AND `run_number` = ?)',
|
||||
'values' =>
|
||||
array (
|
||||
0 => 60,
|
||||
1 => 1,
|
||||
2 => 2,
|
||||
3 => 70,
|
||||
4 => 1,
|
||||
5 => 1,
|
||||
6 => 80,
|
||||
7 => 0,
|
||||
8 => 1,
|
||||
9 => 40,
|
||||
10 => 1,
|
||||
11 => 2,
|
||||
),
|
||||
'intersect_noten' =>
|
||||
array (
|
||||
'60|1|2' =>
|
||||
array (
|
||||
'r' => 2,
|
||||
'g_id' => 1,
|
||||
'n_id' => 60,
|
||||
),
|
||||
'70|1|1' =>
|
||||
array (
|
||||
'r' => 1,
|
||||
'g_id' => 1,
|
||||
'n_id' => 70,
|
||||
),
|
||||
'80|0|1' =>
|
||||
array (
|
||||
'r' => 1,
|
||||
'g_id' => 0,
|
||||
'n_id' => 80,
|
||||
),
|
||||
'40|1|2' =>
|
||||
array (
|
||||
'r' => 2,
|
||||
'g_id' => 1,
|
||||
'n_id' => 40,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
2 =>
|
||||
array (
|
||||
1 =>
|
||||
array (
|
||||
'SQL' => '(`note_bezeichnung_id` = ? AND `geraet_id` = ? AND `run_number` = ?) OR (`note_bezeichnung_id` = ? AND `geraet_id` = ? AND `run_number` = ?) OR (`note_bezeichnung_id` = ? AND `geraet_id` = ? AND `run_number` = ?) OR (`note_bezeichnung_id` = ? AND `geraet_id` = ? AND `run_number` = ?)',
|
||||
'values' =>
|
||||
array (
|
||||
0 => 60,
|
||||
1 => 2,
|
||||
2 => 1,
|
||||
3 => 70,
|
||||
4 => 2,
|
||||
5 => 1,
|
||||
6 => 80,
|
||||
7 => 0,
|
||||
8 => 1,
|
||||
9 => 40,
|
||||
10 => 2,
|
||||
11 => 1,
|
||||
),
|
||||
'intersect_noten' =>
|
||||
array (
|
||||
'60|2|1' =>
|
||||
array (
|
||||
'r' => 1,
|
||||
'g_id' => 2,
|
||||
'n_id' => 60,
|
||||
),
|
||||
'70|2|1' =>
|
||||
array (
|
||||
'r' => 1,
|
||||
'g_id' => 2,
|
||||
'n_id' => 70,
|
||||
),
|
||||
'80|0|1' =>
|
||||
array (
|
||||
'r' => 1,
|
||||
'g_id' => 0,
|
||||
'n_id' => 80,
|
||||
),
|
||||
'40|2|1' =>
|
||||
array (
|
||||
'r' => 1,
|
||||
'g_id' => 2,
|
||||
'n_id' => 40,
|
||||
),
|
||||
),
|
||||
),
|
||||
2 =>
|
||||
array (
|
||||
'SQL' => '(`note_bezeichnung_id` = ? AND `geraet_id` = ? AND `run_number` = ?) OR (`note_bezeichnung_id` = ? AND `geraet_id` = ? AND `run_number` = ?)',
|
||||
'values' =>
|
||||
array (
|
||||
0 => 70,
|
||||
1 => 2,
|
||||
2 => 1,
|
||||
3 => 80,
|
||||
4 => 0,
|
||||
5 => 1,
|
||||
),
|
||||
'intersect_noten' =>
|
||||
array (
|
||||
'70|2|1' =>
|
||||
array (
|
||||
'r' => 1,
|
||||
'g_id' => 2,
|
||||
'n_id' => 70,
|
||||
),
|
||||
'80|0|1' =>
|
||||
array (
|
||||
'r' => 1,
|
||||
'g_id' => 0,
|
||||
'n_id' => 80,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
3 =>
|
||||
array (
|
||||
1 =>
|
||||
array (
|
||||
'SQL' => '(`note_bezeichnung_id` = ? AND `geraet_id` = ? AND `run_number` = ?) OR (`note_bezeichnung_id` = ? AND `geraet_id` = ? AND `run_number` = ?) OR (`note_bezeichnung_id` = ? AND `geraet_id` = ? AND `run_number` = ?) OR (`note_bezeichnung_id` = ? AND `geraet_id` = ? AND `run_number` = ?)',
|
||||
'values' =>
|
||||
array (
|
||||
0 => 60,
|
||||
1 => 3,
|
||||
2 => 1,
|
||||
3 => 70,
|
||||
4 => 3,
|
||||
5 => 1,
|
||||
6 => 80,
|
||||
7 => 0,
|
||||
8 => 1,
|
||||
9 => 40,
|
||||
10 => 3,
|
||||
11 => 1,
|
||||
),
|
||||
'intersect_noten' =>
|
||||
array (
|
||||
'60|3|1' =>
|
||||
array (
|
||||
'r' => 1,
|
||||
'g_id' => 3,
|
||||
'n_id' => 60,
|
||||
),
|
||||
'70|3|1' =>
|
||||
array (
|
||||
'r' => 1,
|
||||
'g_id' => 3,
|
||||
'n_id' => 70,
|
||||
),
|
||||
'80|0|1' =>
|
||||
array (
|
||||
'r' => 1,
|
||||
'g_id' => 0,
|
||||
'n_id' => 80,
|
||||
),
|
||||
'40|3|1' =>
|
||||
array (
|
||||
'r' => 1,
|
||||
'g_id' => 3,
|
||||
'n_id' => 40,
|
||||
),
|
||||
),
|
||||
),
|
||||
2 =>
|
||||
array (
|
||||
'SQL' => '(`note_bezeichnung_id` = ? AND `geraet_id` = ? AND `run_number` = ?) OR (`note_bezeichnung_id` = ? AND `geraet_id` = ? AND `run_number` = ?)',
|
||||
'values' =>
|
||||
array (
|
||||
0 => 70,
|
||||
1 => 3,
|
||||
2 => 1,
|
||||
3 => 80,
|
||||
4 => 0,
|
||||
5 => 1,
|
||||
),
|
||||
'intersect_noten' =>
|
||||
array (
|
||||
'70|3|1' =>
|
||||
array (
|
||||
'r' => 1,
|
||||
'g_id' => 3,
|
||||
'n_id' => 70,
|
||||
),
|
||||
'80|0|1' =>
|
||||
array (
|
||||
'r' => 1,
|
||||
'g_id' => 0,
|
||||
'n_id' => 80,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
4 =>
|
||||
array (
|
||||
1 =>
|
||||
array (
|
||||
'SQL' => '(`note_bezeichnung_id` = ? AND `geraet_id` = ? AND `run_number` = ?) OR (`note_bezeichnung_id` = ? AND `geraet_id` = ? AND `run_number` = ?) OR (`note_bezeichnung_id` = ? AND `geraet_id` = ? AND `run_number` = ?) OR (`note_bezeichnung_id` = ? AND `geraet_id` = ? AND `run_number` = ?)',
|
||||
'values' =>
|
||||
array (
|
||||
0 => 60,
|
||||
1 => 4,
|
||||
2 => 1,
|
||||
3 => 70,
|
||||
4 => 4,
|
||||
5 => 1,
|
||||
6 => 80,
|
||||
7 => 0,
|
||||
8 => 1,
|
||||
9 => 40,
|
||||
10 => 4,
|
||||
11 => 1,
|
||||
),
|
||||
'intersect_noten' =>
|
||||
array (
|
||||
'60|4|1' =>
|
||||
array (
|
||||
'r' => 1,
|
||||
'g_id' => 4,
|
||||
'n_id' => 60,
|
||||
),
|
||||
'70|4|1' =>
|
||||
array (
|
||||
'r' => 1,
|
||||
'g_id' => 4,
|
||||
'n_id' => 70,
|
||||
),
|
||||
'80|0|1' =>
|
||||
array (
|
||||
'r' => 1,
|
||||
'g_id' => 0,
|
||||
'n_id' => 80,
|
||||
),
|
||||
'40|4|1' =>
|
||||
array (
|
||||
'r' => 1,
|
||||
'g_id' => 4,
|
||||
'n_id' => 40,
|
||||
),
|
||||
),
|
||||
),
|
||||
2 =>
|
||||
array (
|
||||
'SQL' => '(`note_bezeichnung_id` = ? AND `geraet_id` = ? AND `run_number` = ?) OR (`note_bezeichnung_id` = ? AND `geraet_id` = ? AND `run_number` = ?)',
|
||||
'values' =>
|
||||
array (
|
||||
0 => 70,
|
||||
1 => 4,
|
||||
2 => 1,
|
||||
3 => 80,
|
||||
4 => 0,
|
||||
5 => 1,
|
||||
),
|
||||
'intersect_noten' =>
|
||||
array (
|
||||
'70|4|1' =>
|
||||
array (
|
||||
'r' => 1,
|
||||
'g_id' => 4,
|
||||
'n_id' => 70,
|
||||
),
|
||||
'80|0|1' =>
|
||||
array (
|
||||
'r' => 1,
|
||||
'g_id' => 0,
|
||||
'n_id' => 80,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
+133
@@ -0,0 +1,133 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
'default_values' => array (
|
||||
10 => 0.0,
|
||||
11 => 0.0,
|
||||
20 => 0.0,
|
||||
40 => 0.0,
|
||||
50 => 0.0,
|
||||
60 => 0.0,
|
||||
70 => 0.0,
|
||||
80 => 0.0,
|
||||
),
|
||||
'pro_geraet' => array (
|
||||
10 => 1,
|
||||
11 => 1,
|
||||
20 => 1,
|
||||
40 => 1,
|
||||
50 => 1,
|
||||
60 => 1,
|
||||
70 => 1,
|
||||
80 => 0,
|
||||
),
|
||||
'geraete_json' => array (
|
||||
10 =>
|
||||
array (
|
||||
),
|
||||
11 =>
|
||||
array (
|
||||
),
|
||||
20 =>
|
||||
array (
|
||||
),
|
||||
40 =>
|
||||
array (
|
||||
),
|
||||
50 =>
|
||||
array (
|
||||
),
|
||||
60 =>
|
||||
array (
|
||||
),
|
||||
70 =>
|
||||
array (
|
||||
),
|
||||
80 =>
|
||||
array (
|
||||
0 => 0,
|
||||
),
|
||||
),
|
||||
'anzahl_laeufe_json' => array (
|
||||
10 =>
|
||||
array (
|
||||
'default' => 1,
|
||||
1 =>
|
||||
array (
|
||||
'all' => 2,
|
||||
),
|
||||
),
|
||||
11 =>
|
||||
array (
|
||||
'default' => 1,
|
||||
1 =>
|
||||
array (
|
||||
'all' => 2,
|
||||
),
|
||||
),
|
||||
20 =>
|
||||
array (
|
||||
'default' => 1,
|
||||
1 =>
|
||||
array (
|
||||
'all' => 2,
|
||||
),
|
||||
),
|
||||
40 =>
|
||||
array (
|
||||
'default' => 1,
|
||||
1 =>
|
||||
array (
|
||||
'all' => 2,
|
||||
),
|
||||
),
|
||||
50 =>
|
||||
array (
|
||||
'default' => 1,
|
||||
1 =>
|
||||
array (
|
||||
'all' => 2,
|
||||
),
|
||||
),
|
||||
60 =>
|
||||
array (
|
||||
'default' => 1,
|
||||
1 =>
|
||||
array (
|
||||
'all' => 2,
|
||||
),
|
||||
),
|
||||
70 =>
|
||||
array (
|
||||
'default' => 1,
|
||||
),
|
||||
80 =>
|
||||
array (
|
||||
'default' => 0,
|
||||
0 =>
|
||||
array (
|
||||
'all' => 1,
|
||||
),
|
||||
),
|
||||
),
|
||||
'rechnungen' => array (
|
||||
10 => '',
|
||||
11 => '',
|
||||
20 => '({10[S]} + {11[S]}) / 2->RSGS',
|
||||
40 => '',
|
||||
50 => '',
|
||||
60 => '10 - {20[S]} + {40[S]} - {50[S]}->RSGS',
|
||||
70 => 'AVGR({60[S]})->R1GS',
|
||||
80 => '{70[1]} + {70[2]} + {70[3]} + {70[4]}->R1G0',
|
||||
),
|
||||
'nullstellen' => array (
|
||||
10 => 3,
|
||||
11 => 3,
|
||||
20 => 3,
|
||||
40 => 2,
|
||||
50 => 2,
|
||||
60 => 2,
|
||||
70 => 2,
|
||||
80 => 2,
|
||||
)
|
||||
];
|
||||
+163
@@ -0,0 +1,163 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
'default_values' => array (
|
||||
10 => 0.0,
|
||||
11 => 0.0,
|
||||
20 => 0.0,
|
||||
40 => 0.0,
|
||||
50 => 0.0,
|
||||
60 => 0.0,
|
||||
70 => 0.0,
|
||||
80 => 0.0,
|
||||
),
|
||||
'pro_geraet' => array (
|
||||
10 => 1,
|
||||
11 => 1,
|
||||
20 => 1,
|
||||
40 => 1,
|
||||
50 => 1,
|
||||
60 => 1,
|
||||
70 => 1,
|
||||
80 => 0,
|
||||
),
|
||||
'geraete_json' => array (
|
||||
10 =>
|
||||
array (
|
||||
),
|
||||
11 =>
|
||||
array (
|
||||
),
|
||||
20 =>
|
||||
array (
|
||||
),
|
||||
40 =>
|
||||
array (
|
||||
),
|
||||
50 =>
|
||||
array (
|
||||
),
|
||||
60 =>
|
||||
array (
|
||||
),
|
||||
70 =>
|
||||
array (
|
||||
),
|
||||
80 =>
|
||||
array (
|
||||
0 => 0,
|
||||
),
|
||||
),
|
||||
'anzahl_laeufe_json' => array (
|
||||
10 =>
|
||||
array (
|
||||
'default' => 1,
|
||||
1 =>
|
||||
array (
|
||||
'all' => 2,
|
||||
),
|
||||
),
|
||||
11 =>
|
||||
array (
|
||||
'default' => 1,
|
||||
1 =>
|
||||
array (
|
||||
'all' => 2,
|
||||
),
|
||||
),
|
||||
20 =>
|
||||
array (
|
||||
'default' => 1,
|
||||
1 =>
|
||||
array (
|
||||
'all' => 2,
|
||||
),
|
||||
),
|
||||
40 =>
|
||||
array (
|
||||
'default' => 1,
|
||||
1 =>
|
||||
array (
|
||||
'all' => 2,
|
||||
),
|
||||
),
|
||||
50 =>
|
||||
array (
|
||||
'default' => 1,
|
||||
1 =>
|
||||
array (
|
||||
'all' => 2,
|
||||
),
|
||||
),
|
||||
60 =>
|
||||
array (
|
||||
'default' => 1,
|
||||
1 =>
|
||||
array (
|
||||
'all' => 2,
|
||||
),
|
||||
),
|
||||
70 =>
|
||||
array (
|
||||
'default' => 1,
|
||||
),
|
||||
80 =>
|
||||
array (
|
||||
'default' => 0,
|
||||
0 =>
|
||||
array (
|
||||
'all' => 1,
|
||||
),
|
||||
),
|
||||
),
|
||||
'nullstellen' => array (
|
||||
10 => 3,
|
||||
11 => 3,
|
||||
20 => 3,
|
||||
40 => 2,
|
||||
50 => 2,
|
||||
60 => 2,
|
||||
70 => 2,
|
||||
80 => 2,
|
||||
),
|
||||
'zeige_in_rank_live' => array (
|
||||
10 => 1,
|
||||
11 => 1,
|
||||
20 => 1,
|
||||
40 => 1,
|
||||
50 => 1,
|
||||
60 => 1,
|
||||
70 => 1,
|
||||
80 => 1,
|
||||
),
|
||||
'display_string' => array (
|
||||
10 => '${note}',
|
||||
11 => '${note}',
|
||||
20 => '${note}',
|
||||
40 => 'D ${note}',
|
||||
50 => '${note}',
|
||||
60 => '${note}',
|
||||
70 => '${note}',
|
||||
80 => '${note}',
|
||||
),
|
||||
'store_run' => array (
|
||||
10 => 'A',
|
||||
11 => 'A',
|
||||
20 => 'A',
|
||||
40 => 'A',
|
||||
50 => 'A',
|
||||
60 => 'A',
|
||||
70 => 1,
|
||||
80 => 1,
|
||||
),
|
||||
'store_geraet' => array (
|
||||
10 => 'A',
|
||||
11 => 'A',
|
||||
20 => 'A',
|
||||
40 => 'A',
|
||||
50 => 'A',
|
||||
60 => 'A',
|
||||
70 => 'A',
|
||||
80 => 0,
|
||||
)
|
||||
];
|
||||
@@ -0,0 +1,185 @@
|
||||
<?php
|
||||
|
||||
function db_get_results($mysqli, $sql) {
|
||||
$result = $mysqli->query($sql);
|
||||
if (!$result) return [];
|
||||
return $result->fetch_all(MYSQLI_ASSOC);
|
||||
}
|
||||
|
||||
function db_get_row($mysqli, $sql) {
|
||||
$result = $mysqli->query($sql);
|
||||
if (!$result) return null;
|
||||
return $result->fetch_assoc();
|
||||
}
|
||||
|
||||
function db_get_col($mysqli, $sql) {
|
||||
$result = $mysqli->query($sql);
|
||||
if (!$result) return [];
|
||||
$col = [];
|
||||
while ($row = $result->fetch_row()) {
|
||||
$col[] = $row[0];
|
||||
}
|
||||
return $col;
|
||||
}
|
||||
|
||||
function db_update($mysqli, $table, $data, $where) {
|
||||
$set = [];
|
||||
$params = [];
|
||||
foreach ($data as $col => $val) {
|
||||
$set[] = "`$col` = ?";
|
||||
$params[] = $val;
|
||||
}
|
||||
|
||||
$cond = [];
|
||||
foreach ($where as $col => $val) {
|
||||
$cond[] = "`$col` = ?";
|
||||
$params[] = $val;
|
||||
}
|
||||
|
||||
$sql = "UPDATE `$table` SET ".implode(", ",$set)." WHERE ".implode(" AND ",$cond);
|
||||
$stmt = $mysqli->prepare($sql);
|
||||
|
||||
// Bind params dynamically
|
||||
$types = str_repeat("s", count($params));
|
||||
$stmt->bind_param($types, ...$params);
|
||||
|
||||
$stmt->execute();
|
||||
return $stmt->affected_rows;
|
||||
}
|
||||
|
||||
function db_delete($mysqli, $table, $where) {
|
||||
$params = [];
|
||||
|
||||
$cond = [];
|
||||
foreach ($where as $col => $val) {
|
||||
$cond[] = "`$col` = ?";
|
||||
$params[] = $val;
|
||||
}
|
||||
|
||||
$sql = "DELETE FROM `$table` WHERE ".implode(" AND ",$cond);
|
||||
$stmt = $mysqli->prepare($sql);
|
||||
|
||||
// Bind params dynamically
|
||||
$types = str_repeat("s", count($params));
|
||||
$stmt->bind_param($types, ...$params);
|
||||
|
||||
$stmt->execute();
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Select rows from a table using mysqli, safely with prepared statements.
|
||||
*
|
||||
* @param mysqli $mysqli The active mysqli connection
|
||||
* @param string $table Table name
|
||||
* @param array|string $columns Array of column names OR "*" for all columns
|
||||
* @param string|null $where Optional WHERE clause (without the "WHERE")
|
||||
* @param array $params Parameters for prepared statement (values only)
|
||||
* @param string|null $order Optional ORDER BY (e.g. "id DESC")
|
||||
* @param string|null $limit Optional LIMIT (e.g. "10", "0,20")
|
||||
* @return array Returns array of associative rows
|
||||
*/
|
||||
function db_select($mysqli, $table, $columns = "*", $where = null, $params = [], $order = null, $limit = null) {
|
||||
|
||||
// Convert array of columns into SQL string
|
||||
if (is_array($columns)) {
|
||||
$columns = implode(", ", array_map(fn($c) => "`$c`", $columns));
|
||||
}
|
||||
|
||||
$sql = "SELECT $columns FROM `$table`";
|
||||
|
||||
if ($where) {
|
||||
$sql .= " WHERE $where";
|
||||
}
|
||||
if ($order) {
|
||||
$sql .= " ORDER BY $order";
|
||||
}
|
||||
if ($limit) {
|
||||
$sql .= " LIMIT $limit";
|
||||
}
|
||||
|
||||
$stmt = $mysqli->prepare($sql);
|
||||
|
||||
if (!$stmt) {
|
||||
return []; // or throw exception
|
||||
}
|
||||
|
||||
// Bind params if there are any
|
||||
if (!empty($params)) {
|
||||
$types = str_repeat("s", count($params)); // simple: treat everything as string
|
||||
$stmt->bind_param($types, ...$params);
|
||||
}
|
||||
|
||||
$stmt->execute();
|
||||
$result = $stmt->get_result();
|
||||
|
||||
if (!$result) return [];
|
||||
|
||||
return $result->fetch_all(MYSQLI_ASSOC);
|
||||
}
|
||||
|
||||
function db_get_var($mysqli, $sql, $params = []) {
|
||||
$stmt = $mysqli->prepare($sql);
|
||||
if (!empty($params)) {
|
||||
$types = str_repeat('s', count($params));
|
||||
$stmt->bind_param($types, ...$params);
|
||||
}
|
||||
$stmt->execute();
|
||||
$stmt->bind_result($value);
|
||||
$stmt->fetch();
|
||||
$stmt->close();
|
||||
return $value;
|
||||
}
|
||||
|
||||
function db_get_variable($mysqli, $db_tabelle_var, $params = []) {
|
||||
if (count($params) !== 1) return null;
|
||||
$stmt = $mysqli->prepare("SELECT `value` FROM $db_tabelle_var WHERE `name` = ?");
|
||||
$stmt->bind_param("s", ...$params);
|
||||
$stmt->execute();
|
||||
$stmt->bind_result($value);
|
||||
$stmt->fetch();
|
||||
$stmt->close();
|
||||
return $value;
|
||||
}
|
||||
|
||||
function db_update_variable($mysqli, $db_tabelle_var, $params = ['name', 'value']) {
|
||||
if (count($params) !== 2) return false;
|
||||
$stmt = $mysqli->prepare("INSERT INTO $db_tabelle_var (`name`, `value`) VALUES (?, ?) ON DUPLICATE KEY UPDATE `value` = VALUES(`value`)");
|
||||
$stmt->bind_param("ss", ...$params);
|
||||
$stmt->execute();
|
||||
$stmt->close();
|
||||
return true;
|
||||
}
|
||||
|
||||
function db_check_var(mysqli $mysqli, string $table, string $where, array $params = []) : bool {
|
||||
|
||||
$table = preg_replace('/[^a-zA-Z0-9_]/', '', $table);
|
||||
|
||||
$stmt = $mysqli->prepare("SELECT 1 FROM `" . $table . "` WHERE " . $where);
|
||||
if (!$stmt) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!empty($params)) {
|
||||
$types = '';
|
||||
foreach ($params as $param) {
|
||||
if (is_int($param)) {
|
||||
$types .= 'i';
|
||||
} elseif (is_float($param)) {
|
||||
$types .= 'd';
|
||||
} else {
|
||||
$types .= 's';
|
||||
}
|
||||
}
|
||||
$stmt->bind_param($types, ...$params);
|
||||
}
|
||||
|
||||
$stmt->execute();
|
||||
|
||||
$stmt->store_result();
|
||||
$exists = $stmt->num_rows > 0;
|
||||
|
||||
$stmt->close();
|
||||
|
||||
return $exists;
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
<?php
|
||||
|
||||
use Dotenv\Dotenv;
|
||||
|
||||
require __DIR__ . '/../../composer/vendor/autoload.php';
|
||||
|
||||
$envFile = realpath(__DIR__ . '/../../config/.env.db-tables');
|
||||
|
||||
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.db-tables');
|
||||
|
||||
$dotenv->load();
|
||||
} catch (Throwable $e) {
|
||||
http_response_code(500);
|
||||
echo json_encode([
|
||||
'success' => false,
|
||||
'message' => "Dotenv error"
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
$prefix = $_ENV['DB_PREFIX'] ?? '';
|
||||
|
||||
|
||||
$tableDefinitions = [
|
||||
'teilnehmende' => 'DB_TABLE_TEILNEHMENDE',
|
||||
'verbuchte_startgebueren' => 'DB_TABLE_VERBUCHTE_STARTGEBUEREN',
|
||||
'warenkorb_startgebueren' => 'DB_TABLE_WARENKORB_STARTGEBUEREN',
|
||||
'var' => 'DB_TABLE_VARIABLES',
|
||||
'einmal_links' => 'DB_EINMAL_LINKS',
|
||||
'kategorien' => 'DB_TABLE_KATEGORIEN',
|
||||
'intern_benutzende' => 'DB_TABLE_INTERN_BENUTZENDE',
|
||||
'vereine' => 'DB_TABLE_VEREINE',
|
||||
'gruppen' => 'DB_TABLE_GRUPPEN',
|
||||
'teilnehmende_gruppen' => 'DB_TABLE_TEILNEHMENDE_GRUPPEN',
|
||||
'disziplinen' => 'DB_TABLE_DISZIPLINEN',
|
||||
'audiofiles' => 'DB_TABLE_AUDIOFILES',
|
||||
'teilnehmende_audiofiles' => 'DB_TABLE_TEILNEHMENDE_AUDIOFILES',
|
||||
'wertungen' => 'DB_TABLE_WERTUNGEN',
|
||||
'wertungen_log' => 'DB_TABLE_WERTUNGEN_LOG',
|
||||
'wertungstypen' => 'DB_TABLE_WERTUNGSTYPEN',
|
||||
'verbuchte_startgebueren_log' => 'DB_TABLE_VERBUCHTE_STARTGEBUEREN_LOG',
|
||||
'zeitplan_types' => 'DB_TABLE_ZEITPLAN_TYPES',
|
||||
'gruppen_zeiten' => 'DB_TABLE_GRUPPEN_ZEITEN',
|
||||
'tabellen_konfiguration' => 'DB_TABLE_TABELLEN_KONFIGURATION',
|
||||
'wettkaempfe' => 'DB_TABLE_WETTKAEMPFE'
|
||||
];
|
||||
|
||||
|
||||
foreach ($tableDefinitions as $baseName => $envVarKey) {
|
||||
|
||||
$rawTableName = $_ENV[$envVarKey] ?? '';
|
||||
|
||||
$fullTableName = $prefix . $rawTableName;
|
||||
|
||||
$variableName = 'db_tabelle_' . $baseName;
|
||||
|
||||
$$variableName = $fullTableName;
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
<?php
|
||||
|
||||
use Dotenv\Dotenv;
|
||||
|
||||
require __DIR__ . '/../../composer/vendor/autoload.php';
|
||||
|
||||
$envFile = realpath(__DIR__ . '/../../config/.env.db-guest');
|
||||
|
||||
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.db-guest');
|
||||
|
||||
$dotenv->load();
|
||||
} catch (Throwable $e) {
|
||||
http_response_code(500);
|
||||
echo json_encode([
|
||||
'success' => false,
|
||||
'message' => "Dotenv error"
|
||||
]);
|
||||
}
|
||||
|
||||
if (!isset($_ENV['DB_HOST']) || !isset($_ENV['DB_NAME']) || !isset($_ENV['DB_GUEST_USER']) || !isset($_ENV['DB_GUEST_PASSWORD']) || !isset($_ENV['DB_PORT'])){
|
||||
echo json_encode([
|
||||
'success' => false,
|
||||
'message' => 'corrupt cofig file'
|
||||
]);
|
||||
exit;
|
||||
}
|
||||
|
||||
$guest = @new mysqli($_ENV['DB_HOST'], $_ENV['DB_GUEST_USER'], $_ENV['DB_GUEST_PASSWORD'], $_ENV['DB_NAME'], $_ENV['DB_PORT']);
|
||||
if ($guest->connect_error) {
|
||||
echo json_encode([
|
||||
'success' => false,
|
||||
'message' => "DB connection failed"
|
||||
]);
|
||||
exit;
|
||||
}
|
||||
|
||||
$guest->set_charset("utf8");
|
||||
@@ -0,0 +1,80 @@
|
||||
<?php
|
||||
|
||||
use Dotenv\Dotenv;
|
||||
|
||||
require_once __DIR__ . '/../session_functions.php';
|
||||
|
||||
ini_wkvs_session();
|
||||
|
||||
if (!isset($type)){
|
||||
return [
|
||||
'success' => false,
|
||||
'message' => 'no type'
|
||||
];
|
||||
}
|
||||
|
||||
if ($type === 'kr'){
|
||||
check_user_permission('kampfrichter');
|
||||
} elseif ($type === 'tr'){
|
||||
check_user_permission('trainer');
|
||||
} elseif ($type === 'wkl') {
|
||||
check_user_permission('wk_leitung');
|
||||
} elseif ($type === 'otl') {
|
||||
if (empty($_SESSION['access_granted_db_otl']) || $_SESSION['access_granted_db_otl'] !== true) {
|
||||
http_response_code(403);
|
||||
exit;
|
||||
}
|
||||
} else {
|
||||
http_response_code(403);
|
||||
exit;
|
||||
}
|
||||
|
||||
require __DIR__ . '/../../composer/vendor/autoload.php';
|
||||
|
||||
$envFile = realpath(__DIR__ . '/../../config/.env.db');
|
||||
|
||||
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.db');
|
||||
|
||||
$dotenv->load();
|
||||
} catch (Throwable $e) {
|
||||
http_response_code(500);
|
||||
echo json_encode([
|
||||
'success' => false,
|
||||
'message' => "Dotenv error"
|
||||
]);
|
||||
}
|
||||
|
||||
if (!isset($_ENV['DB_HOST']) || !isset($_ENV['DB_NAME']) || !isset($_ENV['DB_USER']) || !isset($_ENV['DB_PASSWORD']) || !isset($_ENV['DB_PORT'])){
|
||||
echo json_encode([
|
||||
'success' => false,
|
||||
'message' => 'corrupt cofig file'
|
||||
]);
|
||||
exit;
|
||||
}
|
||||
|
||||
$mysqli = @new mysqli($_ENV['DB_HOST'], $_ENV['DB_USER'], $_ENV['DB_PASSWORD'], $_ENV['DB_NAME'], $_ENV['DB_PORT']);
|
||||
if ($mysqli->connect_error) {
|
||||
echo json_encode([
|
||||
'success' => false,
|
||||
'message' => "DB connection failed"
|
||||
]);
|
||||
exit;
|
||||
}
|
||||
|
||||
$mysqli->set_charset("utf8");
|
||||
|
||||
return [
|
||||
'success' => true
|
||||
];
|
||||
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
function parse_input_to_delete() {
|
||||
global $_DELETE;
|
||||
$_DELETE = [];
|
||||
|
||||
if ($_SERVER['REQUEST_METHOD'] !== 'DELETE') {
|
||||
http_response_code(405);
|
||||
echo json_encode(['success' => false, 'message' => 'Method not allowed']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$rawInput = file_get_contents('php://input');
|
||||
|
||||
$contentType = $_SERVER['CONTENT_TYPE'] ?? '';
|
||||
if (stripos($contentType, 'application/json') !== false) {
|
||||
$_DELETE = json_decode($rawInput, true) ?? [];
|
||||
} else {
|
||||
parse_str($rawInput, $_DELETE);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
<?php
|
||||
// ========== Access control setup ==========
|
||||
$userid = intval($_SESSION['user_id_kampfrichter'] ?? 0);
|
||||
$arrayfreigaben = [];
|
||||
|
||||
if ($userid > 0) {
|
||||
$stmt = $mysqli->prepare("SELECT freigabe, username FROM $db_tabelle_intern_benutzende WHERE id = ?");
|
||||
$stmt->bind_param("s", $userid);
|
||||
$stmt->execute();
|
||||
$result = $stmt->get_result();
|
||||
|
||||
if ($result) {
|
||||
$dbarray = $result->fetch_assoc();
|
||||
}
|
||||
|
||||
$freigabe_json = $dbarray['freigabe'] ?? '';
|
||||
$username = $dbarray['username'] ?? '';
|
||||
|
||||
$stmt->close();
|
||||
|
||||
// Only decode if it’s a string
|
||||
if (is_string($freigabe_json) && $freigabe_json !== '') {
|
||||
$arrayfreigaben = json_decode($freigabe_json, true) ?: [];
|
||||
$arrayfreigaben = $arrayfreigaben['freigabenKampfrichter'] ?? [];
|
||||
}
|
||||
}
|
||||
if (empty($arrayfreigaben)) {
|
||||
echo 'Keine gültigen Freigaben! Sie wurden abgemeldet.';
|
||||
$_SESSION['access_granted_kampfrichter'] = false;
|
||||
$_SESSION['logoDisplay'] = true;
|
||||
exit;
|
||||
}
|
||||
|
||||
$key = array_search("A", $arrayfreigaben, true);
|
||||
if ($key !== false) {
|
||||
unset($arrayfreigaben[$key]);
|
||||
array_unshift($arrayfreigaben, "A");
|
||||
$arrayfreigaben = array_values($arrayfreigaben);
|
||||
}
|
||||
|
||||
$selectedFreigabeId = $_SESSION['selectedFreigabeIdKampfrichter'] ?? $arrayfreigaben[0];
|
||||
|
||||
if (!in_array($selectedFreigabeId, $arrayfreigaben, true)) {
|
||||
$selectedFreigabeId = $arrayfreigaben[0];
|
||||
}
|
||||
|
||||
$_SESSION['selectedFreigabeIdKampfrichter'] = $selectedFreigabeId;
|
||||
|
||||
$isAdmin = $selectedFreigabeId === 'A';
|
||||
@@ -0,0 +1,121 @@
|
||||
<?php
|
||||
|
||||
// ========== Form handling logic ==========
|
||||
$form_message = $_SESSION['form_message'] ?? '';
|
||||
unset($_SESSION['form_message']);
|
||||
|
||||
if (isset($_POST['prev_abt_submit'])) {
|
||||
verify_csrf();
|
||||
$value = $aktabt;
|
||||
if ($value > 1){
|
||||
$value -= 1;
|
||||
db_update_variable($mysqli, $db_tabelle_var, ['wk_panel_current_abt', $value]);
|
||||
}
|
||||
header("Location: /intern/kampfrichter");
|
||||
exit;
|
||||
}
|
||||
|
||||
if (isset($_POST['next_abt_submit'])) {
|
||||
verify_csrf();
|
||||
$value = $aktabt;
|
||||
$maxvalue = (int) (db_get_var($mysqli, "SELECT `order_index` FROM $db_tabelle_gruppen ORDER BY `order_index` DESC LIMIT 1") ?? 1);
|
||||
|
||||
if ($value < $maxvalue){
|
||||
$value += 1;
|
||||
db_update_variable($mysqli, $db_tabelle_var, ['wk_panel_current_abt', $value]);
|
||||
}
|
||||
header("Location: /intern/kampfrichter");
|
||||
exit;
|
||||
}
|
||||
|
||||
if (isset($_POST['prev_subabt_admin_submit']) && $isAdmin) {
|
||||
verify_csrf();
|
||||
$value = $akt_subabt_admin;
|
||||
if ($value > 1){
|
||||
$value -= 1;
|
||||
db_update_variable($mysqli, $db_tabelle_var, ['wk_panel_current_subabt_admin', $value]);
|
||||
$_SESSION['ws_Message_json'] = json_encode(['type' => 'UPDATE_RANKLIVE_C_SUBABT', 'payload' => []]);
|
||||
}
|
||||
header("Location: /intern/kampfrichter");
|
||||
exit;
|
||||
}
|
||||
|
||||
if (isset($_POST['next_subabt_admin_submit']) && $isAdmin) {
|
||||
verify_csrf();
|
||||
$value = $akt_subabt_admin;
|
||||
$max_value_admin_subabt = count($disciplines);
|
||||
|
||||
if ($value < $max_value_admin_subabt){
|
||||
$value += 1;
|
||||
db_update_variable($mysqli, $db_tabelle_var, ['wk_panel_current_subabt_admin', $value]);
|
||||
$_SESSION['ws_Message_json'] = json_encode(['type' => 'UPDATE_RANKLIVE_C_SUBABT', 'payload' => []]);
|
||||
}
|
||||
|
||||
header("Location: /intern/kampfrichter");
|
||||
exit;
|
||||
}
|
||||
|
||||
|
||||
if (!isset($_SESSION['currentsubabt'])){
|
||||
$_SESSION['currentsubabt'] = 1;
|
||||
}
|
||||
|
||||
if (!isset($_SESSION['last_abt'])){
|
||||
$_SESSION['last_abt'] = $aktabt;
|
||||
}
|
||||
|
||||
if ($_SESSION['last_abt'] !== $aktabt){
|
||||
$_SESSION['currentsubabt'] = 1;
|
||||
$_SESSION['last_abt'] = $aktabt;
|
||||
}
|
||||
|
||||
if (isset($_POST['prev_subabt_submit'])) {
|
||||
verify_csrf();
|
||||
$value = $_SESSION['currentsubabt'];
|
||||
if ($value > 1){
|
||||
$_SESSION['currentsubabt']--;
|
||||
$_SESSION['currentEditId'] = false;
|
||||
$_SESSION['last_abt'] = $aktabt;
|
||||
}
|
||||
header("Location: /intern/kampfrichter");
|
||||
exit;
|
||||
}
|
||||
|
||||
if (isset($_POST['next_subabt_submit'])) {
|
||||
verify_csrf();
|
||||
$value = $_SESSION['currentsubabt'];
|
||||
if ($value < $max_subabt){
|
||||
$_SESSION['currentsubabt']++;
|
||||
$_SESSION['currentEditId'] = false;
|
||||
$_SESSION['last_abt'] = $aktabt;
|
||||
}
|
||||
header("Location: /intern/kampfrichter");
|
||||
exit;
|
||||
}
|
||||
|
||||
if (isset($_POST['prog_view_admin_submit'])) {
|
||||
verify_csrf();
|
||||
|
||||
$_SESSION['view_type_admin'] = 'prog';
|
||||
|
||||
header("Location: /intern/kampfrichter");
|
||||
exit;
|
||||
}
|
||||
|
||||
if (isset($_POST['abt_view_admin_submit'])) {
|
||||
verify_csrf();
|
||||
|
||||
$_SESSION['view_type_admin'] = 'abt';
|
||||
|
||||
header("Location: /intern/kampfrichter");
|
||||
exit;
|
||||
}
|
||||
|
||||
if (isset($_POST['live_view_admin_submit'])) {
|
||||
verify_csrf();
|
||||
|
||||
$_SESSION['view_type_admin'] = 'live';
|
||||
|
||||
header("Location: /intern/kampfrichter");
|
||||
exit;
|
||||
}
|
||||
@@ -0,0 +1,173 @@
|
||||
<?php
|
||||
|
||||
require_once __DIR__ . '/../rate-limiter/rate-limiter.php';
|
||||
|
||||
$limiter = new TokenBucket(
|
||||
redis: $redis,
|
||||
capacity: 30,
|
||||
refillRate: 2,
|
||||
refillInterval: 5.0
|
||||
);
|
||||
|
||||
$result = $limiter->allow('RATE_LIMITER:TYPE:login:IP:'. $_SERVER['REMOTE_ADDR']);
|
||||
|
||||
if (!$result['allowed']) {
|
||||
http_response_code(429);
|
||||
include __DIR__ . "/../../www/error-pages/429.html";
|
||||
exit;
|
||||
}
|
||||
|
||||
require_once __DIR__ . '/../session_functions.php';
|
||||
|
||||
ini_wkvs_session();
|
||||
|
||||
if (!isset($error)) {
|
||||
$error = '';
|
||||
}
|
||||
|
||||
// Initialize session variables if not set
|
||||
if (!isset($_SESSION['login_attempts_'. $logintype])) {
|
||||
$_SESSION['login_attempts_'. $logintype] = 0;
|
||||
$_SESSION['lockout_time_'. $logintype] = 0;
|
||||
}
|
||||
|
||||
$max_attempts = 5;
|
||||
$lockout_period = 5 * 60;
|
||||
|
||||
// Check if user is locked out
|
||||
if ($_SESSION['lockout_time_'. $logintype] > time()) {
|
||||
$remaining = $_SESSION['lockout_time_'. $logintype] - time();
|
||||
$minutes = ceil($remaining / 60);
|
||||
$error = "Zu viele fehlgeschlagene Anmeldeversuche. Bitte warte $minutes Minute(n).";
|
||||
} elseif (isset($_POST[$logintype.'_login_submit'])) {
|
||||
|
||||
require __DIR__ .'/../db/db-verbindung-script-guest.php';
|
||||
|
||||
require __DIR__ . "/../db/db-tables.php";
|
||||
|
||||
|
||||
$username = htmlspecialchars(trim($_POST['access_username']), ENT_QUOTES);
|
||||
$password = trim($_POST['access_passcode']);
|
||||
|
||||
// Prepare statement
|
||||
$stmt = $guest->prepare("SELECT * FROM $db_tabelle_intern_benutzende 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();
|
||||
|
||||
if (!$user) {
|
||||
$_SESSION['login_attempts_'. $logintype]++;
|
||||
|
||||
if ($_SESSION['login_attempts_'. $logintype] >= $max_attempts) {
|
||||
$_SESSION['lockout_time_'. $logintype] = time() + $lockout_period;
|
||||
$error = "Zu viele fehlgeschlagene Anmeldeversuche. Bitte versuche es in ".ceil($lockout_period / 60)." Minuten erneut.";
|
||||
} else {
|
||||
$remaining_attempts = $max_attempts - $_SESSION['login_attempts_'. $logintype];
|
||||
$error = "Benutzer / Passwort unbekannt. Noch $remaining_attempts Versuch(e) möglich.";
|
||||
}
|
||||
} else {
|
||||
$freigaben = json_decode($user['freigabe'], true) ?: [];
|
||||
|
||||
$freigabe_values = $freigaben['types'] ?? [];
|
||||
|
||||
// Verify password using PHP native function
|
||||
if (password_verify($password, $user['password_hash']) && in_array($logintype, $freigabe_values)) {
|
||||
foreach ($freigabe_values as $freigabe) {
|
||||
$_SESSION['access_granted_'. $freigabe] = true;
|
||||
$_SESSION['user_id_'. $freigabe] = $user['id'];
|
||||
$_SESSION['lockout_time_'. $freigabe] = 0;
|
||||
$_SESSION['login_attempts_'. $freigabe] = 0;
|
||||
}
|
||||
|
||||
// Redirect using plain PHP
|
||||
header("Location:" . $_SERVER['REQUEST_URI']);
|
||||
exit;
|
||||
} elseif ($password === ' ') {
|
||||
$error = "Kein Passwort eingegeben.";
|
||||
} else {
|
||||
$_SESSION['login_attempts_'. $logintype]++;
|
||||
|
||||
if ($_SESSION['login_attempts_'. $logintype] >= $max_attempts) {
|
||||
$_SESSION['lockout_time_'. $logintype] = time() + $lockout_period;
|
||||
$error = "Zu viele fehlgeschlagene Anmeldeversuche. Bitte versuche es in ".ceil($lockout_period / 60)." Minuten erneut.";
|
||||
} else {
|
||||
$remaining_attempts = $max_attempts - $_SESSION['login_attempts_'. $logintype];
|
||||
$error = "Benutzer / Passwort unbekannt. Noch $remaining_attempts Versuch(e) möglich.";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$array_logintitles = [
|
||||
'wk_leitung' => 'Wettkampfleitung',
|
||||
'trainer' => 'Trainer',
|
||||
'kampfrichter' => 'Kampfrichter'
|
||||
]
|
||||
?>
|
||||
<!DOCTYPE html>
|
||||
<html lang="de">
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Login <?= $array_logintitles[$logintype] ?></title>
|
||||
<link rel="icon" type="png" href="/intern/img/icon.png">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link rel="stylesheet" href="/intern/css/login.css">
|
||||
<link href="/files/fonts/fonts.css" rel="stylesheet">
|
||||
<link rel="stylesheet" href="/intern/css/user.css">
|
||||
|
||||
</head>
|
||||
|
||||
<body class="login">
|
||||
<section class="page-secure-login">
|
||||
<div class="bg-picture-secure-login">
|
||||
<img src="/intern/img/login/bg<?= ucfirst($logintype) ?>.webp">
|
||||
</div>
|
||||
<div class="bg-secure-login">
|
||||
<div class="bg-secure-login-form">
|
||||
<h1>Anmeldung<br><?= $array_logintitles[$logintype] ?? "" ?></h1>
|
||||
|
||||
<form method="post">
|
||||
<label for="access_username">Benutzername eingeben</label><br>
|
||||
<input type="text" id="access_username" name="access_username" required placeholder="Benutzername"><br>
|
||||
<label for="password">Passwort eingeben</label><br>
|
||||
<div id="div_showpw">
|
||||
<input type="password" name="access_passcode" id="access_passcode" placeholder="Passwort" required>
|
||||
<button type="button" id="togglePassword">
|
||||
<svg id="eyeIcon" xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none" stroke="#000" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z"/>
|
||||
<circle cx="12" cy="12" r="3"/>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
<input type="submit" name="<?= $logintype ?>_login_submit" value="Einloggen">
|
||||
</form>
|
||||
|
||||
<?php if ($error !== ''): ?>
|
||||
<p style="color:red;"><?php echo $error; ?></p>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<a class="seclog_home_link" href="/"><img src="/intern/img/logo-normal.png"></a>
|
||||
|
||||
<script>
|
||||
const passwordInput = document.getElementById('access_passcode');
|
||||
const toggleButton = document.getElementById('togglePassword');
|
||||
const eyeIcon = document.getElementById('eyeIcon');
|
||||
|
||||
toggleButton.addEventListener('click', () => {
|
||||
const type = passwordInput.getAttribute('type') === 'password' ? 'text' : 'password';
|
||||
passwordInput.setAttribute('type', type);
|
||||
|
||||
if (type === 'password') {
|
||||
eyeIcon.innerHTML = '<path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z"/><circle cx="12" cy="12" r="3"/>';
|
||||
} else {
|
||||
eyeIcon.innerHTML = '<path d="M17.94 17.94L6.06 6.06"/><path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z"/><circle cx="12" cy="12" r="3"/>';
|
||||
}
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
@@ -0,0 +1,104 @@
|
||||
<?php
|
||||
|
||||
use PHPMailer\PHPMailer\PHPMailer;
|
||||
use PHPMailer\PHPMailer\Exception;
|
||||
use Dotenv\Dotenv;
|
||||
|
||||
require __DIR__ . '/../../composer/vendor/autoload.php';
|
||||
|
||||
$envFile = realpath(__DIR__ . '/../../config/.env.mail');
|
||||
|
||||
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.mail');
|
||||
|
||||
$dotenv->load();
|
||||
} catch (Throwable $e) {
|
||||
http_response_code(500);
|
||||
echo json_encode([
|
||||
'success' => false,
|
||||
'message' => "Dotenv error"
|
||||
]);
|
||||
}
|
||||
|
||||
function newMailer() {
|
||||
global $mailer;
|
||||
|
||||
if (isset($mailer) && $mailer instanceof PHPMailer) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
$mailer = new PHPMailer(true);
|
||||
|
||||
$mailer->isSMTP();
|
||||
$mailer->CharSet = 'UTF-8';
|
||||
$mailer->Host = $_ENV['MAIL_SERVER'];
|
||||
$mailer->SMTPAuth = true;
|
||||
$mailer->Username = $_ENV['MAIL_USER'];
|
||||
$mailer->Password = $_ENV['MAIL_USER_PASSWORD'];
|
||||
|
||||
$port = (int)$_ENV['MAIL_PORT'];
|
||||
if ($port === 465) {
|
||||
$mailer->SMTPSecure = PHPMailer::ENCRYPTION_SMTPS;
|
||||
} else {
|
||||
$mailer->SMTPSecure = PHPMailer::ENCRYPTION_STARTTLS;
|
||||
$mailer->Port = 587;
|
||||
}
|
||||
|
||||
$mailer->Port = $port;
|
||||
|
||||
$mailer->setFrom($_ENV['MAIL_USER'], 'WKVS');
|
||||
|
||||
} catch (Exception $e) {
|
||||
throw new Exception("Konfigurationsfehler des Automailers: " . $e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
function sendMail(string $content = '', string $subject = '', array $recipients = []) {
|
||||
global $mailer;
|
||||
|
||||
if (empty($recipients)) {
|
||||
throw new Exception("Keine Empfänger angegeben");
|
||||
}
|
||||
|
||||
if (!isset($mailer) || !($mailer instanceof PHPMailer)) {
|
||||
try {
|
||||
newMailer();
|
||||
} catch (Exception $e) {
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
foreach ($recipients as $email => $name) {
|
||||
$mailer->addAddress($email, $name);
|
||||
}
|
||||
|
||||
$mailer->isHTML(true);
|
||||
$mailer->Subject = $subject;
|
||||
$mailer->Body = $content;
|
||||
$mailer->AltBody = strip_tags($content);
|
||||
|
||||
if (!$mailer->send()) {
|
||||
throw new Exception("Sendefehler " . $mailer->ErrorInfo);
|
||||
}
|
||||
|
||||
return true;
|
||||
} catch (Exception $e) {
|
||||
error_log("Kritischer Sendefehler: " . $e->getMessage());
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
@@ -0,0 +1,16 @@
|
||||
<header>
|
||||
<a class="rankLiveHeaderTitle" href="/RankLive">
|
||||
RankLive
|
||||
</a>
|
||||
<div class="menuLinksDiv">
|
||||
<?php include __DIR__ ."/rankLive-menu.php"?>
|
||||
</div>
|
||||
<div class="burgerMenuDiv">
|
||||
<div class="burgerMenuLine"></div>
|
||||
<div class="burgerMenuLine"></div>
|
||||
<div class="burgerMenuLine"></div>
|
||||
</div>
|
||||
</header>
|
||||
<div class="sidebar">
|
||||
<?php include __DIR__ ."/rankLive-menu.php"?>
|
||||
</div>
|
||||
@@ -0,0 +1,55 @@
|
||||
<?php
|
||||
|
||||
if (!isset($guest) || !$guest instanceof mysqli) {
|
||||
require $_SERVER['DOCUMENT_ROOT'] . "/../scripts/db/db-verbindung-script-guest.ph";
|
||||
}
|
||||
|
||||
$result = $guest->query("SELECT `programm` FROM $db_tabelle_kategorien WHERE `aktiv` = '1'");
|
||||
|
||||
$yearsGalleryArray = [];
|
||||
|
||||
while ($row = $result->fetch_assoc()) {
|
||||
$kategorien[str_replace(' ', '-', strtolower(htmlspecialchars($row['programm'])))] = htmlspecialchars($row['programm']);
|
||||
}
|
||||
|
||||
?>
|
||||
|
||||
|
||||
<a href="/RankLive/live" class="menu-item">
|
||||
<svg class="menu-icon" xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<circle cx="12" cy="12" r="10"/>
|
||||
<polygon points="10 8 16 12 10 16 10 8"/>
|
||||
</svg>
|
||||
Aktueller Durchgang
|
||||
</a>
|
||||
|
||||
<a href="/RankLive/" class="menu-item">
|
||||
<svg class="menu-icon" xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<line x1="18" y1="20" x2="18" y2="10"/>
|
||||
<line x1="12" y1="20" x2="12" y2="4"/>
|
||||
<line x1="6" y1="20" x2="6" y2="14"/>
|
||||
</svg>
|
||||
Alle Ergebnisse
|
||||
</a>
|
||||
|
||||
<?php if ($kategorien !== []): ?>
|
||||
<div>
|
||||
<span class="menu-item">
|
||||
<svg class="menu-icon" xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<rect x="3" y="3" width="7" height="7"/>
|
||||
<rect x="14" y="3" width="7" height="7"/>
|
||||
<rect x="14" y="14" width="7" height="7"/>
|
||||
<rect x="3" y="14" width="7" height="7"/>
|
||||
</svg>
|
||||
Kategorien
|
||||
<svg class="menu-chevron" viewBox="0 0 16 16" width="14" height="14" aria-hidden="true" focusable="false" style="margin-left: auto;">
|
||||
<path fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round" d="M2.5 5.5L8 11l5.5-5.5"></path>
|
||||
</svg>
|
||||
</span>
|
||||
<div class="dropdown">
|
||||
<?php foreach ($kategorien as $kat_slug => $kat_name) : ?>
|
||||
<a href="/RankLive/programm/<?= $kat_slug ?>"><?= $kat_name ?></a>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
@@ -0,0 +1,218 @@
|
||||
<?php
|
||||
|
||||
use Predis\Client as PredisClient;
|
||||
use Dotenv\Dotenv;
|
||||
|
||||
require __DIR__ . '/../../composer/vendor/autoload.php';
|
||||
|
||||
$envFile = realpath(__DIR__ . '/../../config/.env.redis');
|
||||
|
||||
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.redis');
|
||||
|
||||
$dotenv->load();
|
||||
} catch (Throwable $e) {
|
||||
http_response_code(500);
|
||||
echo json_encode([
|
||||
'success' => false,
|
||||
'message' => "Dotenv error"
|
||||
]);
|
||||
}
|
||||
|
||||
// Create a Redis connection
|
||||
$redis = new PredisClient([
|
||||
'scheme' => 'tcp',
|
||||
'host' => $_ENV['REDDIS_HOST'],
|
||||
'port' => $_ENV['REDDIS_PORT'],
|
||||
'password' => $_ENV['REDDIS_PASSWORD']
|
||||
]);
|
||||
|
||||
/**
|
||||
* Token Bucket Rate Limiter
|
||||
*
|
||||
* A Redis-based token bucket rate limiter implementation using Lua scripts
|
||||
* for atomic operations.
|
||||
*
|
||||
* The token bucket algorithm allows requests at a controlled rate by maintaining
|
||||
* a bucket of tokens that refills over time. Each request consumes a token, and
|
||||
* requests are denied when the bucket is empty.
|
||||
*
|
||||
* Requires: predis/predis
|
||||
*/
|
||||
|
||||
/**
|
||||
* Token bucket rate limiter using Redis for distributed rate limiting.
|
||||
*
|
||||
* The token bucket maintains a fixed capacity of tokens that refill at a
|
||||
* constant rate. Each request consumes one token. When the bucket is empty,
|
||||
* requests are denied until tokens refill.
|
||||
*
|
||||
* Example:
|
||||
* $redis = new Predis\Client(['host' => '127.0.0.1', 'port' => 6379]);
|
||||
* $limiter = new TokenBucket(10, 1, 1.0, $redis);
|
||||
* $result = $limiter->allow('user:123');
|
||||
* if ($result['allowed']) {
|
||||
* echo "Request allowed. {$result['remaining']} tokens remaining.";
|
||||
* } else {
|
||||
* echo "Request denied. Rate limit exceeded.";
|
||||
* }
|
||||
*/
|
||||
class TokenBucket
|
||||
{
|
||||
/** @var string Lua script for atomic token bucket operations */
|
||||
private const LUA_SCRIPT = <<<'LUA'
|
||||
local key = KEYS[1]
|
||||
local capacity = tonumber(ARGV[1])
|
||||
local refill_rate = tonumber(ARGV[2])
|
||||
local refill_interval = tonumber(ARGV[3])
|
||||
local now = tonumber(ARGV[4])
|
||||
|
||||
-- Get current state or initialize
|
||||
local bucket = redis.call('HMGET', key, 'tokens', 'last_refill')
|
||||
local tokens = tonumber(bucket[1])
|
||||
local last_refill = tonumber(bucket[2])
|
||||
|
||||
-- Initialize if this is the first request
|
||||
if tokens == nil then
|
||||
tokens = capacity
|
||||
last_refill = now
|
||||
end
|
||||
|
||||
-- Calculate token refill
|
||||
local time_passed = now - last_refill
|
||||
local refills = math.floor(time_passed / refill_interval)
|
||||
|
||||
if refills > 0 then
|
||||
tokens = math.min(capacity, tokens + (refills * refill_rate))
|
||||
last_refill = last_refill + (refills * refill_interval)
|
||||
end
|
||||
|
||||
-- Try to consume a token
|
||||
local allowed = 0
|
||||
if tokens >= 1 then
|
||||
tokens = tokens - 1
|
||||
allowed = 1
|
||||
end
|
||||
|
||||
-- Update state
|
||||
redis.call('HSET', key, 'tokens', tokens, 'last_refill', last_refill)
|
||||
|
||||
-- Delete the key after one hour
|
||||
redis.call('EXPIRE', key, 3600)
|
||||
|
||||
-- Return result: allowed (1 or 0) and remaining tokens
|
||||
return {allowed, tokens}
|
||||
LUA;
|
||||
|
||||
/** @var PredisClient */
|
||||
private $redis;
|
||||
|
||||
/** @var int */
|
||||
private $capacity;
|
||||
|
||||
/** @var float */
|
||||
private $refillRate;
|
||||
|
||||
/** @var float */
|
||||
private $refillInterval;
|
||||
|
||||
/** @var string */
|
||||
private $scriptSha;
|
||||
|
||||
/** @var bool */
|
||||
private $scriptLoaded = false;
|
||||
|
||||
/**
|
||||
* Initialize the token bucket rate limiter.
|
||||
*
|
||||
* @param int $capacity Maximum number of tokens in the bucket (default: 10)
|
||||
* @param float $refillRate Number of tokens added per refill interval (default: 1.0)
|
||||
* @param float $refillInterval Time in seconds between refills (default: 1.0)
|
||||
* @param PredisClient|null $redis Predis client instance. If null, creates a default client.
|
||||
*/
|
||||
public function __construct(
|
||||
int $capacity = 10,
|
||||
float $refillRate = 1.0,
|
||||
float $refillInterval = 1.0,
|
||||
?PredisClient $redis = null
|
||||
) {
|
||||
$this->capacity = $capacity;
|
||||
$this->refillRate = $refillRate;
|
||||
$this->refillInterval = $refillInterval;
|
||||
$this->redis = $redis ?? new PredisClient([
|
||||
'host' => '127.0.0.1',
|
||||
'port' => 6379,
|
||||
]);
|
||||
$this->scriptSha = sha1(self::LUA_SCRIPT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure the Lua script is loaded into Redis.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private function ensureScriptLoaded(): void
|
||||
{
|
||||
if (!$this->scriptLoaded) {
|
||||
try {
|
||||
$this->scriptSha = $this->redis->script('LOAD', self::LUA_SCRIPT);
|
||||
$this->scriptLoaded = true;
|
||||
} catch (\Exception $e) {
|
||||
// If loading fails, we'll fall back to EVAL
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a request should be allowed for the given key.
|
||||
*
|
||||
* @param string $key The rate limit key (e.g., 'user:123', 'api:endpoint:xyz')
|
||||
*
|
||||
* @return array{allowed: bool, remaining: float} An associative array with:
|
||||
* - 'allowed': true if the request is allowed, false otherwise
|
||||
* - 'remaining': number of tokens remaining in the bucket
|
||||
*
|
||||
* Example:
|
||||
* $result = $limiter->allow('user:123');
|
||||
* echo "Allowed: " . ($result['allowed'] ? 'yes' : 'no');
|
||||
* echo "Remaining: {$result['remaining']}";
|
||||
*/
|
||||
public function allow(string $key): array
|
||||
{
|
||||
$this->ensureScriptLoaded();
|
||||
|
||||
$now = microtime(true);
|
||||
$args = [
|
||||
$this->capacity,
|
||||
$this->refillRate,
|
||||
$this->refillInterval,
|
||||
$now,
|
||||
];
|
||||
|
||||
try {
|
||||
// Try EVALSHA first (faster if script is cached)
|
||||
$result = $this->redis->evalsha($this->scriptSha, 1, $key, ...$args);
|
||||
} catch (\Exception $e) {
|
||||
// Script not in cache, use EVAL and reload
|
||||
$result = $this->redis->eval(self::LUA_SCRIPT, 1, $key, ...$args);
|
||||
$this->scriptLoaded = false;
|
||||
}
|
||||
|
||||
return [
|
||||
'allowed' => (bool) $result[0],
|
||||
'remaining' => (float) $result[1],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,154 @@
|
||||
<?php
|
||||
|
||||
function update_teilnehmende($ids_json = '', $old_status, $new_status, bool $ids_are_array = false) {
|
||||
global $mysqli;
|
||||
global $db_tabelle_teilnehmende;
|
||||
global $db_tabelle_kategorien;
|
||||
|
||||
// 1. Quick exits
|
||||
if (intval($old_status) === intval($new_status)) return false;
|
||||
|
||||
if (!$ids_are_array) {
|
||||
$programm_ids = json_decode($ids_json, true) ?? [];
|
||||
} else {
|
||||
if (!is_array($ids_json)) return false;
|
||||
$programm_ids = $ids_json;
|
||||
}
|
||||
|
||||
if (count($programm_ids) < 1) return false;
|
||||
|
||||
// 2. Extract IDs (which are the keys of the associative array)
|
||||
$ids = array_keys($programm_ids);
|
||||
$tparams = implode(", ", array_fill(0, count($ids), "?"));
|
||||
|
||||
// 3. Fetch current paid amounts
|
||||
$all_teilnehmede_stmt = $mysqli->prepare("SELECT `id`, `betrag_bezahlt`, `programm` FROM $db_tabelle_teilnehmende WHERE `id` IN ($tparams)");
|
||||
$all_teilnehmede_stmt->bind_param(str_repeat("i", count($ids)), ...$ids);
|
||||
$all_teilnehmede_stmt->execute();
|
||||
$all_teilnehmede_res = $all_teilnehmede_stmt->get_result();
|
||||
$all_teilnehmede = $all_teilnehmede_res->fetch_all(MYSQLI_ASSOC);
|
||||
$all_teilnehmede_stmt->close();
|
||||
|
||||
$all_preise_db = db_select($mysqli, $db_tabelle_kategorien, "`programm`, `preis`");
|
||||
|
||||
$all_preise = array_column($all_preise_db, 'preis', 'programm');
|
||||
|
||||
// Creates a clean map of [id => betrag_bezahlt]
|
||||
$all_teilnehmede_indexed = array_column($all_teilnehmede, 'betrag_bezahlt', 'id');
|
||||
$all_teilnehmede_indexed_kat = array_column($all_teilnehmede, 'programm', 'id');
|
||||
|
||||
// 4. Prepare the update statement ONCE
|
||||
$update_teiln_stmt = $mysqli->prepare("UPDATE $db_tabelle_teilnehmende SET `betrag_bezahlt` = ?, `bezahlt` = ? WHERE `id` = ?");
|
||||
|
||||
// Bind variables by reference once
|
||||
$n_preis = 0.0;
|
||||
|
||||
$normal_order_status = match ($new_status) {
|
||||
1 => 3,
|
||||
2 => 4,
|
||||
3 => 1,
|
||||
default => 1
|
||||
};
|
||||
|
||||
$status_to_set = $normal_order_status;
|
||||
|
||||
$s_teiln_id = 0;
|
||||
$update_teiln_stmt->bind_param("dii", $n_preis, $status_to_set, $s_teiln_id);
|
||||
|
||||
// 5. Loop through and execute updates
|
||||
foreach ($programm_ids as $id_key => $preis) {
|
||||
$s_teiln_id = (int) $id_key;
|
||||
|
||||
// FIX: Check directly against the flat ID key map
|
||||
if (!isset($all_teilnehmede_indexed[$s_teiln_id])) continue;
|
||||
|
||||
$eff_preis = 0.0;
|
||||
if (intval($new_status) === 2) {
|
||||
$eff_preis = (float) $preis;
|
||||
} elseif (intval($new_status) !== 2 && intval($old_status) === 2) {
|
||||
$eff_preis = ((float) $preis) * -1;
|
||||
}
|
||||
|
||||
// Calculate the new absolute value
|
||||
$n_preis = max(((float) $all_teilnehmede_indexed[$s_teiln_id]) + $eff_preis, 0);
|
||||
|
||||
if ($normal_order_status === 1) {
|
||||
$kat = $all_teilnehmede_indexed_kat[$s_teiln_id];
|
||||
|
||||
$preis_kat = (float) $all_preise[$kat] ?? PHP_INT_MAX;
|
||||
|
||||
if ($n_preis >= $preis_kat) {
|
||||
$status_to_set = 4;
|
||||
} elseif ($n_preis !== 0.00) {
|
||||
$status_to_set = 2;
|
||||
} else {
|
||||
$status_to_set = 1;
|
||||
}
|
||||
} else {
|
||||
$status_to_set = $normal_order_status;
|
||||
}
|
||||
|
||||
// Execute using the bound references
|
||||
$update_teiln_stmt->execute();
|
||||
}
|
||||
|
||||
$update_teiln_stmt->close();
|
||||
return true;
|
||||
}
|
||||
|
||||
function update_konten_vereine($benutzte_konten = '', $old_status, $new_status, bool $ids_are_array = false): bool {
|
||||
global $mysqli, $db_tabelle_vereine;
|
||||
|
||||
$int_old_status = (int) $old_status;
|
||||
$int_new_status = (int) $new_status;
|
||||
|
||||
// 1. Quick exit: No status change
|
||||
if ($int_old_status === $int_new_status) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 2. Validate status transitions (Fixed $old_status === 0 || $old_status === 1 bug)
|
||||
$isValidTransition =
|
||||
(in_array($int_old_status, [0, 1, 3]) && $int_new_status === 2) ||
|
||||
(in_array($int_new_status, [0, 1, 3]) && $int_old_status === 2) ||
|
||||
($int_old_status === 0 && $int_new_status === 1);
|
||||
|
||||
if (!$isValidTransition) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!$ids_are_array) {
|
||||
$benutzte_konten_array = json_decode($benutzte_konten, true) ?? [];
|
||||
} else {
|
||||
if (!is_array($benutzte_konten)) {
|
||||
return false;
|
||||
}
|
||||
$benutzte_konten_array = $benutzte_konten;
|
||||
}
|
||||
|
||||
if (empty($benutzte_konten_array)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$faktor = ($int_new_status === 3) ? 1 : -1;
|
||||
|
||||
$stmt = $mysqli->prepare("UPDATE `$db_tabelle_vereine` SET `konto` = `konto` + ? WHERE `verein` = ?");
|
||||
|
||||
$konto_change = 0.0;
|
||||
$verein = '';
|
||||
$stmt->bind_param("ds", $konto_change, $verein);
|
||||
|
||||
foreach ($benutzte_konten_array as $verein_key => $konto_change_absolute) {
|
||||
$verein = (string) $verein_key;
|
||||
$konto_change = (float) $konto_change_absolute * $faktor;
|
||||
|
||||
if ($konto_change == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$stmt->execute();
|
||||
}
|
||||
|
||||
$stmt->close();
|
||||
return true;
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
<?php
|
||||
|
||||
use Dotenv\Dotenv;
|
||||
|
||||
require __DIR__ . '/../../composer/vendor/autoload.php';
|
||||
|
||||
$envFile = realpath(__DIR__ . '/../../config/.env.redis');
|
||||
|
||||
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.redis');
|
||||
|
||||
$dotenv->load();
|
||||
} catch (Throwable $e) {
|
||||
http_response_code(500);
|
||||
echo json_encode([
|
||||
'success' => false,
|
||||
'message' => "Dotenv error"
|
||||
]);
|
||||
}
|
||||
|
||||
function connectToRedis(): bool
|
||||
{
|
||||
global $redis;
|
||||
if ($redis instanceof Redis) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$redis = new Redis();
|
||||
|
||||
if (!$redis->connect($_ENV['REDDIS_HOST'], $_ENV['REDDIS_PORT'])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!$redis->auth($_ENV['REDDIS_PASSWORD'])) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -0,0 +1,129 @@
|
||||
<?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(405);
|
||||
die("Access Denied: Invalid Request Type.");
|
||||
}
|
||||
}
|
||||
|
||||
function verify_delete_csrf($_DELETE) {
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'DELETE') {
|
||||
$token = $_DELETE['csrf_token'] ?? '';
|
||||
if (!hash_equals($_SESSION['csrf_token'], $token)) {
|
||||
http_response_code(403);
|
||||
die("Access Denied: Invalid CSRF Token.");
|
||||
}
|
||||
} else {
|
||||
http_response_code(405);
|
||||
die("Access Denied: Invalid Request Type.");
|
||||
}
|
||||
}
|
||||
|
||||
$allowedUserTypes = ['trainer', 'kampfrichter', 'wk_leitung'];
|
||||
|
||||
function check_user_permission(string $type, bool $return = false, bool $display = false) {
|
||||
global $allowedUserTypes;
|
||||
|
||||
if (!in_array($type, $allowedUserTypes, true)) {
|
||||
if ($return) {
|
||||
return false;
|
||||
} else {
|
||||
if ($display) {
|
||||
http_response_code(403);
|
||||
include __DIR__ . "/../www/error-pages/403.html";
|
||||
exit;
|
||||
} 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 {
|
||||
if ($display) {
|
||||
http_response_code(403);
|
||||
include __DIR__ . "/../www/error-pages/403.html";
|
||||
exit;
|
||||
} 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");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,214 @@
|
||||
<?php
|
||||
/**
|
||||
* Shared Sidebar Navigation
|
||||
*
|
||||
* Include this file after <body> on any intern page.
|
||||
* Set $currentPage before including, e.g.:
|
||||
* $currentPage = 'trainer';
|
||||
* require $baseDir . '/../scripts/sidebar/sidebar.php';
|
||||
*/
|
||||
|
||||
$isWKL = $_SESSION['access_granted_wk_leitung'] ?? false;
|
||||
$isTrainer = $_SESSION['access_granted_trainer'] ?? false;
|
||||
$isKampfrichter = $_SESSION['access_granted_kampfrichter'] ?? false;
|
||||
|
||||
if (!isset($currentPage)) $currentPage = '';
|
||||
|
||||
if (isset($_POST['abmelden'])) {
|
||||
|
||||
if (session_status() === PHP_SESSION_ACTIVE) {
|
||||
$_SESSION = array();
|
||||
session_destroy();
|
||||
}
|
||||
|
||||
header("Location: " . $_SERVER['PHP_SELF']);
|
||||
exit;
|
||||
}
|
||||
|
||||
// SVG Icons (stroke-based, 24x24 viewBox)
|
||||
$icons = [
|
||||
'trainer' => '<svg viewBox="0 0 24 24"><path d="M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2"/><circle cx="9" cy="7" r="4"/><path d="M23 21v-2a4 4 0 0 0-3-3.87"/><path d="M16 3.13a4 4 0 0 1 0 7.75"/></svg>',
|
||||
'kampfrichter' => '<svg viewBox="0 0 24 24"><path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z"/></svg>',
|
||||
'rechnungen' => '<svg viewBox="0 0 24 24"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/><polyline points="14 2 14 8 20 8"/><line x1="16" y1="13" x2="8" y2="13"/><line x1="16" y1="17" x2="8" y2="17"/><polyline points="10 9 9 9 8 9"/></svg>',
|
||||
'logindata' => '<svg viewBox="0 0 24 24"><rect x="3" y="11" width="18" height="11" rx="2" ry="2"/><path d="M7 11V7a5 5 0 0 1 10 0v4"/></svg>',
|
||||
'displaycontrol' => '<svg viewBox="0 0 24 24"><rect x="2" y="3" width="20" height="14" rx="2" ry="2"/><line x1="8" y1="21" x2="16" y2="21"/><line x1="12" y1="17" x2="12" y2="21"/></svg>',
|
||||
//'kalender' => '<svg viewBox="0 0 24 24"><rect x="3" y="4" width="18" height="18" rx="2" ry="2"/><line x1="16" y1="2" x2="16" y2="6"/><line x1="8" y1="2" x2="8" y2="6"/><line x1="3" y1="10" x2="21" y2="10"/></svg>',
|
||||
'rankLive' => '<svg viewBox="0 0 24 24"><path d="M12 4h6a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h6"/><line x1="9" y1="9" x2="15" y2="9"/><line x1="9" y1="13" x2="15" y2="13"/><line x1="9" y1="17" x2="15" y2="17"/></svg>',
|
||||
'wettkaempfe' => '<svg viewBox="0 0 24 24"><path d="M12 4h6a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h6"/><line x1="9" y1="9" x2="15" y2="9"/><line x1="9" y1="13" x2="15" y2="13"/><line x1="9" y1="17" x2="15" y2="17"/></svg>',
|
||||
'riegeneinteilung' => '<svg viewBox="0 0 24 24"><path d="M16 4h2a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h2"/><rect x="8" y="2" width="8" height="4" rx="1" ry="1"/><line x1="9" y1="12" x2="15" y2="12"/><line x1="9" y1="16" x2="15" y2="16"/></svg>',
|
||||
'einstellungen' => '<svg viewBox="0 0 24 24"><circle cx="12" cy="12" r="3"></circle><path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1 0 2.83 2 2 0 0 1-2.83 0l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-2 2 2 2 0 0 1-2-2v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83 0 2 2 0 0 1 0-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1-2-2 2 2 0 0 1 2-2h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 0-2.83 2 2 0 0 1 2.83 0l.06.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 2-2 2 2 0 0 1 2 2v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 0 2 2 0 0 1 0 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 2 2 2 2 0 0 1-2 2h-.09a1.65 1.65 0 0 0-1.51 1z"></path></svg>',
|
||||
];
|
||||
|
||||
if (isset($mysqli) && isset($db_tabelle_intern_benutzende)) {
|
||||
|
||||
if ($currentPage === 'kampfrichter' && checkIfUserHasSessionId('kampfrichter')):
|
||||
$userDispId = intval($_SESSION['user_id_kampfrichter']);
|
||||
elseif ($currentPage === 'kampfrichter' && checkIfUserHasSessionId('trainer')):
|
||||
$userDispId = intval($_SESSION['user_id_trainer']);
|
||||
elseif ($isWKL && checkIfUserHasSessionId('wk_leitung')):
|
||||
$userDispId = intval($_SESSION['user_id_wk_leitung']);
|
||||
endif;
|
||||
|
||||
$sql = "SELECT `username`, `freigabe` FROM $db_tabelle_intern_benutzende WHERE id = ?";
|
||||
$stmt = $mysqli->prepare($sql);
|
||||
|
||||
$stmt->bind_param('i', $userDispId);
|
||||
$stmt->execute();
|
||||
|
||||
$stmt->bind_result($usernameDB, $freigabenDB);
|
||||
$stmt->fetch();
|
||||
|
||||
$username = $usernameDB ?? '';
|
||||
|
||||
$decoded = json_decode($freigabenDB, true);
|
||||
$freigabenSidebar = is_array($decoded) ? $decoded : [];
|
||||
|
||||
$stmt->close();
|
||||
}
|
||||
|
||||
$links = [];
|
||||
|
||||
$renderMenu = true;
|
||||
|
||||
// Trainer & Kampfrichter are visible to their own role + WKL
|
||||
if ($isTrainer || $isWKL) {
|
||||
$links[] = ['key' => 'trainer', 'label' => 'Trainer', 'url' => '/intern/trainer', 'freigaben' => true];
|
||||
}
|
||||
if ($isKampfrichter || $isWKL) {
|
||||
$links[] = ['key' => 'kampfrichter', 'label' => 'Kampfrichter', 'url' => '/intern/kampfrichter', 'freigaben' => true];
|
||||
}
|
||||
|
||||
// WKL-only pages
|
||||
if ($isWKL) {
|
||||
$links[] = ['key' => 'rechnungen', 'label' => 'Rechnungen', 'url' => '/intern/wk-leitung/rechnungen', 'freigaben' => false];
|
||||
$links[] = ['key' => 'logindata', 'label' => 'Benutzerverwaltung', 'url' => '/intern/wk-leitung/logindata', 'freigaben' => false];
|
||||
$links[] = ['key' => 'displaycontrol', 'label' => 'Displaycontrol', 'url' => '/intern/wk-leitung/displaycontrol', 'freigaben' => false];
|
||||
//$links[] = ['key' => 'kalender', 'label' => 'Kalender', 'url' => '/intern/wk-leitung/kalender'];
|
||||
$links[] = ['key' => 'rankLive', 'label' => 'Rank Live', 'url' => '/intern/wk-leitung/rank-live', 'freigaben' => false];
|
||||
$links[] = ['key' => 'riegeneinteilung', 'label' => 'Riegeneinteilung', 'url' => '/intern/wk-leitung/riegeneinteilung', 'freigaben' => false];
|
||||
$links[] = ['key' => 'einstellungen', 'label' => 'Einstellungen', 'url' => '/intern/wk-leitung/einstellungen', 'freigaben' => false];
|
||||
$links[] = ['key' => 'wettkaempfe', 'label' => 'Wettkämpfe', 'url' => '/intern/wk-leitung/wettkaempfe', 'freigaben' => false];
|
||||
}
|
||||
|
||||
function checkIfUserHasSessionId($type) : bool {
|
||||
if (isset($_SESSION['user_id_'.$type]) && intval(['user_id_'.$type]) > 0) { return true; }
|
||||
else { return false; }
|
||||
}
|
||||
|
||||
// if (!isset($indexedNotenNames)) { $indexedNotenNames = []; }
|
||||
|
||||
function sidebarRender(string $mode) {
|
||||
global $isWKL, $isTrainer, $isKampfrichter, $links, $currentPage, $icons, $renderMenu, $username, $freigabenSidebar, $indexedArrayGeraete;
|
||||
|
||||
if (!$renderMenu) { return; }
|
||||
|
||||
if ($mode === 'button') {
|
||||
?>
|
||||
<!-- Sidebar Toggle Button -->
|
||||
<button class="sidebar-toggle" id="sidebar-toggle" aria-label="Navigation öffnen">
|
||||
<span></span>
|
||||
<span></span>
|
||||
<span></span>
|
||||
</button>
|
||||
<?php } elseif ($mode === 'modal') { ?>
|
||||
<!-- Sidebar Overlay -->
|
||||
<div class="sidebar-overlay" id="sidebar-overlay"></div>
|
||||
|
||||
<!-- Sidebar Panel -->
|
||||
<nav class="sidebar-nav" id="sidebar-nav">
|
||||
<div class="sidebar-header">
|
||||
<h3>Navigation</h3>
|
||||
<button class="sidebar-close-btn" id="sidebar-close" aria-label="Schliessen">
|
||||
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<?php if ($isWKL && ($isTrainer || $isKampfrichter || true)): ?>
|
||||
<div class="sidebar-section-label">Allgemein</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<ul class="sidebar-links">
|
||||
<?php foreach ($links as $i => $link):
|
||||
$isCurrentPage = ($currentPage === $link['key']);
|
||||
$activeClass = $isCurrentPage ? ' active' : '';
|
||||
$icon = $icons[$link['key']] ?? '';
|
||||
$freigbenArrayName = 'freigaben' . ucfirst($link['key']);
|
||||
|
||||
// Insert section divider before WKL-only links
|
||||
if ($isWKL && $link['key'] === 'rechnungen' && $i > 0): ?>
|
||||
</ul>
|
||||
<div class="sidebar-section-label">WK-Leitung</div>
|
||||
<ul class="sidebar-links">
|
||||
<?php endif; ?>
|
||||
|
||||
<li>
|
||||
<a href="<?php echo $link['url']; ?>" class="<?php echo trim($activeClass); ?>">
|
||||
<?php echo $icon; ?>
|
||||
<?php echo htmlspecialchars($link['label']); ?>
|
||||
</a>
|
||||
</li>
|
||||
<?php if ($isCurrentPage && $link['freigaben'] === true && isset($freigabenSidebar[$freigbenArrayName]) && count($freigabenSidebar[$freigbenArrayName]) > 1) : ?>
|
||||
<?php $selectedFreigabe = ($currentPage === 'kampfrichter') ? $_SESSION['selectedFreigabeIdKampfrichter'] : $_SESSION['selectedFreigabe' . ucfirst($link['key'])] ?? ''; ?>
|
||||
<li class="sidebar-li-freigaben">
|
||||
<label class="sidebar-freigaben-label" for="selectTriggerFreigabe">Freigabe</label>
|
||||
<div class="customSelect" id="selectedOption" data-value="[]">
|
||||
<button type="button" id="selectTriggerFreigabe" class="selectTriggerSidebar" aria-expanded="false">
|
||||
<span class="selectLabel">
|
||||
<?= htmlspecialchars(($currentPage === 'kampfrichter') ? (($selectedFreigabe !== 'A') ? $indexedArrayGeraete[$selectedFreigabe] ?? $selectedFreigabe : 'Admin') : $selectedFreigabe) ?>
|
||||
</span>
|
||||
<svg class="selectArrow" xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' height="14" width="14">
|
||||
<path d='M6 9L12 15L18 9' stroke='currentColor' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/>
|
||||
</svg>
|
||||
</button>
|
||||
<ul class="selectOptionsSidebar">
|
||||
<?php foreach ($freigabenSidebar[$freigbenArrayName] as $f) :?>
|
||||
<?php $selected = ($f === $selectedFreigabe) ? 'selected' : '' ?>
|
||||
<li data-value="<?= htmlspecialchars($f) ?>" class="<?= $selected ?>"><?= htmlspecialchars(($currentPage === 'kampfrichter') ? (($f !== 'A') ? $indexedArrayGeraete[$f] ?? $f : 'Admin') : $f) ?></li>
|
||||
<?php endforeach; ?>
|
||||
</ul>
|
||||
<input type="hidden" name="type" class="selectValue" id="freigabenSidebarSelect" value="">
|
||||
</div>
|
||||
</li>
|
||||
<?php endif; ?>
|
||||
<?php endforeach; ?>
|
||||
</ul>
|
||||
|
||||
|
||||
<?php
|
||||
if (isset($username)) : ?>
|
||||
<div class="sidebarUsername">Benutzer: <?= $username ?></div>
|
||||
<?php endif; ?>
|
||||
|
||||
|
||||
<div class="sidebar-footer">
|
||||
<form method="POST" action="" class="abmelden"><input class="abmeldenbutton" type="submit" href="?logout=1" name="abmelden" value="Abmelden"></form>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<script>
|
||||
|
||||
window.CSRF_TOKEN = "<?= $csrf_token ?? $_SESSION['csrf_token'] ?? '' ?>";
|
||||
|
||||
const siteType = '<?= $currentPage ?>';
|
||||
// Close button binding (inline to avoid race condition with sidebar.js)
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
var closeBtn = document.getElementById('sidebar-close');
|
||||
if (closeBtn) {
|
||||
closeBtn.addEventListener('click', function() {
|
||||
document.getElementById('sidebar-nav').classList.remove('open');
|
||||
document.getElementById('sidebar-overlay').classList.remove('open');
|
||||
document.getElementById('sidebar-toggle').classList.remove('open');
|
||||
localStorage.setItem('intern_sidebar_open', 'false');
|
||||
});
|
||||
}
|
||||
});
|
||||
</script>
|
||||
<script src="/intern/js/sidebar.js"></script>
|
||||
|
||||
<?php
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,324 @@
|
||||
<?php
|
||||
|
||||
if (!isset($baseDir)) {
|
||||
$baseDir = $_SERVER['DOCUMENT_ROOT'];
|
||||
}
|
||||
|
||||
//ini_set('display_errors', 1);
|
||||
//ini_set('display_startup_errors', 1);
|
||||
|
||||
require $baseDir . '/../composer/vendor/autoload.php';
|
||||
|
||||
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:
|
||||
|
||||
$valuesArray = [
|
||||
noten_bezeichnung_id => value,
|
||||
…
|
||||
];
|
||||
*/
|
||||
|
||||
private function santinzeString(string $string) : string
|
||||
{
|
||||
$replacePatterns = [
|
||||
'/->R\w+/', // 1. Removes ->R followed by digits
|
||||
'/[^a-zA-Z0-9(){}+*\/.[\]\-]/' // 2. Fixed syntax: Allowed characters list
|
||||
];
|
||||
return preg_replace($replacePatterns,'', $string);
|
||||
}
|
||||
|
||||
private function sanitizeStringWithRun(string $string) : string
|
||||
{
|
||||
$replacePattern = '/[^a-zA-Z0-9(){}+*\/.\-\[\]>]/';
|
||||
return preg_replace($replacePattern, "", $string);
|
||||
}
|
||||
|
||||
|
||||
public function getBenoetigteIds(string $schemaRaw)
|
||||
{
|
||||
$schema = $this->santinzeString($schemaRaw);
|
||||
|
||||
preg_match_all('/\{(\d+)\}/', $schema, $matches);
|
||||
return $matches[1];
|
||||
|
||||
}
|
||||
|
||||
public function getBenoetigteIdsComplex(string $schemaRaw)
|
||||
{
|
||||
$schema = $this->santinzeString($schemaRaw);
|
||||
$indexedMatches = [];
|
||||
|
||||
// Pattern breakdown:
|
||||
// \{(\d+) -> Match { and capture the first number (Note ID)
|
||||
// (?:\[(\w*)\])? -> OPTIONALLY match [ and capture alphanumeric content inside (Apparatus ID)
|
||||
// (?:\[(\d+)\])? -> OPTIONALLY match [ and capture number inside (Run Number)
|
||||
// \} -> Match the closing }
|
||||
if (preg_match_all('/\{(\d+)(?:\[(\w*)\])?(?:\[(\d+)\])?\}/', $schema, $matches, PREG_SET_ORDER)) {
|
||||
|
||||
foreach ($matches as $match) {
|
||||
$noteId = $match[1];
|
||||
|
||||
$rawGeraet = $match[2] ?? 'S';
|
||||
$geraetId = ($rawGeraet === 'S' || $rawGeraet === '') ? 'A' : $rawGeraet;
|
||||
|
||||
$runNumber = isset($match[3]) ? (int)$match[3] : 1;
|
||||
|
||||
$indexedMatches[] = [
|
||||
'noteId' => $noteId,
|
||||
'geraetId' => $geraetId,
|
||||
'run' => $runNumber
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
return $indexedMatches;
|
||||
|
||||
}
|
||||
|
||||
public function getBenoetigteIdsComplexWithRun(string $schemaRaw)
|
||||
{
|
||||
$schema = $this->sanitizeStringWithRun($schemaRaw);
|
||||
$indexedMatches = [];
|
||||
|
||||
// Pattern breakdown:
|
||||
// \{(\d+) -> Match { and capture the first number (Note ID)
|
||||
// (?:\[(\w*)\])? -> OPTIONALLY match [ and capture alphanumeric content inside (Apparatus ID)
|
||||
// (?:\[(\d+)\])? -> OPTIONALLY match [ and capture number inside (Run Number)
|
||||
// \} -> Match the closing }
|
||||
if (preg_match_all('/\{(\d+)(?:\[(\w*)\])?(?:\[(\d+)\])?\}/', $schema, $matches, PREG_SET_ORDER)) {
|
||||
|
||||
foreach ($matches as $match) {
|
||||
$noteId = $match[1];
|
||||
|
||||
$rawGeraet = $match[2] ?? 'S';
|
||||
$geraetId = ($rawGeraet === 'S' || $rawGeraet === '') ? 'A' : $rawGeraet;
|
||||
|
||||
$runNumber = isset($match[3]) ? (int)$match[3] : 1;
|
||||
|
||||
$indexedMatches[] = [
|
||||
'noteId' => $noteId,
|
||||
'geraetId' => $geraetId,
|
||||
'run' => $runNumber
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
$arrayRes = $this->getStoreGeraetRun($schemaRaw);
|
||||
|
||||
$indexedMatches['targetRun'] = $arrayRes['run_num'] ?? 'A';
|
||||
$indexedMatches['targetGeraet'] = $arrayRes['geraet_id'] ?? 'A';
|
||||
|
||||
return $indexedMatches;
|
||||
|
||||
}
|
||||
|
||||
public function getStoreGeraetRun(string $schemaRaw): array
|
||||
{
|
||||
$schema = $this->sanitizeStringWithRun($schemaRaw);
|
||||
|
||||
$pattern = '/->R(?<run_num>\d+|S)(?:G(?<geraet_id>\d+|S))?/';
|
||||
|
||||
if (preg_match($pattern, $schema, $matchesTagetRun)) {
|
||||
|
||||
$run = $matchesTagetRun['run_num'] ?? 'S';
|
||||
$geraet = $matchesTagetRun['geraet_id'] ?? 'S';
|
||||
|
||||
return [
|
||||
'run_num' => $run === 'S' ? 'A' : (int)$run,
|
||||
'geraet_id' => $geraet === 'S' ? 'A' : (int)$geraet,
|
||||
];
|
||||
}
|
||||
|
||||
return [
|
||||
'run_num' => 'A',
|
||||
'geraet_id' => 'A'
|
||||
];
|
||||
}
|
||||
|
||||
private function insertValuesComplex(string $schemaRaw, array $valuesArray, int $currentId, int $runNumber, bool $avr = false)
|
||||
{
|
||||
$schema = $this->santinzeString($schemaRaw);
|
||||
$idsNeededArray = $this->getBenoetigteIdsComplex($schemaRaw);
|
||||
|
||||
// 1. Validation Loop
|
||||
foreach ($idsNeededArray as $sina) {
|
||||
$noteId = $sina['noteId'];
|
||||
$geraetIdSearch = ($sina['geraetId'] === 'A') ? $currentId : $sina['geraetId'];
|
||||
|
||||
if (!isset($valuesArray[$geraetIdSearch][$noteId][$runNumber]["value"])) {
|
||||
return ['success' => false, 'value' => "Fehlende Daten für Gerät $geraetIdSearch, Note $noteId, Lauf $runNumber"];
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
$returnStr = preg_replace_callback('/\{(\d+)(?:\[(\w*)\])?(?:\[(\d+)\])?\}/', function($m) use ($valuesArray, $currentId, $runNumber, $avr) {
|
||||
$noteId = $m[1];
|
||||
|
||||
// Get value inside brackets, default to 'S' if none exists
|
||||
$rawGeraet = $m[2] ?? 'S';
|
||||
$geraetId = ($rawGeraet === 'S' || $rawGeraet === '') ? $currentId : $rawGeraet;
|
||||
|
||||
if ($avr && $valuesArray[$geraetId][$noteId][$runNumber]["type"] === 'default_value') {
|
||||
return 'default_value_skip';
|
||||
} else {
|
||||
// Return value from [Device][Note][Run]
|
||||
return $valuesArray[$geraetId][$noteId][$runNumber]["value"] ?? 0;
|
||||
}
|
||||
|
||||
}, $schema);
|
||||
|
||||
return ['success' => true, 'value' => $returnStr];
|
||||
|
||||
} catch (\Exception $e) {
|
||||
return ['success' => false, 'value' => 'Problem beim Einsetzen der Werte'];
|
||||
}
|
||||
}
|
||||
|
||||
private function calculate(string $rechnungRaw) {
|
||||
global $rechner;
|
||||
|
||||
$rechnung = $this->santinzeString($rechnungRaw);
|
||||
|
||||
try {
|
||||
$result = $this->rechner->calculate($rechnung);
|
||||
return ['success' => true, 'value' => floatval($result)];
|
||||
} catch (\ChrisKonnertz\StringCalc\Exceptions\StringCalcException $e) {
|
||||
return ['success' => false, 'value' => 'Problem bei der Berechnung: Ungültige Syntax '. $rechnung];
|
||||
} catch (\Exception $e) {
|
||||
return ['success' => false, 'value' => 'Problem bei der Berechnung'];
|
||||
}
|
||||
}
|
||||
|
||||
public function berechneStringComplex(string $schemaRaw, array $valuesArray = [], int $geraetId = -1, 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, $run_number);
|
||||
|
||||
if (!isset($rechnungArray['success']) || !isset($rechnungArray['value']) || !$rechnungArray['success']) {
|
||||
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 = -1, 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[$sid['noteId']][$geraetId]["all"] ?? $arrayRuns["default"] ?? 1;
|
||||
|
||||
if ($runCount !== $runCountN && $runCount !== 0) { return; }
|
||||
$runCount = $runCountN;
|
||||
}
|
||||
|
||||
$string = "";
|
||||
switch ($name) {
|
||||
case "AVGR":
|
||||
case "SUMR":
|
||||
$nulls = 0;
|
||||
|
||||
for ($r = 1; $r <= $runCount; $r++) {
|
||||
|
||||
$res = $this->insertValuesComplex($content, $valuesArray, $currentId, $r, true);
|
||||
|
||||
if (!$res['success']) {
|
||||
return "0";
|
||||
} elseif ($res['value'] === 'default_value_skip') {
|
||||
$nulls++;
|
||||
} else {
|
||||
$parts[] = "(" . $res['value'] . ")";
|
||||
}
|
||||
}
|
||||
|
||||
$innerMath = implode(" + ", $parts);
|
||||
$div_count = $runCount - $nulls;
|
||||
if ($div_count === 0 || count($parts) < 1) return "0";
|
||||
$string = ($name === "AVGR") ? "(($innerMath) / $div_count)" : "($innerMath)";
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,244 @@
|
||||
<?php
|
||||
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);
|
||||
|
||||
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;
|
||||
$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;
|
||||
|
||||
$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;
|
||||
}
|
||||
|
||||
$vereine_plus_array = [];
|
||||
|
||||
if (isset($_POST['delete_id'])) {
|
||||
verify_csrf();
|
||||
$delete_id = intval($_POST['delete_id']);
|
||||
|
||||
$stmt = $mysqli->prepare("DELETE FROM $db_tabelle_teilnehmendee where id = ?");
|
||||
|
||||
$stmt->bind_param('i', $delete_id);
|
||||
|
||||
if ($stmt->execute()) {
|
||||
$_SESSION['form_message'] = 'Eintrag erfolgreich gelöscht.';
|
||||
$_SESSION['form_message_type'] = 1;
|
||||
} else {
|
||||
$_SESSION['form_message'] = 'Löschen fehlgeschlagen.';
|
||||
$_SESSION['form_message_type'] = 0;
|
||||
}
|
||||
|
||||
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']);
|
||||
$edit_rows = db_select($mysqli, $db_tabelle_teilnehmende, "*", 'id = ?', [$edit_id]);
|
||||
if (!isset($edit_rows) || !is_array($edit_rows) || count($edit_rows) !== 1) {
|
||||
http_response_code(422);
|
||||
exit;
|
||||
}
|
||||
$edit_row = $edit_rows[0];
|
||||
if ($edit_row && ($edit_row['verein'] === $selectedverein || $is_admin)) {
|
||||
$_POST['nachname'] = $edit_row['name'] ?? '';
|
||||
$_POST['vorname'] = $edit_row['vorname'] ?? '';
|
||||
$_POST['geburtsdatum'] = $edit_row['geburtsdatum'] ?? '';
|
||||
$kat = $edit_row['programm'] ?? '';
|
||||
$kat_id = db_get_var($mysqli, "SELECT `id` FROM $db_tabelle_kategorien WHERE `programm` = ?", [$kat]) ?: '';
|
||||
$_POST['programm'] = $kat_id;
|
||||
$_POST['edit_id'] = $edit_id;
|
||||
if ($is_admin) {
|
||||
$_POST['verein'] = $edit_row['verein'] ?? '';
|
||||
$_POST['bezahltOverride'] = $edit_row['bezahltoverride'] ?? 0;
|
||||
}
|
||||
} else {
|
||||
$_SESSION['form_message'] = 'Ungültiger Eintrag zum Bearbeiten.';
|
||||
$_SESSION['form_message_type'] = 0;
|
||||
header('Location: ' . $_SERVER['REQUEST_URI']);
|
||||
exit;
|
||||
}
|
||||
}
|
||||
|
||||
// === INSERT/UPDATE Handler ===
|
||||
if ($access_granted_trainer && isset($_POST['submit_turnerinnen_form'])) {
|
||||
|
||||
verify_csrf();
|
||||
|
||||
$name = htmlspecialchars($_POST['nachname']);
|
||||
$vorname = htmlspecialchars($_POST['vorname']);
|
||||
$geburtsdatum = trim($_POST['geburtsdatum']);
|
||||
$kat_id = (int) ($_POST['programm'] ?? 0);
|
||||
|
||||
if (!$is_admin) {
|
||||
$verein = $selectedverein;
|
||||
} else {
|
||||
$verein = htmlspecialchars($_POST['verein']);
|
||||
$bezahlt = intval($_POST['bezahltOverride']);
|
||||
}
|
||||
|
||||
$kat = db_get_var($mysqli, "SELECT `programm` FROM $db_tabelle_kategorien WHERE `id` = ?", [$kat_id]) ?: '';
|
||||
|
||||
if (empty($name) || empty($vorname) || empty($geburtsdatum) || empty($kat_id) || empty($kat)) {
|
||||
$_SESSION['form_message'] = 'Bitte füllen Sie alle erforderlichen Felder aus.';
|
||||
$_SESSION['form_message_type'] = 0;
|
||||
} else {
|
||||
|
||||
$data_to_insert = [
|
||||
'name' => $name,
|
||||
'vorname' => $vorname,
|
||||
'geburtsdatum' => $geburtsdatum,
|
||||
'programm' => $kat,
|
||||
'verein' => $verein,
|
||||
];
|
||||
|
||||
if ($is_admin) {
|
||||
$data_to_insert['bezahltoverride'] = $bezahlt;
|
||||
}
|
||||
|
||||
|
||||
// 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']);
|
||||
|
||||
$entry = db_select($mysqli, $db_tabelle_teilnehmende, '*', 'id = ?', [$edit_id], '', '1');
|
||||
|
||||
if (count($entry) === 1) {
|
||||
$old_data = $entry[0];
|
||||
$data_to_insert = array_merge($data_to_insert, get_kat_price_diff($old_data, $kat));
|
||||
remove_from_basket([$edit_id]);
|
||||
update_verein_balances($vereine_plus_array);
|
||||
}
|
||||
|
||||
var_dump($data_to_insert);
|
||||
|
||||
$columns = array_keys($data_to_insert);
|
||||
|
||||
$set = implode(
|
||||
', ',
|
||||
array_map(fn($col) => "$col = ?", $columns)
|
||||
);
|
||||
|
||||
$sql = "UPDATE $db_tabelle_teilnehmende 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 der Personendaten.';
|
||||
$_SESSION['form_message_type'] = 0;
|
||||
} else if ($updated === 0) {
|
||||
$_SESSION['form_message'] = 'Keine Änderungen vorgenommen.';
|
||||
$_SESSION['form_message_type'] = 0;
|
||||
} else {
|
||||
$_SESSION['form_message'] = $personEinzahl . ' erfolgreich aktualisiert!';
|
||||
$_SESSION['form_message_type'] = 1;
|
||||
$_POST = [];
|
||||
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 $db_tabelle_teilnehmende 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,123 @@
|
||||
<?php
|
||||
|
||||
if (!isset($baseDir)) {
|
||||
$baseDir = $_SERVER['DOCUMENT_ROOT'];
|
||||
}
|
||||
|
||||
require_once $baseDir . '/../scripts/session_functions.php';
|
||||
|
||||
ini_wkvs_session();
|
||||
|
||||
use Dotenv\Dotenv;
|
||||
|
||||
$wsPermissions = [
|
||||
'displaycontrol' => ['access_granted_wk_leitung'],
|
||||
'einstellungen' => ['access_granted_wk_leitung'],
|
||||
'kampfrichter' => ['access_granted_kampfrichter']
|
||||
];
|
||||
|
||||
$baseDir = $_SERVER['DOCUMENT_ROOT'];
|
||||
|
||||
require_once __DIR__ . '/../redis/connect-to-redis.php';
|
||||
|
||||
$redis = null;
|
||||
|
||||
connectToRedis();
|
||||
|
||||
function checkWSTokenPermissions($RPerm) {
|
||||
switch ($RPerm) {
|
||||
case 'wk_leitung':
|
||||
return $_SESSION['access_granted_wk_leitung'] ?? false;
|
||||
case 'kampfrichter';
|
||||
return $_SESSION['access_granted_kampfrichter'] ?? false;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
$envFile = realpath(__DIR__ . '/../../config/.env.wk-id');
|
||||
|
||||
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.wk-id');
|
||||
|
||||
$dotenv->load();
|
||||
} catch (Throwable $e) {
|
||||
http_response_code(500);
|
||||
echo json_encode([
|
||||
'success' => false,
|
||||
'message' => "Dotenv error"
|
||||
]);
|
||||
}
|
||||
|
||||
$wkId = $_ENV['WETTKAMPF_ID'];
|
||||
|
||||
$allowedWkLeitungAccess = ['displaycontrol', 'einstellungen'];
|
||||
|
||||
function generateWSAdminToken($wsRequestedAcesstype, $wsRequestedAccess) {
|
||||
|
||||
global $redis, $wkId, $allowedWkLeitungAccess;
|
||||
|
||||
if (!checkWSTokenPermissions($wsRequestedAcesstype)) return null;
|
||||
|
||||
$wsGrantedPermission = [];
|
||||
|
||||
if ($wsRequestedAcesstype === 'kampfrichter' && isset($_SESSION['selectedFreigabeIdKampfrichter'])) {
|
||||
$wsGrantedPermission['type'] = 'kampfrichter';
|
||||
$wsGrantedPermission['access'] = $_SESSION['selectedFreigabeIdKampfrichter'];
|
||||
} elseif ($wsRequestedAcesstype === 'wk_leitung' && in_array($wsRequestedAccess, $allowedWkLeitungAccess)) {
|
||||
$wsGrantedPermission['type'] = $wsRequestedAcesstype;
|
||||
$wsGrantedPermission['access'] = $wsRequestedAccess;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
|
||||
$wsGrantedPermission['wk_id'] = $wkId;
|
||||
$wsGrantedPermission['authenticated'] = true;
|
||||
|
||||
$token = bin2hex(random_bytes(32));
|
||||
$key = "ws:token:" . $token;
|
||||
|
||||
$success = $redis->set($key, json_encode($wsGrantedPermission), ['nx', 'ex' => 10]);
|
||||
|
||||
$_SESSION['WS_KEY'] = $key;
|
||||
|
||||
return $key;
|
||||
}
|
||||
|
||||
$allowedReadTypes = ['display', 'audio', 'rankLive'];
|
||||
|
||||
function generateWSReadToken($wsRequestedAcesstype, $wsRequestedAccess) {
|
||||
|
||||
global $redis, $wkId, $allowedReadTypes;
|
||||
|
||||
$wsGrantedPermission = [];
|
||||
|
||||
if (!in_array($wsRequestedAcesstype, $allowedReadTypes)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$wsGrantedPermission['access'] = $wsRequestedAccess;
|
||||
$wsGrantedPermission['type'] = $wsRequestedAcesstype;
|
||||
$wsGrantedPermission['wk_id'] = $wkId;
|
||||
$wsGrantedPermission['authenticated'] = false;
|
||||
|
||||
$token = bin2hex(random_bytes(16));
|
||||
$key = "ws:token:" . $token;
|
||||
|
||||
$success = $redis->set($key, json_encode($wsGrantedPermission), ['nx', 'ex' => 30]);
|
||||
|
||||
$_SESSION['WS_KEY'] = $key;
|
||||
|
||||
return $key;
|
||||
}
|
||||
Reference in New Issue
Block a user