From c4fcb8e686a1e17688d8a685f45a51b510a0dd42 Mon Sep 17 00:00:00 2001 From: Zankaria Date: Tue, 18 Mar 2025 14:25:28 +0100 Subject: [PATCH] GdMediaHandler.php: implement metadata stripping, closeHandle and installMediaAndGenerateThumb --- inc/Service/Media/GdMediaHandler.php | 129 +++++++++++++++++++++------ 1 file changed, 101 insertions(+), 28 deletions(-) diff --git a/inc/Service/Media/GdMediaHandler.php b/inc/Service/Media/GdMediaHandler.php index d67278b9..def6f204 100644 --- a/inc/Service/Media/GdMediaHandler.php +++ b/inc/Service/Media/GdMediaHandler.php @@ -18,6 +18,9 @@ class GdMediaHandler implements MediaHandler { ]; + private bool $strip_redraw; + + private static function imageCreateFrom(string $file, string $mime): mixed { switch ($mime) { case 'image/jpeg': @@ -71,38 +74,16 @@ class GdMediaHandler implements MediaHandler { return $gd; } - public function supportsMime(string $mime): bool { - $info = \gd_info(); - return ($mime === 'image/jpeg' && $info['JPEG Support']) - || ($mime === 'image/png' && $info['PNG Support']) - || ($mime === 'image/gif' && $info['GIF Read Support'] && $info['GIF Create Support']) - || ($mime === 'image/webp' && $info['WebP Support']) - || $mime === 'image/bmp' - || ($mime === 'image/avif' && self::PHP81 && $info['AVIF Support']); - } - - public function openHandle(string $file_path, string $file_mime, int $file_kind): mixed { - $gd = self::imageCreateFrom($file_path, $file_mime); - if ($gd === false) { - throw new \RuntimeException("Could not open '$file_path'"); - } - return [ $gd, $file_path, $file_mime, $file_kind ]; - } - - public function generateThumb( - mixed $handle, + private function generateThumbImpl( + mixed $gd, + string $source_file_path, + string $source_file_mime, + string $source_file_kind, string $preferred_out_file_path, string $preferred_out_mime, int $max_width, int $max_height - ): ThumbGenerationResult { - list($gd, $source_file_path, $source_file_mime, $source_file_kind) = $handle; - - $gd = self::imageCreateFrom($source_file_path, $source_file_mime); - if ($gd === false) { - throw new \RuntimeException("Could not open '$source_file_path'"); - } - + ) { $width = \imagesx($gd); $height = \imagesy($gd); @@ -133,9 +114,12 @@ class GdMediaHandler implements MediaHandler { \imagecopyresampled($gd_other, $gd, 0, 0, 0, 0, $max_width, $max_height, $width, $height); if (!self::imageSaveTo($gd_other, $out_path, $preferred_out_mime)) { + \imagedestroy($gd_other); throw new \RuntimeException("Could not create thumbnail file at '$out_path'"); } + \imagedestroy($gd_other); + return new ThumbGenerationResult( $out_path, $preferred_out_mime, @@ -145,4 +129,93 @@ class GdMediaHandler implements MediaHandler { ); } } + + /** + * @param bool $strip_redraw If the EXIF metadata should be stripped by redrawing it. + */ + public function __construct(bool $strip_redraw) { + $this->strip_redraw = $strip_redraw; + } + + public function supportsMime(string $mime): bool { + $info = \gd_info(); + return ($mime === 'image/jpeg' && $info['JPEG Support']) + || ($mime === 'image/png' && $info['PNG Support']) + || ($mime === 'image/gif' && $info['GIF Read Support'] && $info['GIF Create Support']) + || ($mime === 'image/webp' && $info['WebP Support']) + || $mime === 'image/bmp' + || ($mime === 'image/avif' && self::PHP81 && $info['AVIF Support']); + } + + public function openHandle(string $file_path, string $file_mime, int $file_kind): mixed { + $gd = self::imageCreateFrom($file_path, $file_mime); + if ($gd === false) { + throw new \RuntimeException("Could not open '$file_path'"); + } + return [ $gd, $file_path, $file_mime, $file_kind ]; + } + + public function closeHandle(mixed $handle) { + \imagedestroy($handle[0]); + } + + public function installMediaAndGenerateThumb( + mixed $handle, + string $media_preferred_out_file_path, + string $thumb_preferred_out_file_path, + string $thumb_preferred_out_mime, + int $thumb_max_width, + int $thumb_max_height + ) { + list($gd, $source_file_path, $source_file_mime, $source_file_kind) = $handle; + $out_path = $media_preferred_out_file_path . '.' . self::MIME_TO_EXT[$source_file_mime]; + + if ($this->strip_redraw) { + if (!self::imageSaveTo($gd, $out_path, $source_file_mime)) { + throw new \RuntimeException("Could not create media file at '$out_path'"); + } + } else { + if ($source_file_kind === self::FILE_KIND_UPLOADED) { + if (!Fs\move_or_copy_uploaded($source_file_path, $out_path)) { + throw new \RuntimeException("Could not move or copy uploaded file '$source_file_path' to '$out_path'"); + } + } else { + if (!Fs\link_or_copy($source_file_path, $out_path)) { + throw new \RuntimeException("Could not link or copy '$source_file_path' to '$out_path'"); + } + } + } + + return $this->generateThumbImpl( + $gd, + $source_file_path, + $source_file_mime, + $source_file_kind, + $thumb_preferred_out_file_path, + $thumb_preferred_out_mime, + $thumb_max_width, + $thumb_max_height + ); + } + + public function generateThumb( + mixed $handle, + string $preferred_out_file_path, + string $preferred_out_mime, + int $max_width, + int $max_height + ): ThumbGenerationResult { + list($gd, $source_file_path, $source_file_mime, $source_file_kind) = $handle; + + return $this->generateThumbImpl( + $gd, + $source_file_path, + $source_file_mime, + $source_file_kind, + $preferred_out_file_path, + $preferred_out_mime, + $max_width, + $max_height + ); + } }