Files
amare/app/Support/ResponsiveImage.php
Manoel Freitas 3dc1f449ee feat: ship public site with SEO and visuals (#3)
* feat: ship public site with SEO and visuals

Publish CMS content on public routes with responsive media,
accessibility checks, and deterministic visual baselines.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix: make browser visual CI deterministic for media

Mount host public storage into FrankenPHP so seeded fixtures are served,
and replace PNG-as-JPG fixtures with real JPEGs so Chromium can render them.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix: serve public media on same-origin storage paths

Pest Browser hosts on 127.0.0.1:port while Storage::url used
http://localhost, so screenshots captured broken images. Use relative
/storage URLs for media and absolutize only OG tags via url().

Co-authored-by: Cursor <cursoragent@cursor.com>

* test: refresh visual baselines from CI Ubuntu screenshots

Media now loads on same-origin /storage paths, so baselines must
capture the rendered fixtures. Use full-page snapshots from the CI
runner to keep Pest's exact snapshot match stable across environments.

Co-authored-by: Cursor <cursoragent@cursor.com>

---------

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-29 10:12:24 -03:00

152 lines
4.0 KiB
PHP

<?php
declare(strict_types=1);
namespace App\Support;
use Illuminate\Contracts\Filesystem\Filesystem;
use Illuminate\Support\Facades\Storage;
use Intervention\Image\Drivers\Gd\Driver;
use Intervention\Image\ImageManager;
use Throwable;
final class ResponsiveImage
{
/** @var list<int> */
public const WIDTHS = [480, 960, 1440];
public static function generate(string $path, ?string $disk = null): void
{
$filesystem = self::filesystem($disk);
if (! $filesystem->exists($path)) {
return;
}
$manager = new ImageManager(new Driver);
$contents = $filesystem->get($path);
if ($contents === null) {
return;
}
$extension = strtolower(pathinfo($path, PATHINFO_EXTENSION));
foreach (self::WIDTHS as $width) {
$variantPath = self::variantPath($path, $width);
$variant = $manager->read($contents);
if ($variant->width() > $width) {
$variant->scale(width: $width);
}
$encoded = match ($extension) {
'png' => $variant->toPng(),
'webp' => $variant->toWebp(quality: 82),
default => $variant->toJpeg(quality: 82),
};
$filesystem->put($variantPath, (string) $encoded);
}
}
public static function deleteVariants(string $path, ?string $disk = null): void
{
$filesystem = self::filesystem($disk);
foreach (self::WIDTHS as $width) {
$variantPath = self::variantPath($path, $width);
if ($filesystem->exists($variantPath)) {
$filesystem->delete($variantPath);
}
}
}
public static function delete(string $path, ?string $disk = null): void
{
$filesystem = self::filesystem($disk);
self::deleteVariants($path, $disk);
if ($filesystem->exists($path)) {
$filesystem->delete($path);
}
}
public static function replace(string $previousPath, string $newPath, ?string $disk = null): void
{
if ($previousPath !== '' && $previousPath !== $newPath) {
self::delete($previousPath, $disk);
}
self::generate($newPath, $disk);
}
public static function variantPath(string $path, int $width): string
{
$directory = trim(dirname($path), '.');
$filename = pathinfo($path, PATHINFO_FILENAME);
$extension = pathinfo($path, PATHINFO_EXTENSION);
$variantName = $filename.'-'.$width.($extension !== '' ? '.'.$extension : '');
return $directory === '' ? $variantName : $directory.'/'.$variantName;
}
/**
* @return list<array{path: string, width: int}>
*/
public static function availableVariants(string $path, ?string $disk = null): array
{
$filesystem = self::filesystem($disk);
$variants = [];
foreach (self::WIDTHS as $width) {
$variantPath = self::variantPath($path, $width);
if ($filesystem->exists($variantPath)) {
$variants[] = [
'path' => $variantPath,
'width' => $width,
];
}
}
return $variants;
}
/**
* @return array{width: int, height: int}|null
*/
public static function dimensions(string $path, ?string $disk = null): ?array
{
$filesystem = self::filesystem($disk);
if (! $filesystem->exists($path)) {
return null;
}
try {
$contents = $filesystem->get($path);
if ($contents === null) {
return null;
}
$image = (new ImageManager(new Driver))->read($contents);
return [
'width' => $image->width(),
'height' => $image->height(),
];
} catch (Throwable) {
return null;
}
}
private static function filesystem(?string $disk): Filesystem
{
return Storage::disk($disk ?? PublicImageUploadRules::disk());
}
}