table('company')->insert([ 'id' => 123, 'logo' => 'logo-a.jpg', ]); $company = Company::factory()->create([ 'portal' => Portal::Presseecho->value, 'legacy_portal' => Portal::Presseecho->value, 'legacy_id' => 123, 'logo_path' => null, 'logo_variants' => null, ]); $this->artisan('legacy:migrate-media', [ '--portal' => Portal::Presseecho->value, '--type' => 'company-logos', '--base-path' => $basePath, ]) ->assertSuccessful() ->expectsOutputToContain('presseecho/company-logos: Legacy 1, migriert 1, Thumbnail-Fallback 0, DB-Updates 1'); $company->refresh(); expect($company->logo_path)->toBe("company-logos/presseecho/{$company->id}/logo-a.jpg") ->and($company->logo_variants)->toHaveKeys(['sq', 'wide']); Storage::disk('public')->assertExists($company->logo_path); foreach ($company->logo_variants as $variantPath) { Storage::disk('public')->assertExists($variantPath); } }); test('legacy media migration creates press release image records from legacy database rows', function () { /** @var TestCase $this */ Storage::fake('public'); configureLegacyMediaConnection(); $basePath = prepareLegacyMediaFolder(); File::ensureDirectoryExists("{$basePath}/presseecho/uploads/pressreleaseimage"); File::put("{$basePath}/presseecho/uploads/pressreleaseimage/photo-a.jpg", migrateLegacyMediaFakeImageBytes(1600, 1200)); DB::connection('mysql_presseecho')->table('press_release_image')->insert([ 'id' => 987, 'title' => 'Pressefoto', 'description' => 'Beschreibung', 'image' => 'photo-a.jpg', 'copyright' => 'Copyright', 'press_release_id' => 456, 'is_preview_image' => true, ]); $pressRelease = PressRelease::factory()->create([ 'portal' => Portal::Presseecho->value, 'legacy_portal' => Portal::Presseecho->value, 'legacy_id' => 456, ]); $this->artisan('legacy:migrate-media', [ '--portal' => Portal::Presseecho->value, '--type' => 'press-release-images', '--base-path' => $basePath, ]) ->assertSuccessful() ->expectsOutputToContain('presseecho/press-release-images: Legacy 1, migriert 1, Thumbnail-Fallback 0, DB-Updates 1'); $image = PressReleaseImage::query() ->where('legacy_portal', Portal::Presseecho->value) ->where('legacy_id', 987) ->firstOrFail(); expect($image->press_release_id)->toBe($pressRelease->id) ->and($image->path)->toBe("press-releases/{$pressRelease->id}/images/photo-a.jpg") ->and($image->title)->toBe('Pressefoto') ->and($image->is_preview)->toBeTrue() ->and($image->variants)->toHaveKeys(['thumb', 'medium', 'large']) ->and($image->width)->toBe(1600) ->and($image->height)->toBe(1200); Storage::disk('public')->assertExists($image->path); foreach ($image->variants as $variantPath) { Storage::disk('public')->assertExists($variantPath); } }); test('legacy media migration reports missing source files without changing the target record', function () { /** @var TestCase $this */ Storage::fake('public'); configureLegacyMediaConnection(); $basePath = prepareLegacyMediaFolder(); DB::connection('mysql_presseecho')->table('company')->insert([ 'id' => 321, 'logo' => 'missing.png', ]); $company = Company::factory()->create([ 'portal' => Portal::Presseecho->value, 'legacy_portal' => Portal::Presseecho->value, 'legacy_id' => 321, 'logo_path' => null, ]); $this->artisan('legacy:migrate-media', [ '--portal' => Portal::Presseecho->value, '--type' => 'company-logos', '--base-path' => $basePath, ]) ->assertFailed() ->expectsOutputToContain('Datei fehlt: presseecho/company/missing.png'); expect($company->fresh()->logo_path)->toBeNull(); }); test('legacy media migration falls back to legacy thumbnails by image id', function () { /** @var TestCase $this */ Storage::fake('public'); configureLegacyMediaConnection(); $basePath = prepareLegacyMediaFolder(); File::ensureDirectoryExists("{$basePath}/presseecho/thumbnails/pressreleaseimage/press_image_preview/42/01/00"); File::put("{$basePath}/presseecho/thumbnails/pressreleaseimage/press_image_preview/42/01/00/pool-10042.png", migrateLegacyMediaFakeImageBytes(filename: 'legacy.png')); DB::connection('mysql_presseecho')->table('press_release_image')->insert([ 'id' => 10042, 'title' => 'Pool', 'description' => null, 'image' => 'missing-original.jpg', 'copyright' => null, 'press_release_id' => 654, 'is_preview_image' => false, ]); $pressRelease = PressRelease::factory()->create([ 'portal' => Portal::Presseecho->value, 'legacy_portal' => Portal::Presseecho->value, 'legacy_id' => 654, ]); $this->artisan('legacy:migrate-media', [ '--portal' => Portal::Presseecho->value, '--type' => 'press-release-images', '--base-path' => $basePath, ]) ->assertSuccessful() ->expectsOutputToContain('Thumbnail-Fallback 1'); $image = PressReleaseImage::query() ->where('legacy_portal', Portal::Presseecho->value) ->where('legacy_id', 10042) ->firstOrFail(); expect($image->path)->toBe("press-releases/{$pressRelease->id}/images/pool-10042.png") ->and($image->variants)->toHaveKeys(['thumb', 'medium', 'large']); Storage::disk('public')->assertExists($image->path); }); function configureLegacyMediaConnection(): void { Config::set('database.connections.mysql_presseecho', [ 'driver' => 'sqlite', 'database' => ':memory:', 'prefix' => '', 'foreign_key_constraints' => false, ]); DB::purge('mysql_presseecho'); Schema::connection('mysql_presseecho')->dropIfExists('company'); Schema::connection('mysql_presseecho')->dropIfExists('press_release_image'); Schema::connection('mysql_presseecho')->create('company', function (Blueprint $table): void { $table->integer('id')->primary(); $table->string('logo')->nullable(); }); Schema::connection('mysql_presseecho')->create('press_release_image', function (Blueprint $table): void { $table->integer('id')->primary(); $table->string('title')->nullable(); $table->text('description')->nullable(); $table->string('image')->nullable(); $table->string('copyright')->nullable(); $table->integer('press_release_id'); $table->boolean('is_preview_image')->default(false); }); } function prepareLegacyMediaFolder(): string { $basePath = storage_path('framework/testing/legacy-media-'.Str::random(8)); File::deleteDirectory($basePath); File::ensureDirectoryExists($basePath); return $basePath; } function migrateLegacyMediaFakeImageBytes(int $width = 800, int $height = 600, string $filename = 'legacy.jpg'): string { return UploadedFile::fake()->image($filename, $width, $height)->get(); }