)
* tasks_title Überschrift über der Aufgaben-Liste (optional)
* tasks[] wobei Hilfe gebraucht wird
* contacts_intro Zeile über den Ansprechpartnern (optional)
* contacts[] NAMEN — Nummer/Foto zieht die Seite per Namensabgleich aus
* data/ansprechpartner.json (geteilte Quelle, nie duplizieren;
* wie die Kontakt-Seite bewusst live statt Snapshot: ein Fest
* betrifft ohnehin die Zukunft, alte Nummern nützen niemandem)
* link interner Slug fürs Ziel (z. B. „veranstaltungen/sportfest-2026"),
* liefert Link-Zeile + QR im CTA-Fuß
* poster optional, kleines Plakat rechts neben Intro + Aufgaben
* (Varianten-Set {base,widths,alt} oder {src,…}) — z. B. das
* Sportfest-Vorderplakat aus data/veranstaltungen.json
* bin/stadionzeitung-add.php trägt das Feld über erneute Läufe weiter (wie
* `vorwort`/`interview`), plant die Seite nur ein wenn das Feld existiert und
* erzeugt den QR (qr-aufruf.png im Ausgaben-Ordner) aus `link`.
*
* Props: $issue (Eintrag aus data/stadionzeitung.json)
*/
$issue = $issue ?? [];
$aufruf = $issue['aufruf'] ?? null;
if (!is_array($aufruf)) {
return;
}
$slug = (string) ($issue['slug'] ?? '');
$heading = trim((string) ($aufruf['heading'] ?? 'Mach mit'));
$kicker = trim((string) ($aufruf['kicker'] ?? 'Mitmachen'));
// intro darf ein String ODER eine Liste von Zeilen sein — mehrere Zeilen
// werden als EIN Absatz mit weichen Umbrüchen (
) gesetzt, damit ein kurzer
// Aufruf bewusst zeilenweise stehen kann statt als Fließblock.
$introLines = array_values(array_filter(
array_map(static fn ($l): string => trim((string) $l), (array) ($aufruf['intro'] ?? [])),
static fn (string $l): bool => $l !== ''
));
$tasksTitle = trim((string) ($aufruf['tasks_title'] ?? ''));
$tasks = array_values(array_filter(
array_map(static fn ($t): string => trim((string) $t), $aufruf['tasks'] ?? []),
static fn (string $t): bool => $t !== ''
));
$contactsIntro = trim((string) ($aufruf['contacts_intro'] ?? ''));
$link = trim((string) ($aufruf['link'] ?? ''));
$ctaLabel = trim((string) ($aufruf['cta_label'] ?? 'Alle Infos'));
$ctaTitle = trim((string) ($aufruf['cta_title'] ?? ''));
// Kontakte per Namensabgleich aus der geteilten Quelle auflösen (Nummer/Foto),
// die Reihenfolge folgt dem `contacts`-Feld. Ein unbekannter Name bleibt als
// reiner Name stehen (kein Fehler), damit ein Tippfehler die Seite nicht kippt.
$byName = [];
foreach (json_load('ansprechpartner')['persons'] ?? [] as $person) {
$name = (string) ($person['name'] ?? '');
if ($name !== '') {
$byName[$name] = $person;
}
}
$contacts = [];
foreach ($aufruf['contacts'] ?? [] as $name) {
$name = trim((string) $name);
if ($name === '') {
continue;
}
$contacts[] = $byName[$name] ?? ['name' => $name];
}
$qr = ($slug !== '' && is_file(PUBLIC_PATH . "/assets/img/stadionzeitung/{$slug}/qr-aufruf.png"))
? "img/stadionzeitung/{$slug}/qr-aufruf.png"
: null;
$linkLabel = $link !== '' ? club_domain($link) : '';
// Optionales kleines Plakat rechts neben Intro + Aufgaben (z. B. das Sportfest-
// Vorderplakat) — Varianten-Set {base,widths,alt} oder Einzeldatei {src,…}.
$poster = $aufruf['poster'] ?? null;
if (!is_array($poster) || (empty($poster['base']) && empty($poster['src']))) {
$poster = null;
}
?>
= e($kicker) ?>
= implode('
', array_map('e', $introLines)) ?>
= e($tasksTitle) ?>
= e($contactsIntro) ?>
= e($ctaLabel) ?>
= e($ctaTitle) ?>
= e($linkLabel) ?>