10) { return null; } return $aspectRatio; } catch (\Exception $e) { // Log error but don't throw - aspect ratio detection should be non-blocking error_log("Failed to detect aspect ratio for image {$imageUrl}: " . $e->getMessage()); return null; } } /** * Resolve local image path for getimagesize * * @param string $relativeUrl The relative URL of the image * @return string The absolute file path */ private static function resolveLocalImagePath(string $relativeUrl): string { // Remove leading slash if present $relativeUrl = ltrim($relativeUrl, '/'); // Define common image directories $possiblePaths = [ __DIR__ . '/../../public/' . $relativeUrl, __DIR__ . '/../../public/images/' . $relativeUrl, __DIR__ . '/../../public/media/' . $relativeUrl, __DIR__ . '/../../storage/' . $relativeUrl, ]; foreach ($possiblePaths as $path) { if (file_exists($path)) { return $path; } } // If no local file found, return the original URL (might be external) return $relativeUrl; } /** * Get a CSS aspect ratio class based on the aspect ratio value * * @param float|null $aspectRatio The aspect ratio value * @param string $defaultClass The default class to use if aspect ratio is null * @return string The CSS class for the aspect ratio */ public static function getAspectRatioClass(?float $aspectRatio, string $defaultClass = 'aspect-[1/1]'): string { if ($aspectRatio === null) { return $defaultClass; } // Common aspect ratios with nice round numbers if (abs($aspectRatio - 1.333) < 0.05) { // 4:3 return 'aspect-[4/3]'; } elseif (abs($aspectRatio - 1.5) < 0.05) { // 3:2 return 'aspect-[3/2]'; } elseif (abs($aspectRatio - 1.667) < 0.05) { // 5:3 return 'aspect-[5/3]'; } elseif (abs($aspectRatio - 1.778) < 0.05) { // 16:9 return 'aspect-[16/9]'; } elseif (abs($aspectRatio - 0.667) < 0.05) { // 2:3 return 'aspect-[2/3]'; } elseif (abs($aspectRatio - 0.75) < 0.05) { // 3:4 return 'aspect-[3/4]'; } elseif (abs($aspectRatio - 1.0) < 0.05) { // 1:1 return 'aspect-[1/1]'; } // For other ratios, use a custom aspect ratio class // Tailwind doesn't support dynamic aspect ratios, so we'll use a data attribute approach return 'aspect-custom'; } /** * Get inline styles for custom aspect ratios * * @param float|null $aspectRatio The aspect ratio value * @return string CSS style string for custom aspect ratios */ public static function getCustomAspectRatioStyle(?float $aspectRatio): string { if ($aspectRatio === null) { return ''; } // Convert aspect ratio to padding-bottom percentage for aspect ratio simulation $paddingBottom = (1 / $aspectRatio) * 100; return "padding-bottom: {$paddingBottom}%;"; } /** * Batch detect aspect ratios for multiple images * * @param array $imageUrls Array of image URLs * @return array Array of aspect ratios corresponding to the input URLs */ public static function batchDetectAspectRatios(array $imageUrls): array { $aspectRatios = []; foreach ($imageUrls as $url) { $aspectRatios[] = self::detectAspectRatio($url); } return $aspectRatios; } /** * Validate if an aspect ratio value is reasonable * * @param float $aspectRatio The aspect ratio to validate * @return bool True if the aspect ratio is valid */ public static function isValidAspectRatio(float $aspectRatio): bool { return $aspectRatio > 0.1 && $aspectRatio < 10; } }