From fa2bf7d79384b753b2c08965e3629570f5029b5e Mon Sep 17 00:00:00 2001 From: Oliver Vogel Date: Thu, 9 May 2024 09:58:10 +0200 Subject: [PATCH] Implement config options --- src/Config.php | 29 +++++++-- src/Drivers/AbstractDriver.php | 8 ++- .../Gd/Decoders/BinaryImageDecoder.php | 7 +- .../Gd/Decoders/FilePathImageDecoder.php | 7 +- .../Gd/Decoders/NativeObjectDecoder.php | 65 ++++++++++++++++++- .../Gd/Decoders/Traits/CanDecodeGif.php | 54 --------------- .../Imagick/Decoders/NativeObjectDecoder.php | 14 +++- src/Image.php | 31 +++++---- src/ImageManager.php | 3 + src/InputHandler.php | 19 ++++-- src/Interfaces/ConfigInterface.php | 6 +- src/Interfaces/DriverInterface.php | 1 + src/Interfaces/ImageInterface.php | 9 +++ src/Interfaces/SpecializableInterface.php | 3 + src/Traits/CanBeDriverSpecialized.php | 23 +++++++ tests/BaseTestCase.php | 8 +-- tests/GdTestCase.php | 4 +- tests/ImagickTestCase.php | 4 +- .../Gd/Decoders/Base64ImageDecoderTest.php | 2 + .../Gd/Decoders/BinaryImageDecoderTest.php | 21 +++--- .../Gd/Decoders/DataUriImageDecoderTest.php | 2 + .../Gd/Decoders/FilePathImageDecoderTest.php | 46 +++++++------ .../Decoders/FilePointerImageDecoderTest.php | 3 + .../Decoders/SplFileInfoImageDecoderTest.php | 3 + .../Drivers/Gd/Traits/CanDecodeGifTest.php | 57 ---------------- .../Decoders/Base64ImageDecoderTest.php | 2 + .../Decoders/BinaryImageDecoderTest.php | 27 ++++---- .../Decoders/DataUriImageDecoderTest.php | 2 + .../Decoders/FilePathImageDecoderTest.php | 46 +++++++------ .../Decoders/FilePointerImageDecoderTest.php | 2 + .../Decoders/SplFileInfoImageDecoderTest.php | 2 + 31 files changed, 289 insertions(+), 221 deletions(-) delete mode 100644 src/Drivers/Gd/Decoders/Traits/CanDecodeGif.php delete mode 100644 tests/Unit/Drivers/Gd/Traits/CanDecodeGifTest.php diff --git a/src/Config.php b/src/Config.php index aec6d346..10c1a685 100644 --- a/src/Config.php +++ b/src/Config.php @@ -9,9 +9,9 @@ use Intervention\Image\Interfaces\ConfigInterface; class Config implements ConfigInterface { public function __construct( - protected bool $autoOrientate = true, + protected bool $autoOrientation = true, protected bool $decodeAnimation = true, - protected mixed $blendingColor = 'ffffffff', + protected mixed $blendingColor = 'ffffff00', ) { } @@ -20,13 +20,34 @@ class Config implements ConfigInterface return $this->decodeAnimation; } - public function autoOrientate(): bool + public function setDecodeAnimation(bool $status): self { - return $this->autoOrientate; + $this->decodeAnimation = $status; + + return $this; + } + + public function autoOrientation(): bool + { + return $this->autoOrientation; + } + + public function setAutoOrientation(bool $status): self + { + $this->autoOrientation = $status; + + return $this; } public function blendingColor(): mixed { return $this->blendingColor; } + + public function setBlendingColor(mixed $color): self + { + $this->blendingColor = $color; + + return $this; + } } diff --git a/src/Drivers/AbstractDriver.php b/src/Drivers/AbstractDriver.php index abfe9bf0..b2db442e 100644 --- a/src/Drivers/AbstractDriver.php +++ b/src/Drivers/AbstractDriver.php @@ -65,8 +65,10 @@ abstract class AbstractDriver implements DriverInterface return $object; } - // return directly if object is already specialized - if ($object instanceof SpecializedInterface) { + // return directly and only attach driver if object is already specialized + if (($object instanceof SpecializedInterface)) { + $object->setDriver($this); + return $object; } @@ -81,7 +83,7 @@ abstract class AbstractDriver implements DriverInterface ); } - // create driver specialized object with specializable properties of generic object + // create a driver specialized object with the specializable properties of generic object $specialized = (new $specialized_classname(...$object->specializable())); // attach driver diff --git a/src/Drivers/Gd/Decoders/BinaryImageDecoder.php b/src/Drivers/Gd/Decoders/BinaryImageDecoder.php index c71b3232..c4f43749 100644 --- a/src/Drivers/Gd/Decoders/BinaryImageDecoder.php +++ b/src/Drivers/Gd/Decoders/BinaryImageDecoder.php @@ -8,14 +8,11 @@ use Intervention\Image\Exceptions\RuntimeException; use Intervention\Image\Interfaces\ColorInterface; use Intervention\Image\Interfaces\DecoderInterface; use Intervention\Image\Interfaces\ImageInterface; -use Intervention\Image\Drivers\Gd\Decoders\Traits\CanDecodeGif; use Intervention\Image\Exceptions\DecoderException; use Intervention\Image\Modifiers\AlignRotationModifier; class BinaryImageDecoder extends NativeObjectDecoder implements DecoderInterface { - use CanDecodeGif; - /** * {@inheritdoc} * @@ -63,7 +60,9 @@ class BinaryImageDecoder extends NativeObjectDecoder implements DecoderInterface } // adjust image orientation - $image->modify(new AlignRotationModifier()); + if ($this->driver()->config()->autoOrientation()) { + $image->modify(new AlignRotationModifier()); + } return $image; } diff --git a/src/Drivers/Gd/Decoders/FilePathImageDecoder.php b/src/Drivers/Gd/Decoders/FilePathImageDecoder.php index f83252ba..e1606a85 100644 --- a/src/Drivers/Gd/Decoders/FilePathImageDecoder.php +++ b/src/Drivers/Gd/Decoders/FilePathImageDecoder.php @@ -4,7 +4,6 @@ declare(strict_types=1); namespace Intervention\Image\Drivers\Gd\Decoders; -use Intervention\Image\Drivers\Gd\Decoders\Traits\CanDecodeGif; use Intervention\Image\Exceptions\DecoderException; use Intervention\Image\Interfaces\ColorInterface; use Intervention\Image\Interfaces\DecoderInterface; @@ -13,8 +12,6 @@ use Intervention\Image\Modifiers\AlignRotationModifier; class FilePathImageDecoder extends NativeObjectDecoder implements DecoderInterface { - use CanDecodeGif; - public function decode(mixed $input): ImageInterface|ColorInterface { if (!$this->isFile($input)) { @@ -53,7 +50,9 @@ class FilePathImageDecoder extends NativeObjectDecoder implements DecoderInterfa $image->setExif($this->extractExifData($input)); // adjust image orientation - $image->modify(new AlignRotationModifier()); + if ($this->driver()->config()->autoOrientation()) { + $image->modify(new AlignRotationModifier()); + } return $image; } diff --git a/src/Drivers/Gd/Decoders/NativeObjectDecoder.php b/src/Drivers/Gd/Decoders/NativeObjectDecoder.php index ca1bc38d..cf853598 100644 --- a/src/Drivers/Gd/Decoders/NativeObjectDecoder.php +++ b/src/Drivers/Gd/Decoders/NativeObjectDecoder.php @@ -5,13 +5,15 @@ declare(strict_types=1); namespace Intervention\Image\Drivers\Gd\Decoders; use GdImage; +use Intervention\Gif\Decoder as GifDecoder; +use Intervention\Gif\Splitter as GifSplitter; use Intervention\Image\Drivers\Gd\Core; -use Intervention\Image\Drivers\Gd\Driver; use Intervention\Image\Drivers\Gd\Frame; use Intervention\Image\Exceptions\DecoderException; +use Intervention\Image\Exceptions\RuntimeException; use Intervention\Image\Image; -use Intervention\Image\Interfaces\ImageInterface; use Intervention\Image\Interfaces\ColorInterface; +use Intervention\Image\Interfaces\ImageInterface; class NativeObjectDecoder extends AbstractDecoder { @@ -38,10 +40,67 @@ class NativeObjectDecoder extends AbstractDecoder // build image instance return new Image( - new Driver(), + $this->driver(), new Core([ new Frame($input) ]) ); } + + /** + * Decode image from given GIF source which can be either a file path or binary data + * + * Depending on the configuration, this is taken over by the native GD function + * or, if animations are required, by our own extended decoder. + * + * @param mixed $input + * @throws RuntimeException + * @return ImageInterface + */ + protected function decodeGif(mixed $input): ImageInterface + { + // create non-animated image depending on config + if (!$this->driver()->config()->decodeAnimation()) { + $native = match (true) { + $this->isGifFormat($input) => @imagecreatefromstring($input), + default => @imagecreatefromgif($input), + }; + + if ($native === false) { + throw new DecoderException('Unable to decode input.'); + } + + $image = self::decode($native); + $image->origin()->setMediaType('image/gif'); + + return $image; + } + + // create empty core + $core = new Core(); + + $gif = GifDecoder::decode($input); + $splitter = GifSplitter::create($gif)->split(); + $delays = $splitter->getDelays(); + + // set loops on core + if ($loops = $gif->getMainApplicationExtension()?->getLoops()) { + $core->setLoops($loops); + } + + // add GDImage instances to core + foreach ($splitter->coalesceToResources() as $key => $native) { + $core->push( + new Frame($native, $delays[$key] / 100) + ); + } + + // create (possibly) animated image + $image = new Image($this->driver(), $core); + + // set media type + $image->origin()->setMediaType('image/gif'); + + return $image; + } } diff --git a/src/Drivers/Gd/Decoders/Traits/CanDecodeGif.php b/src/Drivers/Gd/Decoders/Traits/CanDecodeGif.php deleted file mode 100644 index 9b1452b9..00000000 --- a/src/Drivers/Gd/Decoders/Traits/CanDecodeGif.php +++ /dev/null @@ -1,54 +0,0 @@ -split(); - $delays = $splitter->getDelays(); - - // build core - $core = new Core(); - - // set loops on core - if ($loops = $gif->getMainApplicationExtension()?->getLoops()) { - $core->setLoops($loops); - } - - // add GDImage instances to core - foreach ($splitter->coalesceToResources() as $key => $native) { - $core->push( - (new Frame($native))->setDelay($delays[$key] / 100) - ); - } - - // create image - $image = new Image(new Driver(), $core); - - // set media type - $image->origin()->setMediaType('image/gif'); - - return $image; - } -} diff --git a/src/Drivers/Imagick/Decoders/NativeObjectDecoder.php b/src/Drivers/Imagick/Decoders/NativeObjectDecoder.php index 15d61b8d..d1ae00f3 100644 --- a/src/Drivers/Imagick/Decoders/NativeObjectDecoder.php +++ b/src/Drivers/Imagick/Decoders/NativeObjectDecoder.php @@ -6,13 +6,13 @@ namespace Intervention\Image\Drivers\Imagick\Decoders; use Imagick; use Intervention\Image\Drivers\Imagick\Core; -use Intervention\Image\Drivers\Imagick\Driver; use Intervention\Image\Drivers\SpecializableDecoder; use Intervention\Image\Exceptions\DecoderException; use Intervention\Image\Image; use Intervention\Image\Interfaces\ColorInterface; use Intervention\Image\Interfaces\ImageInterface; use Intervention\Image\Modifiers\AlignRotationModifier; +use Intervention\Image\Modifiers\RemoveAnimationModifier; class NativeObjectDecoder extends SpecializableDecoder { @@ -33,13 +33,21 @@ class NativeObjectDecoder extends SpecializableDecoder $input = $input->coalesceImages(); } + // create image object $image = new Image( - new Driver(), + $this->driver(), new Core($input) ); + // discard animation depending on config + if (!$this->driver()->config()->decodeAnimation()) { + $image->modify(new RemoveAnimationModifier()); + } + // adjust image rotatation - $image->modify(new AlignRotationModifier()); + if ($this->driver()->config()->autoOrientation()) { + $image->modify(new AlignRotationModifier()); + } // set media type on origin $image->origin()->setMediaType($input->getImageMimeType()); diff --git a/src/Image.php b/src/Image.php index 0c1731c7..124af013 100644 --- a/src/Image.php +++ b/src/Image.php @@ -13,7 +13,6 @@ use Intervention\Image\Analyzers\PixelColorsAnalyzer; use Intervention\Image\Analyzers\ProfileAnalyzer; use Intervention\Image\Analyzers\ResolutionAnalyzer; use Intervention\Image\Analyzers\WidthAnalyzer; -use Intervention\Image\Colors\Rgb\Color; use Intervention\Image\Encoders\AutoEncoder; use Intervention\Image\Encoders\AvifEncoder; use Intervention\Image\Encoders\BmpEncoder; @@ -50,6 +49,7 @@ use Intervention\Image\Interfaces\ModifierInterface; use Intervention\Image\Interfaces\ProfileInterface; use Intervention\Image\Interfaces\ResolutionInterface; use Intervention\Image\Interfaces\SizeInterface; +use Intervention\Image\Modifiers\AlignRotationModifier; use Intervention\Image\Modifiers\BlendTransparencyModifier; use Intervention\Image\Modifiers\BlurModifier; use Intervention\Image\Modifiers\BrightnessModifier; @@ -101,14 +101,6 @@ final class Image implements ImageInterface */ protected Origin $origin; - /** - * Color is mixed with transparent areas when converting to a format which - * does not support transparency. - * - * @var ColorInterface - */ - protected ColorInterface $blendingColor; - /** * Create new instance * @@ -124,9 +116,6 @@ final class Image implements ImageInterface protected CollectionInterface $exif = new Collection() ) { $this->origin = new Origin(); - $this->blendingColor = $this->colorspace()->importColor( - new Color(255, 255, 255, 0) - ); } /** @@ -418,7 +407,9 @@ final class Image implements ImageInterface */ public function blendingColor(): ColorInterface { - return $this->blendingColor; + return $this->driver()->handleInput( + $this->driver()->config()->blendingColor() + ); } /** @@ -428,7 +419,9 @@ final class Image implements ImageInterface */ public function setBlendingColor(mixed $color): ImageInterface { - $this->blendingColor = $this->driver()->handleInput($color); + $this->driver()->config()->setBlendingColor( + $this->driver()->handleInput($color) + ); return $this; } @@ -603,6 +596,16 @@ final class Image implements ImageInterface return $this->modify(new RotateModifier($angle, $background)); } + /** + * {@inheritdoc} + * + * @see ImageInterface::orient() + */ + public function orient(): ImageInterface + { + return $this->modify(new AlignRotationModifier()); + } + /** * {@inheritdoc} * diff --git a/src/ImageManager.php b/src/ImageManager.php index 4f8ca7c1..10327ca8 100644 --- a/src/ImageManager.php +++ b/src/ImageManager.php @@ -8,6 +8,7 @@ use Intervention\Image\Interfaces\DriverInterface; use Intervention\Image\Interfaces\ImageInterface; use Intervention\Image\Drivers\Gd\Driver as GdDriver; use Intervention\Image\Drivers\Imagick\Driver as ImagickDriver; +use Intervention\Image\Exceptions\DriverException; use Intervention\Image\Interfaces\DecoderInterface; use Intervention\Image\Interfaces\ImageManagerInterface; @@ -41,6 +42,7 @@ final class ImageManager implements ImageManagerInterface * * @link https://image.intervention.io/v3/basics/image-manager#static-gd-driver-constructor * @param mixed $options + * @throws DriverException * @return ImageManager */ public static function gd(mixed ...$options): self @@ -53,6 +55,7 @@ final class ImageManager implements ImageManagerInterface * * @link https://image.intervention.io/v3/basics/image-manager#static-imagick-driver-constructor * @param mixed $options + * @throws DriverException * @return ImageManager */ public static function imagick(mixed ...$options): self diff --git a/src/InputHandler.php b/src/InputHandler.php index 9e19bc26..4e8fc2af 100644 --- a/src/InputHandler.php +++ b/src/InputHandler.php @@ -18,8 +18,10 @@ use Intervention\Image\Decoders\DataUriImageDecoder; use Intervention\Image\Decoders\FilePathImageDecoder; use Intervention\Image\Decoders\FilePointerImageDecoder; use Intervention\Image\Decoders\ImageObjectDecoder; +use Intervention\Image\Decoders\NativeObjectDecoder; use Intervention\Image\Decoders\SplFileInfoImageDecoder; use Intervention\Image\Exceptions\DecoderException; +use Intervention\Image\Exceptions\DriverException; use Intervention\Image\Exceptions\NotSupportedException; use Intervention\Image\Interfaces\ColorInterface; use Intervention\Image\Interfaces\DecoderInterface; @@ -35,7 +37,7 @@ class InputHandler implements InputHandlerInterface * @var array */ protected array $decoders = [ - // NativeObjectDecoder::class, + NativeObjectDecoder::class, ImageObjectDecoder::class, ColorObjectDecoder::class, RgbHexColorDecoder::class, @@ -80,9 +82,9 @@ class InputHandler implements InputHandlerInterface */ public function handle($input): ImageInterface|ColorInterface { - foreach ($this->decoders as $decoderClassname) { + foreach ($this->decoders as $decoder) { // resolve river specialized decoder - $decoder = $this->resolve($decoderClassname); + $decoder = $this->resolve($decoder); try { return $decoder->decode($input); @@ -98,11 +100,20 @@ class InputHandler implements InputHandlerInterface * Resolve the given classname to an decoder object * * @param string|DecoderInterface $decoder - * @return DecoderInterface + * @throws DriverException * @throws NotSupportedException + * @return DecoderInterface */ private function resolve(string|DecoderInterface $decoder): DecoderInterface { + if (($decoder instanceof DecoderInterface) && empty($this->driver)) { + return $decoder; + } + + if (($decoder instanceof DecoderInterface) && !empty($this->driver)) { + return $this->driver->specialize($decoder); + } + if (empty($this->driver)) { return new $decoder(); } diff --git a/src/Interfaces/ConfigInterface.php b/src/Interfaces/ConfigInterface.php index 27ceda9c..67cedb06 100644 --- a/src/Interfaces/ConfigInterface.php +++ b/src/Interfaces/ConfigInterface.php @@ -7,6 +7,10 @@ namespace Intervention\Image\Interfaces; interface ConfigInterface { public function decodeAnimation(): bool; - public function autoOrientate(): bool; + + public function autoOrientation(): bool; + public function blendingColor(): mixed; + + public function setBlendingColor(mixed $color): mixed; } diff --git a/src/Interfaces/DriverInterface.php b/src/Interfaces/DriverInterface.php index 31e33080..c7e3c314 100644 --- a/src/Interfaces/DriverInterface.php +++ b/src/Interfaces/DriverInterface.php @@ -32,6 +32,7 @@ interface DriverInterface * * @param ModifierInterface|AnalyzerInterface|EncoderInterface|DecoderInterface $object * @throws NotSupportedException + * @throws DriverException * @return ModifierInterface|AnalyzerInterface|EncoderInterface|DecoderInterface */ public function specialize( diff --git a/src/Interfaces/ImageInterface.php b/src/Interfaces/ImageInterface.php index 4315ac8d..49afbb10 100644 --- a/src/Interfaces/ImageInterface.php +++ b/src/Interfaces/ImageInterface.php @@ -248,6 +248,7 @@ interface ImageInterface extends IteratorAggregate, Countable * does not support transparency. * * @link https://image.intervention.io/v3/basics/colors#transparency + * @throws RuntimeException * @return ColorInterface */ public function blendingColor(): ColorInterface; @@ -430,6 +431,14 @@ interface ImageInterface extends IteratorAggregate, Countable */ public function rotate(float $angle, mixed $background = 'ffffff'): self; + /** + * Rotate the image to be upright according to exif information + * + * @throws RuntimeException + * @return ImageInterface + */ + public function orient(): self; + /** * Draw text on image * diff --git a/src/Interfaces/SpecializableInterface.php b/src/Interfaces/SpecializableInterface.php index e04ee6dc..5c188d01 100644 --- a/src/Interfaces/SpecializableInterface.php +++ b/src/Interfaces/SpecializableInterface.php @@ -4,6 +4,8 @@ declare(strict_types=1); namespace Intervention\Image\Interfaces; +use Intervention\Image\Exceptions\DriverException; + interface SpecializableInterface { /** @@ -18,6 +20,7 @@ interface SpecializableInterface * Set the driver for which the object is specialized * * @param DriverInterface $driver + * @throws DriverException * @return SpecializableInterface */ public function setDriver(DriverInterface $driver): self; diff --git a/src/Traits/CanBeDriverSpecialized.php b/src/Traits/CanBeDriverSpecialized.php index 463050f4..eb597be3 100644 --- a/src/Traits/CanBeDriverSpecialized.php +++ b/src/Traits/CanBeDriverSpecialized.php @@ -4,6 +4,7 @@ declare(strict_types=1); namespace Intervention\Image\Traits; +use Intervention\Image\Exceptions\DriverException; use Intervention\Image\Interfaces\DriverInterface; use Intervention\Image\Interfaces\SpecializableInterface; use ReflectionClass; @@ -53,8 +54,30 @@ trait CanBeDriverSpecialized */ public function setDriver(DriverInterface $driver): SpecializableInterface { + if (!$this->belongsToDriver($driver)) { + throw new DriverException( + "Class '" . $this::class . "' can not be used with " . $driver->id() . " driver." + ); + } + $this->driver = $driver; return $this; } + + /** + * Determine if the given object belongs to the driver's namespace + * + * @param object $object + * @return bool + */ + protected function belongsToDriver(object $object): bool + { + $driverId = function (object $object): string|bool { + $id = substr($object::class, 27); + return strstr($id, "\\", true); + }; + + return $driverId($this) === $driverId($object); + } } diff --git a/tests/BaseTestCase.php b/tests/BaseTestCase.php index 7416909f..41caa2aa 100644 --- a/tests/BaseTestCase.php +++ b/tests/BaseTestCase.php @@ -15,20 +15,20 @@ use PHPUnit\Framework\ExpectationFailedException; abstract class BaseTestCase extends MockeryTestCase { - public function getTestResourcePath($filename = 'test.jpg'): string + public static function getTestResourcePath($filename = 'test.jpg'): string { return sprintf('%s/resources/%s', __DIR__, $filename); } - public function getTestResourceData($filename = 'test.jpg'): string + public static function getTestResourceData($filename = 'test.jpg'): string { - return file_get_contents($this->getTestResourcePath($filename)); + return file_get_contents(self::getTestResourcePath($filename)); } public function getTestResourcePointer($filename = 'test.jpg') { $pointer = fopen('php://temp', 'rw'); - fputs($pointer, $this->getTestResourceData($filename)); + fputs($pointer, self::getTestResourceData($filename)); rewind($pointer); return $pointer; diff --git a/tests/GdTestCase.php b/tests/GdTestCase.php index 6afd44f9..2cfa9527 100644 --- a/tests/GdTestCase.php +++ b/tests/GdTestCase.php @@ -4,8 +4,8 @@ declare(strict_types=1); namespace Intervention\Image\Tests; +use Intervention\Image\Decoders\FilePathImageDecoder; use Intervention\Image\Drivers\Gd\Core; -use Intervention\Image\Drivers\Gd\Decoders\FilePathImageDecoder; use Intervention\Image\Drivers\Gd\Driver; use Intervention\Image\Drivers\Gd\Frame; use Intervention\Image\Image; @@ -14,7 +14,7 @@ abstract class GdTestCase extends BaseTestCase { public function readTestImage($filename = 'test.jpg'): Image { - return (new FilePathImageDecoder())->decode( + return (new Driver())->specialize(new FilePathImageDecoder())->decode( $this->getTestResourcePath($filename) ); } diff --git a/tests/ImagickTestCase.php b/tests/ImagickTestCase.php index ef23695c..cbd24dcc 100644 --- a/tests/ImagickTestCase.php +++ b/tests/ImagickTestCase.php @@ -6,8 +6,8 @@ namespace Intervention\Image\Tests; use Imagick; use ImagickPixel; +use Intervention\Image\Decoders\FilePathImageDecoder; use Intervention\Image\Drivers\Imagick\Core; -use Intervention\Image\Drivers\Imagick\Decoders\FilePathImageDecoder; use Intervention\Image\Drivers\Imagick\Driver; use Intervention\Image\Image; @@ -15,7 +15,7 @@ abstract class ImagickTestCase extends BaseTestCase { public function readTestImage($filename = 'test.jpg'): Image { - return (new FilePathImageDecoder())->decode( + return (new Driver())->specialize(new FilePathImageDecoder())->decode( $this->getTestResourcePath($filename) ); } diff --git a/tests/Unit/Drivers/Gd/Decoders/Base64ImageDecoderTest.php b/tests/Unit/Drivers/Gd/Decoders/Base64ImageDecoderTest.php index 51853e44..ff1bcc81 100644 --- a/tests/Unit/Drivers/Gd/Decoders/Base64ImageDecoderTest.php +++ b/tests/Unit/Drivers/Gd/Decoders/Base64ImageDecoderTest.php @@ -7,6 +7,7 @@ namespace Intervention\Image\Tests\Unit\Drivers\Gd\Decoders; use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\Attributes\RequiresPhpExtension; use Intervention\Image\Drivers\Gd\Decoders\Base64ImageDecoder; +use Intervention\Image\Drivers\Gd\Driver; use Intervention\Image\Exceptions\DecoderException; use Intervention\Image\Image; use Intervention\Image\Tests\BaseTestCase; @@ -20,6 +21,7 @@ final class Base64ImageDecoderTest extends BaseTestCase protected function setUp(): void { $this->decoder = new Base64ImageDecoder(); + $this->decoder->setDriver(new Driver()); } public function testDecode(): void diff --git a/tests/Unit/Drivers/Gd/Decoders/BinaryImageDecoderTest.php b/tests/Unit/Drivers/Gd/Decoders/BinaryImageDecoderTest.php index d09690a3..f7309f40 100644 --- a/tests/Unit/Drivers/Gd/Decoders/BinaryImageDecoderTest.php +++ b/tests/Unit/Drivers/Gd/Decoders/BinaryImageDecoderTest.php @@ -7,6 +7,7 @@ namespace Intervention\Image\Tests\Unit\Drivers\Gd\Decoders; use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\Attributes\RequiresPhpExtension; use Intervention\Image\Drivers\Gd\Decoders\BinaryImageDecoder; +use Intervention\Image\Drivers\Gd\Driver; use Intervention\Image\Image; use Intervention\Image\Tests\BaseTestCase; @@ -14,10 +15,17 @@ use Intervention\Image\Tests\BaseTestCase; #[CoversClass(\Intervention\Image\Drivers\Gd\Decoders\BinaryImageDecoder::class)] final class BinaryImageDecoderTest extends BaseTestCase { + protected BinaryImageDecoder $decoder; + + protected function setUp(): void + { + $this->decoder = new BinaryImageDecoder(); + $this->decoder->setDriver(new Driver()); + } + public function testDecodePng(): void { - $decoder = new BinaryImageDecoder(); - $image = $decoder->decode(file_get_contents($this->getTestResourcePath('tile.png'))); + $image = $this->decoder->decode(file_get_contents($this->getTestResourcePath('tile.png'))); $this->assertInstanceOf(Image::class, $image); $this->assertEquals(16, $image->width()); $this->assertEquals(16, $image->height()); @@ -26,8 +34,7 @@ final class BinaryImageDecoderTest extends BaseTestCase public function testDecodeGif(): void { - $decoder = new BinaryImageDecoder(); - $image = $decoder->decode(file_get_contents($this->getTestResourcePath('red.gif'))); + $image = $this->decoder->decode(file_get_contents($this->getTestResourcePath('red.gif'))); $this->assertInstanceOf(Image::class, $image); $this->assertEquals(16, $image->width()); $this->assertEquals(16, $image->height()); @@ -36,8 +43,7 @@ final class BinaryImageDecoderTest extends BaseTestCase public function testDecodeAnimatedGif(): void { - $decoder = new BinaryImageDecoder(); - $image = $decoder->decode(file_get_contents($this->getTestResourcePath('cats.gif'))); + $image = $this->decoder->decode(file_get_contents($this->getTestResourcePath('cats.gif'))); $this->assertInstanceOf(Image::class, $image); $this->assertEquals(75, $image->width()); $this->assertEquals(50, $image->height()); @@ -46,8 +52,7 @@ final class BinaryImageDecoderTest extends BaseTestCase public function testDecodeJpegWithExif(): void { - $decoder = new BinaryImageDecoder(); - $image = $decoder->decode(file_get_contents($this->getTestResourcePath('exif.jpg'))); + $image = $this->decoder->decode(file_get_contents($this->getTestResourcePath('exif.jpg'))); $this->assertInstanceOf(Image::class, $image); $this->assertEquals(16, $image->width()); $this->assertEquals(16, $image->height()); diff --git a/tests/Unit/Drivers/Gd/Decoders/DataUriImageDecoderTest.php b/tests/Unit/Drivers/Gd/Decoders/DataUriImageDecoderTest.php index 100fd982..8c2f604e 100644 --- a/tests/Unit/Drivers/Gd/Decoders/DataUriImageDecoderTest.php +++ b/tests/Unit/Drivers/Gd/Decoders/DataUriImageDecoderTest.php @@ -7,6 +7,7 @@ namespace Intervention\Image\Tests\Unit\Drivers\Gd\Decoders; use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\Attributes\RequiresPhpExtension; use Intervention\Image\Drivers\Gd\Decoders\DataUriImageDecoder; +use Intervention\Image\Drivers\Gd\Driver; use Intervention\Image\Exceptions\DecoderException; use Intervention\Image\Image; use Intervention\Image\Tests\BaseTestCase; @@ -21,6 +22,7 @@ final class DataUriImageDecoderTest extends BaseTestCase protected function setUp(): void { $this->decoder = new DataUriImageDecoder(); + $this->decoder->setDriver(new Driver()); } public function testDecode(): void diff --git a/tests/Unit/Drivers/Gd/Decoders/FilePathImageDecoderTest.php b/tests/Unit/Drivers/Gd/Decoders/FilePathImageDecoderTest.php index 0a1a3d95..9a76bd2f 100644 --- a/tests/Unit/Drivers/Gd/Decoders/FilePathImageDecoderTest.php +++ b/tests/Unit/Drivers/Gd/Decoders/FilePathImageDecoderTest.php @@ -7,10 +7,11 @@ namespace Intervention\Image\Tests\Unit\Drivers\Gd\Decoders; use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\Attributes\RequiresPhpExtension; use Intervention\Image\Drivers\Gd\Decoders\FilePathImageDecoder; +use Intervention\Image\Drivers\Gd\Driver; use Intervention\Image\Exceptions\DecoderException; use Intervention\Image\Image; use Intervention\Image\Tests\BaseTestCase; -use stdClass; +use PHPUnit\Framework\Attributes\DataProvider; #[RequiresPhpExtension('gd')] #[CoversClass(\Intervention\Image\Drivers\Gd\Decoders\FilePathImageDecoder::class)] @@ -21,32 +22,35 @@ final class FilePathImageDecoderTest extends BaseTestCase protected function setUp(): void { $this->decoder = new FilePathImageDecoder(); + $this->decoder->setDriver(new Driver()); } - public function testDecode(): void + #[DataProvider('validFormatPathsProvider')] + public function testDecode(string $path, bool $result): void { - $result = $this->decoder->decode( - $this->getTestResourcePath() - ); + if ($result === false) { + $this->expectException(DecoderException::class); + } - $this->assertInstanceOf(Image::class, $result); + $result = $this->decoder->decode($path); + + if ($result === true) { + $this->assertInstanceOf(Image::class, $result); + } } - public function testDecoderNonString(): void + public static function validFormatPathsProvider(): array { - $this->expectException(DecoderException::class); - $this->decoder->decode(new stdClass()); - } - - public function testDecoderNoPath(): void - { - $this->expectException(DecoderException::class); - $this->decoder->decode('no-path'); - } - - public function testDecoderTooLongPath(): void - { - $this->expectException(DecoderException::class); - $this->decoder->decode(str_repeat('x', PHP_MAXPATHLEN + 1)); + return [ + [self::getTestResourcePath('cats.gif'), true], + [self::getTestResourcePath('animation.gif'), true], + [self::getTestResourcePath('red.gif'), true], + [self::getTestResourcePath('green.gif'), true], + [self::getTestResourcePath('blue.gif'), true], + [self::getTestResourcePath('gradient.bmp'), true], + [self::getTestResourcePath('circle.png'), true], + ['no-path', false], + [str_repeat('x', PHP_MAXPATHLEN + 1), false], + ]; } } diff --git a/tests/Unit/Drivers/Gd/Decoders/FilePointerImageDecoderTest.php b/tests/Unit/Drivers/Gd/Decoders/FilePointerImageDecoderTest.php index bf2281bc..e40777ef 100644 --- a/tests/Unit/Drivers/Gd/Decoders/FilePointerImageDecoderTest.php +++ b/tests/Unit/Drivers/Gd/Decoders/FilePointerImageDecoderTest.php @@ -7,6 +7,7 @@ namespace Intervention\Image\Tests\Unit\Drivers\Gd\Decoders; use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\Attributes\RequiresPhpExtension; use Intervention\Image\Drivers\Gd\Decoders\FilePointerImageDecoder; +use Intervention\Image\Drivers\Gd\Driver; use Intervention\Image\Image; use Intervention\Image\Tests\GdTestCase; @@ -17,6 +18,8 @@ final class FilePointerImageDecoderTest extends GdTestCase public function testDecode(): void { $decoder = new FilePointerImageDecoder(); + $decoder->setDriver(new Driver()); + $fp = fopen($this->getTestResourcePath('test.jpg'), 'r'); $result = $decoder->decode($fp); $this->assertInstanceOf(Image::class, $result); diff --git a/tests/Unit/Drivers/Gd/Decoders/SplFileInfoImageDecoderTest.php b/tests/Unit/Drivers/Gd/Decoders/SplFileInfoImageDecoderTest.php index e7517235..d0a5617e 100644 --- a/tests/Unit/Drivers/Gd/Decoders/SplFileInfoImageDecoderTest.php +++ b/tests/Unit/Drivers/Gd/Decoders/SplFileInfoImageDecoderTest.php @@ -7,6 +7,7 @@ namespace Intervention\Image\Tests\Unit\Drivers\Gd\Decoders; use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\Attributes\RequiresPhpExtension; use Intervention\Image\Drivers\Gd\Decoders\SplFileInfoImageDecoder; +use Intervention\Image\Drivers\Gd\Driver; use Intervention\Image\Image; use Intervention\Image\Tests\BaseTestCase; use SplFileInfo; @@ -18,6 +19,8 @@ final class SplFileInfoImageDecoderTest extends BaseTestCase public function testDecode(): void { $decoder = new SplFileInfoImageDecoder(); + $decoder->setDriver(new Driver()); + $result = $decoder->decode( new SplFileInfo($this->getTestResourcePath('blue.gif')) ); diff --git a/tests/Unit/Drivers/Gd/Traits/CanDecodeGifTest.php b/tests/Unit/Drivers/Gd/Traits/CanDecodeGifTest.php deleted file mode 100644 index f8cdafe8..00000000 --- a/tests/Unit/Drivers/Gd/Traits/CanDecodeGifTest.php +++ /dev/null @@ -1,57 +0,0 @@ -makePartial(); - - $result = $decoder->decodeGif($this->getTestResourceData('animation.gif')); - $this->assertInstanceOf(ImageInterface::class, $result); - $this->assertEquals('image/gif', $result->origin()->mediaType()); - } - - public function testDecodeGifFromBinaryStatic(): void - { - $decoder = Mockery::mock(new class () { - use CanDecodeGif; - })->makePartial(); - - $result = $decoder->decodeGif($this->getTestResourceData('red.gif')); - $this->assertInstanceOf(ImageInterface::class, $result); - $this->assertEquals('image/gif', $result->origin()->mediaType()); - } - - public function testDecodeGifFromPathAnimation(): void - { - $decoder = Mockery::mock(new class () { - use CanDecodeGif; - })->makePartial(); - - $result = $decoder->decodeGif($this->getTestResourcePath('animation.gif')); - $this->assertInstanceOf(ImageInterface::class, $result); - $this->assertEquals('image/gif', $result->origin()->mediaType()); - } - - public function testDecodeGifFromPathStatic(): void - { - $decoder = Mockery::mock(new class () { - use CanDecodeGif; - })->makePartial(); - - $result = $decoder->decodeGif($this->getTestResourcePath('red.gif')); - $this->assertInstanceOf(ImageInterface::class, $result); - $this->assertEquals('image/gif', $result->origin()->mediaType()); - } -} diff --git a/tests/Unit/Drivers/Imagick/Decoders/Base64ImageDecoderTest.php b/tests/Unit/Drivers/Imagick/Decoders/Base64ImageDecoderTest.php index 82910d26..d4f622eb 100644 --- a/tests/Unit/Drivers/Imagick/Decoders/Base64ImageDecoderTest.php +++ b/tests/Unit/Drivers/Imagick/Decoders/Base64ImageDecoderTest.php @@ -7,6 +7,7 @@ namespace Intervention\Image\Tests\Unit\Drivers\Imagick\Decoders; use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\Attributes\RequiresPhpExtension; use Intervention\Image\Drivers\Imagick\Decoders\Base64ImageDecoder; +use Intervention\Image\Drivers\Imagick\Driver; use Intervention\Image\Exceptions\DecoderException; use Intervention\Image\Image; use Intervention\Image\Tests\BaseTestCase; @@ -20,6 +21,7 @@ final class Base64ImageDecoderTest extends BaseTestCase protected function setUp(): void { $this->decoder = new Base64ImageDecoder(); + $this->decoder->setDriver(new Driver()); } public function testDecode(): void diff --git a/tests/Unit/Drivers/Imagick/Decoders/BinaryImageDecoderTest.php b/tests/Unit/Drivers/Imagick/Decoders/BinaryImageDecoderTest.php index 6cab39a4..2b221166 100644 --- a/tests/Unit/Drivers/Imagick/Decoders/BinaryImageDecoderTest.php +++ b/tests/Unit/Drivers/Imagick/Decoders/BinaryImageDecoderTest.php @@ -7,6 +7,7 @@ namespace Intervention\Image\Tests\Unit\Drivers\Imagick\Decoders; use Intervention\Image\Colors\Cmyk\Colorspace as CmykColorspace; use Intervention\Image\Colors\Rgb\Colorspace as RgbColorspace; use Intervention\Image\Drivers\Imagick\Decoders\BinaryImageDecoder; +use Intervention\Image\Drivers\Imagick\Driver; use Intervention\Image\Exceptions\DecoderException; use Intervention\Image\Image; use Intervention\Image\Tests\BaseTestCase; @@ -14,10 +15,17 @@ use stdClass; final class BinaryImageDecoderTest extends BaseTestCase { + protected BinaryImageDecoder $decoder; + + protected function setUp(): void + { + $this->decoder = new BinaryImageDecoder(); + $this->decoder->setDriver(new Driver()); + } + public function testDecodePng(): void { - $decoder = new BinaryImageDecoder(); - $image = $decoder->decode(file_get_contents($this->getTestResourcePath('tile.png'))); + $image = $this->decoder->decode(file_get_contents($this->getTestResourcePath('tile.png'))); $this->assertInstanceOf(Image::class, $image); $this->assertInstanceOf(RgbColorspace::class, $image->colorspace()); $this->assertEquals(16, $image->width()); @@ -27,8 +35,7 @@ final class BinaryImageDecoderTest extends BaseTestCase public function testDecodeGif(): void { - $decoder = new BinaryImageDecoder(); - $image = $decoder->decode(file_get_contents($this->getTestResourcePath('red.gif'))); + $image = $this->decoder->decode(file_get_contents($this->getTestResourcePath('red.gif'))); $this->assertInstanceOf(Image::class, $image); $this->assertEquals(16, $image->width()); $this->assertEquals(16, $image->height()); @@ -37,8 +44,7 @@ final class BinaryImageDecoderTest extends BaseTestCase public function testDecodeAnimatedGif(): void { - $decoder = new BinaryImageDecoder(); - $image = $decoder->decode(file_get_contents($this->getTestResourcePath('cats.gif'))); + $image = $this->decoder->decode(file_get_contents($this->getTestResourcePath('cats.gif'))); $this->assertInstanceOf(Image::class, $image); $this->assertEquals(75, $image->width()); $this->assertEquals(50, $image->height()); @@ -47,8 +53,7 @@ final class BinaryImageDecoderTest extends BaseTestCase public function testDecodeJpegWithExif(): void { - $decoder = new BinaryImageDecoder(); - $image = $decoder->decode(file_get_contents($this->getTestResourcePath('exif.jpg'))); + $image = $this->decoder->decode(file_get_contents($this->getTestResourcePath('exif.jpg'))); $this->assertInstanceOf(Image::class, $image); $this->assertEquals(16, $image->width()); $this->assertEquals(16, $image->height()); @@ -58,16 +63,14 @@ final class BinaryImageDecoderTest extends BaseTestCase public function testDecodeCmykImage(): void { - $decoder = new BinaryImageDecoder(); - $image = $decoder->decode(file_get_contents($this->getTestResourcePath('cmyk.jpg'))); + $image = $this->decoder->decode(file_get_contents($this->getTestResourcePath('cmyk.jpg'))); $this->assertInstanceOf(Image::class, $image); $this->assertInstanceOf(CmykColorspace::class, $image->colorspace()); } public function testDecodeNonString(): void { - $decoder = new BinaryImageDecoder(); $this->expectException(DecoderException::class); - $decoder->decode(new stdClass()); + $this->decoder->decode(new stdClass()); } } diff --git a/tests/Unit/Drivers/Imagick/Decoders/DataUriImageDecoderTest.php b/tests/Unit/Drivers/Imagick/Decoders/DataUriImageDecoderTest.php index 1a4ca500..db8de4d5 100644 --- a/tests/Unit/Drivers/Imagick/Decoders/DataUriImageDecoderTest.php +++ b/tests/Unit/Drivers/Imagick/Decoders/DataUriImageDecoderTest.php @@ -7,6 +7,7 @@ namespace Intervention\Image\Tests\Unit\Drivers\Imagick\Decoders; use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\Attributes\RequiresPhpExtension; use Intervention\Image\Drivers\Imagick\Decoders\DataUriImageDecoder; +use Intervention\Image\Drivers\Imagick\Driver; use Intervention\Image\Exceptions\DecoderException; use Intervention\Image\Image; use Intervention\Image\Tests\BaseTestCase; @@ -21,6 +22,7 @@ final class DataUriImageDecoderTest extends BaseTestCase protected function setUp(): void { $this->decoder = new DataUriImageDecoder(); + $this->decoder->setDriver(new Driver()); } public function testDecode(): void diff --git a/tests/Unit/Drivers/Imagick/Decoders/FilePathImageDecoderTest.php b/tests/Unit/Drivers/Imagick/Decoders/FilePathImageDecoderTest.php index 2a8ffcd6..8e5cd768 100644 --- a/tests/Unit/Drivers/Imagick/Decoders/FilePathImageDecoderTest.php +++ b/tests/Unit/Drivers/Imagick/Decoders/FilePathImageDecoderTest.php @@ -7,10 +7,11 @@ namespace Intervention\Image\Tests\Unit\Drivers\Imagick\Decoders; use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\Attributes\RequiresPhpExtension; use Intervention\Image\Drivers\Imagick\Decoders\FilePathImageDecoder; +use Intervention\Image\Drivers\Imagick\Driver; use Intervention\Image\Exceptions\DecoderException; use Intervention\Image\Image; use Intervention\Image\Tests\BaseTestCase; -use stdClass; +use PHPUnit\Framework\Attributes\DataProvider; #[RequiresPhpExtension('imagick')] #[CoversClass(\Intervention\Image\Drivers\Imagick\Decoders\FilePathImageDecoder::class)] @@ -21,32 +22,35 @@ final class FilePathImageDecoderTest extends BaseTestCase protected function setUp(): void { $this->decoder = new FilePathImageDecoder(); + $this->decoder->setDriver(new Driver()); } - public function testDecode(): void + #[DataProvider('validFormatPathsProvider')] + public function testDecode(string $path, bool $result): void { - $result = $this->decoder->decode( - $this->getTestResourcePath() - ); + if ($result === false) { + $this->expectException(DecoderException::class); + } - $this->assertInstanceOf(Image::class, $result); + $result = $this->decoder->decode($path); + + if ($result === true) { + $this->assertInstanceOf(Image::class, $result); + } } - public function testDecoderNonString(): void + public static function validFormatPathsProvider(): array { - $this->expectException(DecoderException::class); - $this->decoder->decode(new stdClass()); - } - - public function testDecoderNoPath(): void - { - $this->expectException(DecoderException::class); - $this->decoder->decode('no-path'); - } - - public function testDecoderTooLongPath(): void - { - $this->expectException(DecoderException::class); - $this->decoder->decode(str_repeat('x', PHP_MAXPATHLEN + 1)); + return [ + [self::getTestResourcePath('cats.gif'), true], + [self::getTestResourcePath('animation.gif'), true], + [self::getTestResourcePath('red.gif'), true], + [self::getTestResourcePath('green.gif'), true], + [self::getTestResourcePath('blue.gif'), true], + [self::getTestResourcePath('gradient.bmp'), true], + [self::getTestResourcePath('circle.png'), true], + ['no-path', false], + [str_repeat('x', PHP_MAXPATHLEN + 1), false], + ]; } } diff --git a/tests/Unit/Drivers/Imagick/Decoders/FilePointerImageDecoderTest.php b/tests/Unit/Drivers/Imagick/Decoders/FilePointerImageDecoderTest.php index 8165b3c2..15724014 100644 --- a/tests/Unit/Drivers/Imagick/Decoders/FilePointerImageDecoderTest.php +++ b/tests/Unit/Drivers/Imagick/Decoders/FilePointerImageDecoderTest.php @@ -7,6 +7,7 @@ namespace Intervention\Image\Tests\Unit\Drivers\Imagick\Decoders; use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\Attributes\RequiresPhpExtension; use Intervention\Image\Drivers\Imagick\Decoders\FilePointerImageDecoder; +use Intervention\Image\Drivers\Imagick\Driver; use Intervention\Image\Image; use Intervention\Image\Tests\ImagickTestCase; @@ -17,6 +18,7 @@ final class FilePointerImageDecoderTest extends ImagickTestCase public function testDecode(): void { $decoder = new FilePointerImageDecoder(); + $decoder->setDriver(new Driver()); $fp = fopen($this->getTestResourcePath('test.jpg'), 'r'); $result = $decoder->decode($fp); $this->assertInstanceOf(Image::class, $result); diff --git a/tests/Unit/Drivers/Imagick/Decoders/SplFileInfoImageDecoderTest.php b/tests/Unit/Drivers/Imagick/Decoders/SplFileInfoImageDecoderTest.php index 3e549909..c4c26c86 100644 --- a/tests/Unit/Drivers/Imagick/Decoders/SplFileInfoImageDecoderTest.php +++ b/tests/Unit/Drivers/Imagick/Decoders/SplFileInfoImageDecoderTest.php @@ -7,6 +7,7 @@ namespace Intervention\Image\Tests\Unit\Drivers\Imagick\Decoders; use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\Attributes\RequiresPhpExtension; use Intervention\Image\Drivers\Imagick\Decoders\SplFileInfoImageDecoder; +use Intervention\Image\Drivers\Imagick\Driver; use Intervention\Image\Image; use Intervention\Image\Tests\BaseTestCase; use SplFileInfo; @@ -18,6 +19,7 @@ final class SplFileInfoImageDecoderTest extends BaseTestCase public function testDecode(): void { $decoder = new SplFileInfoImageDecoder(); + $decoder->setDriver(new Driver()); $result = $decoder->decode( new SplFileInfo($this->getTestResourcePath('blue.gif')) );