diff --git a/public/ajax/insert_observationtips.php b/public/ajax/insert_observationtips.php new file mode 100644 index 0000000..cd22457 --- /dev/null +++ b/public/ajax/insert_observationtips.php @@ -0,0 +1,140 @@ + false, + 'message' => 'Nur POST ist erlaubt.', + ], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES); + exit; +} + +$sessionToken = isset($_SESSION['observation_tip_insert_token']) && is_string($_SESSION['observation_tip_insert_token']) + ? $_SESSION['observation_tip_insert_token'] + : ''; +$submittedToken = isset($_POST['observation_tip_insert_token']) ? (string) $_POST['observation_tip_insert_token'] : ''; + +if ($sessionToken === '' || $submittedToken === '' || !hash_equals($sessionToken, $submittedToken)) { + http_response_code(403); + echo json_encode([ + 'success' => false, + 'message' => 'Sicherheitspruefung fehlgeschlagen. Bitte die Seite neu laden und erneut versuchen.', + ], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES); + exit; +} + +$payloadJson = isset($_POST['observation_tip_payload']) ? (string) $_POST['observation_tip_payload'] : ''; +$rows = json_decode($payloadJson, true); +if (!is_array($rows)) { + http_response_code(400); + echo json_encode([ + 'success' => false, + 'message' => 'Ungueltige Ereignisdaten empfangen.', + ], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES); + exit; +} + +$normalized = []; +foreach ($rows as $row) { + if (!is_array($row)) { + continue; + } + + $moment = trim((string) ($row['moment'] ?? '')); + $tip = trim((string) ($row['tip'] ?? '')); + if ($moment === '' || $tip === '') { + continue; + } + + $normalized[] = [ + 'moment' => $moment, + 'tip' => $tip, + ]; +} + +if ($normalized === []) { + echo json_encode([ + 'success' => false, + 'message' => 'Keine gueltigen Ereignisse zum Eintragen vorhanden.', + 'inserted' => 0, + 'skipped' => 0, + ], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES); + exit; +} + +try { + $dbConfig = require __DIR__ . '/../../config/observationtips_database.php'; + $dsn = sprintf( + 'mysql:host=%s;dbname=%s;charset=%s', + $dbConfig['host'], + $dbConfig['dbname'], + $dbConfig['charset'] ?? 'utf8mb4' + ); + $pdo = new PDO( + $dsn, + $dbConfig['user'], + $dbConfig['pass'], + [ + PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, + PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, + ] + ); + + $checkStmt = $pdo->prepare( + 'SELECT 1 FROM `astro_sonobs_observationtips` WHERE `moment` = :moment AND `tip` = :tip LIMIT 1' + ); + $insertStmt = $pdo->prepare( + 'INSERT INTO `astro_sonobs_observationtips` (`moment`, `tip`) VALUES (:moment, :tip)' + ); + + $inserted = 0; + $skipped = 0; + + $pdo->beginTransaction(); + try { + foreach ($normalized as $row) { + $checkStmt->execute([ + ':moment' => $row['moment'], + ':tip' => $row['tip'], + ]); + + if ($checkStmt->fetchColumn()) { + $skipped++; + continue; + } + + $insertStmt->execute([ + ':moment' => $row['moment'], + ':tip' => $row['tip'], + ]); + $inserted++; + } + + $pdo->commit(); + } catch (Throwable $e) { + if ($pdo->inTransaction()) { + $pdo->rollBack(); + } + throw $e; + } + + echo json_encode([ + 'success' => true, + 'message' => sprintf('%d Ereignisse eingetragen, %d bereits vorhanden.', $inserted, $skipped), + 'inserted' => $inserted, + 'skipped' => $skipped, + ], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES); +} catch (Throwable $e) { + http_response_code(500); + echo json_encode([ + 'success' => false, + 'message' => 'Eintragen in `astro_sonobs_observationtips` fehlgeschlagen: ' . $e->getMessage(), + 'inserted' => 0, + 'skipped' => 0, + ], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES); +} diff --git a/public/monatsvorhersage.php b/public/monatsvorhersage.php index c0408a0..55f4283 100644 --- a/public/monatsvorhersage.php +++ b/public/monatsvorhersage.php @@ -257,11 +257,12 @@ $favoriteCometEvents = []; $seasonChanges = []; $timeChanges = []; $monthEventList = []; -$observationTipInsertResult = null; $starDataError = null; $monthNarrativeText = ''; $observationTipInsertSql = ''; $observationTipCalendarIcs = ''; +$observationTipInsertPayloadJson = '[]'; +$observationTipInsertEndpoint = $publicBasePath . 'ajax/insert_observationtips.php'; $chartConfig = null; $chartConfigJson = 'null'; $starDataJson = '[]'; @@ -635,62 +636,6 @@ if (!function_exists('normalizeObservationTipEvents')) { } } -if (!function_exists('insertObservationTipEvents')) { - function insertObservationTipEvents(PDO $pdo, array $events, DateTimeZone $timezone): array - { - $normalized = normalizeObservationTipEvents($events, $timezone); - if ($normalized === []) { - return [ - 'inserted' => 0, - 'skipped' => 0, - ]; - } - - $checkStmt = $pdo->prepare( - 'SELECT 1 FROM `astro_sonobs_observationtips` WHERE `moment` = :moment AND `tip` = :tip LIMIT 1' - ); - $insertStmt = $pdo->prepare( - 'INSERT INTO `astro_sonobs_observationtips` (`moment`, `tip`) VALUES (:moment, :tip)' - ); - - $inserted = 0; - $skipped = 0; - - $pdo->beginTransaction(); - try { - foreach ($normalized as $row) { - $checkStmt->execute([ - ':moment' => $row['moment'], - ':tip' => $row['tip'], - ]); - - if ($checkStmt->fetchColumn()) { - $skipped++; - continue; - } - - $insertStmt->execute([ - ':moment' => $row['moment'], - ':tip' => $row['tip'], - ]); - $inserted++; - } - - $pdo->commit(); - } catch (Throwable $e) { - if ($pdo->inTransaction()) { - $pdo->rollBack(); - } - throw $e; - } - - return [ - 'inserted' => $inserted, - 'skipped' => $skipped, - ]; - } -} - if (!function_exists('escapeIcalText')) { function escapeIcalText(string $value): string { @@ -2490,56 +2435,10 @@ $monthNarrativeText = monthForecastBuildNarrativeText($monthEventList, $selected $observationTipInsertSql = buildObservationTipInsertSql($monthEventList, new DateTimeZone($chartTimezone)); $observationTipCalendarIcs = buildObservationTipCalendarIcs($monthEventList, new DateTimeZone($chartTimezone)); - -if ( - $_SERVER['REQUEST_METHOD'] === 'POST' - && isset($_POST['insert_observation_tips']) - && $_POST['insert_observation_tips'] === '1' -) { - $submittedToken = isset($_POST['observation_tip_insert_token']) ? (string) $_POST['observation_tip_insert_token'] : ''; - if (!hash_equals($observationTipInsertToken, $submittedToken)) { - $observationTipInsertResult = [ - 'success' => false, - 'message' => 'Sicherheitspruefung fehlgeschlagen. Bitte die Seite neu laden und erneut versuchen.', - ]; - } else { - try { - $observationTipDbConfig = require __DIR__ . '/../config/observationtips_database.php'; - $observationTipDsn = sprintf( - 'mysql:host=%s;dbname=%s;charset=%s', - $observationTipDbConfig['host'], - $observationTipDbConfig['dbname'], - $observationTipDbConfig['charset'] ?? 'utf8mb4' - ); - $observationTipPdo = new PDO( - $observationTipDsn, - $observationTipDbConfig['user'], - $observationTipDbConfig['pass'], - [ - PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, - PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, - ] - ); - - $observationTipInsertResult = insertObservationTipEvents( - $observationTipPdo, - $monthEventList, - new DateTimeZone($chartTimezone) - ); - $observationTipInsertResult['success'] = true; - $observationTipInsertResult['message'] = sprintf( - '%d Ereignisse eingetragen, %d bereits vorhanden.', - (int) $observationTipInsertResult['inserted'], - (int) $observationTipInsertResult['skipped'] - ); - } catch (Throwable $e) { - $observationTipInsertResult = [ - 'success' => false, - 'message' => 'Eintragen in `astro_sonobs_observationtips` fehlgeschlagen: ' . $e->getMessage(), - ]; - } - } -} +$observationTipInsertPayloadJson = json_encode( + normalizeObservationTipEvents($monthEventList, new DateTimeZone($chartTimezone)), + JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES +) ?: '[]'; $chartConfig = [ 'monthName' => $months[$selectedMonth], @@ -2768,10 +2667,11 @@ $observationTipCalendarFilenameJson = json_encode(sprintf('astrotools-monatserei