false, 'error' => 'Unauthorized']); exit; } $requestMethod = strtoupper((string) ($_SERVER['REQUEST_METHOD'] ?? 'GET')); if ($requestMethod === 'POST') { $csrf = (string) ($_SERVER['HTTP_X_CSRF_TOKEN'] ?? ''); if (!auth_validate_csrf_token($csrf)) { http_response_code(419); echo json_encode(['ok' => false, 'error' => 'Ungültiges Sicherheits-Token']); exit; } $payload = json_decode((string) file_get_contents('php://input'), true); if (!is_array($payload)) { http_response_code(400); echo json_encode(['ok' => false, 'error' => 'Ungültige Anfrage']); exit; } try { if (($payload['action'] ?? '') === 'create') { $fields = is_array($payload['fields'] ?? null) ? $payload['fields'] : []; $occurrence = market_management_create_occurrence($pdo, [ 'market_definition_id' => $fields['market_definition_id'] ?? null, 'days' => [['date' => $fields['date'] ?? null]], ]); echo json_encode(['ok' => true, 'occurrence_id' => (int) $occurrence['id']], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES); exit; } $scope = (string) ($payload['scope'] ?? ''); $id = market_management_require_positive_id($payload['id'] ?? null, 'id'); $fields = is_array($payload['fields'] ?? null) ? $payload['fields'] : []; $costTransactionStarted = false; if (($payload['action'] ?? '') === 'delete') { if (($payload['confirmation'] ?? '') !== 'DELETE') { throw new InvalidArgumentException('Die Löschbestätigung muss exakt DELETE lauten.'); } market_management_set_occurrence_archive($pdo, $id, true); } elseif (($payload['action'] ?? '') === 'create_day') { $fields['occurrence_id'] = $id; $day = market_management_create_day($pdo, $fields); echo json_encode(['ok' => true, 'day' => $day]); exit; } elseif (($payload['action'] ?? '') === 'delete_day') { if (($payload['confirmation'] ?? '') !== 'DELETE') { throw new InvalidArgumentException('Bestätigung muss exakt DELETE lauten.'); } $day = market_management_delete_day($pdo, $id); echo json_encode(['ok' => true, 'day' => $day]); exit; } elseif (($payload['action'] ?? '') === 'create_cost_item') { $fields['occurrence_id'] = $id; $costItem = market_management_create_cost_item($pdo, $fields); echo json_encode(['ok' => true, 'cost_item' => $costItem], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES); exit; } elseif (($payload['action'] ?? '') === 'update_cost_item') { $costItem = market_management_update_cost_item($pdo, $id, $fields); echo json_encode(['ok' => true, 'cost_item' => $costItem], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES); exit; } elseif (($payload['action'] ?? '') === 'delete_cost_item') { if (($payload['confirmation'] ?? '') !== 'DELETE') { throw new InvalidArgumentException('Bestätigung muss exakt DELETE lauten.'); } $costItem = market_management_delete_cost_item($pdo, $id); echo json_encode(['ok' => true, 'cost_item' => $costItem], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES); exit; } elseif ($scope === 'day') { market_management_update_day($pdo, $id, $fields); } elseif (in_array($scope, ['occurrence', 'status', 'overview', 'participation', 'infrastructure', 'travel', 'notes'], true)) { $contactFields = []; foreach (['contact_person_name', 'contact_email', 'contact_phone'] as $contactField) { if (array_key_exists($contactField, $fields)) { $contactFields[$contactField] = $fields[$contactField]; unset($fields[$contactField]); } } $existingOccurrence = null; if ($contactFields !== []) { $existingOccurrence = market_management_get_occurrence($pdo, $id, true); } if ($contactFields !== []) { $contactFields['occurrence_id'] = $id; market_management_set_occurrence_contact($pdo, $contactFields); } if ($fields !== []) { $costItems = null; if (array_key_exists('cost_items', $fields)) { $costItems = is_string($fields['cost_items']) ? json_decode($fields['cost_items'], true) : $fields['cost_items']; if (!is_array($costItems)) { throw new InvalidArgumentException('Kostenpositionen sind ungültig.'); } if (!$pdo->inTransaction()) { $pdo->beginTransaction(); $costTransactionStarted = true; } unset($fields['cost_items']); $keptCostItemIds = array_values(array_filter(array_map( static fn (array $costItem): ?int => isset($costItem['id']) ? (int) $costItem['id'] : null, array_filter($costItems, 'is_array') ))); $existingCostItems = $pdo->prepare('SELECT id FROM market_occurrence_cost_item WHERE occurrence_id = :occurrence_id ORDER BY id ASC'); $existingCostItems->execute([':occurrence_id' => $id]); foreach ($existingCostItems->fetchAll(PDO::FETCH_COLUMN) as $existingCostItemId) { if (!in_array((int) $existingCostItemId, $keptCostItemIds, true)) { market_management_delete_cost_item($pdo, (int) $existingCostItemId); } } foreach ($costItems as $costItem) { if (!is_array($costItem)) { throw new InvalidArgumentException('Kostenposition ist ungültig.'); } if (($costItem['cost_type_id'] ?? null) === '__new__') { $newCostTypeName = trim((string) ($costItem['cost_type_name'] ?? '')); $newCostType = market_management_create_cost_type($pdo, $newCostTypeName); $costItem['cost_type_id'] = (int) $newCostType['id']; } unset($costItem['cost_type_name']); if (isset($costItem['id'])) { $costItemId = market_management_require_positive_id($costItem['id'], 'cost_item_id'); unset($costItem['id']); market_management_update_cost_item($pdo, $costItemId, $costItem); } else { $costItem['occurrence_id'] = $id; market_management_create_cost_item($pdo, $costItem); } } } market_management_update_occurrence($pdo, $id, $fields); if ($costTransactionStarted) { $pdo->commit(); $costTransactionStarted = false; } } } else { throw new InvalidArgumentException('Ungültiger Bearbeitungsbereich.'); } echo json_encode(['ok' => true]); exit; } catch (Throwable $error) { if ($costTransactionStarted && $pdo->inTransaction()) { $pdo->rollBack(); } http_response_code(422); echo json_encode(['ok' => false, 'error' => $error->getMessage()], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES); exit; } } if (($requestMethod === 'GET') && ($_GET['action'] ?? '') === 'create_options') { echo json_encode([ 'ok' => true, 'market_definitions' => market_management_list_active_market_definitions($pdo), ], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES); exit; } $occurrenceId = filter_input(INPUT_GET, 'id', FILTER_VALIDATE_INT); if (!is_int($occurrenceId) || $occurrenceId <= 0) { http_response_code(400); echo json_encode(['ok' => false, 'error' => 'Invalid occurrence id']); exit; } $occurrence = market_management_get_occurrence($pdo, $occurrenceId); if ($occurrence === null) { http_response_code(404); echo json_encode(['ok' => false, 'error' => 'Occurrence not found']); exit; } $market = market_management_get_market($pdo, (int) $occurrence['market_definition_id']); if ($market === null) { http_response_code(404); echo json_encode(['ok' => false, 'error' => 'Market not found']); exit; } echo json_encode(['ok' => true, 'market' => $market, 'occurrence' => $occurrence], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);