- press_release_images: Kundenangabe/Portalkennzeichnung getrennt, Herkunftsbefund, Beweisoriginal, Snapshot-Pfade, published_ever_at, rules_version, Fokus/Letterbox; Bestand unangetastet - legal_texts (insert-only) mit img-confirm-v1 (alter Wortlaut), v2 (AGB 0.6), v3 (AGB 0.7, noch ohne Datum); image-rights:backfill-confirmations - image_rights_confirmations polymorph, insert-only, IP als versionierter HMAC; Löschung nur für nie veröffentlichte Uploads - ImageProvenanceInspector (Imagick/exif): IPTC, XMP, EXIF; algorithmicallyEnhanced nur Vermerk; unlesbare Datei = error - PressReleaseImageUploader: Original vor Derivaten, Hash-Bindung, Titelbild-Regel unter Sperre, Dateien bei Fehlern zurückgerollt; Admin-Upload ohne Bestätigung - ImageService: kein Rückfall auf die Quelldatei, og-Variante, Fokuspunkt und no_crop Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
106 lines
3 KiB
PHP
106 lines
3 KiB
PHP
<?php
|
|
|
|
namespace App\Enums;
|
|
|
|
/**
|
|
* Selbst-Deklaration des KI-Einsatzes je PM-Bild (Art. 50 Abs. 4 KI-VO).
|
|
*
|
|
* Pflichtauswahl beim Bild-Upload (Decision-Update KI-Kennzeichnung,
|
|
* 08.07.2026). Bewusste Über-Erfüllung: gelabelt wird jedes deklarierte
|
|
* KI-Bild — auch stilisiert/abstrakt, nicht nur fotorealistische Deepfakes.
|
|
*
|
|
* Seit Formular v2 (Bildkennzeichnung, 22.09.2026) heißt die erste Option
|
|
* „Ohne generative KI erstellt oder bearbeitet": Sie gilt auch für Logos,
|
|
* Grafiken und Screenshots, nicht nur für Fotos (Feedback F11). Der
|
|
* gespeicherte Wert `original` bleibt aus Kompatibilitätsgründen.
|
|
*/
|
|
enum AiImageDeclaration: string
|
|
{
|
|
case Original = 'original';
|
|
case AiGenerated = 'ai_generated';
|
|
case AiEdited = 'ai_edited';
|
|
|
|
/**
|
|
* Wortlaut der Auswahloption im Upload-Formular.
|
|
*/
|
|
public function label(): string
|
|
{
|
|
return match ($this) {
|
|
self::Original => __('Ohne generative KI erstellt oder bearbeitet'),
|
|
self::AiGenerated => __('KI-generiert'),
|
|
self::AiEdited => __('KI-bearbeitet (z. B. generative Füllung, KI-Retusche)'),
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Öffentlicher Bildhinweis direkt am Bild (Badge) — null bei Originalfotos
|
|
* (keine Nicht-KI-Zertifizierung in Portalstimme). Kurzform „KI-generiert"
|
|
* statt Satz-Wortlaut (User-Entscheidung 10.07.2026).
|
|
*/
|
|
public function publicLabel(): ?string
|
|
{
|
|
return match ($this) {
|
|
self::Original => null,
|
|
self::AiGenerated => __('KI-generiert'),
|
|
self::AiEdited => __('KI-bearbeitet'),
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Rangfolge für die Portalregel „Kennzeichnung = max(geprüfter Befund,
|
|
* Kundenangabe)" (Bildkennzeichnung A.4). Das ist eine bewusste
|
|
* Portalregel und keine Aussage über den Wahrheitsgehalt: Ein
|
|
* KI-erzeugter Bestandteil macht ein Bild nicht automatisch vollständig
|
|
* KI-generiert (Feedback F11) — der Befund wird vorher fachlich
|
|
* zugeordnet, erst dann greift die Mindestkennzeichnung.
|
|
*/
|
|
public function rank(): int
|
|
{
|
|
return match ($this) {
|
|
self::Original => 0,
|
|
self::AiEdited => 1,
|
|
self::AiGenerated => 2,
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Die strengere von zwei Kennzeichnungen nach rank(); null zählt als
|
|
* „keine Angabe".
|
|
*/
|
|
public static function strictest(?self $a, ?self $b): ?self
|
|
{
|
|
if ($a === null) {
|
|
return $b;
|
|
}
|
|
|
|
if ($b === null) {
|
|
return $a;
|
|
}
|
|
|
|
return $b->rank() > $a->rank() ? $b : $a;
|
|
}
|
|
|
|
/**
|
|
* Optionsliste für Radios/Selects: value => label.
|
|
*
|
|
* @return array<string, string>
|
|
*/
|
|
public static function options(): array
|
|
{
|
|
$options = [];
|
|
|
|
foreach (self::cases() as $case) {
|
|
$options[$case->value] = $case->label();
|
|
}
|
|
|
|
return $options;
|
|
}
|
|
|
|
/**
|
|
* @return list<string>
|
|
*/
|
|
public static function values(): array
|
|
{
|
|
return array_column(self::cases(), 'value');
|
|
}
|
|
}
|