From e45a4b536924956e1b20f5d023800557d466eda7 Mon Sep 17 00:00:00 2001 From: Jonathan Reinink Date: Mon, 25 Jan 2016 08:35:12 -0500 Subject: [PATCH 01/23] Add support for Symfony 3.x components. --- composer.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/composer.json b/composer.json index e970ac92..40180825 100644 --- a/composer.json +++ b/composer.json @@ -24,8 +24,8 @@ "php": ">=5.4", "intervention/image": "~2.1", "league/flysystem": "~1.0", - "symfony/http-foundation": "~2.3", - "symfony/http-kernel": "~2.3" + "symfony/http-foundation": "~2.3|~3.0", + "symfony/http-kernel": "~2.3|~3.0" }, "require-dev": { "mockery/mockery": "~0.9", From 0b5a047616e6b0ffb41815b4f7f67e9aabeecd93 Mon Sep 17 00:00:00 2001 From: Thomas Date: Mon, 16 Dec 2024 14:29:42 -0600 Subject: [PATCH 02/23] Encode by media type instead of the extension Fixes animated webp (image/x-webp) --- src/Api/Encoder.php | 63 ++++++++++++++++++++++++++------------------- 1 file changed, 37 insertions(+), 26 deletions(-) diff --git a/src/Api/Encoder.php b/src/Api/Encoder.php index 80aad014..bcead847 100644 --- a/src/Api/Encoder.php +++ b/src/Api/Encoder.php @@ -6,6 +6,7 @@ use Intervention\Image\Interfaces\EncodedImageInterface; use Intervention\Image\Interfaces\ImageInterface; +use Intervention\Image\MediaType; /** * Encoder Api class to convert a given image to a specific format. @@ -60,36 +61,40 @@ public function getParam(string $name): mixed */ public function run(ImageInterface $image): EncodedImageInterface { - $format = $this->getFormat($image); + $mediaType = $this->getMediaType($image); $quality = $this->getQuality(); $shouldInterlace = filter_var($this->getParam('interlace'), FILTER_VALIDATE_BOOLEAN); - if ('pjpg' === $format) { - $shouldInterlace = true; - $format = 'jpg'; - } + $encoderOptions = array_filter([ + 'quality' => $quality, + 'interlaced' => $mediaType === MediaType::IMAGE_PNG ? $shouldInterlace : null, + ]); + + return $image->encodeByMediaType($mediaType, ...$encoderOptions); + } + + public function getMediaType(ImageInterface $image): MediaType + { + $fm = (string) $this->getParam('fm'); - $encoderOptions = []; - switch ($format) { - case 'avif': - case 'heic': - case 'tiff': - case 'webp': - $encoderOptions['quality'] = $quality; - break; - case 'jpg': - $encoderOptions['quality'] = $quality; - $encoderOptions['progressive'] = $shouldInterlace; - break; - case 'gif': - case 'png': - $encoderOptions['interlaced'] = $shouldInterlace; - break; - default: - throw new \Exception("Invalid format provided: {$format}"); + if ($fm && array_key_exists($fm, static::supportedFormats())) { + return match ($fm) { + 'avif' => MediaType::IMAGE_AVIF, + 'gif' => MediaType::IMAGE_GIF, + 'jpg' => MediaType::IMAGE_JPEG, + 'pjpg' => MediaType::IMAGE_PJPEG, + 'png' => MediaType::IMAGE_PNG, + 'webp' => MediaType::IMAGE_WEBP, + 'tiff' => MediaType::IMAGE_TIFF, + 'heic' => MediaType::IMAGE_HEIC, + }; } - return $image->encodeByExtension($format, ...$encoderOptions); + try { + return MediaType::tryFrom($image->origin()->mediaType()); + } catch (\Exception) { + return MediaType::IMAGE_JPEG; + } } /** @@ -107,8 +112,14 @@ public function getFormat(ImageInterface $image): string return $fm; } - /** @psalm-suppress RiskyTruthyFalsyComparison */ - return array_search($image->origin()->mediaType(), static::supportedFormats(), true) ?: 'jpg'; + try { + $format = MediaType::tryFrom($image->origin()->mediaType())->format(); + $extension = $format->fileExtension()->value; + + return isset(static::supportedFormats()[$extension]) ? $extension : 'jpg'; + } catch (\Exception) { + return 'jpg'; + } } /** From 03de2859eed0896e06d73b6d2914e3c10c61fc4d Mon Sep 17 00:00:00 2001 From: Thomas Date: Mon, 16 Dec 2024 14:42:14 -0600 Subject: [PATCH 03/23] fixed tests --- tests/Api/ApiTest.php | 5 +++++ tests/Api/EncoderTest.php | 11 +++++++++++ 2 files changed, 16 insertions(+) diff --git a/tests/Api/ApiTest.php b/tests/Api/ApiTest.php index b102b6cc..87093841 100644 --- a/tests/Api/ApiTest.php +++ b/tests/Api/ApiTest.php @@ -7,6 +7,7 @@ use Intervention\Image\ImageManager; use Intervention\Image\Interfaces\EncodedImageInterface; use Intervention\Image\Interfaces\ImageInterface; +use Intervention\Image\MediaType; use League\Glide\Manipulators\ManipulatorInterface; use PHPUnit\Framework\TestCase; @@ -70,6 +71,10 @@ public function testRun() $mock->shouldReceive('encodeByExtension')->with('png')->andReturn(\Mockery::mock(EncodedImageInterface::class, function ($mock) { $mock->shouldReceive('toString')->andReturn('encoded'); })); + + $mock->shouldReceive('encodeByMediaType')->with(MediaType::IMAGE_PNG)->andReturn(\Mockery::mock(EncodedImageInterface::class, function ($mock) { + $mock->shouldReceive('toString')->andReturn('encoded'); + })); }); $manager = ImageManager::gd(); diff --git a/tests/Api/EncoderTest.php b/tests/Api/EncoderTest.php index 6a4723a9..3de268c3 100644 --- a/tests/Api/EncoderTest.php +++ b/tests/Api/EncoderTest.php @@ -19,6 +19,7 @@ class EncoderTest extends TestCase private ImageInterface $gif; private ImageInterface $tif; private ImageInterface $webp; + private ImageInterface $webpx; private ImageInterface $avif; private ImageInterface $heic; @@ -39,6 +40,9 @@ public function setUp(): void $this->webp = $manager->read( $manager->create(100, 100)->encode(new MediaTypeEncoder('image/webp'))->toFilePointer() ); + $this->webpx = $manager->read( + $manager->create(100, 100)->encode(new MediaTypeEncoder('image/x-webp'))->toFilePointer() + ); } if (function_exists('imagecreatefromavif')) { @@ -87,6 +91,12 @@ public function testRun(): void $this->assertSame('image/webp', $this->getMime($this->encoder->setParams(['fm' => 'webp'])->run($this->png))); $this->assertSame('image/webp', $this->getMime($this->encoder->setParams(['fm' => 'webp'])->run($this->gif))); $this->assertSame('image/webp', $this->getMime($this->encoder->setParams(['fm' => 'webp'])->run($this->webp))); + + $this->assertSame('image/jpeg', $this->getMime($this->encoder->setParams(['fm' => 'jpg'])->run($this->webpx))); + $this->assertSame('image/jpeg', $this->getMime($this->encoder->setParams(['fm' => 'pjpg'])->run($this->webpx))); + $this->assertSame('image/png', $this->getMime($this->encoder->setParams(['fm' => 'png'])->run($this->webpx))); + $this->assertSame('image/gif', $this->getMime($this->encoder->setParams(['fm' => 'gif'])->run($this->webpx))); + $this->assertSame('image/webp', $this->getMime($this->encoder->setParams(['fm' => 'webp'])->run($this->webpx))); } if (function_exists('imagecreatefromavif')) { $this->assertSame('image/jpeg', $this->getMime($this->encoder->setParams(['fm' => 'jpg'])->run($this->avif))); @@ -102,6 +112,7 @@ public function testRun(): void if (function_exists('imagecreatefromwebp') && function_exists('imagecreatefromavif')) { $this->assertSame('image/webp', $this->getMime($this->encoder->setParams(['fm' => 'webp'])->run($this->avif))); $this->assertSame('image/avif', $this->getMime($this->encoder->setParams(['fm' => 'avif'])->run($this->webp))); + $this->assertSame('image/avif', $this->getMime($this->encoder->setParams(['fm' => 'avif'])->run($this->webpx))); } } From 4d00add8a12e11205317e0dd7fa554d85b8ccfcb Mon Sep 17 00:00:00 2001 From: Thomas Date: Mon, 16 Dec 2024 15:22:40 -0600 Subject: [PATCH 04/23] fixed tests --- src/Api/Encoder.php | 44 +++++++++++++-------------------------- tests/Api/EncoderTest.php | 19 ++++++++++------- 2 files changed, 26 insertions(+), 37 deletions(-) diff --git a/src/Api/Encoder.php b/src/Api/Encoder.php index bcead847..ea018503 100644 --- a/src/Api/Encoder.php +++ b/src/Api/Encoder.php @@ -4,6 +4,7 @@ namespace League\Glide\Api; +use Intervention\Image\Format; use Intervention\Image\Interfaces\EncodedImageInterface; use Intervention\Image\Interfaces\ImageInterface; use Intervention\Image\MediaType; @@ -77,17 +78,8 @@ public function getMediaType(ImageInterface $image): MediaType { $fm = (string) $this->getParam('fm'); - if ($fm && array_key_exists($fm, static::supportedFormats())) { - return match ($fm) { - 'avif' => MediaType::IMAGE_AVIF, - 'gif' => MediaType::IMAGE_GIF, - 'jpg' => MediaType::IMAGE_JPEG, - 'pjpg' => MediaType::IMAGE_PJPEG, - 'png' => MediaType::IMAGE_PNG, - 'webp' => MediaType::IMAGE_WEBP, - 'tiff' => MediaType::IMAGE_TIFF, - 'heic' => MediaType::IMAGE_HEIC, - }; + if ($fm !== '') { + return self::supportedFormats()[$fm] ?? throw new \Exception("Invalid format provided: {$fm}"); } try { @@ -106,17 +98,10 @@ public function getMediaType(ImageInterface $image): MediaType */ public function getFormat(ImageInterface $image): string { - $fm = (string) $this->getParam('fm'); - - if ($fm && array_key_exists($fm, static::supportedFormats())) { - return $fm; - } - try { - $format = MediaType::tryFrom($image->origin()->mediaType())->format(); - $extension = $format->fileExtension()->value; + $mediaType = $this->getMediaType($image); - return isset(static::supportedFormats()[$extension]) ? $extension : 'jpg'; + return $mediaType->format()->fileExtension()->value; } catch (\Exception) { return 'jpg'; } @@ -125,19 +110,20 @@ public function getFormat(ImageInterface $image): string /** * Get a list of supported image formats and MIME types. * - * @return array + * @return array */ public static function supportedFormats(): array { return [ - 'avif' => 'image/avif', - 'gif' => 'image/gif', - 'jpg' => 'image/jpeg', - 'pjpg' => 'image/jpeg', - 'png' => 'image/png', - 'webp' => 'image/webp', - 'tiff' => 'image/tiff', - 'heic' => 'image/heic', + 'avif' => MediaType::IMAGE_AVIF, + 'bpm' => MediaType::IMAGE_BMP, + 'gif' => MediaType::IMAGE_GIF, + 'heic' => MediaType::IMAGE_HEIC, + 'jpg' => MediaType::IMAGE_JPEG, + 'pjpg' => MediaType::IMAGE_PJPEG, + 'png' => MediaType::IMAGE_PNG, + 'tiff' => MediaType::IMAGE_TIFF, + 'webp' => MediaType::IMAGE_WEBP, ]; } diff --git a/tests/Api/EncoderTest.php b/tests/Api/EncoderTest.php index 3de268c3..26ee383a 100644 --- a/tests/Api/EncoderTest.php +++ b/tests/Api/EncoderTest.php @@ -8,6 +8,7 @@ use Intervention\Image\ImageManager; use Intervention\Image\Interfaces\EncodedImageInterface; use Intervention\Image\Interfaces\ImageInterface; +use Intervention\Image\MediaType; use Mockery; use PHPUnit\Framework\TestCase; @@ -146,6 +147,7 @@ public function testGetFormat(): void $this->assertSame('jpg', $this->encoder->setParams(['fm' => null])->getFormat($image)); $this->assertSame('png', $this->encoder->setParams(['fm' => null])->getFormat($image)); $this->assertSame('gif', $this->encoder->setParams(['fm' => null])->getFormat($image)); + $this->assertSame('bmp', $this->encoder->setParams(['fm' => null])->getFormat($image)); $this->assertSame('jpg', $this->encoder->setParams(['fm' => null])->getFormat($image)); $this->assertSame('jpg', $this->encoder->setParams(['fm' => ''])->getFormat($image)); @@ -198,14 +200,15 @@ public function testWithImagick(): void public function testSupportedFormats(): void { $expected = [ - 'avif' => 'image/avif', - 'gif' => 'image/gif', - 'jpg' => 'image/jpeg', - 'pjpg' => 'image/jpeg', - 'png' => 'image/png', - 'webp' => 'image/webp', - 'tiff' => 'image/tiff', - 'heic' => 'image/heic', + 'avif' => MediaType::IMAGE_AVIF, + 'bpm' => MediaType::IMAGE_BMP, + 'gif' => MediaType::IMAGE_GIF, + 'heic' => MediaType::IMAGE_HEIC, + 'jpg' => MediaType::IMAGE_JPEG, + 'pjpg' => MediaType::IMAGE_PJPEG, + 'png' => MediaType::IMAGE_PNG, + 'tiff' => MediaType::IMAGE_TIFF, + 'webp' => MediaType::IMAGE_WEBP, ]; $this->assertSame($expected, Encoder::supportedFormats()); From 49212dc2034d645bcd15051a1db9e580126c7085 Mon Sep 17 00:00:00 2001 From: Thomas Date: Mon, 16 Dec 2024 15:30:33 -0600 Subject: [PATCH 05/23] check format is available --- src/Api/Encoder.php | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/src/Api/Encoder.php b/src/Api/Encoder.php index ea018503..231fb0d3 100644 --- a/src/Api/Encoder.php +++ b/src/Api/Encoder.php @@ -79,14 +79,16 @@ public function getMediaType(ImageInterface $image): MediaType $fm = (string) $this->getParam('fm'); if ($fm !== '') { - return self::supportedFormats()[$fm] ?? throw new \Exception("Invalid format provided: {$fm}"); + $mediaType = self::supportedFormats()[$fm] ?? throw new \Exception("Invalid format provided: {$fm}"); + } else { + try { + $mediaType = MediaType::tryFrom($image->origin()->mediaType()); + } catch (\Exception) { + $mediaType = MediaType::IMAGE_JPEG; + } } - try { - return MediaType::tryFrom($image->origin()->mediaType()); - } catch (\Exception) { - return MediaType::IMAGE_JPEG; - } + return $image->driver()->supports($mediaType) ? $mediaType : throw new \Exception("Unsupported format: {$mediaType->value}"); } /** @@ -116,7 +118,7 @@ public static function supportedFormats(): array { return [ 'avif' => MediaType::IMAGE_AVIF, - 'bpm' => MediaType::IMAGE_BMP, + 'bmp' => MediaType::IMAGE_BMP, 'gif' => MediaType::IMAGE_GIF, 'heic' => MediaType::IMAGE_HEIC, 'jpg' => MediaType::IMAGE_JPEG, From a75bf9b00f04223c843ed45ee72118817bb16cb6 Mon Sep 17 00:00:00 2001 From: Thomas Date: Mon, 16 Dec 2024 16:03:52 -0600 Subject: [PATCH 06/23] style fix --- src/Api/Encoder.php | 4 ++-- tests/Api/EncoderTest.php | 15 +++++++++------ 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/src/Api/Encoder.php b/src/Api/Encoder.php index 231fb0d3..075fcd11 100644 --- a/src/Api/Encoder.php +++ b/src/Api/Encoder.php @@ -68,7 +68,7 @@ public function run(ImageInterface $image): EncodedImageInterface $encoderOptions = array_filter([ 'quality' => $quality, - 'interlaced' => $mediaType === MediaType::IMAGE_PNG ? $shouldInterlace : null, + 'interlaced' => MediaType::IMAGE_PNG === $mediaType ? $shouldInterlace : null, ]); return $image->encodeByMediaType($mediaType, ...$encoderOptions); @@ -78,7 +78,7 @@ public function getMediaType(ImageInterface $image): MediaType { $fm = (string) $this->getParam('fm'); - if ($fm !== '') { + if ('' !== $fm) { $mediaType = self::supportedFormats()[$fm] ?? throw new \Exception("Invalid format provided: {$fm}"); } else { try { diff --git a/tests/Api/EncoderTest.php b/tests/Api/EncoderTest.php index 26ee383a..8a452199 100644 --- a/tests/Api/EncoderTest.php +++ b/tests/Api/EncoderTest.php @@ -6,9 +6,11 @@ use Intervention\Image\Encoders\MediaTypeEncoder; use Intervention\Image\ImageManager; +use Intervention\Image\Interfaces\DriverInterface; use Intervention\Image\Interfaces\EncodedImageInterface; use Intervention\Image\Interfaces\ImageInterface; use Intervention\Image\MediaType; +use Intervention\Image\Origin; use Mockery; use PHPUnit\Framework\TestCase; @@ -147,7 +149,6 @@ public function testGetFormat(): void $this->assertSame('jpg', $this->encoder->setParams(['fm' => null])->getFormat($image)); $this->assertSame('png', $this->encoder->setParams(['fm' => null])->getFormat($image)); $this->assertSame('gif', $this->encoder->setParams(['fm' => null])->getFormat($image)); - $this->assertSame('bmp', $this->encoder->setParams(['fm' => null])->getFormat($image)); $this->assertSame('jpg', $this->encoder->setParams(['fm' => null])->getFormat($image)); $this->assertSame('jpg', $this->encoder->setParams(['fm' => ''])->getFormat($image)); @@ -201,7 +202,7 @@ public function testSupportedFormats(): void { $expected = [ 'avif' => MediaType::IMAGE_AVIF, - 'bpm' => MediaType::IMAGE_BMP, + 'bmp' => MediaType::IMAGE_BMP, 'gif' => MediaType::IMAGE_GIF, 'heic' => MediaType::IMAGE_HEIC, 'jpg' => MediaType::IMAGE_JPEG, @@ -229,12 +230,14 @@ protected function getMime(EncodedImageInterface $image): string */ protected function assertMediaType($mock, $mediaType): Mockery\CompositeExpectation { - /* - * @var Mock $mock - */ /** * @psalm-suppress LessSpecificReturnStatement, UndefinedMagicMethod */ - return $mock->shouldReceive('origin')->andReturn(\Mockery::mock('Intervention\Image\Origin', ['mediaType' => $mediaType])); + return $mock->shouldReceive('origin') + ->andReturn(\Mockery::mock(Origin::class, ['mediaType' => $mediaType])) + ->shouldReceive('driver') + ->andReturn(\Mockery::mock(DriverInterface::class , function ($mock) { + $mock->shouldReceive('supports'); + })); } } From 6754ae50bd8e5f30d026fc68d9f822404470dd1b Mon Sep 17 00:00:00 2001 From: Thomas Date: Mon, 16 Dec 2024 16:08:01 -0600 Subject: [PATCH 07/23] fixed mock --- tests/Api/ApiTest.php | 8 +++++++- tests/Api/EncoderTest.php | 2 +- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/tests/Api/ApiTest.php b/tests/Api/ApiTest.php index 87093841..bfe4e434 100644 --- a/tests/Api/ApiTest.php +++ b/tests/Api/ApiTest.php @@ -5,9 +5,11 @@ namespace League\Glide\Api; use Intervention\Image\ImageManager; +use Intervention\Image\Interfaces\DriverInterface; use Intervention\Image\Interfaces\EncodedImageInterface; use Intervention\Image\Interfaces\ImageInterface; use Intervention\Image\MediaType; +use Intervention\Image\Origin; use League\Glide\Manipulators\ManipulatorInterface; use PHPUnit\Framework\TestCase; @@ -64,7 +66,7 @@ public function testGetManipulators() public function testRun() { $image = \Mockery::mock(ImageInterface::class, function ($mock) { - $mock->shouldReceive('origin')->andReturn(\Mockery::mock('\Intervention\Image\Origin', function ($mock) { + $mock->shouldReceive('origin')->andReturn(\Mockery::mock(Origin::class, function ($mock) { $mock->shouldReceive('mediaType')->andReturn('image/png'); })); @@ -75,6 +77,10 @@ public function testRun() $mock->shouldReceive('encodeByMediaType')->with(MediaType::IMAGE_PNG)->andReturn(\Mockery::mock(EncodedImageInterface::class, function ($mock) { $mock->shouldReceive('toString')->andReturn('encoded'); })); + + $mock->shouldReceive('driver')->andReturn(\Mockery::mock(DriverInterface::class, function ($mock) { + $mock->shouldReceive('supports'); + })); }); $manager = ImageManager::gd(); diff --git a/tests/Api/EncoderTest.php b/tests/Api/EncoderTest.php index 8a452199..046c890c 100644 --- a/tests/Api/EncoderTest.php +++ b/tests/Api/EncoderTest.php @@ -236,7 +236,7 @@ protected function assertMediaType($mock, $mediaType): Mockery\CompositeExpectat return $mock->shouldReceive('origin') ->andReturn(\Mockery::mock(Origin::class, ['mediaType' => $mediaType])) ->shouldReceive('driver') - ->andReturn(\Mockery::mock(DriverInterface::class , function ($mock) { + ->andReturn(\Mockery::mock(DriverInterface::class, function ($mock) { $mock->shouldReceive('supports'); })); } From 856843f9ac4d90cb45e9989c9b2a8d791afe40bc Mon Sep 17 00:00:00 2001 From: Thomas Date: Mon, 16 Dec 2024 18:07:47 -0600 Subject: [PATCH 08/23] fixed tests --- src/Api/Encoder.php | 17 ++++++------- tests/Api/EncoderTest.php | 53 ++++++++++++++++----------------------- 2 files changed, 29 insertions(+), 41 deletions(-) diff --git a/src/Api/Encoder.php b/src/Api/Encoder.php index 075fcd11..cb1ebacb 100644 --- a/src/Api/Encoder.php +++ b/src/Api/Encoder.php @@ -79,16 +79,14 @@ public function getMediaType(ImageInterface $image): MediaType $fm = (string) $this->getParam('fm'); if ('' !== $fm) { - $mediaType = self::supportedFormats()[$fm] ?? throw new \Exception("Invalid format provided: {$fm}"); - } else { - try { - $mediaType = MediaType::tryFrom($image->origin()->mediaType()); - } catch (\Exception) { - $mediaType = MediaType::IMAGE_JPEG; - } + return self::supportedFormats()[$fm] ?? throw new \Exception("Invalid format provided: {$fm}"); } - return $image->driver()->supports($mediaType) ? $mediaType : throw new \Exception("Unsupported format: {$mediaType->value}"); + try { + return MediaType::tryFrom($image->origin()->mediaType()); + } catch (\Exception) { + return MediaType::IMAGE_JPEG; + } } /** @@ -104,7 +102,8 @@ public function getFormat(ImageInterface $image): string $mediaType = $this->getMediaType($image); return $mediaType->format()->fileExtension()->value; - } catch (\Exception) { + } catch (\Exception $e) { + var_dump($e->getMessage()); return 'jpg'; } } diff --git a/tests/Api/EncoderTest.php b/tests/Api/EncoderTest.php index 046c890c..ab03b1b5 100644 --- a/tests/Api/EncoderTest.php +++ b/tests/Api/EncoderTest.php @@ -121,48 +121,37 @@ public function testRun(): void public function testGetFormat(): void { - /** - * @psalm-suppress MissingClosureParamType - */ - $image = \Mockery::mock(ImageInterface::class, function ($mock) { - /* - * @var Mock $mock - */ - $this->assertMediaType($mock, 'image/jpeg')->once(); - $this->assertMediaType($mock, 'image/png')->once(); - $this->assertMediaType($mock, 'image/gif')->once(); - $this->assertMediaType($mock, 'image/bmp')->once(); - $this->assertMediaType($mock, 'image/jpeg')->twice(); - - if (function_exists('imagecreatefromwebp')) { - $this->assertMediaType($mock, 'image/webp')->once(); - } - - if (function_exists('imagecreatefromavif')) { - $this->assertMediaType($mock, 'image/avif')->once(); - } - }); + $this->assertSame('jpg', $this->encoder->setParams(['fm' => 'jpg'])->getFormat($this->getImageByMimeType('image/jpeg'))); + $this->assertSame('png', $this->encoder->setParams(['fm' => 'png'])->getFormat($this->getImageByMimeType('image/png'))); + $this->assertSame('gif', $this->encoder->setParams(['fm' => 'gif'])->getFormat($this->getImageByMimeType('image/gif'))); + $this->assertSame('bmp', $this->encoder->setParams(['fm' => 'bmp'])->getFormat($this->getImageByMimeType('image/bmp'))); - $this->assertSame('jpg', $this->encoder->setParams(['fm' => 'jpg'])->getFormat($image)); - $this->assertSame('png', $this->encoder->setParams(['fm' => 'png'])->getFormat($image)); - $this->assertSame('gif', $this->encoder->setParams(['fm' => 'gif'])->getFormat($image)); - $this->assertSame('jpg', $this->encoder->setParams(['fm' => null])->getFormat($image)); - $this->assertSame('png', $this->encoder->setParams(['fm' => null])->getFormat($image)); - $this->assertSame('gif', $this->encoder->setParams(['fm' => null])->getFormat($image)); - $this->assertSame('jpg', $this->encoder->setParams(['fm' => null])->getFormat($image)); + // Make sure we keep the current format if no format is provided + $this->assertSame('jpg', $this->encoder->setParams(['fm' => null])->getFormat($this->getImageByMimeType('image/jpeg'))); + $this->assertSame('png', $this->encoder->setParams(['fm' => null])->getFormat($this->getImageByMimeType('image/png'))); + $this->assertSame('gif', $this->encoder->setParams(['fm' => null])->getFormat($this->getImageByMimeType('image/gif'))); + $this->assertSame('bmp', $this->encoder->setParams(['fm' => null])->getFormat($this->getImageByMimeType('image/bmp'))); - $this->assertSame('jpg', $this->encoder->setParams(['fm' => ''])->getFormat($image)); - $this->assertSame('jpg', $this->encoder->setParams(['fm' => 'invalid'])->getFormat($image)); + $this->assertSame('jpg', $this->encoder->setParams(['fm' => ''])->getFormat($this->getImageByMimeType('image/jpeg'))); + $this->assertSame('png', $this->encoder->setParams(['fm' => ''])->getFormat($this->getImageByMimeType('image/png'))); + $this->assertSame('jpg', $this->encoder->setParams(['fm' => 'invalid'])->getFormat($this->getImageByMimeType('image/jpeg'))); if (function_exists('imagecreatefromwebp')) { - $this->assertSame('webp', $this->encoder->setParams(['fm' => null])->getFormat($image)); + $this->assertSame('webp', $this->encoder->setParams(['fm' => null])->getFormat($this->getImageByMimeType('image/webp'))); } if (function_exists('imagecreatefromavif')) { - $this->assertSame('avif', $this->encoder->setParams(['fm' => null])->getFormat($image)); + $this->assertSame('avif', $this->encoder->setParams(['fm' => null])->getFormat($this->getImageByMimeType('image/avif'))); } } + protected function getImageByMimeType(string $mimeType): ImageInterface + { + return \Mockery::mock(ImageInterface::class, function ($mock) use ($mimeType) { + $this->assertMediaType($mock, $mimeType); + }); + } + public function testGetQuality(): void { $this->assertSame(100, $this->encoder->setParams(['q' => '100'])->getQuality()); From 6a465c6552078d3b5b3afc301b138f5acffd4ad9 Mon Sep 17 00:00:00 2001 From: Thomas Date: Mon, 16 Dec 2024 18:08:36 -0600 Subject: [PATCH 09/23] removed debug --- src/Api/Encoder.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/Api/Encoder.php b/src/Api/Encoder.php index cb1ebacb..303e9040 100644 --- a/src/Api/Encoder.php +++ b/src/Api/Encoder.php @@ -102,8 +102,7 @@ public function getFormat(ImageInterface $image): string $mediaType = $this->getMediaType($image); return $mediaType->format()->fileExtension()->value; - } catch (\Exception $e) { - var_dump($e->getMessage()); + } catch (\Exception) { return 'jpg'; } } From 6d6897741a5893c502c6c6ce720437f6404a424f Mon Sep 17 00:00:00 2001 From: Thomas Date: Mon, 16 Dec 2024 18:29:16 -0600 Subject: [PATCH 10/23] use encoder from MediaType --- src/Api/Encoder.php | 21 ++++++++++++--------- tests/Api/ApiTest.php | 10 +++------- 2 files changed, 15 insertions(+), 16 deletions(-) diff --git a/src/Api/Encoder.php b/src/Api/Encoder.php index 303e9040..b91a3323 100644 --- a/src/Api/Encoder.php +++ b/src/Api/Encoder.php @@ -63,15 +63,18 @@ public function getParam(string $name): mixed public function run(ImageInterface $image): EncodedImageInterface { $mediaType = $this->getMediaType($image); - $quality = $this->getQuality(); - $shouldInterlace = filter_var($this->getParam('interlace'), FILTER_VALIDATE_BOOLEAN); - $encoderOptions = array_filter([ - 'quality' => $quality, - 'interlaced' => MediaType::IMAGE_PNG === $mediaType ? $shouldInterlace : null, - ]); + $encoderOptions = [ + 'shouldInterlace' => filter_var($this->getParam('interlace'), FILTER_VALIDATE_BOOLEAN), + 'quality' => $this->getQuality(), + 'progressive' => null, + ]; + + if (MediaType::IMAGE_PJPEG === $mediaType) { + $encoderOptions['progressive'] = true; + } - return $image->encodeByMediaType($mediaType, ...$encoderOptions); + return $mediaType->format()->encoder(...array_filter($encoderOptions))->encode($image); } public function getMediaType(ImageInterface $image): MediaType @@ -83,8 +86,8 @@ public function getMediaType(ImageInterface $image): MediaType } try { - return MediaType::tryFrom($image->origin()->mediaType()); - } catch (\Exception) { + return MediaType::from($image->origin()->mediaType()); + } catch (\ValueError) { return MediaType::IMAGE_JPEG; } } diff --git a/tests/Api/ApiTest.php b/tests/Api/ApiTest.php index bfe4e434..47f1aa89 100644 --- a/tests/Api/ApiTest.php +++ b/tests/Api/ApiTest.php @@ -70,17 +70,13 @@ public function testRun() $mock->shouldReceive('mediaType')->andReturn('image/png'); })); - $mock->shouldReceive('encodeByExtension')->with('png')->andReturn(\Mockery::mock(EncodedImageInterface::class, function ($mock) { - $mock->shouldReceive('toString')->andReturn('encoded'); + $mock->shouldReceive('driver')->andReturn(\Mockery::mock(DriverInterface::class, function ($mock) { + $mock->shouldReceive('supports'); })); - $mock->shouldReceive('encodeByMediaType')->with(MediaType::IMAGE_PNG)->andReturn(\Mockery::mock(EncodedImageInterface::class, function ($mock) { + $mock->shouldReceive('encode')->andReturn(\Mockery::mock(EncodedImageInterface::class, function ($mock) { $mock->shouldReceive('toString')->andReturn('encoded'); })); - - $mock->shouldReceive('driver')->andReturn(\Mockery::mock(DriverInterface::class, function ($mock) { - $mock->shouldReceive('supports'); - })); }); $manager = ImageManager::gd(); From 81106cf35b77fd17e24949176735e77248168c1c Mon Sep 17 00:00:00 2001 From: Thomas Date: Mon, 16 Dec 2024 18:38:09 -0600 Subject: [PATCH 11/23] fixed style --- composer.json | 2 +- src/Api/Encoder.php | 25 ++++++++++++++++++------- tests/Api/ApiTest.php | 1 - 3 files changed, 19 insertions(+), 9 deletions(-) diff --git a/composer.json b/composer.json index a10af1cd..7d22d307 100644 --- a/composer.json +++ b/composer.json @@ -17,7 +17,7 @@ { "name": "Jonathan Reinink", "email": "jonathan@reinink.ca", - "homepage": "http://reinink.ca" + "homepage": "https://reinink.ca/" }, { "name": "Titouan Galopin", diff --git a/src/Api/Encoder.php b/src/Api/Encoder.php index b91a3323..13bce032 100644 --- a/src/Api/Encoder.php +++ b/src/Api/Encoder.php @@ -4,7 +4,6 @@ namespace League\Glide\Api; -use Intervention\Image\Format; use Intervention\Image\Interfaces\EncodedImageInterface; use Intervention\Image\Interfaces\ImageInterface; use Intervention\Image\MediaType; @@ -64,19 +63,31 @@ public function run(ImageInterface $image): EncodedImageInterface { $mediaType = $this->getMediaType($image); - $encoderOptions = [ - 'shouldInterlace' => filter_var($this->getParam('interlace'), FILTER_VALIDATE_BOOLEAN), - 'quality' => $this->getQuality(), - 'progressive' => null, - ]; - if (MediaType::IMAGE_PJPEG === $mediaType) { $encoderOptions['progressive'] = true; } + if ( + MediaType::IMAGE_PNG !== $mediaType + || MediaType::IMAGE_GIF !== $mediaType + ) { + $encoderOptions['quality'] = $this->getQuality(); + } else { + $encoderOptions['interlaced'] = filter_var($this->getParam('interlace'), FILTER_VALIDATE_BOOLEAN); + } + return $mediaType->format()->encoder(...array_filter($encoderOptions))->encode($image); } + /** + * Resolve media type. + * + * @param ImageInterface $image + * + * @throws \Exception + * + * @return MediaType + */ public function getMediaType(ImageInterface $image): MediaType { $fm = (string) $this->getParam('fm'); diff --git a/tests/Api/ApiTest.php b/tests/Api/ApiTest.php index 47f1aa89..be06f9a1 100644 --- a/tests/Api/ApiTest.php +++ b/tests/Api/ApiTest.php @@ -8,7 +8,6 @@ use Intervention\Image\Interfaces\DriverInterface; use Intervention\Image\Interfaces\EncodedImageInterface; use Intervention\Image\Interfaces\ImageInterface; -use Intervention\Image\MediaType; use Intervention\Image\Origin; use League\Glide\Manipulators\ManipulatorInterface; use PHPUnit\Framework\TestCase; From 2f927a3162195b821f027ab4ffbc89f112566224 Mon Sep 17 00:00:00 2001 From: Thomas Date: Mon, 16 Dec 2024 18:47:10 -0600 Subject: [PATCH 12/23] check valid encoder parameters --- src/Api/Encoder.php | 49 ++++++++++++++++++++++++++++++++++++--------- 1 file changed, 39 insertions(+), 10 deletions(-) diff --git a/src/Api/Encoder.php b/src/Api/Encoder.php index 13bce032..72abc0b3 100644 --- a/src/Api/Encoder.php +++ b/src/Api/Encoder.php @@ -4,6 +4,7 @@ namespace League\Glide\Api; +use Intervention\Image\Format; use Intervention\Image\Interfaces\EncodedImageInterface; use Intervention\Image\Interfaces\ImageInterface; use Intervention\Image\MediaType; @@ -61,18 +62,18 @@ public function getParam(string $name): mixed */ public function run(ImageInterface $image): EncodedImageInterface { - $mediaType = $this->getMediaType($image); + $encoderOptions = []; + $mediaType = $this->getMediaType($image); if (MediaType::IMAGE_PJPEG === $mediaType) { $encoderOptions['progressive'] = true; } - if ( - MediaType::IMAGE_PNG !== $mediaType - || MediaType::IMAGE_GIF !== $mediaType - ) { + if ($this->allowsQuality($mediaType)) { $encoderOptions['quality'] = $this->getQuality(); - } else { + } + + if ($this->allowsInterlaced($mediaType)) { $encoderOptions['interlaced'] = filter_var($this->getParam('interlace'), FILTER_VALIDATE_BOOLEAN); } @@ -82,11 +83,7 @@ public function run(ImageInterface $image): EncodedImageInterface /** * Resolve media type. * - * @param ImageInterface $image - * * @throws \Exception - * - * @return MediaType */ public function getMediaType(ImageInterface $image): MediaType { @@ -141,6 +138,38 @@ public static function supportedFormats(): array ]; } + /** + * Checks if we can pass the quality parameter to the encoder. + */ + public function allowsQuality(MediaType $mediaType): bool + { + return !in_array($mediaType, [ + MediaType::IMAGE_GIF, + MediaType::IMAGE_PNG, + MediaType::IMAGE_X_PNG, + MediaType::IMAGE_BMP, + MediaType::IMAGE_MS_BMP, + MediaType::IMAGE_X_BITMAP, + MediaType::IMAGE_X_BMP, + MediaType::IMAGE_X_MS_BMP, + MediaType::IMAGE_X_XBITMAP, + MediaType::IMAGE_X_WINDOWS_BMP, + MediaType::IMAGE_X_WIN_BITMAP, + ]); + } + + /** + * hecks if we can pass the interlaced parameter to the encoder. + */ + public function allowsInterlaced(MediaType $mediaType): bool + { + return in_array($mediaType, [ + MediaType::IMAGE_PNG, + MediaType::IMAGE_X_PNG, + MediaType::IMAGE_GIF, + ]); + } + /** * Resolve quality. * From 94a85c9e06f8e879cff7db4364def43eadf3e23a Mon Sep 17 00:00:00 2001 From: Thomas Date: Mon, 16 Dec 2024 18:57:31 -0600 Subject: [PATCH 13/23] remove method not available with 8.1 --- src/Api/Encoder.php | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/Api/Encoder.php b/src/Api/Encoder.php index 72abc0b3..73d71027 100644 --- a/src/Api/Encoder.php +++ b/src/Api/Encoder.php @@ -63,7 +63,7 @@ public function getParam(string $name): mixed public function run(ImageInterface $image): EncodedImageInterface { $encoderOptions = []; - $mediaType = $this->getMediaType($image); + $mediaType = $this->getMediaType($image); if (MediaType::IMAGE_PJPEG === $mediaType) { $encoderOptions['progressive'] = true; @@ -110,9 +110,10 @@ public function getMediaType(ImageInterface $image): MediaType public function getFormat(ImageInterface $image): string { try { - $mediaType = $this->getMediaType($image); + $mediaType = $this->getMediaType($image); + $extensions = $mediaType->format()->fileExtensions(); - return $mediaType->format()->fileExtension()->value; + return reset($extensions)->value; } catch (\Exception) { return 'jpg'; } From 61cbfa6a8fa939b0f20a1156688b55eb7e4b9b2f Mon Sep 17 00:00:00 2001 From: Thomas Date: Mon, 16 Dec 2024 19:11:16 -0600 Subject: [PATCH 14/23] phpstan fixes --- src/Api/Api.php | 12 +++--------- src/Api/Encoder.php | 5 +++-- src/ServerFactory.php | 3 ++- 3 files changed, 8 insertions(+), 12 deletions(-) diff --git a/src/Api/Api.php b/src/Api/Api.php index d66a42ee..63d7864f 100644 --- a/src/Api/Api.php +++ b/src/Api/Api.php @@ -27,7 +27,7 @@ class Api implements ApiInterface * Create API instance. * * @param ImageManager $imageManager Intervention image manager. - * @param array $manipulators Collection of manipulators. + * @param list $manipulators Collection of manipulators. */ public function __construct(ImageManager $imageManager, array $manipulators) { @@ -58,17 +58,11 @@ public function getImageManager(): ImageManager /** * Set the manipulators. * - * @param ManipulatorInterface[] $manipulators Collection of manipulators. + * @param list $manipulators Collection of manipulators. */ public function setManipulators(array $manipulators): void { - foreach ($manipulators as $manipulator) { - if (!($manipulator instanceof ManipulatorInterface)) { - throw new \InvalidArgumentException('Not a valid manipulator.'); - } - } - - $this->manipulators = $manipulators; + $this->manipulators = array_filter($manipulators, fn ($manipulator) => $manipulator instanceof ManipulatorInterface); } /** diff --git a/src/Api/Encoder.php b/src/Api/Encoder.php index 73d71027..fd797fad 100644 --- a/src/Api/Encoder.php +++ b/src/Api/Encoder.php @@ -4,6 +4,7 @@ namespace League\Glide\Api; +use Intervention\Image\FileExtension; use Intervention\Image\Format; use Intervention\Image\Interfaces\EncodedImageInterface; use Intervention\Image\Interfaces\ImageInterface; @@ -110,10 +111,10 @@ public function getMediaType(ImageInterface $image): MediaType public function getFormat(ImageInterface $image): string { try { - $mediaType = $this->getMediaType($image); + $mediaType = $this->getMediaType($image); $extensions = $mediaType->format()->fileExtensions(); - return reset($extensions)->value; + return reset($extensions)->value; // @phpstan-ignore-line } catch (\Exception) { return 'jpg'; } diff --git a/src/ServerFactory.php b/src/ServerFactory.php index abb42be9..3e66a934 100644 --- a/src/ServerFactory.php +++ b/src/ServerFactory.php @@ -18,6 +18,7 @@ use League\Glide\Manipulators\Filter; use League\Glide\Manipulators\Flip; use League\Glide\Manipulators\Gamma; +use League\Glide\Manipulators\ManipulatorInterface; use League\Glide\Manipulators\Orientation; use League\Glide\Manipulators\Pixelate; use League\Glide\Manipulators\Sharpen; @@ -237,7 +238,7 @@ public function getImageManager(): ImageManager /** * Get image manipulators. * - * @return array Image manipulators. + * @return list Image manipulators. */ public function getManipulators(): array { From 287a2484d6716149d287cbd7b02db515492d916d Mon Sep 17 00:00:00 2001 From: Thomas Date: Mon, 16 Dec 2024 19:15:36 -0600 Subject: [PATCH 15/23] add exception back --- src/Api/Api.php | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/Api/Api.php b/src/Api/Api.php index 63d7864f..9acdbb96 100644 --- a/src/Api/Api.php +++ b/src/Api/Api.php @@ -62,7 +62,13 @@ public function getImageManager(): ImageManager */ public function setManipulators(array $manipulators): void { - $this->manipulators = array_filter($manipulators, fn ($manipulator) => $manipulator instanceof ManipulatorInterface); + foreach ($manipulators as $manipulator) { + if (!($manipulator instanceof ManipulatorInterface)) { + throw new \InvalidArgumentException('Not a valid manipulator.'); + } + } + + $this->manipulators = $manipulators; // @phpstan-ignore-line } /** From 2e21930c688863f8dd48a2bf5f69dbfa20e28b68 Mon Sep 17 00:00:00 2001 From: Thomas Date: Mon, 16 Dec 2024 19:19:26 -0600 Subject: [PATCH 16/23] psalm fix --- src/Api/Api.php | 10 ++-------- src/Api/Encoder.php | 2 -- 2 files changed, 2 insertions(+), 10 deletions(-) diff --git a/src/Api/Api.php b/src/Api/Api.php index 9acdbb96..aa7389c3 100644 --- a/src/Api/Api.php +++ b/src/Api/Api.php @@ -58,17 +58,11 @@ public function getImageManager(): ImageManager /** * Set the manipulators. * - * @param list $manipulators Collection of manipulators. + * @param array $manipulators Collection of manipulators. */ public function setManipulators(array $manipulators): void { - foreach ($manipulators as $manipulator) { - if (!($manipulator instanceof ManipulatorInterface)) { - throw new \InvalidArgumentException('Not a valid manipulator.'); - } - } - - $this->manipulators = $manipulators; // @phpstan-ignore-line + $this->manipulators = array_filter($manipulators, fn ($manipulator) => $manipulator instanceof ManipulatorInterface || throw new \InvalidArgumentException('Not a valid manipulator.')); } /** diff --git a/src/Api/Encoder.php b/src/Api/Encoder.php index fd797fad..6ada37e1 100644 --- a/src/Api/Encoder.php +++ b/src/Api/Encoder.php @@ -4,8 +4,6 @@ namespace League\Glide\Api; -use Intervention\Image\FileExtension; -use Intervention\Image\Format; use Intervention\Image\Interfaces\EncodedImageInterface; use Intervention\Image\Interfaces\ImageInterface; use Intervention\Image\MediaType; From 7f3ca11673e9bda140ce7194f13eb8697013bed3 Mon Sep 17 00:00:00 2001 From: Thomas Date: Mon, 16 Dec 2024 19:20:42 -0600 Subject: [PATCH 17/23] style fix --- src/Api/Api.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Api/Api.php b/src/Api/Api.php index aa7389c3..f826e8db 100644 --- a/src/Api/Api.php +++ b/src/Api/Api.php @@ -26,7 +26,7 @@ class Api implements ApiInterface /** * Create API instance. * - * @param ImageManager $imageManager Intervention image manager. + * @param ImageManager $imageManager Intervention image manager. * @param list $manipulators Collection of manipulators. */ public function __construct(ImageManager $imageManager, array $manipulators) From 48b7765e4a31c782506bc8d2ed71d9895f14d4b1 Mon Sep 17 00:00:00 2001 From: Thomas Date: Tue, 17 Dec 2024 05:29:17 -0600 Subject: [PATCH 18/23] added tests and keep same type for supportedFormats --- src/Api/Encoder.php | 14 ++++++++++++-- tests/Api/EncoderTest.php | 31 +++++++++++++++++++++++++++---- 2 files changed, 39 insertions(+), 6 deletions(-) diff --git a/src/Api/Encoder.php b/src/Api/Encoder.php index 6ada37e1..95ff7ff6 100644 --- a/src/Api/Encoder.php +++ b/src/Api/Encoder.php @@ -89,7 +89,7 @@ public function getMediaType(ImageInterface $image): MediaType $fm = (string) $this->getParam('fm'); if ('' !== $fm) { - return self::supportedFormats()[$fm] ?? throw new \Exception("Invalid format provided: {$fm}"); + return self::supportedMediaTypes()[$fm] ?? throw new \Exception("Invalid format provided: {$fm}"); } try { @@ -121,9 +121,19 @@ public function getFormat(ImageInterface $image): string /** * Get a list of supported image formats and MIME types. * - * @return array + * @return array */ public static function supportedFormats(): array + { + return array_map(fn (MediaType $mediaType) => $mediaType->value, self::supportedMediaTypes()); + } + + /** + * Get a list of supported image formats and media types. + * + * @return array + */ + public static function supportedMediaTypes(): array { return [ 'avif' => MediaType::IMAGE_AVIF, diff --git a/tests/Api/EncoderTest.php b/tests/Api/EncoderTest.php index ab03b1b5..492caa7d 100644 --- a/tests/Api/EncoderTest.php +++ b/tests/Api/EncoderTest.php @@ -126,6 +126,11 @@ public function testGetFormat(): void $this->assertSame('gif', $this->encoder->setParams(['fm' => 'gif'])->getFormat($this->getImageByMimeType('image/gif'))); $this->assertSame('bmp', $this->encoder->setParams(['fm' => 'bmp'])->getFormat($this->getImageByMimeType('image/bmp'))); + // Make sure 'fm' parameter takes precedence + $this->assertSame('png', $this->encoder->setParams(['fm' => 'png'])->getFormat($this->getImageByMimeType('image/jpeg'))); + $this->assertSame('gif', $this->encoder->setParams(['fm' => 'gif'])->getFormat($this->getImageByMimeType('image/jpeg'))); + $this->assertSame('bmp', $this->encoder->setParams(['fm' => 'bmp'])->getFormat($this->getImageByMimeType('image/jpeg'))); + // Make sure we keep the current format if no format is provided $this->assertSame('jpg', $this->encoder->setParams(['fm' => null])->getFormat($this->getImageByMimeType('image/jpeg'))); $this->assertSame('png', $this->encoder->setParams(['fm' => null])->getFormat($this->getImageByMimeType('image/png'))); @@ -138,10 +143,12 @@ public function testGetFormat(): void if (function_exists('imagecreatefromwebp')) { $this->assertSame('webp', $this->encoder->setParams(['fm' => null])->getFormat($this->getImageByMimeType('image/webp'))); + $this->assertSame('webp', $this->encoder->setParams(['fm' => 'webp'])->getFormat($this->getImageByMimeType('image/jpeg'))); } if (function_exists('imagecreatefromavif')) { $this->assertSame('avif', $this->encoder->setParams(['fm' => null])->getFormat($this->getImageByMimeType('image/avif'))); + $this->assertSame('avif', $this->encoder->setParams(['fm' => 'avif'])->getFormat($this->getImageByMimeType('image/jpeg'))); } } @@ -188,6 +195,23 @@ public function testWithImagick(): void } public function testSupportedFormats(): void + { + $expected = [ + 'avif' => 'image/avif', + 'bmp' => 'image/bmp', + 'gif' => 'image/gif', + 'heic' => 'image/heic', + 'jpg' => 'image/jpeg', + 'pjpg' => 'image/pjpeg', + 'png' => 'image/png', + 'tiff' => 'image/tiff', + 'webp' => 'image/webp', + ]; + + $this->assertSame($expected, Encoder::supportedFormats()); + } + + public function testSupportedMediaTypes(): void { $expected = [ 'avif' => MediaType::IMAGE_AVIF, @@ -201,7 +225,7 @@ public function testSupportedFormats(): void 'webp' => MediaType::IMAGE_WEBP, ]; - $this->assertSame($expected, Encoder::supportedFormats()); + $this->assertSame($expected, Encoder::supportedMediaTypes()); } protected function getMime(EncodedImageInterface $image): string @@ -212,12 +236,11 @@ protected function getMime(EncodedImageInterface $image): string /** * Creates an assertion to check media type. * - * @param Mock $mock - * @param string $mediaType + * @param Mockery\Mock $mock * * @psalm-suppress MoreSpecificReturnType */ - protected function assertMediaType($mock, $mediaType): Mockery\CompositeExpectation + protected function assertMediaType($mock, string $mediaType): Mockery\CompositeExpectation { /** * @psalm-suppress LessSpecificReturnStatement, UndefinedMagicMethod From e138f4e9c4333a9136b95070edd33303ce9c073c Mon Sep 17 00:00:00 2001 From: Thomas Date: Tue, 17 Dec 2024 05:52:18 -0600 Subject: [PATCH 19/23] add tests for pjpg --- src/Api/Encoder.php | 3 +-- tests/Api/ApiTest.php | 18 +++++++++--------- tests/Api/EncoderTest.php | 2 ++ 3 files changed, 12 insertions(+), 11 deletions(-) diff --git a/src/Api/Encoder.php b/src/Api/Encoder.php index 95ff7ff6..420ced97 100644 --- a/src/Api/Encoder.php +++ b/src/Api/Encoder.php @@ -110,9 +110,8 @@ public function getFormat(ImageInterface $image): string { try { $mediaType = $this->getMediaType($image); - $extensions = $mediaType->format()->fileExtensions(); - return reset($extensions)->value; // @phpstan-ignore-line + return array_search($mediaType->value, self::supportedFormats(), true) ?: 'jpg'; } catch (\Exception) { return 'jpg'; } diff --git a/tests/Api/ApiTest.php b/tests/Api/ApiTest.php index be06f9a1..a95f6f9e 100644 --- a/tests/Api/ApiTest.php +++ b/tests/Api/ApiTest.php @@ -14,7 +14,7 @@ class ApiTest extends TestCase { - private $api; + private Api $api; public function setUp(): void { @@ -26,30 +26,30 @@ public function tearDown(): void \Mockery::close(); } - public function testCreateInstance() + public function testCreateInstance(): void { $this->assertInstanceOf(Api::class, $this->api); } - public function testSetImageManager() + public function testSetImageManager(): void { $this->api->setImageManager(ImageManager::gd()); $this->assertInstanceOf(ImageManager::class, $this->api->getImageManager()); } - public function testGetImageManager() + public function testGetImageManager(): void { $this->assertInstanceOf(ImageManager::class, $this->api->getImageManager()); } - public function testSetManipulators() + public function testSetManipulators(): void { $this->api->setManipulators([\Mockery::mock(ManipulatorInterface::class)]); $manipulators = $this->api->getManipulators(); $this->assertInstanceOf(ManipulatorInterface::class, $manipulators[0]); } - public function testSetInvalidManipulator() + public function testSetInvalidManipulator(): void { $this->expectException(\InvalidArgumentException::class); $this->expectExceptionMessage('Not a valid manipulator.'); @@ -57,12 +57,12 @@ public function testSetInvalidManipulator() $this->api->setManipulators([new \stdClass()]); } - public function testGetManipulators() + public function testGetManipulators(): void { $this->assertEquals([], $this->api->getManipulators()); } - public function testRun() + public function testRun(): void { $image = \Mockery::mock(ImageInterface::class, function ($mock) { $mock->shouldReceive('origin')->andReturn(\Mockery::mock(Origin::class, function ($mock) { @@ -88,7 +88,7 @@ public function testRun() $api = new Api($manager, [$manipulator]); $this->assertEquals('encoded', $api->run( - file_get_contents(dirname(__FILE__, 2).'/files/red-pixel.png'), + (string) file_get_contents(dirname(__FILE__, 2).'/files/red-pixel.png'), [] )); } diff --git a/tests/Api/EncoderTest.php b/tests/Api/EncoderTest.php index 492caa7d..78b9e8e9 100644 --- a/tests/Api/EncoderTest.php +++ b/tests/Api/EncoderTest.php @@ -130,12 +130,14 @@ public function testGetFormat(): void $this->assertSame('png', $this->encoder->setParams(['fm' => 'png'])->getFormat($this->getImageByMimeType('image/jpeg'))); $this->assertSame('gif', $this->encoder->setParams(['fm' => 'gif'])->getFormat($this->getImageByMimeType('image/jpeg'))); $this->assertSame('bmp', $this->encoder->setParams(['fm' => 'bmp'])->getFormat($this->getImageByMimeType('image/jpeg'))); + $this->assertSame('pjpg', $this->encoder->setParams(['fm' => 'pjpg'])->getFormat($this->getImageByMimeType('image/jpeg'))); // Make sure we keep the current format if no format is provided $this->assertSame('jpg', $this->encoder->setParams(['fm' => null])->getFormat($this->getImageByMimeType('image/jpeg'))); $this->assertSame('png', $this->encoder->setParams(['fm' => null])->getFormat($this->getImageByMimeType('image/png'))); $this->assertSame('gif', $this->encoder->setParams(['fm' => null])->getFormat($this->getImageByMimeType('image/gif'))); $this->assertSame('bmp', $this->encoder->setParams(['fm' => null])->getFormat($this->getImageByMimeType('image/bmp'))); + $this->assertSame('jpg', $this->encoder->setParams(['fm' => 'null'])->getFormat($this->getImageByMimeType('image/pjpeg'))); $this->assertSame('jpg', $this->encoder->setParams(['fm' => ''])->getFormat($this->getImageByMimeType('image/jpeg'))); $this->assertSame('png', $this->encoder->setParams(['fm' => ''])->getFormat($this->getImageByMimeType('image/png'))); From 1a8d3bd4de8fc5f2f27cffdb077de0f5f3c0003c Mon Sep 17 00:00:00 2001 From: Thomas Date: Tue, 17 Dec 2024 06:00:20 -0600 Subject: [PATCH 20/23] psalm suppress --- src/Api/Encoder.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Api/Encoder.php b/src/Api/Encoder.php index 420ced97..8c3188d4 100644 --- a/src/Api/Encoder.php +++ b/src/Api/Encoder.php @@ -105,6 +105,8 @@ public function getMediaType(ImageInterface $image): MediaType * @param ImageInterface $image The source image. * * @return string The resolved format. + * + * @psalm-suppress RiskyTruthyFalsyComparison */ public function getFormat(ImageInterface $image): string { From 3ea96b87fadae18f103a196c2a5d1850bec1de8a Mon Sep 17 00:00:00 2001 From: Thomas Date: Tue, 17 Dec 2024 08:33:49 -0600 Subject: [PATCH 21/23] php doc fix --- src/Api/Api.php | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/Api/Api.php b/src/Api/Api.php index f826e8db..7a218ff9 100644 --- a/src/Api/Api.php +++ b/src/Api/Api.php @@ -26,8 +26,8 @@ class Api implements ApiInterface /** * Create API instance. * - * @param ImageManager $imageManager Intervention image manager. - * @param list $manipulators Collection of manipulators. + * @param ImageManager $imageManager Intervention image manager. + * @param list $manipulators Collection of manipulators. */ public function __construct(ImageManager $imageManager, array $manipulators) { @@ -59,6 +59,8 @@ public function getImageManager(): ImageManager * Set the manipulators. * * @param array $manipulators Collection of manipulators. + * + * @throws \InvalidArgumentException */ public function setManipulators(array $manipulators): void { From aa8e8b2463d30e602a34cd179da9927a5dad88f2 Mon Sep 17 00:00:00 2001 From: Thomas Date: Tue, 17 Dec 2024 08:59:53 -0600 Subject: [PATCH 22/23] rerun tests --- tests/Api/EncoderTest.php | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/Api/EncoderTest.php b/tests/Api/EncoderTest.php index 78b9e8e9..b1d76b0d 100644 --- a/tests/Api/EncoderTest.php +++ b/tests/Api/EncoderTest.php @@ -183,6 +183,7 @@ public function testWithImagick(): void ); } $manager = ImageManager::imagick(); + // These need to be recreated with the imagick driver selected in the manager $this->jpg = $manager->read($manager->create(100, 100)->encode(new MediaTypeEncoder('image/jpeg'))->toFilePointer()); $this->png = $manager->read($manager->create(100, 100)->encode(new MediaTypeEncoder('image/png'))->toFilePointer()); From e7cfec07d1de0679b631aa9abcbd6d4bfd4d58c8 Mon Sep 17 00:00:00 2001 From: Thomas Date: Tue, 17 Dec 2024 09:50:03 -0600 Subject: [PATCH 23/23] updated ubuntu version --- .github/workflows/test.yaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 36bbaa0f..cdc44647 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -8,7 +8,7 @@ on: jobs: tests: - runs-on: ubuntu-24.04 + runs-on: ubuntu-22.04 strategy: fail-fast: false matrix: @@ -44,7 +44,7 @@ jobs: uses: codecov/codecov-action@v3 coding-style: - runs-on: ubuntu-24.04 + runs-on: ubuntu-22.04 steps: - uses: actions/checkout@v4 @@ -61,7 +61,7 @@ jobs: vendor/bin/php-cs-fixer fix --dry-run --diff --allow-risky=yes static-analysis: - runs-on: ubuntu-24.04 + runs-on: ubuntu-22.04 steps: - uses: actions/checkout@v4