Files
Ai/aurora-livecam/SettingsManager.php
T
Claude 7eda2fbbe8 Add weather widget with OpenWeatherMap integration
Implementiert vollständiges Wetter-Widget oberhalb des Webcam-Videos:

**Features:**
🌤️ **Wetter-Anzeige:**
- Temperatur (°C)
- Windgeschwindigkeit & Richtung (km/h)
- Luftdruck (hPa)
- Luftfeuchtigkeit (%)
- Wetterbeschreibung mit Emoji-Icons
- Niederschlag (Regen/Schnee) wenn vorhanden

⚙️ **Technisch:**
- OpenWeatherMap API Integration
- 5 Minuten Cache (konfigurierbar)
- Auto-Update alle X Minuten (Frontend)
- WeatherManager Klasse für Backend
- Schönes Gradient-Design mit Hover-Effekten
- Responsive für Mobile

🎛️ **Admin-Settings:**
- Wetter-Widget ein/aus
- API Key Eingabefeld + Registrierungs-Link
- Standort konfigurierbar (Stadt,Land)
- GPS-Koordinaten (Lat/Lon)
- Update-Intervall (5-60 Minuten)
- Einheiten (Metrisch/Imperial)

**Dateien:**
- WeatherManager.php: Neue Klasse für API-Calls & Caching
- SettingsManager.php: Weather Settings Defaults & Helper
- index.php: Widget HTML, CSS, JavaScript Auto-Update
- settings.json: Weather Defaults initialisiert

**Koordinaten Oberdürnten:**
Lat: 47.2833, Lon: 8.7167

**Setup für User:**
1. Gratis Account auf openweathermap.org erstellen
2. API Key im Admin-Panel einfügen
3. Fertig! Widget zeigt Live-Wetter an
2026-01-22 18:50:16 +00:00

281 lines
8.6 KiB
PHP

