169 lines
5.1 KiB
PHP
169 lines
5.1 KiB
PHP
<?php
|
|
namespace App\Services;
|
|
|
|
use App\Models\Artwork;
|
|
|
|
class ThumbnailPresenter
|
|
{
|
|
private const MISSING_BASE = 'https://files.skinbase.org/default';
|
|
|
|
private const WIDTHS = [
|
|
'xs' => 160,
|
|
'sm' => 320,
|
|
'thumb' => 320,
|
|
'md' => 640,
|
|
'lg' => 1280,
|
|
'xl' => 1920,
|
|
'sq' => 400,
|
|
];
|
|
|
|
private const HEIGHTS = [
|
|
'xs' => 90,
|
|
'sm' => 180,
|
|
'thumb' => 180,
|
|
'md' => 360,
|
|
'lg' => 720,
|
|
'xl' => 1080,
|
|
'sq' => 400,
|
|
];
|
|
|
|
/**
|
|
* Present thumbnail data for an item which may be a model or an array.
|
|
* Returns ['id' => int|null, 'title' => string, 'url' => string, 'srcset' => string|null]
|
|
*/
|
|
public static function present($item, string $size = 'md'): array
|
|
{
|
|
$size = self::normalizeSize($size);
|
|
$id = null;
|
|
$title = '';
|
|
|
|
if ($item instanceof Artwork) {
|
|
$id = $item->id;
|
|
$title = (string) $item->title;
|
|
$url = self::resolveArtworkUrl($item, $size);
|
|
return [
|
|
'id' => $id,
|
|
'title' => $title,
|
|
'url' => $url,
|
|
'width' => self::WIDTHS[$size] ?? null,
|
|
'height' => self::HEIGHTS[$size] ?? null,
|
|
'srcset' => self::buildSrcsetFromArtwork($item),
|
|
];
|
|
}
|
|
|
|
$uext = 'webp';
|
|
$isEloquent = $item instanceof \Illuminate\Database\Eloquent\Model;
|
|
|
|
if ($isEloquent) {
|
|
$id = $item->id ?? null;
|
|
$title = $item->title ?? ($item->name ?? '');
|
|
$url = $item->thumb_url ?? $item->thumb ?? '';
|
|
$srcset = $item->thumb_srcset ?? null;
|
|
if (empty($url)) {
|
|
$url = self::missingUrl($size);
|
|
}
|
|
return [
|
|
'id' => $id,
|
|
'title' => $title,
|
|
'url' => $url,
|
|
'width' => self::WIDTHS[$size] ?? null,
|
|
'height' => self::HEIGHTS[$size] ?? null,
|
|
'srcset' => $srcset,
|
|
];
|
|
}
|
|
|
|
// If it's an object but not an Eloquent model (e.g. stdClass row), cast to array
|
|
if (is_object($item)) {
|
|
$item = (array) $item;
|
|
}
|
|
|
|
$id = $item['id'] ?? null;
|
|
$title = $item['name'] ?? '';
|
|
|
|
// If array contains direct hash/thumb_ext, use CDN fromHash
|
|
$hash = $item['hash'] ?? null;
|
|
$thumbExt = 'webp';
|
|
if (!empty($hash) && !empty($thumbExt)) {
|
|
$url = ThumbnailService::fromHash($hash, $thumbExt, $size) ?: ThumbnailService::url(null, $id, $thumbExt, 6);
|
|
$srcset = ThumbnailService::srcsetFromHash($hash, $thumbExt);
|
|
if (empty($url)) {
|
|
$url = self::missingUrl($size);
|
|
}
|
|
return [
|
|
'id' => $id,
|
|
'title' => $title,
|
|
'url' => $url,
|
|
'width' => self::WIDTHS[$size] ?? null,
|
|
'height' => self::HEIGHTS[$size] ?? null,
|
|
'srcset' => $srcset,
|
|
];
|
|
}
|
|
|
|
// Fallback: ask ThumbnailService to resolve by id or file path
|
|
$url = ThumbnailService::url(null, $id, $uext, 6);
|
|
if (empty($url)) {
|
|
$url = self::missingUrl($size);
|
|
}
|
|
|
|
return [
|
|
'id' => $id,
|
|
'title' => $title,
|
|
'url' => $url,
|
|
'width' => self::WIDTHS[$size] ?? null,
|
|
'height' => self::HEIGHTS[$size] ?? null,
|
|
'srcset' => null,
|
|
];
|
|
}
|
|
|
|
public static function srcsetForArtwork(Artwork $artwork): string
|
|
{
|
|
return self::buildSrcsetFromArtwork($artwork);
|
|
}
|
|
|
|
private static function resolveArtworkUrl(Artwork $artwork, string $size): string
|
|
{
|
|
$hash = $artwork->hash ?? null;
|
|
if (!empty($hash)) {
|
|
$url = ThumbnailService::fromHash((string) $hash, 'webp', $size);
|
|
if (!empty($url)) {
|
|
return $url;
|
|
}
|
|
}
|
|
|
|
$filePath = $artwork->file_path ?? $artwork->file_name ?? null;
|
|
if (!empty($filePath)) {
|
|
$cdn = rtrim((string) config('cdn.files_url', 'https://files.skinbase.org'), '/');
|
|
$path = ltrim((string) $filePath, '/');
|
|
$pathWithoutExt = preg_replace('/\.[^.]+$/', '', $path);
|
|
|
|
return sprintf('%s/%s/%s.webp', $cdn, $size, $pathWithoutExt);
|
|
}
|
|
|
|
return self::missingUrl($size);
|
|
}
|
|
|
|
private static function buildSrcsetFromArtwork(Artwork $artwork): string
|
|
{
|
|
$md = self::resolveArtworkUrl($artwork, 'md');
|
|
$lg = self::resolveArtworkUrl($artwork, 'lg');
|
|
$xl = self::resolveArtworkUrl($artwork, 'xl');
|
|
|
|
return implode(', ', [
|
|
$md . ' 640w',
|
|
$lg . ' 1280w',
|
|
$xl . ' 1920w',
|
|
]);
|
|
}
|
|
|
|
private static function normalizeSize(string $size): string
|
|
{
|
|
$size = strtolower(trim($size));
|
|
return array_key_exists($size, self::WIDTHS) ? $size : 'md';
|
|
}
|
|
|
|
private static function missingUrl(string $size): string
|
|
{
|
|
return sprintf('%s/missing_%s.webp', self::MISSING_BASE, $size);
|
|
}
|
|
}
|