// This acts as a placeholder to look for ImagesController // I will not edit ImagesTrait yet until I confirm the controller. namespace App\Traits; use Illuminate\Support\Facades\Route; use Illuminate\Support\Facades\Storage; use Intervention\Image\Facades\Image; use Illuminate\Support\Facades\Cache; use InvalidArgumentException; trait ImagesTrait { protected static $defaultImage = 'dashboard/photo_logo_step.webp'; protected static $imageDisk = 'public'; protected static $imageDirectory = 'uploads/'; // تقليل الأحجام بشكل كبير - فقط الأحجام المعقولة protected static $srcsetWidths = [400, 800, 1200]; private static function getSafePath(?string $pathInput): string { if (empty($pathInput) || !static::validateImage($pathInput)) { if (empty(static::$defaultImage)) { throw new InvalidArgumentException('Default image path is not set or empty in ImagesTrait. Cannot generate image URL.'); } return static::$defaultImage; } return $pathInput; } public static function getResponsiveImage(?string $pathInput): string { $path = static::getSafePath($pathInput); $src = route('image', ['path' => $path, 'size' => 'original']); $srcset = collect(static::$srcsetWidths) ->map(fn($w) => route('image', ['path' => $path, 'size' => 'original']) . "?width={$w} {$w}w") ->implode(', '); return static::buildImageTag([ 'src' => $src, 'srcset' => $srcset, 'loading' => 'lazy', 'style' => 'max-width: 100%' ]); } public static function getCroppedResponsiveImage(?string $pathInput, int $width, int $height): string { $path = static::getSafePath($pathInput); $src = static::generateImageUrl($path, "{$width}x{$height}"); $srcset = collect(static::$srcsetWidths) ->filter(fn($w) => $w >= $width) // فقط الأحجام الأكبر ->take(2) // أقصى حجمين إضافيين ->map(fn($w) => route('image', ['path' => $path, 'size' => "{$width}x{$height}"]) . "?width={$w} {$w}w") ->implode(', '); return static::buildImageTag([ 'src' => $src, 'srcset' => $srcset, 'sizes' => '100vw', 'width' => $width, 'height' => $height, 'loading' => 'lazy' ]); } public static function getCroppedImage(?string $pathInput, int $w, int $h): string { $path = static::getSafePath($pathInput); $src = static::generateImageUrl($path, "{$w}x{$h}"); return 'src="' . htmlspecialchars($src, ENT_QUOTES, 'UTF-8') . '"'; } public static function getOriginalImage(?string $pathInput): string { $path = static::getSafePath($pathInput); $src = static::generateImageUrl($path, 'original'); return "src=\"" . htmlspecialchars($src, ENT_QUOTES, 'UTF-8') . "\""; } public static function getPathImage(?string $pathInput, string $w = '', string $h = ''): string { $path = static::getSafePath($pathInput); $size = (!empty($w) && !empty($h)) ? "{$w}x{$h}" : 'original'; return static::generateImageUrl($path, $size); } /** * دالة محسّنة للصور الصغيرة بدون quality parameters */ public static function getSmallResponsiveImage(?string $pathInput, int $width, int $height): string { $path = static::getSafePath($pathInput); // أحجام مناسبة للصور المتوسطة $widths = collect([100, 200, 300, 400]) ->filter(fn($w) => $w >= $width) ->take(3); $src = static::generateImageUrl($path, "{$width}x{$height}"); $srcset = $widths->map(function($w) use ($path, $width, $height) { $scaledHeight = intval(($height * $w) / $width); return route('image', ['path' => $path, 'size' => "{$width}x{$height}"]) . " {$w}w"; })->implode(', '); $sizes = $width <= 300 ? "(max-width: 768px) {$width}px, {$width}px" : "(max-width: 768px) 90vw, {$width}px"; return static::buildImageTag([ 'src' => $src, 'srcset' => $srcset, 'sizes' => $sizes, 'width' => $width, 'height' => $height, 'loading' => 'lazy' ]); } /** * نسخة محسّنة من getCroppedResponsiveImage للصور المتوسطة */ public static function getMediumResponsiveImage(?string $pathInput, int $width, int $height): string { $path = static::getSafePath($pathInput); // أحجام مناسبة للصور المتوسطة $widths = collect([300, 400, 600, 800]) ->filter(fn($w) => $w >= $width) ->take(3); $src = static::generateImageUrl($path, "{$width}x{$height}"); $srcset = $widths->map(function($w) use ($path, $width, $height) { $scaledHeight = intval(($height * $w) / $width); return route('image', ['path' => $path, 'size' => "{$width}x{$height}"]) . " {$w}w"; })->implode(', '); $sizes = $width <= 300 ? "(max-width: 768px) {$width}px, {$width}px" : "(max-width: 768px) 90vw, {$width}px"; return static::buildImageTag([ 'src' => $src, 'srcset' => $srcset, 'sizes' => $sizes, 'width' => $width, 'height' => $height, 'loading' => 'lazy' ]); } private static function generateImageUrl(string $path, string $size): string { return route('image', [ 'path' => $path, 'size' => $size ]); } private static function validateImage(string $path): bool { return Storage::disk(static::$imageDisk) ->exists(static::$imageDirectory . $path); } private static function generateSrcset(string $path, array $widths): string { return collect($widths) ->map(fn($w) => static::generateImageUrl($path, (string)$w) . " {$w}w") ->implode(', '); } private static function generateResponsiveSrcset(string $path): string { return collect(static::$srcsetWidths) ->map(fn($w) => static::generateImageUrl($path, "original") . " {$w}w") ->implode(', '); } private static function generateCroppedSrcset(string $path, int $baseWidth, int $baseHeight): string { $aspectRatio = $baseHeight / $baseWidth; return collect(static::$srcsetWidths) ->filter(fn($w) => $w >= $baseWidth) ->take(3) ->map(function ($w) use ($path, $aspectRatio) { $h = (int) round($w * $aspectRatio); return static::generateImageUrl($path, "{$w}x{$h}") . " {$w}w"; }) ->implode(', '); } private static function calculateHeight(string $path, int $width): int { $cacheKey = "image-height-{$path}-{$width}"; return Cache::remember($cacheKey, 3600, function() use ($path, $width) { try { $imagePath = Storage::disk(static::$imageDisk) ->path(static::$imageDirectory . $path); $image = Image::make($imagePath); if ($image->width() == 0) return (int) ($width * 0.75); return (int) round(($width * $image->height()) / $image->width()); } catch (\Exception $e) { return (int) ($width * 0.75); } }); } private static function buildImageTag(array $attributes): string { // إذا كان fetchpriority='high' موجود، احذف loading='lazy' if (isset($attributes['fetchpriority']) && $attributes['fetchpriority'] === 'high') { unset($attributes['loading']); } // إذا لم يكن loading موجود وما في fetchpriority='high'، ضع lazy كافتراضي elseif (!isset($attributes['loading']) && (!isset($attributes['fetchpriority']) || $attributes['fetchpriority'] !== 'high')) { $attributes['loading'] = 'lazy'; } return collect($attributes) ->map(fn($value, $key) => "{$key}=\"" . htmlspecialchars($value, ENT_QUOTES, 'UTF-8') . "\"") ->implode(' '); } public static function ratio(int $w, int $h): string { return "width=\"{$w}\" height=\"{$h}\" style=\"height:auto;width:100%;\""; } public static function eager(): string { return "loading=\"eager\""; } public static function aspectRatio($width = 160, $height = 60) { return "style=\"aspect-ratio: {$width} / {$height}; object-fit: contain;\""; } /** * للصورة الأولى/الأهم في الصفحة - بدون lazy loading مع أولوية عالية */ public static function getCroppedResponsiveImagePriority(?string $pathInput, int $width, int $height): string { $path = static::getSafePath($pathInput); $src = static::generateImageUrl($path, "{$width}x{$height}"); $srcset = collect(static::$srcsetWidths) ->filter(fn($w) => $w >= $width) ->take(2) ->map(fn($w) => route('image', ['path' => $path, 'size' => "{$width}x{$height}"]) . "?width={$w} {$w}w") ->implode(', '); return static::buildImageTag([ 'src' => $src, 'srcset' => $srcset, 'sizes' => '100vw', 'width' => $width, 'height' => $height, 'fetchpriority' => 'high', // أولوية عالية - سيلغي loading=lazy تلقائياً ]); } public static function getMediumResponsiveImagePriority(?string $pathInput, int $width, int $height): string { $path = static::getSafePath($pathInput); // أحجام مناسبة للصور المتوسطة $widths = collect([300, 400, 600, 800]) ->filter(fn($w) => $w >= $width) ->take(3); $src = static::generateImageUrl($path, "{$width}x{$height}"); $srcset = $widths->map(function($w) use ($path, $width, $height) { $scaledHeight = intval(($height * $w) / $width); return route('image', ['path' => $path, 'size' => "{$width}x{$height}"]) . " {$w}w"; })->implode(', '); $sizes = $width <= 300 ? "(max-width: 768px) {$width}px, {$width}px" : "(max-width: 768px) 90vw, {$width}px"; return static::buildImageTag([ 'src' => $src, 'srcset' => $srcset, 'sizes' => $sizes, 'width' => $width, 'height' => $height, 'fetchpriority' => 'high', ]); } public static function highPriority(): string { return "fetchpriority=\"high\""; } /** * للصور الأولى في القائمة - بدون lazy */ public static function getResponsiveImagePriority(?string $pathInput): string { $path = static::getSafePath($pathInput); $src = route('image', ['path' => $path, 'size' => 'original']); $srcset = collect(static::$srcsetWidths) ->map(fn($w) => route('image', ['path' => $path, 'size' => 'original']) . "?width={$w} {$w}w") ->implode(', '); return static::buildImageTag([ 'src' => $src, 'srcset' => $srcset, 'fetchpriority' => 'high', 'style' => 'max-width: 100%' ]); } public static function getLogoImage(?string $pathInput, int $width = 200, int $height = 80): string { $path = static::getSafePath($pathInput); // أحجام مناسبة للوغو $widths = collect([150, 200, 250, 300])->filter(fn($w) => $w >= $width); $src = static::generateImageUrl($path, "{$width}x{$height}"); $srcset = $widths->map(function($w) use ($path, $width, $height) { $scaledHeight = intval(($height * $w) / $width); return static::generateImageUrl($path, "{$width}x{$height}") . " {$w}w"; })->implode(', '); return static::buildImageTag([ 'src' => $src, 'srcset' => $srcset, 'sizes' => "(max-width: 768px) {$width}px, {$width}px", 'width' => $width, 'height' => $height, 'fetchpriority' => 'high', 'alt' => 'Logo' ]); } public static function dimensions(int $w, int $h): string { return "width=\"{$w}\" height=\"{$h}\""; } protected static function getImageWidthFromCache(string $path): ?int { return Cache::rememberForever("image-width-{$path}", function() use ($path) { try { $imagePath = Storage::disk(static::$imageDisk) ->path(static::$imageDirectory . $path); return Image::make($imagePath)->width(); } catch (\Exception $e) { return null; } }); } }