<?php
/**
* SettingsManager - Verwaltet Admin-Einstellungen
* Speichert in settings.json, lädt ohne Reload
*/
class SettingsManager {
private $settingsFile;
private $settings = [];
public function __construct($file = null) {
$this->settingsFile = $file ?: (__DIR__ . '/settings.json');
$this->load();
}
private function load() {
if (file_exists($this->settingsFile)) {
$content = file_get_contents($this->settingsFile);
$this->settings = json_decode($content, true) ?? $this->getDefaults();
} else {
$this->settings = $this->getDefaults();
$this->save();
}
}
private function getDefaults() {
return [
'viewer_display' => [
'enabled' => true,
'min_viewers' => 1,
'update_interval' => 5 // Sekunden
],
'video_mode' => [
'play_in_player' => true,
'allow_download' => true
],
'timelapse' => [
'default_speed' => 1,
'available_speeds' => [1, 10, 100]
],
// Punkt 2: UI-Anzeige Features
'ui_display' => [
'show_recommendation_banner' => true,
'show_qr_code' => true,
'show_social_media' => true,
'show_patrouille_suisse' => true
],
// Punkt 3: Zoom & Timelapse
'zoom_timelapse' => [
'show_zoom_controls' => true,
'max_zoom_level' => 4.0,
'timelapse_reverse_enabled' => true
],
// Punkt 5: Content Management
'content' => [
'guestbook_enabled' => true,
'gallery_enabled' => true,
'ai_events_enabled' => true,
'max_guestbook_entries' => 50
],
// Punkt 6: Technische Settings
'technical' => [
'viewer_update_interval' => 5, // Sekunden
'session_timeout' => 30 // Sekunden
],
// Punkt 7: Theme & Design
'theme' => [
'default_theme' => 'theme-legacy',
'show_theme_switcher' => false
],
// Punkt 8: SEO & Meta
'seo' => [
'custom_title' => '',
'meta_description' => '',
'meta_keywords' => ''
],
// Weather Widget
'weather' => [
'enabled' => true,
'api_key' => '',
'location' => 'Oberdürnten,CH',
'lat' => '47.2833',
'lon' => '8.7167',
'update_interval' => 5, // Minuten
'units' => 'metric' // metric (Celsius) oder imperial (Fahrenheit)
],
'last_updated' => null,
'updated_by' => null
];
}
public function get($key = null) {
if ($key === null) return $this->settings;
$keys = explode('.', $key);
$value = $this->settings;
foreach ($keys as $k) {
if (!isset($value[$k])) return null;
$value = $value[$k];
}
return $value;
}
public function set($key, $value) {
$keys = explode('.', $key);
$ref = &$this->settings;
foreach ($keys as $i => $k) {
if ($i === count($keys) - 1) {
$ref[$k] = $value;
} else {
if (!isset($ref[$k])) $ref[$k] = [];
$ref = &$ref[$k];
}
}
$this->settings['last_updated'] = date('Y-m-d H:i:s');
return $this->save();
}
private function save() {
$payload = json_encode($this->settings, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);
if ($payload === false) {
return false;
}
return file_put_contents($this->settingsFile, $payload, LOCK_EX) !== false;
}
// Für AJAX-Anfragen
public function handleAjax() {
if ($_SERVER['REQUEST_METHOD'] !== 'POST') return;
if (!isset($_POST['settings_action'])) return;
header('Content-Type: application/json');
switch ($_POST['settings_action']) {
case 'get':
echo json_encode(['success' => true, 'settings' => $this->settings]);
exit;
case 'update':
$key = $_POST['key'] ?? null;
$value = $_POST['value'] ?? null;
// Boolean-Werte konvertieren
if ($value === 'true') $value = true;
if ($value === 'false') $value = false;
if (is_numeric($value)) $value = intval($value);
if ($key && $this->set($key, $value)) {
echo json_encode(['success' => true, 'message' => 'Einstellung gespeichert']);
} else {
echo json_encode([
'success' => false,
'message' => 'Fehler beim Speichern. Bitte Dateirechte prüfen.'
]);
}
exit;
}
}
// Viewer-Anzeige prüfen
public function shouldShowViewers($currentCount) {
if (!$this->get('viewer_display.enabled')) return false;
return $currentCount >= $this->get('viewer_display.min_viewers');
}
// Video-Modus prüfen
public function shouldPlayInPlayer() {
return $this->get('video_mode.play_in_player') === true;
}
public function shouldAllowDownload() {
return $this->get('video_mode.allow_download') === true;
}
// UI Display Helper
public function shouldShowRecommendationBanner() {
return $this->get('ui_display.show_recommendation_banner') === true;
}
public function shouldShowQRCode() {
return $this->get('ui_display.show_qr_code') === true;
}
public function shouldShowSocialMedia() {
return $this->get('ui_display.show_social_media') === true;
}
public function shouldShowPatrouillesuisse() {
return $this->get('ui_display.show_patrouille_suisse') === true;
}
// Content Management Helper
public function isGuestbookEnabled() {
return $this->get('content.guestbook_enabled') === true;
}
public function isGalleryEnabled() {
return $this->get('content.gallery_enabled') === true;
}
public function isAIEventsEnabled() {
return $this->get('content.ai_events_enabled') === true;
}
public function getMaxGuestbookEntries() {
return $this->get('content.max_guestbook_entries') ?? 50;
}
// Theme Helper
public function getDefaultTheme() {
return $this->get('theme.default_theme') ?? 'theme-legacy';
}
public function shouldShowThemeSwitcher() {
return $this->get('theme.show_theme_switcher') === true;
}
// Technical Helper
public function getViewerUpdateInterval() {
return $this->get('technical.viewer_update_interval') ?? 5;
}
public function getSessionTimeout() {
return $this->get('technical.session_timeout') ?? 30;
}
// Zoom & Timelapse Helper
public function shouldShowZoomControls() {
return $this->get('zoom_timelapse.show_zoom_controls') === true;
}
public function getMaxZoomLevel() {
return $this->get('zoom_timelapse.max_zoom_level') ?? 4.0;
}
public function isTimelapseReverseEnabled() {
return $this->get('zoom_timelapse.timelapse_reverse_enabled') === true;
}
// SEO Helper
public function getCustomTitle() {
$title = $this->get('seo.custom_title');
return !empty($title) ? $title : null;
}
public function getMetaDescription() {
return $this->get('seo.meta_description') ?? '';
}
public function getMetaKeywords() {
return $this->get('seo.meta_keywords') ?? '';
}
// Weather Helper
public function isWeatherEnabled() {
return $this->get('weather.enabled') === true;
}
public function getWeatherApiKey() {
return $this->get('weather.api_key') ?? '';
}
public function getWeatherLocation() {
return $this->get('weather.location') ?? 'Oberdürnten,CH';
}
public function getWeatherCoords() {
return [
'lat' => $this->get('weather.lat') ?? '47.2833',
'lon' => $this->get('weather.lon') ?? '8.7167'
];
}
public function getWeatherUpdateInterval() {
return $this->get('weather.update_interval') ?? 5;
}
public function getWeatherUnits() {
return $this->get('weather.units') ?? 'metric';
}
}