QA-Luecke geschlossen: Legacy-Medien-URLs redirecten wieder (301)
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 <noreply@anthropic.com>
This commit is contained in:
parent
9a9e31360e
commit
d0ffe664b8
3 changed files with 120 additions and 0 deletions
55
app/Http/Controllers/Web/LegacyMediaRedirectController.php
Normal file
55
app/Http/Controllers/Web/LegacyMediaRedirectController.php
Normal file
|
|
@ -0,0 +1,55 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers\Web;
|
||||||
|
|
||||||
|
use App\Http\Controllers\Controller;
|
||||||
|
use App\Models\Company;
|
||||||
|
use App\Models\PressReleaseImage;
|
||||||
|
use Illuminate\Http\RedirectResponse;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Redirect alter Symfony-Medien-URLs (QA-Punkt "Alter /thumbnails/...-Link
|
||||||
|
* redirectet korrekt", 06-FEATURES-SCOPE §11/§15): Die Altportale lieferten
|
||||||
|
* Bilder unter /uploads/... und /thumbnails/...; der Medien-Import
|
||||||
|
* (migrate:legacy-media) behält den Original-Dateinamen im neuen Pfad —
|
||||||
|
* darüber wird hier 301 auf die neue Storage-URL geleitet. Unbekannte
|
||||||
|
* Dateien bleiben 404.
|
||||||
|
*/
|
||||||
|
class LegacyMediaRedirectController extends Controller
|
||||||
|
{
|
||||||
|
public function __invoke(string $prefix, string $dir, string $path): RedirectResponse
|
||||||
|
{
|
||||||
|
$filename = basename($path);
|
||||||
|
|
||||||
|
abort_if($filename === '' || $filename === '.', 404);
|
||||||
|
|
||||||
|
$target = str_contains($dir, 'company')
|
||||||
|
? $this->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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -5,6 +5,7 @@ use App\Http\Controllers\PressReleasePreviewController;
|
||||||
use App\Http\Controllers\Web\CategoryController;
|
use App\Http\Controllers\Web\CategoryController;
|
||||||
use App\Http\Controllers\Web\ContactController;
|
use App\Http\Controllers\Web\ContactController;
|
||||||
use App\Http\Controllers\Web\HomeController;
|
use App\Http\Controllers\Web\HomeController;
|
||||||
|
use App\Http\Controllers\Web\LegacyMediaRedirectController;
|
||||||
use App\Http\Controllers\Web\NewsroomDetailController;
|
use App\Http\Controllers\Web\NewsroomDetailController;
|
||||||
use App\Http\Controllers\Web\NewsroomsController;
|
use App\Http\Controllers\Web\NewsroomsController;
|
||||||
use App\Http\Controllers\Web\PreiseController;
|
use App\Http\Controllers\Web\PreiseController;
|
||||||
|
|
@ -183,6 +184,14 @@ Route::get('{path}', function (string $path) use ($htmlRedirect) {
|
||||||
return $htmlRedirect(SetEdition::DEFAULT_EDITION, $path);
|
return $htmlRedirect(SetEdition::DEFAULT_EDITION, $path);
|
||||||
})->where('path', '.*\.html');
|
})->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/...
|
// Öffentliche Inhalte je Ausgabe (Sprache): /de/... und /en/...
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
|
|
||||||
56
tests/Feature/Web/LegacyMediaRedirectTest.php
Normal file
56
tests/Feature/Web/LegacyMediaRedirectTest.php
Normal file
|
|
@ -0,0 +1,56 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
use App\Enums\Portal;
|
||||||
|
use App\Models\Company;
|
||||||
|
use App\Models\PressRelease;
|
||||||
|
use App\Models\PressReleaseImage;
|
||||||
|
use Illuminate\Support\Facades\Storage;
|
||||||
|
use Tests\TestCase;
|
||||||
|
|
||||||
|
test('old thumbnail and upload image urls redirect to the new storage url', function (string $prefix, string $dir) {
|
||||||
|
/** @var TestCase $this */
|
||||||
|
$release = PressRelease::factory()
|
||||||
|
->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();
|
||||||
|
});
|
||||||
Loading…
Add table
Add a link
Reference in a new issue