legal/web: Zustimmungsgate je Dokumentversion (aus bis AGB 0.7), OG-Variante mit eingebranntem Bildnachweis, Nachweis in Teasern (Bildkennzeichnung Blöcke G und H)

- legal_document_acceptances (insert-only), LegalAcceptanceGate, Pflicht-Schalter im Einreichungs-Modal über den gemeinsamen Trait; API: GET/POST /api/v1/legal/acceptances, submit antwortet 428 mit den geforderten Fassungen; LEGAL_ACCEPTANCE_GATE
- ImageService: og-Variante (1200×630) mit halbtransparentem Balken und Inter SemiBold, regenerateOgVariant() für Korrekturen und Bestand; Fokuspunkt/Letterbox getestet
- Uploader brennt den Nachweis beim Upload ein, ImageCorrectionService baut die OG-Variante nach einer Korrektur neu; Artikelseite nutzt og für og:image
- Teaser: Nachweis in alt/title (Feed, Hero, Kategorie, Newsroom), Unterschrift am Hero-Bild; PressRelease::cardImageCredit()

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
Kevin Adametz 2026-09-22 10:12:17 +00:00
parent b5b70416f2
commit 075d0d931f
27 changed files with 866 additions and 15 deletions

View file

@ -75,6 +75,26 @@ final readonly class ImageCredit
);
}
/**
* Zeile aus Einzelteilen — für den eingebrannten OG-Balken beim Upload,
* bevor es ein Modell gibt (H.1).
*/
public static function compose(?string $credit, ?string $aiLabel, ?string $label = null): ?string
{
$credit = self::clean($credit);
$parts = [];
if ($credit !== null) {
$parts[] = ($label ?? __('web.detail.photo')).': '.$credit;
}
if ($aiLabel !== null && $aiLabel !== '') {
$parts[] = $aiLabel;
}
return $parts === [] ? null : implode(' · ', $parts);
}
/**
* Sichtbare Zeile unter dem Bild, z. B. „Foto: Musterfirma · KI-generiert".
*/