- publish()/changeStatusFromAdmin(): kein Bild aus Formular v2 ohne gültige Bestätigung (ImageRightsConfirmationRequiredException, Admin-Seite meldet es); published_ever_at an PM und Bildern; PublishedImageSnapshot (Cover + JSON mit Nachweis/Kennzeichnung) - deleteFromAdmin() und press-releases:purge-drafts löschen Bilder nie veröffentlichter Meldungen samt Original und Bestätigung sofort (E4, O1) - press-releases:backfill-published-ever (Status-Log), press-release-images:purge-inactive-legacy (E-B11, Trockenlauf Standard) - Admin-Route für Beweisoriginal und veröffentlichte Fassung nur mit Zweck, ActivityType EvidenceAccess; Architekturtest: original_path nur in vier Dateien - ImageCorrectionService + image_declaration_corrections (insert-only), withheld_at blendet das Bild öffentlich aus (publiclyVisible-Scope), Korrekturpanel auf der Admin-Seite - Systemstatus: fehlgeschlagene Herkunftsprüfungen der letzten 7 Tage Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
85 lines
3.3 KiB
PHP
85 lines
3.3 KiB
PHP
<?php
|
|
|
|
namespace App\Services\PressRelease\Images;
|
|
|
|
use App\Models\PressRelease;
|
|
use App\Models\PressReleaseImage;
|
|
use App\Support\ImageCredit;
|
|
use Illuminate\Support\Facades\Storage;
|
|
|
|
/**
|
|
* Snapshot der veröffentlichten Bildfassung (Bildkennzeichnung E.2,
|
|
* Decision-Update E2/S1): beim Veröffentlichen wird die ausgelieferte
|
|
* Cover-Variante zusammen mit dem gerenderten Nachweis und der Kennzeichnung
|
|
* auf den privaten Snapshot-Pfad kopiert. So lässt sich später belegen, was
|
|
* mit welchem Nachweis öffentlich war — auch nach Korrektur oder Entfernung.
|
|
*/
|
|
class PublishedImageSnapshot
|
|
{
|
|
public function captureForPressRelease(PressRelease $pressRelease): void
|
|
{
|
|
$pressRelease->loadMissing('company');
|
|
|
|
foreach ($pressRelease->images()->whereNotNull('rules_version')->get() as $image) {
|
|
$this->capture($image, $pressRelease);
|
|
}
|
|
}
|
|
|
|
public function capture(PressReleaseImage $image, ?PressRelease $pressRelease = null): void
|
|
{
|
|
$pressRelease ??= $image->pressRelease;
|
|
|
|
if ($pressRelease === null || $image->isLegacyRules() || $image->original_sha256 === null) {
|
|
return;
|
|
}
|
|
|
|
$sourceDisk = Storage::disk($image->disk);
|
|
$coverPath = $image->pathForVariant('cover') ?? $image->path;
|
|
|
|
if (! $sourceDisk->exists($coverPath)) {
|
|
return;
|
|
}
|
|
|
|
$bytes = (string) $sourceDisk->get($coverPath);
|
|
$sha = hash('sha256', $bytes);
|
|
|
|
// Unverändert seit dem letzten Snapshot: nichts zu tun.
|
|
if ($image->published_snapshot_sha256 !== null && hash_equals($image->published_snapshot_sha256, $sha) && $image->published_snapshot_path !== null) {
|
|
return;
|
|
}
|
|
|
|
$credit = ImageCredit::for($image, $pressRelease->company);
|
|
$extension = pathinfo($coverPath, PATHINFO_EXTENSION) ?: 'jpg';
|
|
$base = sprintf(
|
|
'%s/%d/%d-%s',
|
|
config('images.published_snapshot_directory'),
|
|
$pressRelease->getKey(),
|
|
$image->getKey(),
|
|
substr($sha, 0, 12),
|
|
);
|
|
|
|
$targetDisk = Storage::disk($image->original_disk ?? (string) config('images.originals_disk'));
|
|
$targetDisk->put($base.'.'.$extension, $bytes);
|
|
$targetDisk->put($base.'.json', (string) json_encode([
|
|
'captured_at' => now()->toIso8601String(),
|
|
'press_release_id' => $pressRelease->getKey(),
|
|
'image_id' => $image->getKey(),
|
|
'variant' => 'cover',
|
|
'variant_sha256' => $sha,
|
|
'original_sha256' => $image->original_sha256,
|
|
'credit_line' => $credit->line(),
|
|
'credit' => $credit->credit,
|
|
'ai_declaration' => $image->ai_declaration?->value,
|
|
'ai_declaration_source' => $image->ai_declaration_source?->value,
|
|
'responsible_line' => $credit->responsibleLine,
|
|
'confirmation_key' => $credit->confirmation?->legal_text_key,
|
|
'confirmation_at' => $credit->confirmation?->confirmed_at?->toIso8601String(),
|
|
], JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
|
|
|
|
$image->forceFill([
|
|
'published_snapshot_path' => $base.'.'.$extension,
|
|
'published_snapshot_sha256' => $sha,
|
|
'published_ever_at' => $image->published_ever_at ?? now(),
|
|
])->save();
|
|
}
|
|
}
|