Sportfest-Ausgabe der Stadionzeitung zum Heimspiel gegen ATS Wartenfels
Neue Live-Seiten, geschaltet vom chat-gepflegten Feld `veranstaltung` (Slug aus data/veranstaltungen.json) — Programm und Turnierpläne kommen damit aus derselben Quelle wie die Website, nicht als Kopie ins Heft: - Programm-Seite (programm[], rendert zugleich auf /veranstaltungen/sportfest-2026) - vier Turnierplan-Seiten (turniere[]) mit leerer Ergebnisspalte und leerer Abschlusstabelle zum Eintragen am Platz - Gegnerseite je Mannschaft mit Heimspiel am Fest statt nur der tragenden: stadionzeitung_gegner_fixtures() ist die einzige Stelle, die das entscheidet, Seitenplanung und Snapshot lesen beide dort. `gegner` ist deshalb eine Map je Team-Key; die Vorschau überspringt jedes Spiel mit eigener Gegnerseite - Danke-Seite mit Partner-Logo-Wand aus data/partners.json und QR auf /partner-werden, dazu das Anzeigen-Feld `platzierung` für Motive mit festem Platz auf einer Live-Seite (Emons über der Logo-Wand). Vorher klebte der Dank als leere Fläche unten an einem Anzeigen-Bild - Cover einer Sonderausgabe: das Fest als Titelgeschichte statt einer der drei Begegnungen, dazu das Hauptplakat schräg gelegt an Stelle des Spielerfotos Ausgabe 2026-09-04-ats-wartenfels als ENTWURF angelegt, 48 Seiten (12 Bögen), Tabellen auf gerader Seite, längster Anzeigenblock zwei. Veröffentlicht wird auf dem Server, dort liegt der frische Matchcenter-Stand. Nebenbei behoben: bin/anzeige-add.php räumte beim Anlegen alle Motive weg, deren Slug mit demselben Text beginnt (`emons` löschte `emons-partnerdank` und `emons-stuebinger`). Muster jetzt auf die Breiten-Endung eingeschränkt. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KubsajzuV6N6QsSd3xKNjC
This commit is contained in:
@@ -58,6 +58,16 @@ declare(strict_types=1);
|
||||
* Interview → Aufruf. Für die Aufruf-Seite erzeugt das Skript zusätzlich den
|
||||
* QR (qr-aufruf.png im Ausgaben-Ordner) aus `aufruf.link`.
|
||||
*
|
||||
* Sportfest-Ausgabe (03.09.2026): trägt die Ausgabe ein `veranstaltung`-Feld
|
||||
* (Slug aus data/veranstaltungen.json, chat-gepflegt), kommen dazu: die
|
||||
* Programm-Seite im Aufschlag (aus programm[] der Veranstaltung, dieselbe Liste
|
||||
* wie die Website), ein Block Turnierplan-Seiten (je Eintrag in turniere[] eine
|
||||
* Seite) direkt danach, und eine Gegnerseite je Mannschaft mit HEIMspiel im
|
||||
* Zeitraum der Veranstaltung statt nur für die tragende Mannschaft — welche das
|
||||
* sind, sagt stadionzeitung_gegner_fixtures() (helpers.php), dieselbe Funktion,
|
||||
* aus der der Snapshot die Daten baut. `cover` ({edition, teaser}) kennzeichnet
|
||||
* das Cover als Sonderausgabe. Beide Felder überleben erneute Läufe wie `vorwort`.
|
||||
*
|
||||
* Erneuter Aufruf mit demselben Slug ersetzt die Ausgabe vollständig (alte
|
||||
* Seiten-Bilder werden vorher gelöscht) — idempotent für Korrekturen.
|
||||
*/
|
||||
@@ -188,6 +198,19 @@ $oldVorwort = $oldIssue['vorwort'] ?? null;
|
||||
$oldInterview = $oldIssue['interview'] ?? null;
|
||||
// Aufruf-Seite (z. B. Sportfest-Helferaufruf) ebenso chat-gepflegt.
|
||||
$oldAufruf = $oldIssue['aufruf'] ?? null;
|
||||
// Sportfest-Ausgabe: Slug-Verweis auf data/veranstaltungen.json (Programm,
|
||||
// Turnierpläne, Gegnerseiten je Heimspiel) und Cover-Kennung — chat-gepflegt.
|
||||
$oldVeranstaltung = $oldIssue['veranstaltung'] ?? null;
|
||||
$oldCover = $oldIssue['cover'] ?? null;
|
||||
$veranstaltung = null;
|
||||
if (is_string($oldVeranstaltung) && $oldVeranstaltung !== '') {
|
||||
$veranstaltung = veranstaltung_find($oldVeranstaltung);
|
||||
if ($veranstaltung === null) {
|
||||
$log("veranstaltung '{$oldVeranstaltung}' steht nicht in data/veranstaltungen.json — Programm-, Turnier- und Zusatz-Gegnerseiten entfallen.", 'WARN');
|
||||
} else {
|
||||
$log("Sportfest-Ausgabe: Veranstaltung '{$oldVeranstaltung}' (" . count($veranstaltung['programm'] ?? []) . ' Programmtage, ' . count($veranstaltung['turniere'] ?? []) . ' Turniere).');
|
||||
}
|
||||
}
|
||||
|
||||
// --- Ziel-Ordner vorbereiten: bei erneutem Lauf alte Seiten dieser Ausgabe wegräumen ---
|
||||
$destDir = PUBLIC_PATH . "/assets/img/stadionzeitung/{$slug}";
|
||||
@@ -215,6 +238,28 @@ $widths = [480, 960, 1440];
|
||||
// erscheint oft. Gepflegt wird der Bestand über bin/anzeige-add.php (Bilder) und
|
||||
// im Chat (Sponsorenname, Reihenfolge, aktiv). Hier wird nichts gerendert, die
|
||||
// Bilder liegen schon. ---
|
||||
// Anzeigen mit `platzierung` haben einen FESTEN Platz auf einer Live-Seite
|
||||
// (derzeit `danke`: die Emons-Anzeige über der Partner-Logo-Wand) und laufen
|
||||
// deshalb nicht im Streu-Pool mit — sonst stünden sie zweimal im Heft.
|
||||
$platzierteAnzeigen = [];
|
||||
foreach (json_load('anzeigen')['anzeigen'] ?? [] as $a) {
|
||||
$platz = trim((string) ($a['platzierung'] ?? ''));
|
||||
if ($platz === '' || ($a['aktiv'] ?? true) === false || empty($a['base'])) {
|
||||
continue;
|
||||
}
|
||||
if (!empty($a['bis']) && (string) $a['bis'] < $date) {
|
||||
continue;
|
||||
}
|
||||
if (isset($platzierteAnzeigen[$platz])) {
|
||||
continue;
|
||||
}
|
||||
$platzierteAnzeigen[$platz] = [
|
||||
'base' => (string) $a['base'],
|
||||
'widths' => $a['widths'] ?? [],
|
||||
'alt' => (string) ($a['alt'] ?? ('Anzeige: ' . trim((string) ($a['sponsor'] ?? '')))),
|
||||
];
|
||||
}
|
||||
|
||||
$anzeigenSeiten = array_values(array_map(
|
||||
static function (array $a): array {
|
||||
$sponsor = trim((string) ($a['sponsor'] ?? ''));
|
||||
@@ -237,6 +282,7 @@ $anzeigenSeiten = array_values(array_map(
|
||||
// nächsten Handgriff im Heft zu bleiben.
|
||||
static fn (array $a): bool => ($a['aktiv'] ?? true)
|
||||
&& !empty($a['base'])
|
||||
&& empty($a['platzierung'])
|
||||
&& (empty($a['bis']) || (string) $a['bis'] >= $date)
|
||||
)
|
||||
));
|
||||
@@ -245,12 +291,8 @@ $anzeigenSeiten = array_values(array_map(
|
||||
// Ausgaben-Bilder (Vorwort-Fallback, Rückseite) schon. Beide bekommen SPRECHENDE
|
||||
// Dateinamen statt der früheren Positionsnummern (page-07) — die verschoben sich
|
||||
// bei jeder Umverteilung. ---
|
||||
$live = static function (string $page, ?string $team = null): array {
|
||||
$entry = ['type' => 'live', 'page' => $page];
|
||||
if ($team !== null) {
|
||||
$entry['team'] = $team;
|
||||
}
|
||||
return $entry;
|
||||
$live = static function (string $page, array $extra = []): array {
|
||||
return ['type' => 'live', 'page' => $page] + $extra;
|
||||
};
|
||||
|
||||
$bild = static function (string $src, string $name, string $alt) use ($destDir, $widths, $slug): array {
|
||||
@@ -293,6 +335,11 @@ try {
|
||||
} elseif ($vorwort !== null) {
|
||||
$aufschlag[] = $bild($vorwort, 'vorwort', 'Vorwort der Stadionzeitung');
|
||||
}
|
||||
// Programm-Seite der Sportfest-Ausgabe direkt hinter dem Vorwort: aufgeschlagen
|
||||
// liegen Vorwort (links) und Programm (rechts) als Doppelseite 2/3 nebeneinander.
|
||||
if ($veranstaltung !== null && !empty($veranstaltung['programm'])) {
|
||||
$aufschlag[] = $live('programm');
|
||||
}
|
||||
// Interview-Seite nur, wenn die Ausgabe ein Interview trägt (chat-gepflegtes
|
||||
// Feld) — das Cover zeigt dann automatisch die Teaser-Zeile dazu.
|
||||
if ($oldInterview !== null) {
|
||||
@@ -308,8 +355,40 @@ try {
|
||||
$bloecke[] = ['name' => 'aufschlag', 'seiten' => $aufschlag, 'anzeigen_danach' => true];
|
||||
}
|
||||
|
||||
// Turnierplan-Seiten der Sportfest-Ausgabe: je Turnier eine Seite, EIN Block
|
||||
// (zusammenhängender Sportfest-Teil, keine Anzeige zwischen zwei Turnieren),
|
||||
// gleich nach dem Aufschlag und vor dem Fußball-Teil.
|
||||
$turniere = [];
|
||||
foreach ($veranstaltung['turniere'] ?? [] as $turnier) {
|
||||
if (is_array($turnier) && !empty($turnier['key'])) {
|
||||
$turniere[] = $live('turnier', ['turnier' => (string) $turnier['key']]);
|
||||
}
|
||||
}
|
||||
if ($turniere !== []) {
|
||||
$bloecke[] = ['name' => 'turniere', 'seiten' => $turniere, 'anzeigen_danach' => true];
|
||||
}
|
||||
|
||||
$bloecke[] = ['name' => 'ergebnisse', 'seiten' => [$live('ergebnisse')], 'anzeigen_danach' => true];
|
||||
$bloecke[] = ['name' => 'gegner', 'seiten' => [$live('gegner')], 'anzeigen_danach' => true];
|
||||
|
||||
// Gegnerseite(n): normal nur die tragende Mannschaft; in der Sportfest-Ausgabe
|
||||
// je Mannschaft mit Heimspiel am Fest eine (drei Heimspiele, drei Seiten), als
|
||||
// EIN Block. Welche das sind, entscheidet stadionzeitung_gegner_fixtures() —
|
||||
// dieselbe Funktion, aus der stadionzeitung_build_snapshot() die Daten baut,
|
||||
// damit nie eine Seite ohne Daten oder Daten ohne Seite entstehen.
|
||||
$gegnerSeiten = [];
|
||||
foreach (stadionzeitung_gegner_fixtures([
|
||||
'date' => $date, 'team_key' => $teamKey, 'opponent' => $opponent,
|
||||
'veranstaltung' => $oldVeranstaltung,
|
||||
]) as $gegnerTeam => $fixture) {
|
||||
$gegnerSeiten[] = $live('gegner', ['team' => (string) $gegnerTeam]);
|
||||
$log("Gegnerseite {$gegnerTeam}: {$fixture['opponent']} ({$fixture['date']}).");
|
||||
}
|
||||
if ($gegnerSeiten === []) {
|
||||
// Ohne Treffer (Gegner leer) bleibt die Seite der tragenden Mannschaft —
|
||||
// sie meldet dann selbst, dass keine Vergleichsdaten vorliegen.
|
||||
$gegnerSeiten[] = $live('gegner', ['team' => $teamKey]);
|
||||
}
|
||||
$bloecke[] = ['name' => 'gegner', 'seiten' => $gegnerSeiten, 'anzeigen_danach' => true];
|
||||
|
||||
// Eine Tabellen-Seite je Mannschaft, Reihenfolge wie in matchcenter.json
|
||||
// (= config 'matchcenter.teams'). Kommt eine Mannschaft dazu (z. B. die
|
||||
@@ -317,15 +396,28 @@ try {
|
||||
$tabellen = [];
|
||||
foreach ($mc['teams'] ?? [] as $team) {
|
||||
if (!empty($team['key'])) {
|
||||
$tabellen[] = $live('tabelle', (string) $team['key']);
|
||||
$tabellen[] = $live('tabelle', ['team' => (string) $team['key']]);
|
||||
}
|
||||
}
|
||||
if ($tabellen !== []) {
|
||||
$bloecke[] = ['name' => 'tabellen', 'seiten' => $tabellen, 'anzeigen_danach' => true];
|
||||
}
|
||||
|
||||
foreach (['vorschau', 'termine', 'news', 'kontakt', 'mitglied', 'historie', 'sportheim', 'partner', 'momente'] as $seite) {
|
||||
$bloecke[] = ['name' => $seite, 'seiten' => [$live($seite)], 'anzeigen_danach' => true];
|
||||
foreach (['vorschau', 'termine', 'news', 'kontakt', 'mitglied', 'historie', 'sportheim', 'partner', 'danke', 'momente'] as $seite) {
|
||||
// Die Danke-Seite trägt ihr Anzeigenmotiv im Seiteneintrag (siehe oben),
|
||||
// direkt hinter der Partner-werden-Seite: aufgeschlagen liegen damit
|
||||
// Akquise und Dank als Partner-Doppelseite nebeneinander.
|
||||
$extra = ($seite === 'danke' && isset($platzierteAnzeigen['danke']))
|
||||
? ['anzeige' => $platzierteAnzeigen['danke']]
|
||||
: [];
|
||||
// Hinter der Partner-werden-Seite bleibt die Lücke leer, damit die
|
||||
// Danke-Seite direkt folgt: Akquise und Dank gehören zusammen und
|
||||
// liegen aufgeschlagen im günstigen Fall als Doppelseite nebeneinander.
|
||||
$bloecke[] = [
|
||||
'name' => $seite,
|
||||
'seiten' => [$live($seite, $extra)],
|
||||
'anzeigen_danach' => $seite !== 'partner',
|
||||
];
|
||||
}
|
||||
|
||||
$bloecke[] = ['name' => 'impressum', 'seiten' => [$live('impressum')], 'anzeigen_danach' => false];
|
||||
@@ -651,6 +743,8 @@ $issues[] = [
|
||||
'vorwort' => $oldVorwort,
|
||||
'interview' => $oldInterview,
|
||||
'aufruf' => $oldAufruf,
|
||||
'veranstaltung' => $oldVeranstaltung,
|
||||
'cover' => $oldCover,
|
||||
'verfasser_photo' => $verfasserPhoto,
|
||||
'termine_snapshot' => $termineSnapshot,
|
||||
'images' => $images,
|
||||
|
||||
Reference in New Issue
Block a user