From 3813d0e976b641f1b8e21560ea622010ca375c43 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20M=C3=BCller?= Date: Wed, 6 May 2026 18:31:51 +0200 Subject: [PATCH] Daten direkt in datenbank bei Monatsvorhersage --- config/observationtips_database.php | 10 ++ public/monatsvorhersage.php | 197 ++++++++++++++++++++++++++++ 2 files changed, 207 insertions(+) create mode 100644 config/observationtips_database.php diff --git a/config/observationtips_database.php b/config/observationtips_database.php new file mode 100644 index 0000000..233ca4a --- /dev/null +++ b/config/observationtips_database.php @@ -0,0 +1,10 @@ + 'paulahnert.de', + 'dbname' => 'd03bc4ae', + 'user' => 'd03bc4ae', + 'pass' => 'eRutYnNXA6DhqK9T', + 'charset' => 'utf8mb4', +]; diff --git a/public/monatsvorhersage.php b/public/monatsvorhersage.php index 8ac1c52..c0408a0 100644 --- a/public/monatsvorhersage.php +++ b/public/monatsvorhersage.php @@ -14,6 +14,10 @@ $selectedMonth = isset($_GET['month']) ? max(1, min(12, (int) $_GET['month'])) : $selectedWeek = isset($_GET['week']) ? max(1, min(53, (int) $_GET['week'])) : (int) date('W'); $selectedWeekYear = isset($_GET['week_year']) ? (int) $_GET['week_year'] : $currentYear; $shouldRunForecast = isset($_GET['run']) && $_GET['run'] === '1'; +if (!isset($_SESSION['observation_tip_insert_token']) || !is_string($_SESSION['observation_tip_insert_token'])) { + $_SESSION['observation_tip_insert_token'] = bin2hex(random_bytes(16)); +} +$observationTipInsertToken = $_SESSION['observation_tip_insert_token']; // ------------------------------------------------------------------------- // Bereits berechnete Bausteine der Monatsvorschau @@ -253,6 +257,7 @@ $favoriteCometEvents = []; $seasonChanges = []; $timeChanges = []; $monthEventList = []; +$observationTipInsertResult = null; $starDataError = null; $monthNarrativeText = ''; $observationTipInsertSql = ''; @@ -583,6 +588,109 @@ if (!function_exists('buildObservationTipInsertSql')) { } } +if (!function_exists('normalizeObservationTipEvents')) { + function normalizeObservationTipEvents(array $events, DateTimeZone $timezone): array + { + $normalized = []; + + foreach ($events as $event) { + if (!is_array($event)) { + continue; + } + + $tip = trim((string) ($event['event'] ?? '')); + if ($tip === '') { + continue; + } + + $moment = null; + $localIso = trim((string) ($event['local_iso'] ?? '')); + if ($localIso !== '') { + try { + $moment = new DateTimeImmutable($localIso); + } catch (Throwable) { + $moment = null; + } + } + + if (!$moment instanceof DateTimeImmutable) { + $date = trim((string) ($event['date'] ?? '')); + $time = trim((string) ($event['time'] ?? '')); + if ($date !== '' && $time !== '') { + $moment = DateTimeImmutable::createFromFormat('d.m.Y H:i', $date . ' ' . $time, $timezone) ?: null; + } + } + + if (!$moment instanceof DateTimeImmutable) { + continue; + } + + $normalized[] = [ + 'moment' => $moment->setTimezone($timezone)->format('Y-m-d H:i:s'), + 'tip' => $tip, + ]; + } + + return $normalized; + } +} + +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 { @@ -2383,6 +2491,56 @@ $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(), + ]; + } + } +} + $chartConfig = [ 'monthName' => $months[$selectedMonth], 'year' => $selectedYear, @@ -2609,6 +2767,15 @@ $observationTipCalendarFilenameJson = json_encode(sprintf('astrotools-monatserei

Chronologische Monatsliste für

+ +
+ + + +
+