false, 'message' => 'Critical DB Error.']); exit; } $recalculateJSONs = false; $action = $_POST['action'] ?? ''; if ($action === 'add') { $name = trim($_POST['name'] ?? ''); $type_val = $_POST['type_val'] ?? 'input'; $berechnung = trim($_POST['berechnung'] ?? ''); $pro_geraet = intval($_POST['pro_geraet'] ?? 0); $default_value = (isset($_POST['default_value'])) ? floatval($_POST['default_value']) : null; $min_value = (isset($_POST['min_value'])) ? floatval($_POST['min_value']) : null; $max_value = (isset($_POST['max_value'])) ? floatval($_POST['max_value']) : null; $id = (isset($_POST['id'])) ? floatval($_POST['id']) : 1; if (!$id) { echo json_encode(['success' => false, 'message' => 'Id ist erforderlich.']); exit; } $stmt = $mysqli->prepare("SELECT 1 FROM $tableNotenBezeichnungen WHERE id = ?"); $stmt->bind_param("i", $id); $stmt->execute(); $result = $stmt->get_result(); if ($result->num_rows > 0) { echo json_encode([ 'success' => false, 'message' => 'Eine Note mit dieser Id existiert bereits.' ]); $stmt->close(); exit; } $stmt->close(); if (!$name) { echo json_encode(['success' => false, 'message' => 'Name ist erforderlich.']); exit; } $stmt = $mysqli->prepare("INSERT INTO $tableNotenBezeichnungen (id, name, type, berechnung, pro_geraet, default_value, min_value, max_value) VALUES (?, ?, ?, ?, ?, ?, ?, ?)"); $stmt->bind_param("isssisss", $id, $name, $type_val, $berechnung, $pro_geraet, $default_value, $min_value, $max_value); $success = $stmt->execute(); $new_id = $mysqli->insert_id; $stmt->close(); $recalculateJSONs = true; if ($success) { if (!$recalculateJSONs) { echo json_encode(['success' => true, 'id' => $new_id]); } } else { echo json_encode(['success' => false, 'message' => 'Fehler beim Hinzufügen.']); exit; } } elseif ($action === 'update') { $id = intval($_POST['id'] ?? 0); $field = $_POST['field'] ?? ''; $value = $_POST['value'] ?? ''; $allowedFields = ['name', 'type', 'berechnung', 'pro_geraet', 'geraete_json', 'anzahl_laeufe_json', 'default_value', 'min_value', 'max_value', 'zeige_in_tabelle', 'zeige_in_tabelle_mobile', 'zeige_in_tabelle_admin', 'zeige_auf_rangliste', 'nullstellen', 'prefix_display']; if ($id > 0 && in_array($field, $allowedFields)) { if ($field === 'pro_geraet') { $value = intval($value); } if ($field === 'berechnung' || $field === 'type') { $recalculateJSONs = true; } $updated = db_update($mysqli, $tableNotenBezeichnungen, [$field => $value], ['id' => $id]); if ($updated !== false) { if (!$recalculateJSONs) { echo json_encode(['success' => true]); } } else { echo json_encode(['success' => false, 'message' => 'DB Update failed.']); exit; } } else { echo json_encode(['success' => false, 'message' => 'Invalid parameters.']); exit; } } elseif ($action === 'delete') { $id = intval($_POST['id'] ?? 0); if ($id > 0) { db_delete($mysqli, $tableNotenBezeichnungen, ['id' => $id]); echo json_encode(['success' => true]); } else { echo json_encode(['success' => false, 'message' => 'Invalid ID.']); } } else { echo json_encode(['success' => false, 'message' => 'Action not found.']); exit; } if ($recalculateJSONs) { $noten = db_select($mysqli, $tableNotenBezeichnungen, "id, berechnung, type"); // 1. Re-index the array so the keys match the database IDs $notenById = array_column($noten, null, 'id'); $berechnungen = []; foreach ($notenById as $id => $sn) { if ($sn['type'] === 'berechnung') { $berechnungen[] = $sn; } } if (empty($berechnungen)) { echo json_encode(['success' => true, 'message' => "Keine Berechnungen ausgewählt"]); exit; } require $baseDir . "/../scripts/string-calculator/string-calculator-functions.php"; $notenRechner = new NotenRechner(); // 1. Build the direct map // Format: [ Changed_Note_ID => [ "CalcId|GeraetId" => [CalcId, GeraetId] ] ] $dependencyMap = []; foreach ($berechnungen as $calc) { $neededIdsArray = $notenRechner->getBenoetigteIdsComplex($calc['berechnung']); if (empty($neededIdsArray)) { continue; } $calcId = (int)$calc['id']; foreach ($neededIdsArray as $needed) { $nId = (int)$needed['noteId']; // Keep geraetId as integer if it's a number (e.g., 3), otherwise string ('S') $gId = is_numeric($needed['geraetId']) ? (int)$needed['geraetId'] : $needed['geraetId']; // Create a unique string key so we don't store exact duplicates $nodeKey = $calcId . '|' . $gId; if (!isset($dependencyMap[$nId])) { $dependencyMap[$nId] = []; } // Store it as the "little array" you requested: [DependentCalcId, GeraetId] $dependencyMap[$nId][$nodeKey] = [$calcId, $gId]; } } // 2. Our recursive helper function (Updated for complex nodes) function getCompleteDependencyChain($id, $directMap, $visited = []) { // If this ID doesn't have anything depending on it, return empty if (!isset($directMap[$id])) { return []; } $allDependencies = []; foreach ($directMap[$id] as $nodeKey => $complexNode) { // CIRCULAR DEPENDENCY CHECK: // We check against the string key (e.g., "10|S") to prevent infinite loops if (isset($visited[$nodeKey])) { continue; } // 1. Mark this specific node as visited $visited[$nodeKey] = true; // 2. Add the little array [CalcId, GeraetId] to our master list $allDependencies[$nodeKey] = $complexNode; // 3. Recursively find everything that depends on THIS calculation ID // $complexNode[0] is the dependent Calc ID $childDependencies = getCompleteDependencyChain($complexNode[0], $directMap, $visited); // 4. Merge the child results into our master list safely foreach ($childDependencies as $childKey => $childNode) { $allDependencies[$childKey] = $childNode; $visited[$childKey] = true; // Ensure the parent loop knows this was visited } } return $allDependencies; } // 3. Create the final flattened map for ALL IDs $flatDependencyMap = []; foreach (array_keys($notenById) as $id) { $chain = getCompleteDependencyChain($id, $dependencyMap); // Only add it if dependencies exist if (!empty($chain)) { // array_values() removes the "10|S" string keys, turning it into a perfect // 0-indexed array for clean JSON encoding: [[10, "S"], [12, 3]] $flatDependencyMap[$id] = array_values($chain); } } // 4. Database Updates // Step 1: Reset all rows to NULL in a single query $resetSql = "UPDATE $tableNotenBezeichnungen SET `berechnung_json` = NULL"; $mysqli->query($resetSql); // Step 2: Prepare the statement $updateSql = "UPDATE $tableNotenBezeichnungen SET `berechnung_json` = ? WHERE id = ?"; $stmt = $mysqli->prepare($updateSql); foreach ($flatDependencyMap as $id => $completeDependencyArray) { if (empty($completeDependencyArray)) { continue; } $jsonString = json_encode($completeDependencyArray); // Bind parameters: 's' for string (JSON), 'i' for integer (ID) $stmt->bind_param("si", $jsonString, $id); $stmt->execute(); } $stmt->close(); echo json_encode(['success' => true, 'message' => "Abhaengigkeiten berechnet"]); exit; }