From d754ef4bef986494df065decedb7075639a172c5 Mon Sep 17 00:00:00 2001 From: Kevin Adametz Date: Mon, 6 Jul 2026 10:12:35 +0000 Subject: [PATCH] QA-Luecke geschlossen: Legacy-Medien-URLs redirecten wieder (301) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Die Scope-Doku fuehrte den /thumbnails-Redirect als "ANGEPASST", im Code existierte er nicht — alte Symfony-Bild-URLs (/thumbnails/..., /uploads/ ...) liefen ins 404. Neuer LegacyMediaRedirectController mappt den Original-Dateinamen (bleibt beim Medien-Import erhalten) auf die neue Storage-URL fuer PM-Bilder und Firmenlogos; unbekannte Dateien bleiben 404. Gefunden bei der R6.1-Vorpruefung. Co-Authored-By: Claude Fable 5 --- .../Web/LegacyMediaRedirectController.php | 55 ++++++++++++++++++ routes/web.php | 9 +++ tests/Feature/Web/LegacyMediaRedirectTest.php | 56 +++++++++++++++++++ 3 files changed, 120 insertions(+) create mode 100644 app/Http/Controllers/Web/LegacyMediaRedirectController.php create mode 100644 tests/Feature/Web/LegacyMediaRedirectTest.php diff --git a/app/Http/Controllers/Web/LegacyMediaRedirectController.php b/app/Http/Controllers/Web/LegacyMediaRedirectController.php new file mode 100644 index 00000000..23a1eb99 --- /dev/null +++ b/app/Http/Controllers/Web/LegacyMediaRedirectController.php @@ -0,0 +1,55 @@ +companyLogoUrl($filename) + : $this->pressReleaseImageUrl($filename); + + abort_if($target === null, 404); + + return redirect($target, 301); + } + + private function pressReleaseImageUrl(string $filename): ?string + { + $image = PressReleaseImage::query() + ->where('path', 'like', '%/'.$filename) + ->orderBy('id') + ->first(); + + return $image?->url(); + } + + private function companyLogoUrl(string $filename): ?string + { + $company = Company::query() + ->withoutGlobalScopes() + ->where('logo_path', 'like', '%/'.$filename) + ->orderBy('id') + ->first(); + + return $company?->logoUrl(); + } +} diff --git a/routes/web.php b/routes/web.php index 7b4b91a1..3d6d4fba 100644 --- a/routes/web.php +++ b/routes/web.php @@ -5,6 +5,7 @@ use App\Http\Controllers\PressReleasePreviewController; use App\Http\Controllers\Web\CategoryController; use App\Http\Controllers\Web\ContactController; use App\Http\Controllers\Web\HomeController; +use App\Http\Controllers\Web\LegacyMediaRedirectController; use App\Http\Controllers\Web\NewsroomDetailController; use App\Http\Controllers\Web\NewsroomsController; use App\Http\Controllers\Web\PreiseController; @@ -183,6 +184,14 @@ Route::get('{path}', function (string $path) use ($htmlRedirect) { return $htmlRedirect(SetEdition::DEFAULT_EDITION, $path); })->where('path', '.*\.html'); +// Alte Symfony-Medien-URLs (Bestands-Backlinks): /thumbnails/... und +// /uploads/... -> 301 auf die neue Storage-URL, sonst 404. +Route::get('{prefix}/{dir}/{path}', LegacyMediaRedirectController::class) + ->whereIn('prefix', ['thumbnails', 'uploads']) + ->whereIn('dir', ['company', 'pressreleaseimage', 'pressreleaseimage_', '_pressreleaseimage']) + ->where('path', '.+') + ->name('legacy.media'); + // --------------------------------------------------------------------------- // Öffentliche Inhalte je Ausgabe (Sprache): /de/... und /en/... // --------------------------------------------------------------------------- diff --git a/tests/Feature/Web/LegacyMediaRedirectTest.php b/tests/Feature/Web/LegacyMediaRedirectTest.php new file mode 100644 index 00000000..91df19b5 --- /dev/null +++ b/tests/Feature/Web/LegacyMediaRedirectTest.php @@ -0,0 +1,56 @@ +published() + ->forPortal(Portal::Businessportal24) + ->create(['published_at' => now()->subDay()]); + + $image = PressReleaseImage::query()->create([ + 'press_release_id' => $release->id, + 'disk' => 'public', + 'path' => "press-releases/{$release->id}/images/altes-pressebild.jpg", + ]); + + $this->get("https://businessportal24.test/{$prefix}/{$dir}/altes-pressebild.jpg") + ->assertStatus(301) + ->assertRedirect($image->url()); +})->with([ + 'thumbnails' => ['thumbnails', 'pressreleaseimage'], + 'uploads' => ['uploads', 'pressreleaseimage'], + 'uploads underscore variant' => ['uploads', 'pressreleaseimage_'], +]); + +test('old company logo urls redirect to the new logo url', function () { + /** @var TestCase $this */ + // logoUrl() prüft die Existenz auf der Disk — Datei real anlegen. + Storage::fake('public'); + + $company = Company::factory()->create([ + 'portal' => Portal::Businessportal24, + 'logo_path' => 'company-logos/businessportal24/1/firmenlogo.png', + ]); + Storage::disk('public')->put($company->logo_path, 'png'); + + $this->get('https://businessportal24.test/thumbnails/company/firmenlogo.png') + ->assertStatus(301) + ->assertRedirect($company->logoUrl()); +}); + +test('unknown legacy media files stay 404', function () { + /** @var TestCase $this */ + $this->get('https://businessportal24.test/thumbnails/pressreleaseimage/gibt-es-nicht.jpg') + ->assertNotFound(); + + // Andere Verzeichnisse werden nicht angefasst. + $this->get('https://businessportal24.test/thumbnails/sonstwas/datei.jpg') + ->assertNotFound(); +});