New Filestructure for Docker

This commit is contained in:
2026-07-31 23:53:14 +02:00
parent 1e10ed4de8
commit 5bcf2a3546
239 changed files with 710 additions and 2000 deletions
@@ -0,0 +1,86 @@
<?php
header('Content-Type: application/json');
ini_set("display_errors", 1);
if (!isset($baseDir)) {
$baseDir = $_SERVER['DOCUMENT_ROOT'];
}
require_once $baseDir . '/../scripts/session_functions.php';
ini_wkvs_session();
check_user_permission('wk_leitung');
verify_csrf();
require $baseDir . '/../scripts/db/db-functions.php';
require $baseDir . '/../scripts/db/db-tables.php';
$type = 'wkl';
$dbconnection = require $baseDir . '/../scripts/db/db-verbindung-script.php';
if ($dbconnection['success'] !== true){
echo json_encode(['success' => false, 'message' => 'Critical DB Error.']);
exit;
}
$action = $_POST['action'] ?? '';
if ($action === 'update') {
$abt_id = intval($_POST['abt'] ?? 0);
$field = $_POST['type'] ?? '';
$type_id = intval($_POST['type_id'] ?? 0);
$value = $_POST['value'] ?? '';
if (!preg_match('/^\d{2}:\d{2}$/', $value)) {
echo json_encode(['success' => false, 'message' => 'Invalid parameters.']);
http_response_code(400);
exit;
}
$allowedFields = ['start', 'end'];
if (
$abt_id > 0 &&
$type_id > 0 &&
db_check_var($mysqli, $db_tabelle_gruppen, 'id = ?', [$abt_id]) &&
db_check_var($mysqli, $db_tabelle_zeitplan_types, 'id = ?', [$type_id]) &&
($field === 'start' || ($field === 'end' && db_check_var($mysqli, $db_tabelle_zeitplan_types, 'id = ? AND has_endtime = ?', [$type_id, 1])))
) {
$stmt = $mysqli->prepare("INSERT INTO $db_tabelle_gruppen_zeiten (`abt_id`, `zeitplan_id`, `" . $field . "_time`) VALUES (?, ?, ?) ON DUPLICATE KEY UPDATE `" . $field . "_time` = VALUES(`" . $field . "_time`)");
$stmt->bind_param("iis", $abt_id, $type_id, $value);
$stmt->execute();
$stmt->close();
echo json_encode(['success' => true]);
} else {
echo json_encode(['success' => false, 'message' => 'Invalid parameters.']);
http_response_code(400);
exit;
}
} elseif ($action === 'delete') {
$abt_id = intval($_POST['abt'] ?? 0);
$type_id = intval($_POST['type_id'] ?? 0);
if ($type_id > 0 && $abt_id > 0) {
db_delete($mysqli, $db_tabelle_gruppen_zeiten, ['abt_id' => $abt_id, 'zeitplan_id' => $type_id]);
echo json_encode(['success' => true]);
} else {
echo json_encode(['success' => false, 'message' => 'Invalid ID.']);
http_response_code(400);
exit;
}
} else {
echo json_encode(['success' => false, 'message' => 'Action not found.']);
}
@@ -0,0 +1,183 @@
<?php
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
// Show all errors except deprecation notices (these come from vendor libraries
// that aren't yet typed for newer PHP versions). Long-term fix: update
// dependencies to versions compatible with your PHP runtime.
error_reporting(E_ALL & ~E_DEPRECATED & ~E_USER_DEPRECATED);
if (!isset($baseDir)) {
$baseDir = $_SERVER['DOCUMENT_ROOT'];
}
require_once $baseDir . '/../scripts/session_functions.php';
ini_wkvs_session();
check_user_permission('wk_leitung');
verify_csrf();
$allowed_operations = ['overrite', 'add'];
if (!isset($_POST['operation']) || !in_array($_POST['operation'], $allowed_operations, true)) {
http_response_code(400);
echo 'Invalid operation.';
exit;
}
$operation = $_POST['operation'];
$type = 'wkl';
$dbconnection = require $baseDir . '/../scripts/db/db-verbindung-script.php';
if ($dbconnection['success'] !== true){
echo 'Critical DB Error.';
exit;
}
require $baseDir . '/../scripts/db/db-functions.php';
require $baseDir . '/../scripts/db/db-tables.php';
$allGeraete = db_select($mysqli, $db_tabelle_disziplinen, "id, name, start_index", "", [], "start_index ASC");
$allAbt = db_select($mysqli, $db_tabelle_gruppen, "name, id, order_index", "", [], "order_index ASC");
$indexded_order_index_abt = array_column($allAbt, null, 'order_index');
$maxTurnerinnenGruppe = 8;
$allTurnerinnen = db_select($mysqli, $db_tabelle_teilnehmende, "id, programm, verein, name" , "", [], "programm ASC");
$grouped = [];
foreach ($allTurnerinnen as $t) {
$grouped[strtolower($t['programm'])][$t['verein']][] = $t;
}
function getMinKey(array $array): string|int {
return array_search(min($array), $array, true);
}
function arrayRiegeneiteilung($allturnerinnen, $maxTurnerinnenGruppe, $allGeraete) {
$indabt = 1;
$arrayAutoRiegeneinteilung = [];
foreach ($allturnerinnen as $prog => $vereine) {
// ABTEILUNG BERECHNEN
$countturterinnenprog = 0;
foreach ($vereine as $verein => $turnerinnen) {
foreach ($turnerinnen as $ind => $turnerin) {
$countturterinnenprog++;
$abt = intdiv($countturterinnenprog, $maxTurnerinnenGruppe * count($allGeraete)) + $indabt;
$allturnerinnen[$prog][$verein][$ind]['abt'] = $abt;
$arrayAbt[$abt][$verein][] = $turnerin;
}
}
$indabt += intdiv($countturterinnenprog - 1, $maxTurnerinnenGruppe * count($allGeraete)) + 1;
}
foreach ($arrayAbt as $abt => $vereine) {
// AUSGLEICHEN DER GRUPPEN
$arrayAbt = [];
$arrayGruppen = [];
foreach ($allGeraete as $geraet) {
$arrayGruppen[$geraet['id']] = 0;
}
$turnerinnenCount = 0;
foreach ($vereine as $verein => $turnerinnen) {
$turnerinnenCount += count($turnerinnen);
}
foreach ($vereine as $verein => $turnerinnen) {
if (count($turnerinnen) > $maxTurnerinnenGruppe || count($turnerinnen) > $turnerinnenCount / count($allGeraete)) {
if (count($turnerinnen) > $turnerinnenCount / count($allGeraete)) {
$maxTurnerinnenGruppeTemp = ceil($turnerinnenCount / count($allGeraete));
} else {
$maxTurnerinnenGruppeTemp = $maxTurnerinnenGruppe;
}
// AUFTEILEN IN MEHRERE GRUPPEN
$chunks = array_chunk($turnerinnen, $maxTurnerinnenGruppeTemp);
foreach ($chunks as $chunk) {
$minKey = getMinKey($arrayGruppen);
$arrayGruppen[$minKey] += count($chunk);
foreach ($chunk as $ind =>$turnerin) {
$arrayAutoRiegeneinteilung[$abt][$minKey][] = $turnerin;
}
}
continue;
}
$minKey = getMinKey($arrayGruppen);
$arrayGruppen[$minKey] += count($turnerinnen);
foreach ($turnerinnen as $ind =>$turnerin) {
$arrayAutoRiegeneinteilung[$abt][$minKey][] = $turnerin;
}
}
}
foreach ($arrayAutoRiegeneinteilung as $indAbt => $abt) {
foreach ($abt as $indGeraet => $geraet) {
foreach ($geraet as $indTurnerin => $turnerin) {
$arrayAutoRiegeneinteilung[$indAbt][$indGeraet][$indTurnerin]['turnerin_index'] = $indTurnerin + 1;
}
}
}
return $arrayAutoRiegeneinteilung;
}
$arrayAutoRiegeneinteilung = arrayRiegeneiteilung($grouped, $maxTurnerinnenGruppe, $allGeraete);
if ($operation === 'overrite') {
$stmt = $mysqli->prepare("DELETE FROM $db_tabelle_gruppen");
$stmt->execute();
$stmt->close();
}
$stmt = $mysqli->prepare("DELETE FROM $db_tabelle_teilnehmende_gruppen");
$stmt->execute();
$stmt->close();
foreach ($arrayAutoRiegeneinteilung as $indAbt => $abt) {
if ($operation === 'overrite' || !isset($indexded_order_index_abt[$indAbt])) {
$var_name = "Abteilung $indAbt";
$stmt = $mysqli->prepare("INSERT INTO $db_tabelle_gruppen (`name`, `order_index`) VALUES (?, ?)");
$stmt->bind_param("si", $var_name, $indAbt);
$stmt->execute();
$idAbt = $stmt->insert_id;
$stmt->close();
} else {
$idAbt = $indexded_order_index_abt[$indAbt]['id'];
}
foreach ($abt as $indGeraet => $geraet) {
foreach ($geraet as $indTurnerin => $turnerin) {
$stmt = $mysqli->prepare("INSERT INTO $db_tabelle_teilnehmende_gruppen (turnerin_id, abteilung_id, geraet_id, turnerin_index) VALUES (?, ?, ?, ?)");
$stmt->bind_param("ssss", $turnerin['id'], $idAbt, $indGeraet, $turnerin['turnerin_index']);
$stmt->execute();
$stmt->close();
}
}
}
return http_response_code(200);
@@ -0,0 +1,44 @@
<?php
$baseDir = $_SERVER['DOCUMENT_ROOT'];
require_once $baseDir . '/../scripts/session_functions.php';
ini_wkvs_session();
check_user_permission('wk_leitung');
verify_csrf();
// Validate input
if (!isset($_POST['abt']) || !ctype_digit($_POST['abt']) || !isset($_POST['newName'])) {
http_response_code(406);
exit;
}
$abtInput = (int) $_POST['abt'];
$new_name = trim($_POST['newName']);
$type = 'wkl';
$dbconnection = require $baseDir . '/../scripts/db/db-verbindung-script.php';
if ($dbconnection['success'] !== true){
echo 'Critical DB Error.';
exit;
}
require $baseDir . '/../scripts/db/db-functions.php';
require $baseDir . '/../scripts/db/db-tables.php';
db_update(
$mysqli,
$db_tabelle_gruppen,
['name' => $new_name],
['id' => $abtInput]
);
http_response_code(200);
echo json_encode(['success' => true]);
exit;
@@ -0,0 +1,68 @@
<?php
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
// Show all errors except deprecation notices (these come from vendor libraries
// that aren't yet typed for newer PHP versions). Long-term fix: update
// dependencies to versions compatible with your PHP runtime.
error_reporting(E_ALL & ~E_DEPRECATED & ~E_USER_DEPRECATED);
if (!isset($baseDir)) {
$baseDir = $_SERVER['DOCUMENT_ROOT'];
}
require_once $baseDir . '/../scripts/session_functions.php';
ini_wkvs_session();
check_user_permission('wk_leitung');
verify_csrf();
// Validate input
if (!isset($_POST['anz_abt']) || !ctype_digit($_POST['anz_abt'])) {
http_response_code(406);
exit;
}
$anz_abt = (int) $_POST['anz_abt'];
$type = 'wkl';
$dbconnection = require $baseDir . '/../scripts/db/db-verbindung-script.php';
if ($dbconnection['success'] !== true){
echo 'Critical DB Error.';
exit;
}
require $baseDir . '/../scripts/db/db-functions.php';
require $baseDir . '/../scripts/db/db-tables.php';
// Fetch existing Abteilungen
$abts = db_select($mysqli, $db_tabelle_gruppen, '*');
// Delete excess Abteilungen
foreach ($abts as $dbabt) {
if ((int) $dbabt['order_index'] > $anz_abt) {
db_delete($mysqli, $db_tabelle_gruppen, ['id' => $dbabt['id']]);
}
}
// Build lookup of existing names
$existing = array_map('intval', array_column($abts, 'order_index'));
// Insert missing Abteilungen
$stmt = $mysqli->prepare("INSERT INTO $db_tabelle_gruppen (`name`, `order_index`) VALUES (?, ?)");
for ($i = 1; $i <= $anz_abt; $i++) {
if (!in_array($i, $existing, true)) {
$var_name = "Abteilung $i";
$stmt->bind_param('si', $var_name, $i);
$stmt->execute();
}
}
$stmt->close();
http_response_code(201);
@@ -0,0 +1,67 @@
<?php
$baseDir = $_SERVER['DOCUMENT_ROOT'];
require_once $baseDir . '/../scripts/session_functions.php';
ini_wkvs_session();
check_user_permission('wk_leitung');
verify_csrf();
// Validate input
if (!isset($_POST['abt']) || !ctype_digit($_POST['abt']) || !isset($_POST['newOrderIndex'])) {
http_response_code(406);
exit;
}
$abtInput = (int) $_POST['abt'];
$newOrderIndex_input = (int) $_POST['newOrderIndex'];
$type = 'wkl';
$dbconnection = require $baseDir . '/../scripts/db/db-verbindung-script.php';
if ($dbconnection['success'] !== true){
echo 'Critical DB Error.';
exit;
}
require $baseDir . '/../scripts/db/db-functions.php';
require $baseDir . '/../scripts/db/db-tables.php';
$allAbts = db_select($mysqli, $db_tabelle_gruppen, 'id', 'id != ? ORDER BY order_index ASC', [$abtInput]);
$ids = array_column($allAbts, 'id');
$targetIndex = max(0, $newOrderIndex_input - 1);
array_splice($ids, $targetIndex, 0, $abtInput);
$mysqli->begin_transaction();
$one_based_indexes = [];
try {
foreach ($ids as $zeroBasedIndex => $abtId) {
$newIndex = $zeroBasedIndex + 1;
db_update(
$mysqli,
$db_tabelle_gruppen,
['order_index' => $newIndex],
['id' => $abtId]
);
$one_based_indexes[$abtId] = $newIndex;
}
$mysqli->commit();
} catch (Exception $e) {
$mysqli->rollback();
http_response_code(500);
echo json_encode(['success' => false, 'error' => $e->getMessage()]);
exit;
}
http_response_code(200);
echo json_encode(['success' => true, 'newIndexes' => $one_based_indexes]);
exit;
@@ -0,0 +1,68 @@
<?php
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
// Show all errors except deprecation notices (these come from vendor libraries
// that aren't yet typed for newer PHP versions). Long-term fix: update
// dependencies to versions compatible with your PHP runtime.
error_reporting(E_ALL & ~E_DEPRECATED & ~E_USER_DEPRECATED);
if (!isset($baseDir)) {
$baseDir = $_SERVER['DOCUMENT_ROOT'];
}
require_once $baseDir . '/../scripts/session_functions.php';
ini_wkvs_session();
check_user_permission('wk_leitung');
verify_csrf();
// Validate input
if (!isset($_POST['abtId']) || !ctype_digit($_POST['abtId'])) {
http_response_code(406);
exit;
}
$abtInputId = (int) $_POST['abtId'];
$type = 'wkl';
$dbconnection = require $baseDir . '/../scripts/db/db-verbindung-script.php';
if ($dbconnection['success'] !== true){
echo 'Critical DB Error.';
exit;
}
require $baseDir . '/../scripts/db/db-functions.php';
require $baseDir . '/../scripts/db/db-tables.php';
// Fetch existing Abteilungen ordered by order_index
$abts = db_select($mysqli, $db_tabelle_gruppen, '*', '', [], 'order_index ASC');
$indexed_abts = array_column($abts, null, 'id');
$deleteIndex = $indexed_abts[$abtInputId]['order_index'] ?? null;
if ($deleteIndex === null) {
http_response_code(406);
exit;
}
// Delete selected row
db_delete($mysqli, $db_tabelle_gruppen, ['id' => $abtInputId]);
// Reindex subsequent rows
for ($i = $deleteIndex + 1; $i < count($abts); $i++) {
db_update(
$mysqli,
$db_tabelle_gruppen,
['order_index' => (int)$abts[$i]['order_index'] - 1],
['id' => (int)$abts[$i]['id']]
);
}
http_response_code(201);
@@ -0,0 +1,161 @@
<?php
ini_set("display_errors", 1);
ini_set("display_startup_errors", 1);
if (!isset($baseDir)) {
$baseDir = $_SERVER['DOCUMENT_ROOT'];
}
require_once $baseDir . '/../scripts/session_functions.php';
ini_wkvs_session();
check_user_permission('wk_leitung');
verify_csrf();
$type = 'wkl';
$dbconnection = require $baseDir . '/../scripts/db/db-verbindung-script.php';
if ($dbconnection['success'] !== true) {
echo 'Critical DB Error.';
exit;
}
require $baseDir . '/../scripts/db/db-tables.php';
require $baseDir . '/../scripts/db/db-functions.php';
$turnerin_ids = $_POST['turnerin_ids'] ?? [];
$neu_abteilung_id = intval($_POST['neuAbteilungId'] ?? 0);
$neu_geraet_id = intval($_POST['neuGeraetId'] ?? 0);
$alt_abteilung_id = intval($_POST['altAbteilungId'] ?? 0);
$alt_geraet_id = intval($_POST['altGeraetId'] ?? 0);
$neu_first_index = intval($_POST['neuFirstIndex'] ?? 0);
// Resolve Abteilung ID
if ($neu_abteilung_id < 1) {
http_response_code(400);
echo json_encode(['success' => false, 'message' => 'Keine Abteilungs ID angegeben.']);
exit;
} else {
$stmt = $mysqli->prepare("SELECT 1 FROM $db_tabelle_gruppen WHERE id = ?");
$stmt->bind_param("i", $neu_abteilung_id);
$stmt->execute();
if (!$stmt->get_result()->fetch_assoc()) {
http_response_code(400);
echo json_encode(['success' => false, 'message' => 'Invalide Abteilungs ID angegeben.']);
exit;
}
$stmt->close();
}
// Resolve Gerät ID
if ($neu_geraet_id < 1) {
http_response_code(400);
echo json_encode(['success' => false, 'message' => 'Keine neue Geräte ID angegeben.']);
exit;
} else {
$stmt = $mysqli->prepare("SELECT 1 FROM $db_tabelle_disziplinen WHERE id = ?");
$stmt->bind_param("i", $neu_geraet_id);
$stmt->execute();
if (!$stmt->get_result()->fetch_assoc()) {
http_response_code(400);
echo json_encode(['success' => false, 'message' => 'Invalide Geräte ID angegeben.']);
exit;
}
$stmt->close();
}
function arrayshift($v) {
return intval($v) + 1;
}
$array_ids = array_map('intval', $turnerin_ids);
$mysqli->begin_transaction();
try {
// 1. Move/Upsert the specific gymnasts into the new group
$stmt = $mysqli->prepare("
INSERT INTO $db_tabelle_teilnehmende_gruppen (turnerin_id, abteilung_id, geraet_id)
VALUES (?, ?, ?)
ON DUPLICATE KEY UPDATE abteilung_id = VALUES(abteilung_id), geraet_id = VALUES(geraet_id)
");
foreach ($array_ids as $id) {
$stmt->bind_param("iii", $id, $neu_abteilung_id, $neu_geraet_id);
$stmt->execute();
}
$stmt->close();
// 2. Reorder the old group to fill any gaps left by the moved gymnasts
if ($alt_abteilung_id !== 0 && $alt_geraet_id !== 0 && ($alt_abteilung_id !== $neu_abteilung_id || $alt_geraet_id !== $neu_geraet_id)) {
$old_group_rows_zero_based = db_select($mysqli, $db_tabelle_teilnehmende_gruppen, "turnerin_id",
"abteilung_id = ? AND geraet_id = ?", [$alt_abteilung_id, $alt_geraet_id], "turnerin_index ASC");
$updOld = $mysqli->prepare("UPDATE $db_tabelle_teilnehmende_gruppen SET `turnerin_index` = ? WHERE `turnerin_id` = ?");
$old_group_rows = [];
foreach ($old_group_rows_zero_based as $i => $row) {
$new_idx = $i + 1; // Start indexing at 1
$updOld->bind_param("ii", $new_idx, $row['turnerin_id']);
$updOld->execute();
$old_group_rows[$row['turnerin_id']] = $new_idx;
}
$updOld->close();
}
// 3. Fetch all gymnasts now in this group to determine final order
// Order by start_index so we preserve the existing relative order of gymnasts already there
$rows = db_select(
$mysqli,
$db_tabelle_teilnehmende_gruppen,
"turnerin_id",
"abteilung_id = ? AND geraet_id = ?",
[$neu_abteilung_id, $neu_geraet_id],
"turnerin_index ASC"
);
$current_ids = array_column($rows, 'turnerin_id');
// 4. Reconstruct the order: [Remaining ones before index] -> [Prioritized] -> [Remaining ones after index]
$remaining_ids = array_values(array_diff($current_ids, $array_ids));
$final_order_zero_based = [];
// Adjust index to 0-based for array manipulation
$target_pos = max(0, $neu_first_index - 1);
// Splice the prioritized IDs into the remaining list at the target position
array_splice($remaining_ids, $target_pos, 0, $array_ids);
$final_order_zero_based = $remaining_ids;
$final_order = [];
// 5. Update the database with the new continuous indices
$updStmt = $mysqli->prepare("UPDATE $db_tabelle_teilnehmende_gruppen SET `turnerin_index` = ? WHERE `turnerin_id` = ?");
foreach ($final_order_zero_based as $array_index => $t_id) {
$actual_index = $array_index + 1;
$updStmt->bind_param("ii", $actual_index, $t_id);
$updStmt->execute();
$final_order[$t_id] = $actual_index;
}
$updStmt->close();
$mysqli->commit();
http_response_code(200);
echo json_encode([
'success' => true,
'old_new_start_indexes' => $old_group_rows ?? null,
'new_new_start_indexes' => $final_order
]);
} catch (Throwable $e) {
$mysqli->rollback();
http_response_code(500);
echo json_encode(['success' => false]);
}