Daten direkt in datenbank bei Monatsvorhersage
This commit is contained in:
@@ -0,0 +1,10 @@
|
|||||||
|
<?php
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
return [
|
||||||
|
'host' => 'paulahnert.de',
|
||||||
|
'dbname' => 'd03bc4ae',
|
||||||
|
'user' => 'd03bc4ae',
|
||||||
|
'pass' => 'eRutYnNXA6DhqK9T',
|
||||||
|
'charset' => 'utf8mb4',
|
||||||
|
];
|
||||||
@@ -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');
|
$selectedWeek = isset($_GET['week']) ? max(1, min(53, (int) $_GET['week'])) : (int) date('W');
|
||||||
$selectedWeekYear = isset($_GET['week_year']) ? (int) $_GET['week_year'] : $currentYear;
|
$selectedWeekYear = isset($_GET['week_year']) ? (int) $_GET['week_year'] : $currentYear;
|
||||||
$shouldRunForecast = isset($_GET['run']) && $_GET['run'] === '1';
|
$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
|
// Bereits berechnete Bausteine der Monatsvorschau
|
||||||
@@ -253,6 +257,7 @@ $favoriteCometEvents = [];
|
|||||||
$seasonChanges = [];
|
$seasonChanges = [];
|
||||||
$timeChanges = [];
|
$timeChanges = [];
|
||||||
$monthEventList = [];
|
$monthEventList = [];
|
||||||
|
$observationTipInsertResult = null;
|
||||||
$starDataError = null;
|
$starDataError = null;
|
||||||
$monthNarrativeText = '';
|
$monthNarrativeText = '';
|
||||||
$observationTipInsertSql = '';
|
$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')) {
|
if (!function_exists('escapeIcalText')) {
|
||||||
function escapeIcalText(string $value): string
|
function escapeIcalText(string $value): string
|
||||||
{
|
{
|
||||||
@@ -2383,6 +2491,56 @@ $monthNarrativeText = monthForecastBuildNarrativeText($monthEventList, $selected
|
|||||||
$observationTipInsertSql = buildObservationTipInsertSql($monthEventList, new DateTimeZone($chartTimezone));
|
$observationTipInsertSql = buildObservationTipInsertSql($monthEventList, new DateTimeZone($chartTimezone));
|
||||||
$observationTipCalendarIcs = buildObservationTipCalendarIcs($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 = [
|
$chartConfig = [
|
||||||
'monthName' => $months[$selectedMonth],
|
'monthName' => $months[$selectedMonth],
|
||||||
'year' => $selectedYear,
|
'year' => $selectedYear,
|
||||||
@@ -2609,6 +2767,15 @@ $observationTipCalendarFilenameJson = json_encode(sprintf('astrotools-monatserei
|
|||||||
<p>Chronologische Monatsliste für <?= htmlspecialchars($chartTimezone, ENT_QUOTES, 'UTF-8') ?></p>
|
<p>Chronologische Monatsliste für <?= htmlspecialchars($chartTimezone, ENT_QUOTES, 'UTF-8') ?></p>
|
||||||
</div>
|
</div>
|
||||||
<div class="monatskarte-export">
|
<div class="monatskarte-export">
|
||||||
|
<?php if ($monthEventList): ?>
|
||||||
|
<form method="post" class="monatskarte-inline-form">
|
||||||
|
<input type="hidden" name="insert_observation_tips" value="1">
|
||||||
|
<input type="hidden" name="observation_tip_insert_token" value="<?= htmlspecialchars($observationTipInsertToken, ENT_QUOTES, 'UTF-8') ?>">
|
||||||
|
<button type="submit" class="monatskarte-export-button">
|
||||||
|
Direkt in Datenbank eintragen
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
<?php endif; ?>
|
||||||
<?php if ($observationTipInsertSql !== ''): ?>
|
<?php if ($observationTipInsertSql !== ''): ?>
|
||||||
<button type="button" class="monatskarte-export-button" id="toggleObservationTipSql">
|
<button type="button" class="monatskarte-export-button" id="toggleObservationTipSql">
|
||||||
SQL-Insert anzeigen
|
SQL-Insert anzeigen
|
||||||
@@ -2623,6 +2790,11 @@ $observationTipCalendarFilenameJson = json_encode(sprintf('astrotools-monatserei
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="monatskarte-footer">
|
<div class="monatskarte-footer">
|
||||||
|
<?php if (is_array($observationTipInsertResult)): ?>
|
||||||
|
<p class="monatskarte-insert-status <?= !empty($observationTipInsertResult['success']) ? 'is-success' : 'is-error' ?>">
|
||||||
|
<?= htmlspecialchars((string) ($observationTipInsertResult['message'] ?? ''), ENT_QUOTES, 'UTF-8') ?>
|
||||||
|
</p>
|
||||||
|
<?php endif; ?>
|
||||||
<?php if ($observationTipInsertSql !== ''): ?>
|
<?php if ($observationTipInsertSql !== ''): ?>
|
||||||
<div class="monatskarte-sql-export" id="observationTipSqlPanel" hidden>
|
<div class="monatskarte-sql-export" id="observationTipSqlPanel" hidden>
|
||||||
<label class="monatskarte-sql-label" for="observationTipSqlOutput">SQL für `astro_sonobs_observationtips`</label>
|
<label class="monatskarte-sql-label" for="observationTipSqlOutput">SQL für `astro_sonobs_observationtips`</label>
|
||||||
@@ -2674,6 +2846,29 @@ $observationTipCalendarFilenameJson = json_encode(sprintf('astrotools-monatserei
|
|||||||
padding: 18px;
|
padding: 18px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.monatskarte-inline-form {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.monatskarte-insert-status {
|
||||||
|
margin: 0 0 14px;
|
||||||
|
padding: 10px 12px;
|
||||||
|
border-radius: 10px;
|
||||||
|
font-size: 0.95rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.monatskarte-insert-status.is-success {
|
||||||
|
background: #e8f7ec;
|
||||||
|
color: #1d5c2f;
|
||||||
|
border: 1px solid #b7dfc1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.monatskarte-insert-status.is-error {
|
||||||
|
background: #fff0f0;
|
||||||
|
color: #7a1f1f;
|
||||||
|
border: 1px solid #efc0c0;
|
||||||
|
}
|
||||||
|
|
||||||
.monatsvorhersage-shell {
|
.monatsvorhersage-shell {
|
||||||
display: grid;
|
display: grid;
|
||||||
gap: 18px;
|
gap: 18px;
|
||||||
@@ -2804,6 +2999,8 @@ $observationTipCalendarFilenameJson = json_encode(sprintf('astrotools-monatserei
|
|||||||
.monatskarte-export {
|
.monatskarte-export {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
gap: 10px;
|
||||||
|
flex-wrap: wrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
.monatskarte-export-button {
|
.monatskarte-export-button {
|
||||||
|
|||||||
Reference in New Issue
Block a user