Stadionzeitung, Veranstaltungen, News-Artikel, Lightbox und Anzeigen-Verteilung
Stadionzeitung: Live-Seiten (Tabellen, Ergebnisse, Vorschau, Termine, News, Kontakt, Historie, Sportheim, Partner, Momente, Impressum), automatisches Cover, Swipe-Viewer mit Vollbildmodus und die Druckfassung als Falt-Heft. Anzeigen kommen jetzt aus dem Bestand und werden gleichmäßig verteilt, nie mehr als zwei hintereinander (vorher vier Blöcke à fünf). Die Doppelseiten-Regel rechnet das Skript selbst, statt sie von Hand zu prüfen. Veranstaltungen: Bereich /veranstaltungen mit Detailseite pro Fest, Lebenszyklus über das Datum (Ankündigung vor dem Fest, Rückblick danach), Galerie mit Lightbox. veranstaltungen.json ist dritte Termin-Quelle, damit ein Fest nie doppelt gepflegt wird. News-Artikel als dritte dynamische Prefix-Route, gemeinsamer detail-head. Behobene Fehler: - Wappen-Kontexte setzten Zeilen-Layout auf .crest statt auf die Zeile; das Wappen wurde zum Grid, Vereinsname und Tore rutschten darunter zusammen (Ergebnis-Rückblick, Vorschau, Cover). - --header-h (60px) unterschätzt die Kopfleiste um 32px (Logo 72px + 20px Versatz): neues abgeleitetes --header-space, sonst klebten Zurück-Links unter dem Logo. - base_url in der Produktions-Config ohne www, während .htaccess auf www umleitet; preflight prüft das jetzt. - .lightbox brauchte display:none mit (0,2,0), sonst lag das Overlay offen. Neue Werkzeuge: bin/anzeige-add.php (Anzeigen-Bestand), bin/veranstaltung-bilder.php (Plakate und Galerien, Alt-Texte folgen der Quelldatei), bin/qr.php (Druck-QR mit Warnung, wenn base_url nicht auf die echte Domain zeigt). Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NzeVVgMCrzCDJAKeLEdKr7
This commit is contained in:
@@ -7,7 +7,26 @@
|
||||
* config.php ist gitignored und liegt außerhalb des Webroots (zusätzlich per .htaccess gesperrt).
|
||||
*
|
||||
* ---------------------------------------------------------------------------
|
||||
* CRONJOBS (im KAS anlegen, Typ „eigener Cronjob“ / Shell)
|
||||
* TAKT DER SYNC-SKRIPTE — zwei Wege, je nach Tarif
|
||||
* ---------------------------------------------------------------------------
|
||||
* A) Der Tarif hat Cronjobs → Shell-Cronjobs unten verwenden. Sauberster Weg,
|
||||
* kein Endpoint, kein Dritter im Spiel.
|
||||
* B) Der Tarif hat KEINE Cronjobs (Stand 27.07.2026 bei uns der Fall, KAS meldet
|
||||
* „in deinem Tarif nicht verfügbar“) → public/cron.php + externer Cron-Dienst.
|
||||
* Dann `cron.key` unten setzen und beim Dienst diese URLs im gewünschten Takt
|
||||
* aufrufen lassen (Schlüssel besser als Header X-Cron-Key als in der URL):
|
||||
*
|
||||
* https://www.tsv08kulmbach.de/cron.php?job=matchcenter
|
||||
* https://www.tsv08kulmbach.de/cron.php?job=instagram
|
||||
*
|
||||
* Takt wie unten bei den Cronjobs. Der Dienst muss keine Antwort auswerten:
|
||||
* 204 = angenommen oder wegen Mindestabstand übersprungen, 403 = Schlüssel oder
|
||||
* Job falsch (dann ist der Dienst falsch eingerichtet und es syncte nichts).
|
||||
* Erwarteter Fehlerfall: Instagram sperrt Rechenzentrums-IPs. Einmal von Hand
|
||||
* prüfen, ob der Scraper auf dem Server überhaupt durchkommt.
|
||||
*
|
||||
* ---------------------------------------------------------------------------
|
||||
* CRONJOBS (im KAS anlegen, Typ „eigener Cronjob“ / Shell) — nur Weg A
|
||||
* ---------------------------------------------------------------------------
|
||||
* SITE=/www/htdocs/<KAS-User>/tsv08kulmbach (echten Pfad einsetzen: pwd auf dem Server)
|
||||
* PHP=/usr/bin/php (All-Inkl ggf. /usr/local/bin/php8.2 — `which php8.2` prüft es)
|
||||
@@ -22,7 +41,7 @@
|
||||
* # damit Ergebnisse und Tabelle zeitnah stehen.
|
||||
* 7,37 13-21 * * 6,0 cd $SITE && $PHP bin/matchcenter-sync.php >> storage/logs/matchcenter.log 2>&1
|
||||
*
|
||||
* # Logrotation: sonntags nachts, damit spam.log/php-errors.log nicht unbegrenzt wachsen.
|
||||
* # Logpflege: sonntags nachts. Rotiert Dateien über 2 MB und löscht Einträge älter als 90 Tage.
|
||||
* 23 3 * * 0 cd $SITE && $PHP bin/log-rotate.php > /dev/null 2>&1
|
||||
*
|
||||
* Alle Skripte sind CLI-only; die Syncs sperren sich per Lock gegen Parallelläufe und lassen
|
||||
@@ -35,6 +54,14 @@
|
||||
* php bin/preflight.php Config, Secrets, Schreibrechte, vendor/, PHP-Version prüfen
|
||||
* php bin/smtp-test.php SMTP-Login testen (ohne Mailversand)
|
||||
* danach je eine Testmail über /kontakt, /mitglied-werden und /sportheimbuchung
|
||||
*
|
||||
* IM BETRIEB
|
||||
* php bin/logs.php Läuft alles? Fehler der letzten 7 Tage + Stand aller Kanäle
|
||||
*
|
||||
* Für die Dateiablage /dateien zusätzlich:
|
||||
* storage/dateien/uploads und storage/dateien/system müssen beschreibbar sein
|
||||
* php bin/filesgallery-update.php --check (Patch + self-hosted Assets prüfen)
|
||||
* php bin/dateien-init.php Ordnerstruktur Jahr → Abteilung anlegen
|
||||
*/
|
||||
return [
|
||||
// Kanonische Basis-URL ohne trailing slash (für Canonical, OG, Sitemap).
|
||||
@@ -65,12 +92,50 @@ return [
|
||||
'to' => 'info@tsv08kulmbach.de',
|
||||
],
|
||||
|
||||
// Cron-Endpoint public/cron.php — nur nötig, wenn der Tarif keine Cronjobs hat
|
||||
// (Weg B oben). Leer oder 'CHANGE_ME' lassen heißt: der Endpoint ist zu und
|
||||
// antwortet auf jeden Aufruf mit 403.
|
||||
'cron' => [
|
||||
// Langes Zufallsgeheimnis, NICHT app_secret wiederverwenden — der Schlüssel
|
||||
// reist bei einem externen Dienst mit und darf dort nichts anderes aufschließen.
|
||||
// Erzeugen: php -r 'echo bin2hex(random_bytes(24)), "\n";'
|
||||
'key' => 'CHANGE_ME',
|
||||
// Mindestabstand zwischen zwei Läufen desselben Jobs in Sekunden. Schützt bei
|
||||
// geleaktem Link davor, dass BFV oder Instagram unsere Server-IP sperren.
|
||||
// Muss kleiner sein als der engste gewünschte Takt (½-stündlich = 1800 s).
|
||||
'min_interval' => 240,
|
||||
],
|
||||
|
||||
// Instagram-Scraper (bin/instagram-sync.php).
|
||||
'instagram' => [
|
||||
'username' => 'tsv08kulmbach',
|
||||
'max_posts' => 9,
|
||||
],
|
||||
|
||||
// Zentrale News-Seite (app/pages/news.php) — mischt data/news.json,
|
||||
// Instagram-Cache und Matchcenter-Ergebnisse; hier nur die Obergrenze für
|
||||
// die Gesamtliste (News allein könnte sonst unbegrenzt wachsen).
|
||||
'news' => [
|
||||
'max_items' => 20,
|
||||
],
|
||||
|
||||
// Dateiablage /dateien (Files Gallery, vendored unter public/dateien/) — der Verein
|
||||
// lädt dort Fotos und Videos hoch, eingearbeitet werden sie danach von Hand.
|
||||
// Konfiguriert wird die App in public/dateien/_filesconfig.php; hier stehen nur die
|
||||
// Geheimnisse. Passwort-Hash erzeugen mit:
|
||||
// php -r "echo password_hash('DAS-PASSWORT', PASSWORD_DEFAULT), PHP_EOL;"
|
||||
// Klartext-Passwörter würden auch funktionieren (index.php:507) — aber nicht in einer Datei.
|
||||
// Solange hier CHANGE_ME steht, ist der Zugang gesperrt (kein Passwort = kein Login).
|
||||
'dateien' => [
|
||||
'license_key' => 'CHANGE_ME', // Vollversion-Schlüssel von files.gallery
|
||||
'users' => [
|
||||
// Gemeinsames Konto zum Hochladen — Passwort im Verein weitergeben.
|
||||
'verein' => ['password_hash' => 'CHANGE_ME'],
|
||||
// Verwaltung (Aufräumen, Sortieren, Löschen).
|
||||
'admin' => ['password_hash' => 'CHANGE_ME'],
|
||||
],
|
||||
],
|
||||
|
||||
// Matchcenter-Scraper (bin/matchcenter-sync.php) — Spielplan/Ergebnisse/Tabelle
|
||||
// aus der öffentlichen BFV-Widget-JSON-API. Die IDs sind keine Geheimnisse
|
||||
// (sie steckten schon im alten BFV-Widget-Embed) und dürfen hier stehen.
|
||||
@@ -86,11 +151,11 @@ return [
|
||||
// übernommen wird. compound_id nur pflegen, falls die Auto-Erkennung mal fehlt.
|
||||
'teams' => [
|
||||
['key' => 'erste-mannschaft', 'team_id' => '016PKHIPIO000000VV0AG811VUDIC8D7', 'compound_id' => '02TBKEVREG000006VS5489BTVVQ0O654-G'],
|
||||
// Vorerst deaktiviert (27.07.2026): Die BFV-Mannschaft hinter dieser ID lief in
|
||||
// der Saison 25/26 als „(SG1) TSV Melkendorf I/ TSV 08 Kulmbach II" und liefert
|
||||
// in 26/27 nur noch „TSV Melkendorf" — also Spiele ohne den TSV 08. Erst nach
|
||||
// Klärung im Verein wieder aktivieren (ggf. mit neuer team_id).
|
||||
// ['key' => 'zweite-mannschaft', 'team_id' => '016PCRVRJC000000VV0AG811VTE5EA5R', 'compound_id' => '02TD8CKMD8000006VS5489BTVTLPPK10-G'],
|
||||
// Zweite = Spielgemeinschaft „(SG1) TSV Melkendorf III/ TSV 08 Kulmbach II".
|
||||
// team_id ist die Saison-26/27-ID (reaktiviert 29.07.2026 — die alte ID
|
||||
// 016PCRVRJC… lieferte ab 26/27 nur noch den TSV Melkendorf ohne uns; bei
|
||||
// SG-Umbauten zur neuen Saison die ID von der BFV-Mannschaftsseite prüfen).
|
||||
['key' => 'zweite-mannschaft', 'team_id' => '030RNM1V6K000000VS5489BRVVPSQ1LR'],
|
||||
['key' => 'damen', 'team_id' => '01HLQ7QVES000000VV0AG80NVVKQLCU9', 'compound_id' => '02TK5AGFE0000004VS5489BUVVPGA9RV-G'],
|
||||
],
|
||||
],
|
||||
|
||||
Reference in New Issue
Block a user