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());