['height' => 240, 'quality' => 78, 'dir' => 'sm'], 'md' => ['height' => 360, 'quality' => 82, 'dir' => 'md'], 'lg' => ['height' => 1200, 'quality' => 85, 'dir' => 'lg'], 'xl' => ['height' => 2400, 'quality' => 90, 'dir' => 'xl'], ]; /** * Build a thumbnail URL from a filePath/hash/id and ext. * Accepts either a direct hash string in $filePath, or an $id + $ext pair. * Legacy size codes (4 -> sm, others -> md) are supported. */ public static function url(?string $filePath, ?int $id = null, ?string $ext = null, $size = 6): string { // If $filePath seems to be a content hash and $ext is provided, build directly if (!empty($filePath) && !empty($ext) && preg_match('/^[0-9a-f]{16,128}$/i', $filePath)) { $sizeKey = is_string($size) ? $size : (($size === 4) ? 'sm' : 'md'); return self::fromHash($filePath, $ext, $sizeKey) ?: ''; } // Resolve by id when provided if ($id !== null) { try { $artClass = '\\App\\Models\\Artwork'; if (class_exists($artClass)) { $art = $artClass::where('id', $id)->orWhere('legacy_id', $id)->first(); if ($art) { $hash = $art->hash ?? null; $extToUse = $ext ?? ($art->thumb_ext ?? null); $sizeKey = is_string($size) ? $size : (($size === 4) ? 'sm' : 'md'); if (!empty($hash) && !empty($extToUse)) { return self::fromHash($hash, $extToUse, $sizeKey) ?: ''; } } } } catch (\Throwable $e) { // fallthrough to storage/filePath fallback } } // Fallback to Storage::url or return provided path if (!empty($filePath)) { try { return Storage::url($filePath); } catch (\Throwable $e) { return $filePath; } } return ''; } /** * Build CDN URL from hash and extension. */ public static function fromHash(?string $hash, ?string $ext, string $sizeKey = 'md'): ?string { if (empty($hash) || empty($ext)) return null; $sizeKey = in_array($sizeKey, self::VALID_SIZES) ? $sizeKey : 'md'; $h = $hash; $h1 = substr($h, 0, 2); $h2 = substr($h, 2, 2); return sprintf('%s/%s/%s/%s/%s.%s', rtrim(self::CDN_HOST, '/'), $sizeKey, $h1, $h2, $h, $ext); } /** * Build srcset using sm and md sizes for legacy layouts. */ public static function srcsetFromHash(?string $hash, ?string $ext): ?string { $a = self::fromHash($hash, $ext, 'sm'); $b = self::fromHash($hash, $ext, 'md'); if (!$a || !$b) return null; return $a . ' 320w, ' . $b . ' 600w'; } }