PDO::ERRMODE_EXCEPTION, PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, ] ); $userId = (int) $_SESSION['user_id']; $errors = []; $successMessage = ''; $satelliteSearchResults = []; $minorplanetSearchResults = []; $satelliteSearchQuery = trim($_GET['sat_q'] ?? ''); $minorplanetSearchQuery = trim($_GET['mp_q'] ?? ''); $pageTitle = 'Favoriten - AstroTools'; $headerIntroPre = 'Merkliste'; $headerIntroTitle = 'Favoriten'; $headerIntroSub = 'Satelliten und Kleinplaneten zentral verwalten.'; function h(?string $value): string { return htmlspecialchars((string) $value, ENT_QUOTES, 'UTF-8'); } function validTimezone(string $timezone): bool { return in_array($timezone, timezone_identifiers_list(), true); } function setExclusiveFavorite(PDO $pdo, string $tableName, string $idColumn, int $userId, int $entityId): bool { $pdo->beginTransaction(); try { $stmtCurrent = $pdo->prepare(" SELECT `is_favorite` FROM `{$tableName}` WHERE `user_id` = :user_id AND `{$idColumn}` = :entity_id LIMIT 1 "); $stmtCurrent->execute([ ':user_id' => $userId, ':entity_id' => $entityId, ]); $current = $stmtCurrent->fetchColumn(); if ($current === false) { $pdo->rollBack(); return false; } $newValue = (int) $current === 1 ? 0 : 1; if ($newValue === 1) { $stmtReset = $pdo->prepare(" UPDATE `{$tableName}` SET `is_favorite` = 0 WHERE `user_id` = :user_id "); $stmtReset->execute([ ':user_id' => $userId, ]); } $stmtSet = $pdo->prepare(" UPDATE `{$tableName}` SET `is_favorite` = :is_favorite WHERE `user_id` = :user_id AND `{$idColumn}` = :entity_id "); $stmtSet->execute([ ':is_favorite' => $newValue, ':user_id' => $userId, ':entity_id' => $entityId, ]); $pdo->commit(); return true; } catch (Throwable $e) { if ($pdo->inTransaction()) { $pdo->rollBack(); } throw $e; } } if ($_SERVER['REQUEST_METHOD'] === 'POST') { $action = $_POST['action'] ?? ''; if ($action === 'add_satellite') { $satelliteId = (int) ($_POST['satellite_id'] ?? 0); if ($satelliteId <= 0) { $errors[] = 'Ungueltiger Satellit.'; } if (empty($errors)) { $stmtCheck = $pdo->prepare(" SELECT `id` FROM `sat_satellites` WHERE `id` = :id LIMIT 1 "); $stmtCheck->execute([ ':id' => $satelliteId, ]); if (!$stmtCheck->fetch()) { $errors[] = 'Der Satellit wurde nicht gefunden.'; } } if (empty($errors)) { $stmtInsert = $pdo->prepare(" INSERT INTO `app_user_satellites` ( `user_id`, `satellite_id`, `is_favorite`, `created_at` ) VALUES ( :user_id, :satellite_id, 0, NOW() ) ON DUPLICATE KEY UPDATE `satellite_id` = VALUES(`satellite_id`) "); $stmtInsert->execute([ ':user_id' => $userId, ':satellite_id' => $satelliteId, ]); $successMessage = 'Der Satellit wurde hinzugefuegt.'; } } if ($action === 'remove_satellite') { $satelliteId = (int) ($_POST['satellite_id'] ?? 0); if ($satelliteId <= 0) { $errors[] = 'Ungueltiger Satellit.'; } if (empty($errors)) { $stmtDelete = $pdo->prepare(" DELETE FROM `app_user_satellites` WHERE `user_id` = :user_id AND `satellite_id` = :satellite_id "); $stmtDelete->execute([ ':user_id' => $userId, ':satellite_id' => $satelliteId, ]); $successMessage = 'Der Satellit wurde entfernt.'; } } if ($action === 'toggle_satellite_favorite') { $satelliteId = (int) ($_POST['satellite_id'] ?? 0); if ($satelliteId <= 0) { $errors[] = 'Ungueltiger Satellit.'; } if (empty($errors)) { if (!setExclusiveFavorite($pdo, 'app_user_satellites', 'satellite_id', $userId, $satelliteId)) { $errors[] = 'Der Satellit ist nicht in deiner Liste vorhanden.'; } else { $successMessage = 'Der Satelliten-Favorit wurde aktualisiert.'; } } } if ($action === 'add_minorplanet') { $minorplanetId = (int) ($_POST['minorplanet_id'] ?? 0); if ($minorplanetId <= 0) { $errors[] = 'Ungueltiger Kleinplanet.'; } if (empty($errors)) { $stmtCheck = $pdo->prepare(" SELECT `id` FROM `minorplanets_mpc` WHERE `id` = :id LIMIT 1 "); $stmtCheck->execute([ ':id' => $minorplanetId, ]); if (!$stmtCheck->fetch()) { $errors[] = 'Der Kleinplanet wurde nicht gefunden.'; } } if (empty($errors)) { $stmtInsert = $pdo->prepare(" INSERT INTO `app_user_minorplanets` ( `user_id`, `minorplanet_id`, `is_favorite`, `created_at` ) VALUES ( :user_id, :minorplanet_id, 0, NOW() ) ON DUPLICATE KEY UPDATE `minorplanet_id` = VALUES(`minorplanet_id`) "); $stmtInsert->execute([ ':user_id' => $userId, ':minorplanet_id' => $minorplanetId, ]); $successMessage = 'Der Kleinplanet wurde hinzugefuegt.'; } } if ($action === 'remove_minorplanet') { $minorplanetId = (int) ($_POST['minorplanet_id'] ?? 0); if ($minorplanetId <= 0) { $errors[] = 'Ungueltiger Kleinplanet.'; } if (empty($errors)) { $stmtDelete = $pdo->prepare(" DELETE FROM `app_user_minorplanets` WHERE `user_id` = :user_id AND `minorplanet_id` = :minorplanet_id "); $stmtDelete->execute([ ':user_id' => $userId, ':minorplanet_id' => $minorplanetId, ]); $successMessage = 'Der Kleinplanet wurde entfernt.'; } } if ($action === 'toggle_minorplanet_favorite') { $minorplanetId = (int) ($_POST['minorplanet_id'] ?? 0); if ($minorplanetId <= 0) { $errors[] = 'Ungueltiger Kleinplanet.'; } if (empty($errors)) { if (!setExclusiveFavorite($pdo, 'app_user_minorplanets', 'minorplanet_id', $userId, $minorplanetId)) { $errors[] = 'Der Kleinplanet ist nicht in deiner Liste vorhanden.'; } else { $successMessage = 'Der Kleinplaneten-Favorit wurde aktualisiert.'; } } } if ($action === 'add_location') { $name = trim($_POST['name'] ?? ''); $latitude = trim($_POST['latitude'] ?? ''); $longitude = trim($_POST['longitude'] ?? ''); $elevation = trim($_POST['elevation'] ?? ''); $timezone = trim($_POST['timezone'] ?? 'Europe/Berlin'); $isDefault = isset($_POST['is_default']) ? 1 : 0; if ($name === '') { $errors[] = 'Bitte einen Namen fuer den Standort eingeben.'; } if ($latitude === '' || !is_numeric($latitude)) { $errors[] = 'Bitte einen gueltigen Breitengrad eingeben.'; } else { $lat = (float) $latitude; if ($lat < -90 || $lat > 90) { $errors[] = 'Der Breitengrad muss zwischen -90 und 90 liegen.'; } } if ($longitude === '' || !is_numeric($longitude)) { $errors[] = 'Bitte einen gueltigen Laengengrad eingeben.'; } else { $lon = (float) $longitude; if ($lon < -180 || $lon > 180) { $errors[] = 'Der Laengengrad muss zwischen -180 und 180 liegen.'; } } if ($elevation !== '' && !is_numeric($elevation)) { $errors[] = 'Die Hoehe muss numerisch sein.'; } if (!validTimezone($timezone)) { $errors[] = 'Bitte eine gueltige IANA-Zeitzone angeben, z. B. Europe/Berlin.'; } if (empty($errors)) { $pdo->beginTransaction(); try { if ($isDefault === 1) { $stmtReset = $pdo->prepare(" UPDATE `app_user_locations` SET `is_default` = 0 WHERE `user_id` = :user_id "); $stmtReset->execute([ ':user_id' => $userId, ]); } $stmtInsertLocation = $pdo->prepare(" INSERT INTO `app_user_locations` ( `user_id`, `name`, `latitude`, `longitude`, `elevation`, `timezone`, `is_default`, `created_at`, `updated_at` ) VALUES ( :user_id, :name, :latitude, :longitude, :elevation, :timezone, :is_default, NOW(), NOW() ) "); $stmtInsertLocation->execute([ ':user_id' => $userId, ':name' => $name, ':latitude' => (float) $latitude, ':longitude' => (float) $longitude, ':elevation' => $elevation !== '' ? (float) $elevation : null, ':timezone' => $timezone, ':is_default' => $isDefault, ]); $pdo->commit(); $successMessage = 'Der Standort wurde gespeichert.'; $_POST = []; } catch (Throwable $e) { if ($pdo->inTransaction()) { $pdo->rollBack(); } $errors[] = 'Der Standort konnte nicht gespeichert werden.'; } } } if ($action === 'set_default_location') { $locationId = (int) ($_POST['location_id'] ?? 0); if ($locationId <= 0) { $errors[] = 'Ungueltiger Standort.'; } if (empty($errors)) { $stmtCheckLocation = $pdo->prepare(" SELECT `id` FROM `app_user_locations` WHERE `id` = :id AND `user_id` = :user_id LIMIT 1 "); $stmtCheckLocation->execute([ ':id' => $locationId, ':user_id' => $userId, ]); if (!$stmtCheckLocation->fetch()) { $errors[] = 'Der Standort wurde nicht gefunden.'; } } if (empty($errors)) { $pdo->beginTransaction(); try { $stmtReset = $pdo->prepare(" UPDATE `app_user_locations` SET `is_default` = 0 WHERE `user_id` = :user_id "); $stmtReset->execute([ ':user_id' => $userId, ]); $stmtSet = $pdo->prepare(" UPDATE `app_user_locations` SET `is_default` = 1 WHERE `id` = :id AND `user_id` = :user_id "); $stmtSet->execute([ ':id' => $locationId, ':user_id' => $userId, ]); $pdo->commit(); $successMessage = 'Der Standard-Standort wurde gesetzt.'; } catch (Throwable $e) { if ($pdo->inTransaction()) { $pdo->rollBack(); } $errors[] = 'Der Standard-Standort konnte nicht gesetzt werden.'; } } } if ($action === 'delete_location') { $locationId = (int) ($_POST['location_id'] ?? 0); if ($locationId <= 0) { $errors[] = 'Ungueltiger Standort.'; } if (empty($errors)) { $stmtDelete = $pdo->prepare(" DELETE FROM `app_user_locations` WHERE `id` = :id AND `user_id` = :user_id "); $stmtDelete->execute([ ':id' => $locationId, ':user_id' => $userId, ]); $successMessage = 'Der Standort wurde geloescht.'; } } } $stmtLocations = $pdo->prepare(" SELECT `id`, `name`, `latitude`, `longitude`, `elevation`, `timezone`, `is_default` FROM `app_user_locations` WHERE `user_id` = :user_id ORDER BY `is_default` DESC, `name` ASC "); $stmtLocations->execute([ ':user_id' => $userId, ]); $locations = $stmtLocations->fetchAll(); $defaultLocation = null; foreach ($locations as $location) { if ((int) $location['is_default'] === 1) { $defaultLocation = $location; break; } } $mapLat = isset($_POST['latitude']) && is_numeric($_POST['latitude']) ? (float) $_POST['latitude'] : ($defaultLocation ? (float) $defaultLocation['latitude'] : 51.1657); $mapLon = isset($_POST['longitude']) && is_numeric($_POST['longitude']) ? (float) $_POST['longitude'] : ($defaultLocation ? (float) $defaultLocation['longitude'] : 10.4515); $mapZoom = $defaultLocation ? 10 : 6; if ($satelliteSearchQuery !== '') { if (ctype_digit($satelliteSearchQuery)) { $stmtSatelliteSearch = $pdo->prepare(" SELECT s.`id`, s.`norad_cat_id`, s.`object_name`, CASE WHEN aus.`satellite_id` IS NULL THEN 0 ELSE 1 END AS `already_added` FROM `sat_satellites` s LEFT JOIN `app_user_satellites` aus ON aus.`satellite_id` = s.`id` AND aus.`user_id` = :user_id WHERE s.`norad_cat_id` = :norad_cat_id ORDER BY s.`object_name` ASC LIMIT 50 "); $stmtSatelliteSearch->execute([ ':user_id' => $userId, ':norad_cat_id' => (int) $satelliteSearchQuery, ]); } else { $stmtSatelliteSearch = $pdo->prepare(" SELECT s.`id`, s.`norad_cat_id`, s.`object_name`, CASE WHEN aus.`satellite_id` IS NULL THEN 0 ELSE 1 END AS `already_added` FROM `sat_satellites` s LEFT JOIN `app_user_satellites` aus ON aus.`satellite_id` = s.`id` AND aus.`user_id` = :user_id WHERE s.`object_name` LIKE :query ORDER BY s.`object_name` ASC LIMIT 50 "); $stmtSatelliteSearch->execute([ ':user_id' => $userId, ':query' => '%' . $satelliteSearchQuery . '%', ]); } $satelliteSearchResults = $stmtSatelliteSearch->fetchAll(); } if ($minorplanetSearchQuery !== '') { if (ctype_digit($minorplanetSearchQuery)) { $stmtMinorplanetSearch = $pdo->prepare(" SELECT mp.`id`, mp.`mp_number`, mp.`designation_text`, mp.`desig_packed`, CASE WHEN aum.`minorplanet_id` IS NULL THEN 0 ELSE 1 END AS `already_added` FROM `minorplanets_mpc` mp LEFT JOIN `app_user_minorplanets` aum ON aum.`minorplanet_id` = mp.`id` AND aum.`user_id` = :user_id WHERE mp.`mp_number` = :mp_number ORDER BY mp.`mp_number` ASC, mp.`designation_text` ASC LIMIT 50 "); $stmtMinorplanetSearch->execute([ ':user_id' => $userId, ':mp_number' => (int) $minorplanetSearchQuery, ]); } else { $stmtMinorplanetSearch = $pdo->prepare(" SELECT mp.`id`, mp.`mp_number`, mp.`designation_text`, mp.`desig_packed`, CASE WHEN aum.`minorplanet_id` IS NULL THEN 0 ELSE 1 END AS `already_added` FROM `minorplanets_mpc` mp LEFT JOIN `app_user_minorplanets` aum ON aum.`minorplanet_id` = mp.`id` AND aum.`user_id` = :user_id WHERE mp.`designation_text` LIKE :query OR mp.`desig_packed` LIKE :query ORDER BY mp.`mp_number` IS NULL ASC, mp.`mp_number` ASC, mp.`designation_text` ASC LIMIT 50 "); $stmtMinorplanetSearch->execute([ ':user_id' => $userId, ':query' => '%' . $minorplanetSearchQuery . '%', ]); } $minorplanetSearchResults = $stmtMinorplanetSearch->fetchAll(); } $stmtTrackedSatellites = $pdo->prepare(" SELECT s.`id`, s.`norad_cat_id`, s.`object_name`, aus.`is_favorite`, aus.`created_at` FROM `app_user_satellites` aus INNER JOIN `sat_satellites` s ON s.`id` = aus.`satellite_id` WHERE aus.`user_id` = :user_id ORDER BY aus.`is_favorite` DESC, s.`object_name` ASC "); $stmtTrackedSatellites->execute([ ':user_id' => $userId, ]); $trackedSatellites = $stmtTrackedSatellites->fetchAll(); $stmtTrackedMinorplanets = $pdo->prepare(" SELECT mp.`id`, mp.`mp_number`, mp.`designation_text`, mp.`desig_packed`, aum.`is_favorite`, aum.`created_at` FROM `app_user_minorplanets` aum INNER JOIN `minorplanets_mpc` mp ON mp.`id` = aum.`minorplanet_id` WHERE aum.`user_id` = :user_id ORDER BY aum.`is_favorite` DESC, mp.`mp_number` IS NULL ASC, mp.`mp_number` ASC, mp.`designation_text` ASC "); $stmtTrackedMinorplanets->execute([ ':user_id' => $userId, ]); $trackedMinorplanets = $stmtTrackedMinorplanets->fetchAll(); $loggedIn = true; ?>

Standorte

Es sind noch keine Standorte gespeichert.

Name Breitengrad Laengengrad Hoehe Zeitzone Standard

Standort hinzufuegen

Suche einen Ort, nutze den Browser-Standort oder klicke direkt in die Karte.

Satelliten suchen

Suchergebnisse

Keine passenden Satelliten gefunden.

Name NORAD
Bereits hinzugefuegt

Kleinplaneten suchen

Suchergebnisse

Keine passenden Kleinplaneten gefunden.

Bezeichnung Nummer
Bereits hinzugefuegt

Meine Satelliten

Du hast noch keine Satelliten ausgewaehlt.

Name NORAD Favorit Hinzugefuegt

Meine Kleinplaneten

Du hast noch keine Kleinplaneten ausgewaehlt.

Bezeichnung Nummer Favorit Hinzugefuegt