prepare('SELECT "Admin" FROM user_permissions WHERE user_id = ?'); $stmt->execute([$_SESSION['user_id']]); $isAdmin = $stmt->fetchColumn(); if ((int)$isAdmin !== 1) { header("Location: {$g_httpHomePath}"); exit(); } const NOTICE_MAX_TITLE_LENGTH = 180; const NOTICE_MAX_MESSAGE_LENGTH = 4000; $noticeTypes = [ 'info' => 'Information', 'warning' => 'Warnung', 'success' => 'Erfolg', 'error' => 'Wichtig', ]; if (empty($_SESSION['admin_notices_csrf'])) { $_SESSION['admin_notices_csrf'] = bin2hex(random_bytes(32)); } $csrfToken = $_SESSION['admin_notices_csrf']; function noticeRedirect(string $status): void { header('Location: admin_notices.php?status=' . rawurlencode($status)); exit(); } function noticeVerifyCsrf(): void { $postedToken = $_POST['csrf_token'] ?? ''; $sessionToken = $_SESSION['admin_notices_csrf'] ?? ''; if (!is_string($postedToken) || !is_string($sessionToken) || $sessionToken === '' || !hash_equals($sessionToken, $postedToken)) { http_response_code(400); exit('Ungültige Anfrage. Bitte laden Sie die Seite neu.'); } } function noticeParseLocalDateTime(?string $value): ?string { $value = trim((string)$value); if ($value === '') { return null; } $tz = new DateTimeZone('Europe/Berlin'); $date = DateTimeImmutable::createFromFormat('!Y-m-d\TH:i', $value, $tz); $errors = DateTimeImmutable::getLastErrors(); if (!$date || ($errors !== false && ($errors['warning_count'] > 0 || $errors['error_count'] > 0))) { throw new InvalidArgumentException('Ungültiges Datum.'); } // Mit explizitem Offset an PostgreSQL senden, damit TIMESTAMPTZ eindeutig ist. return $date->format('Y-m-d H:i:sP'); } function noticeFormatLocalDateTime(?string $value): string { if (empty($value)) { return ''; } try { return (new DateTimeImmutable($value))->setTimezone(new DateTimeZone('Europe/Berlin'))->format('Y-m-d\TH:i'); } catch (Throwable $e) { return ''; } } function noticeDisplayDate(?string $value): string { if (empty($value)) { return 'unbegrenzt'; } try { return (new DateTimeImmutable($value))->setTimezone(new DateTimeZone('Europe/Berlin'))->format('d.m.Y, H:i') . ' Uhr'; } catch (Throwable $e) { return '–'; } } function noticeDbBool($value): bool { return $value === true || $value === 1 || $value === '1' || $value === 't' || $value === 'true'; } function noticeTextLength(string $value): int { return function_exists('mb_strlen') ? mb_strlen($value, 'UTF-8') : strlen($value); } function noticeValidateInput(array $noticeTypes): array { $title = trim((string)($_POST['title'] ?? '')); $message = trim((string)($_POST['message'] ?? '')); $type = (string)($_POST['type'] ?? 'info'); $sortOrder = filter_var($_POST['sort_order'] ?? 0, FILTER_VALIDATE_INT); $isActive = isset($_POST['is_active']); if ($title === '' || noticeTextLength($title) > NOTICE_MAX_TITLE_LENGTH) { throw new InvalidArgumentException('Titel fehlt oder ist zu lang.'); } if ($message === '' || noticeTextLength($message) > NOTICE_MAX_MESSAGE_LENGTH) { throw new InvalidArgumentException('Meldung fehlt oder ist zu lang.'); } if (!array_key_exists($type, $noticeTypes)) { throw new InvalidArgumentException('Ungültiger Meldungstyp.'); } if ($sortOrder === false || $sortOrder < -9999 || $sortOrder > 9999) { throw new InvalidArgumentException('Ungültige Sortierung.'); } $startsAt = noticeParseLocalDateTime($_POST['starts_at'] ?? null); $endsAt = noticeParseLocalDateTime($_POST['ends_at'] ?? null); if ($startsAt !== null && $endsAt !== null) { $start = new DateTimeImmutable($startsAt); $end = new DateTimeImmutable($endsAt); if ($end <= $start) { throw new InvalidArgumentException('Das Ende muss nach dem Beginn liegen.'); } } return [ 'title' => $title, 'message' => $message, 'type' => $type, 'sort_order' => (int)$sortOrder, 'is_active' => $isActive, 'starts_at' => $startsAt, 'ends_at' => $endsAt, ]; } if ($_SERVER['REQUEST_METHOD'] === 'POST') { noticeVerifyCsrf(); $action = (string)($_POST['action'] ?? ''); try { if ($action === 'create') { $data = noticeValidateInput($noticeTypes); $stmt = $pdo->prepare( 'INSERT INTO mainpage_notices (title, message, type, is_active, starts_at, ends_at, sort_order, created_by, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, NOW(), NOW())' ); $stmt->execute([ $data['title'], $data['message'], $data['type'], $data['is_active'] ? 'true' : 'false', $data['starts_at'], $data['ends_at'], $data['sort_order'], (int)$_SESSION['user_id'], ]); noticeRedirect('created'); } if ($action === 'update') { $id = filter_var($_POST['id'] ?? null, FILTER_VALIDATE_INT); if (!$id || $id < 1) { throw new InvalidArgumentException('Ungültige Meldungs-ID.'); } $data = noticeValidateInput($noticeTypes); $stmt = $pdo->prepare( 'UPDATE mainpage_notices SET title = ?, message = ?, type = ?, is_active = ?, starts_at = ?, ends_at = ?, sort_order = ?, updated_at = NOW() WHERE id = ?' ); $stmt->execute([ $data['title'], $data['message'], $data['type'], $data['is_active'] ? 'true' : 'false', $data['starts_at'], $data['ends_at'], $data['sort_order'], (int)$id, ]); noticeRedirect('updated'); } if ($action === 'toggle') { $id = filter_var($_POST['id'] ?? null, FILTER_VALIDATE_INT); if (!$id || $id < 1) { throw new InvalidArgumentException('Ungültige Meldungs-ID.'); } $stmt = $pdo->prepare('UPDATE mainpage_notices SET is_active = NOT is_active, updated_at = NOW() WHERE id = ?'); $stmt->execute([(int)$id]); noticeRedirect('toggled'); } if ($action === 'delete') { $id = filter_var($_POST['id'] ?? null, FILTER_VALIDATE_INT); if (!$id || $id < 1) { throw new InvalidArgumentException('Ungültige Meldungs-ID.'); } $stmt = $pdo->prepare('DELETE FROM mainpage_notices WHERE id = ?'); $stmt->execute([(int)$id]); noticeRedirect('deleted'); } throw new InvalidArgumentException('Unbekannte Aktion.'); } catch (InvalidArgumentException $e) { $_SESSION['admin_notices_error'] = $e->getMessage(); noticeRedirect('error'); } catch (PDOException $e) { $_SESSION['admin_notices_error'] = 'Datenbankfehler. Prüfen Sie, ob die Tabelle mainpage_notices angelegt wurde.'; noticeRedirect('error'); } } $noticeError = $_SESSION['admin_notices_error'] ?? ''; unset($_SESSION['admin_notices_error']); $status = (string)($_GET['status'] ?? ''); $statusMessages = [ 'created' => 'Meldung wurde angelegt.', 'updated' => 'Meldung wurde gespeichert.', 'toggled' => 'Status der Meldung wurde geändert.', 'deleted' => 'Meldung wurde gelöscht.', ]; $tableAvailable = true; $notices = []; try { $notices = $pdo->query( 'SELECT id, title, message, type, is_active, starts_at, ends_at, sort_order, created_at, updated_at FROM mainpage_notices ORDER BY sort_order ASC, created_at DESC, id DESC' )->fetchAll(PDO::FETCH_ASSOC); } catch (PDOException $e) { $tableAvailable = false; $noticeError = 'Die Tabelle mainpage_notices fehlt. Führen Sie zuerst general_files/ini/mainpage_notices.sql aus.'; } ?>
Adminpanel
Meldungen im Hauptmenü
Meldungen erscheinen ausschließlich oberhalb der Kacheln auf der Intranet-Hauptseite.
Noch keine Meldungen vorhanden.
$noticeId, 'title' => $notice['title'], 'message' => $notice['message'], 'type' => $noticeType, 'is_active' => noticeDbBool($notice['is_active']), 'starts_at' => noticeFormatLocalDateTime($notice['starts_at']), 'ends_at' => noticeFormatLocalDateTime($notice['ends_at']), 'sort_order' => (int)$notice['sort_order'], ]; ?>
Deaktiviert
Von: Bis: Sortierung: