refactor: consolidate ImageHelper resize paths, drop unused validate() (#104)
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || github.ref_name }}) (push) Successful in 12s

- resize() is now a thin wrapper over resizeToSize() (added a $quality param),
  removing ~80 lines of duplicated crop/resample/encode logic. resize(path)
  and resizeToSize(path, 1200, 630, '') produce identical output paths/files,
  so behavior is unchanged.
- Removed the unused ImageHelper::validate() method (no callers).

Net: -130/+11 lines. Closes the remaining #104 consolidation items.
This commit is contained in:
2026-06-29 12:26:13 -05:00
parent fd28cb8a93
commit 236baed80d
@@ -57,96 +57,8 @@ class ImageHelper
int $targetHeight = self::TARGET_HEIGHT,
int $quality = self::JPEG_QUALITY
): string {
// Resolve absolute path
$absPath = JPATH_ROOT . '/' . ltrim($imagePath, '/');
if (!is_file($absPath)) {
return $imagePath;
}
$imageInfo = getimagesize($absPath);
if (!$imageInfo) {
Log::add('MokoOG ImageHelper: Cannot read image dimensions: ' . basename($absPath), Log::WARNING, 'mokoog');
return $imagePath;
}
[$origWidth, $origHeight, $type] = $imageInfo;
// Skip if already at or below target size
if ($origWidth <= $targetWidth && $origHeight <= $targetHeight) {
return $imagePath;
}
// Ensure output directory exists
$outputDir = JPATH_ROOT . '/' . self::OUTPUT_DIR;
if (!is_dir($outputDir) && !Folder::create($outputDir)) {
Log::add('MokoOG ImageHelper: Cannot create output directory: ' . self::OUTPUT_DIR, Log::WARNING, 'mokoog');
return $imagePath;
}
// Generate output filename based on source hash + dimensions
$hash = md5($imagePath . $targetWidth . $targetHeight);
$outputName = $hash . '.jpg';
$outputPath = $outputDir . '/' . $outputName;
$outputRel = self::OUTPUT_DIR . '/' . $outputName;
// Skip if already generated
if (is_file($outputPath) && filemtime($outputPath) >= filemtime($absPath)) {
return $outputRel;
}
// Load source image
$source = self::loadImage($absPath, $type);
if (!$source) {
return $imagePath;
}
// Calculate crop dimensions (center crop to target aspect ratio)
$targetRatio = $targetWidth / $targetHeight;
$sourceRatio = $origWidth / $origHeight;
if ($sourceRatio > $targetRatio) {
// Source is wider — crop sides
$cropHeight = $origHeight;
$cropWidth = (int) round($origHeight * $targetRatio);
$cropX = (int) round(($origWidth - $cropWidth) / 2);
$cropY = 0;
} else {
// Source is taller — crop top/bottom
$cropWidth = $origWidth;
$cropHeight = (int) round($origWidth / $targetRatio);
$cropX = 0;
$cropY = (int) round(($origHeight - $cropHeight) / 2);
}
// Create output canvas and resample
$output = imagecreatetruecolor($targetWidth, $targetHeight);
imagecopyresampled(
$output,
$source,
0,
0,
$cropX,
$cropY,
$targetWidth,
$targetHeight,
$cropWidth,
$cropHeight
);
// Save as JPEG
imagejpeg($output, $outputPath, $quality);
imagedestroy($source);
imagedestroy($output);
return $outputRel;
// Thin wrapper over the shared implementation (no subdirectory).
return self::resizeToSize($imagePath, $targetWidth, $targetHeight, '', $quality);
}
/**
@@ -182,11 +94,17 @@ class ImageHelper
* @param int $width Target width
* @param int $height Target height
* @param string $subdir Subdirectory name for output (e.g. platform name)
* @param int $quality JPEG quality 1-100
*
* @return string Path to the output image (relative to JPATH_ROOT)
*/
private static function resizeToSize(string $imagePath, int $width, int $height, string $subdir = ''): string
{
private static function resizeToSize(
string $imagePath,
int $width,
int $height,
string $subdir = '',
int $quality = self::JPEG_QUALITY
): string {
// Resolve absolute path
$absPath = JPATH_ROOT . '/' . ltrim($imagePath, '/');
@@ -272,7 +190,7 @@ class ImageHelper
);
// Save as JPEG
imagejpeg($output, $outputPath, self::JPEG_QUALITY);
imagejpeg($output, $outputPath, $quality);
imagedestroy($source);
imagedestroy($output);
@@ -333,43 +251,6 @@ class ImageHelper
}
}
/**
* Check if an image meets minimum OG size requirements.
*
* @param string $imagePath Image path relative to JPATH_ROOT
*
* @return array{valid: bool, width: int, height: int, message: string}
*/
public static function validate(string $imagePath): array
{
$absPath = JPATH_ROOT . '/' . ltrim($imagePath, '/');
if (!is_file($absPath)) {
return ['valid' => false, 'width' => 0, 'height' => 0, 'message' => 'File not found'];
}
$imageInfo = getimagesize($absPath);
if (!$imageInfo) {
return ['valid' => false, 'width' => 0, 'height' => 0, 'message' => 'Not a valid image'];
}
[$width, $height] = $imageInfo;
// Facebook minimum: 200x200, recommended: 1200x630
// WhatsApp minimum: 300x200
if ($width < 200 || $height < 200) {
return [
'valid' => false,
'width' => $width,
'height' => $height,
'message' => "Image too small ({$width}x{$height}). Minimum: 200x200px.",
];
}
return ['valid' => true, 'width' => $width, 'height' => $height, 'message' => 'OK'];
}
/**
* Load an image resource from a file.
*