diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index fc404d8..c9f79fc 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -18,6 +18,8 @@ jobs: sca: uses: zenstruck/.github/.github/workflows/php-stan.yml@main + with: + php: 8.2 fixcs: name: Run php-cs-fixer diff --git a/README.md b/README.md index 2578736..d8109af 100644 --- a/README.md +++ b/README.md @@ -55,6 +55,7 @@ The following transformers are available: - [Imagick](https://www.php.net/manual/en/book.imagick.php) - [intervention\image](https://github.com/Intervention/image) - [imagine\imagine](https://github.com/php-imagine/Imagine) +- [spatie\image](https://github.com/spatie/image) To use the desired transformer, type-hint the first parameter of the callable passed to `Zenstruck\ImageFileInfo::transform()` with the desired transformer's @@ -64,6 +65,7 @@ _image object_: - **Imagick**: `\Imagick` - **intervention\image**: `Intervention\Image\Image` - **imagine\imagine**: `Imagine\Image\ImageInterface` +- **spatie\image**: `Spatie\Image\Image` > **Note**: The return value of the callable must be the same as the passed parameter. diff --git a/composer.json b/composer.json index d3c6f26..3138216 100644 --- a/composer.json +++ b/composer.json @@ -22,6 +22,7 @@ "phpstan/phpstan": "^1.4", "phpunit/phpunit": "^9.5.0", "psr/container": "^1.0|^2.0", + "spatie/image": "^2.0|^3.2", "symfony/phpunit-bridge": "^6.1", "symfony/var-dumper": "^5.4|^6.0" }, diff --git a/phpunit.xml.dist b/phpunit.xml.dist index d432555..973de93 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -10,7 +10,7 @@ > - + diff --git a/src/Image/Transformer/MultiTransformer.php b/src/Image/Transformer/MultiTransformer.php index 4294095..21efc5d 100644 --- a/src/Image/Transformer/MultiTransformer.php +++ b/src/Image/Transformer/MultiTransformer.php @@ -19,6 +19,7 @@ use Intervention\Image\Filters\FilterInterface as InterventionFilter; use Intervention\Image\Image as InterventionImage; use Psr\Container\ContainerInterface; +use Spatie\Image\Image as SpatieImage; use Zenstruck\Image\Transformer; /** @@ -104,6 +105,7 @@ private static function defaultTransformer(string $class): Transformer \Imagick::class => new ImagickTransformer(), ImagineImage::class, GdImagineImage::class, ImagickImagineImage::class, GmagickImagineImage::class => ImagineTransformer::createFor($class), InterventionImage::class => new InterventionTransformer(), + SpatieImage::class => new SpatieImageTransformer(), default => throw new \InvalidArgumentException(\sprintf('No transformer available for "%s".', $class)), }; } diff --git a/src/Image/Transformer/SpatieImageTransformer.php b/src/Image/Transformer/SpatieImageTransformer.php new file mode 100644 index 0000000..93bd2b2 --- /dev/null +++ b/src/Image/Transformer/SpatieImageTransformer.php @@ -0,0 +1,42 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Zenstruck\Image\Transformer; + +use Spatie\Image\Image; + +/** + * @author Kevin Bond + * + * @internal + * + * @extends FileTransformer + */ +final class SpatieImageTransformer extends FileTransformer +{ + protected function object(\SplFileInfo $image): object + { + return Image::load($image); + } + + protected static function expectedClass(): string + { + return Image::class; + } + + protected function save(object $object, array $options): void + { + $object + ->format($options['format']) + ->save($options['output']) + ; + } +} diff --git a/tests/Transformer/FilterObjectTransformerTest.php b/tests/Transformer/FilterObjectTransformerTestCase.php similarity index 95% rename from tests/Transformer/FilterObjectTransformerTest.php rename to tests/Transformer/FilterObjectTransformerTestCase.php index 521311c..3cdcbb2 100644 --- a/tests/Transformer/FilterObjectTransformerTest.php +++ b/tests/Transformer/FilterObjectTransformerTestCase.php @@ -11,14 +11,14 @@ namespace Zenstruck\Image\Tests\Transformer; -use Zenstruck\Image\Tests\TransformerTest; +use Zenstruck\Image\Tests\TransformerTestCase; use Zenstruck\ImageFileInfo; use Zenstruck\TempFile; /** * @author Kevin Bond */ -abstract class FilterObjectTransformerTest extends TransformerTest +abstract class FilterObjectTransformerTestCase extends TransformerTestCase { /** * @test diff --git a/tests/Transformer/GdImageTransformerTest.php b/tests/Transformer/GdImageTransformerTest.php index c8f9e0b..ee11d4c 100644 --- a/tests/Transformer/GdImageTransformerTest.php +++ b/tests/Transformer/GdImageTransformerTest.php @@ -11,12 +11,12 @@ namespace Zenstruck\Image\Tests\Transformer; -use Zenstruck\Image\Tests\TransformerTest; +use Zenstruck\Image\Tests\TransformerTestCase; /** * @author Kevin Bond */ -final class GdImageTransformerTest extends TransformerTest +final class GdImageTransformerTest extends TransformerTestCase { protected function filterInvokable(): object { diff --git a/tests/Transformer/ImagickTransformerTest.php b/tests/Transformer/ImagickTransformerTest.php index 060add7..03b9bc0 100644 --- a/tests/Transformer/ImagickTransformerTest.php +++ b/tests/Transformer/ImagickTransformerTest.php @@ -11,12 +11,12 @@ namespace Zenstruck\Image\Tests\Transformer; -use Zenstruck\Image\Tests\TransformerTest; +use Zenstruck\Image\Tests\TransformerTestCase; /** * @author Kevin Bond */ -final class ImagickTransformerTest extends TransformerTest +final class ImagickTransformerTest extends TransformerTestCase { protected function setUp(): void { diff --git a/tests/Transformer/ImagineTransformerTest.php b/tests/Transformer/ImagineTransformerTest.php index 680a906..d7850db 100644 --- a/tests/Transformer/ImagineTransformerTest.php +++ b/tests/Transformer/ImagineTransformerTest.php @@ -17,7 +17,7 @@ /** * @author Kevin Bond */ -final class ImagineTransformerTest extends FilterObjectTransformerTest +final class ImagineTransformerTest extends FilterObjectTransformerTestCase { protected function filterCallback(): callable { diff --git a/tests/Transformer/InterventionTransformerTest.php b/tests/Transformer/InterventionTransformerTest.php index 53ee869..5b1b335 100644 --- a/tests/Transformer/InterventionTransformerTest.php +++ b/tests/Transformer/InterventionTransformerTest.php @@ -17,7 +17,7 @@ /** * @author Kevin Bond */ -final class InterventionTransformerTest extends FilterObjectTransformerTest +final class InterventionTransformerTest extends FilterObjectTransformerTestCase { protected function filterCallback(): callable { diff --git a/tests/Transformer/SpatieImageTransformerTest.php b/tests/Transformer/SpatieImageTransformerTest.php new file mode 100644 index 0000000..46b476b --- /dev/null +++ b/tests/Transformer/SpatieImageTransformerTest.php @@ -0,0 +1,41 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Zenstruck\Image\Tests\Transformer; + +use Spatie\Image\Image; +use Zenstruck\Image\Tests\TransformerTestCase; + +/** + * @author Kevin Bond + */ +final class SpatieImageTransformerTest extends TransformerTestCase +{ + protected function invalidFilterCallback(): callable + { + return fn(Image $i) => null; + } + + protected function filterInvokable(): object + { + return new class() { + public function __invoke(Image $image): Image + { + return $image->width(100); + } + }; + } + + protected function filterCallback(): callable + { + return fn(Image $i) => $i->width(100); + } +} diff --git a/tests/TransformerTest.php b/tests/TransformerTestCase.php similarity index 92% rename from tests/TransformerTest.php rename to tests/TransformerTestCase.php index ade18a9..d325726 100644 --- a/tests/TransformerTest.php +++ b/tests/TransformerTestCase.php @@ -18,7 +18,7 @@ /** * @author Kevin Bond */ -abstract class TransformerTest extends TestCase +abstract class TransformerTestCase extends TestCase { /** * @test @@ -47,7 +47,7 @@ public function can_transform_into_temp_image(): void */ public function can_transform_to_specific_file(): void { - $output = TempFile::new(); + $output = TempFile::withExtension('jpg'); $image = new ImageFileInfo(__DIR__.'/Fixture/files/symfony.jpg'); $resized = $image->transform($this->filterCallback(), ['output' => $output]); @@ -63,7 +63,7 @@ public function can_transform_to_specific_file(): void */ public function can_transform_in_place(): void { - $image = ImageFileInfo::from(new \SplFileInfo(__DIR__.'/Fixture/files/symfony.jpg')); + $image = new ImageFileInfo(TempFile::for(new \SplFileInfo(__DIR__.'/Fixture/files/symfony.jpg'), extension: 'jpg')); $this->assertSame(678, $image->dimensions()->height()); $this->assertSame(563, $image->dimensions()->width()); @@ -105,7 +105,7 @@ public function can_transform_into_temp_image_with_invokable_object(): void */ public function can_transform_to_specific_file_with_invokable_object(): void { - $output = TempFile::new(); + $output = TempFile::withExtension('jpg'); $image = new ImageFileInfo(__DIR__.'/Fixture/files/symfony.jpg'); $resized = $image->transform($this->filterInvokable(), ['output' => $output]); @@ -121,7 +121,7 @@ public function can_transform_to_specific_file_with_invokable_object(): void */ public function can_transform_in_place_with_invokable_object(): void { - $image = ImageFileInfo::from(new \SplFileInfo(__DIR__.'/Fixture/files/symfony.jpg')); + $image = new ImageFileInfo(TempFile::for(new \SplFileInfo(__DIR__.'/Fixture/files/symfony.jpg'), extension: 'jpg')); $this->assertSame(678, $image->dimensions()->height()); $this->assertSame(563, $image->dimensions()->width());