feat: Optimize image handling for OnTicket tenant
- Added migration to optimize OnTicket images using OptimizeOnticketImagesSeeder. - Updated OnTicketTenantSeeder to reference optimized image formats (AVIF). - Modified OnticketImmersiveHeroCarouselSeeder to use AVIF images for hero carousel. - Created OptimizeOnticketImagesSeeder to replace existing attachments with optimized images. - Adjusted TestEventsSeeder to utilize AVIF images for events. - Updated tests to verify the correct image formats and ensure optimized images are stored. - Added new image files in AVIF format for logos, backgrounds, and event images.
This commit is contained in:
155
database/seeders/OptimizeOnticketImagesSeeder.php
Normal file
155
database/seeders/OptimizeOnticketImagesSeeder.php
Normal file
@@ -0,0 +1,155 @@
|
||||
<?php
|
||||
|
||||
namespace Database\Seeders;
|
||||
|
||||
use App\Domains\Core\Tenant\Models\Tenant;
|
||||
use App\Shared\Attachable\Models\Attachment;
|
||||
use Illuminate\Database\Seeder;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use RuntimeException;
|
||||
use Throwable;
|
||||
|
||||
class OptimizeOnticketImagesSeeder extends Seeder
|
||||
{
|
||||
private const IMAGE_DIRECTORY = 'images/tennants/onticket_otpimizado';
|
||||
|
||||
private const CAROUSEL_IMAGES = [
|
||||
'onticket_hero_carousel_1.avif',
|
||||
'onticket_hero_carousel_2.avif',
|
||||
'onticket_hero_carousel_3.avif',
|
||||
'onticket_hero_carousel_4.avif',
|
||||
'onticket_hero_carousel_5.avif',
|
||||
'onticket_hero_carousel_6.avif',
|
||||
'onticket_hero_carousel_7.avif',
|
||||
'onticket_hero_carousel_8.avif',
|
||||
];
|
||||
|
||||
private const EVENT_IMAGES = [
|
||||
'[Prueba] Noche de Música en Vivo' => 'live-music.avif',
|
||||
'[Prueba] Festival de Sabores' => 'food-festival.avif',
|
||||
'[Prueba] Stand Up en el Centro' => 'stand-up.avif',
|
||||
];
|
||||
|
||||
public function run(): void
|
||||
{
|
||||
$tenant = Tenant::query()->where('codigo', 'onticket')->first();
|
||||
|
||||
if ($tenant === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->replaceAttachment(
|
||||
$tenant->headerBackgroundImage,
|
||||
'onticket_header_background.avif',
|
||||
);
|
||||
|
||||
$carousel = $tenant->websiteExtras()
|
||||
->whereHas(
|
||||
'websiteTypeExtra',
|
||||
fn ($query) => $query->where('codigo', 'immersiveHeroCarousel')
|
||||
)
|
||||
->first();
|
||||
$carouselIds = is_array($carousel?->config) ? array_values($carousel->config) : [];
|
||||
|
||||
foreach (self::CAROUSEL_IMAGES as $index => $filename) {
|
||||
$attachmentId = $carouselIds[$index] ?? null;
|
||||
|
||||
if (is_int($attachmentId)) {
|
||||
$this->replaceAttachment(
|
||||
Attachment::query()->find($attachmentId),
|
||||
'onticket_tennant_hero_carousel/'.$filename,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
foreach (self::EVENT_IMAGES as $title => $filename) {
|
||||
$event = $tenant->events()->where('title', $title)->first();
|
||||
|
||||
$this->replaceAttachment(
|
||||
$event?->attachment,
|
||||
'test-events/'.$filename,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private function replaceAttachment(?Attachment $attachment, string $relativePath): void
|
||||
{
|
||||
if ($attachment === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
$sourcePath = public_path(self::IMAGE_DIRECTORY.'/'.$relativePath);
|
||||
|
||||
if (! is_file($sourcePath)) {
|
||||
throw new RuntimeException("Image not found at path: {$sourcePath}");
|
||||
}
|
||||
|
||||
$contents = file_get_contents($sourcePath);
|
||||
|
||||
if (! is_string($contents) || $contents === '') {
|
||||
throw new RuntimeException("Could not read image at path: {$sourcePath}");
|
||||
}
|
||||
|
||||
$filename = basename($relativePath);
|
||||
$extension = strtolower(pathinfo($filename, PATHINFO_EXTENSION));
|
||||
$mimeType = match ($extension) {
|
||||
'avif' => 'image/avif',
|
||||
'svg' => 'image/svg+xml',
|
||||
default => 'image/png',
|
||||
};
|
||||
$directory = trim(str_replace('\\', '/', dirname($attachment->path)), './');
|
||||
$storedFilename = $attachment->key.($extension === '' ? '' : '.'.$extension);
|
||||
$newPath = $directory === '' ? $storedFilename : $directory.'/'.$storedFilename;
|
||||
$disk = Storage::disk('s3');
|
||||
|
||||
if (
|
||||
$attachment->path === $newPath
|
||||
&& $attachment->filename === $filename
|
||||
&& $attachment->mime_type === $mimeType
|
||||
&& $attachment->size === strlen($contents)
|
||||
&& $disk->exists($newPath)
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
$oldPath = $attachment->path;
|
||||
$oldContents = $disk->exists($oldPath) ? $disk->get($oldPath) : null;
|
||||
|
||||
if (! $disk->put($newPath, $contents)) {
|
||||
throw new RuntimeException("Could not store optimized image at path: {$newPath}");
|
||||
}
|
||||
|
||||
try {
|
||||
DB::transaction(function () use (
|
||||
$attachment,
|
||||
$extension,
|
||||
$filename,
|
||||
$mimeType,
|
||||
$newPath,
|
||||
$contents,
|
||||
): void {
|
||||
$attachment->update([
|
||||
'path' => $newPath,
|
||||
'filename' => $filename,
|
||||
'type' => 'image',
|
||||
'mime_type' => $mimeType,
|
||||
'extension' => $extension,
|
||||
'size' => strlen($contents),
|
||||
]);
|
||||
});
|
||||
} catch (Throwable $throwable) {
|
||||
if ($newPath === $oldPath && is_string($oldContents)) {
|
||||
$disk->put($oldPath, $oldContents);
|
||||
} else {
|
||||
$disk->delete($newPath);
|
||||
}
|
||||
|
||||
throw $throwable;
|
||||
}
|
||||
|
||||
if ($oldPath !== $newPath && $disk->exists($oldPath)) {
|
||||
$disk->delete($oldPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user