From b79650acee726d3aee719de161f45ef67c404408 Mon Sep 17 00:00:00 2001 From: Oliver Vogel Date: Fri, 10 May 2024 10:04:11 +0200 Subject: [PATCH] Refactor config handling --- src/Config.php | 63 ++++++++++++------- src/Drivers/AbstractDriver.php | 9 ++- .../Gd/Decoders/BinaryImageDecoder.php | 2 +- .../Gd/Decoders/FilePathImageDecoder.php | 2 +- .../Gd/Decoders/NativeObjectDecoder.php | 2 +- .../Imagick/Decoders/NativeObjectDecoder.php | 4 +- src/Image.php | 5 +- src/ImageManager.php | 21 +++---- src/Interfaces/ConfigInterface.php | 31 +++++++-- tests/Unit/ConfigTest.php | 53 +++++++++++++++- 10 files changed, 143 insertions(+), 49 deletions(-) diff --git a/src/Config.php b/src/Config.php index 10c1a685..5b7a4b86 100644 --- a/src/Config.php +++ b/src/Config.php @@ -4,10 +4,19 @@ declare(strict_types=1); namespace Intervention\Image; +use Intervention\Image\Exceptions\InputException; use Intervention\Image\Interfaces\ConfigInterface; class Config implements ConfigInterface { + /** + * Create config object instance + * + * @param bool $autoOrientation + * @param bool $decodeAnimation + * @param mixed $blendingColor + * @return void + */ public function __construct( protected bool $autoOrientation = true, protected bool $decodeAnimation = true, @@ -15,38 +24,46 @@ class Config implements ConfigInterface ) { } - public function decodeAnimation(): bool + /** + * {@inheritdoc} + * + * @see ConfigInterface::option() + */ + public function option(string $name, mixed $default = null): mixed { - return $this->decodeAnimation; + if (!property_exists($this, $name)) { + return $default; + } + + return $this->{$name}; } - public function setDecodeAnimation(bool $status): self + /** + * {@inheritdoc} + * + * @see ConfigInterface::setOption() + */ + public function setOption(string $name, mixed $value): self { - $this->decodeAnimation = $status; + if (!property_exists($this, $name)) { + throw new InputException('Property ' . $name . ' does not exists for ' . $this::class . '.'); + } + + $this->{$name} = $value; return $this; } - public function autoOrientation(): bool + /** + * {@inheritdoc} + * + * @see COnfigInterface::setOptions() + */ + public function setOptions(mixed ...$options): self { - 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; + foreach ($options as $name => $value) { + $this->setOption($name, $value); + } return $this; } diff --git a/src/Drivers/AbstractDriver.php b/src/Drivers/AbstractDriver.php index b2db442e..1ccd79fd 100644 --- a/src/Drivers/AbstractDriver.php +++ b/src/Drivers/AbstractDriver.php @@ -23,12 +23,17 @@ use ReflectionClass; abstract class AbstractDriver implements DriverInterface { /** - * @param ConfigInterface $config + * Driver options + */ + protected ConfigInterface $config; + + /** * @throws DriverException * @return void */ - public function __construct(protected ConfigInterface $config = new Config()) + public function __construct() { + $this->config = new Config(); $this->checkHealth(); } diff --git a/src/Drivers/Gd/Decoders/BinaryImageDecoder.php b/src/Drivers/Gd/Decoders/BinaryImageDecoder.php index c4f43749..b775eb09 100644 --- a/src/Drivers/Gd/Decoders/BinaryImageDecoder.php +++ b/src/Drivers/Gd/Decoders/BinaryImageDecoder.php @@ -60,7 +60,7 @@ class BinaryImageDecoder extends NativeObjectDecoder implements DecoderInterface } // adjust image orientation - if ($this->driver()->config()->autoOrientation()) { + if ($this->driver()->config()->option('autoOrientation') === true) { $image->modify(new AlignRotationModifier()); } diff --git a/src/Drivers/Gd/Decoders/FilePathImageDecoder.php b/src/Drivers/Gd/Decoders/FilePathImageDecoder.php index e1606a85..e3f1780e 100644 --- a/src/Drivers/Gd/Decoders/FilePathImageDecoder.php +++ b/src/Drivers/Gd/Decoders/FilePathImageDecoder.php @@ -50,7 +50,7 @@ class FilePathImageDecoder extends NativeObjectDecoder implements DecoderInterfa $image->setExif($this->extractExifData($input)); // adjust image orientation - if ($this->driver()->config()->autoOrientation()) { + if ($this->driver()->config()->option('autoOrientation') === true) { $image->modify(new AlignRotationModifier()); } diff --git a/src/Drivers/Gd/Decoders/NativeObjectDecoder.php b/src/Drivers/Gd/Decoders/NativeObjectDecoder.php index cf853598..d0e48381 100644 --- a/src/Drivers/Gd/Decoders/NativeObjectDecoder.php +++ b/src/Drivers/Gd/Decoders/NativeObjectDecoder.php @@ -60,7 +60,7 @@ class NativeObjectDecoder extends AbstractDecoder protected function decodeGif(mixed $input): ImageInterface { // create non-animated image depending on config - if (!$this->driver()->config()->decodeAnimation()) { + if (!$this->driver()->config()->option('decodeAnimation') === true) { $native = match (true) { $this->isGifFormat($input) => @imagecreatefromstring($input), default => @imagecreatefromgif($input), diff --git a/src/Drivers/Imagick/Decoders/NativeObjectDecoder.php b/src/Drivers/Imagick/Decoders/NativeObjectDecoder.php index d1ae00f3..4c399c7b 100644 --- a/src/Drivers/Imagick/Decoders/NativeObjectDecoder.php +++ b/src/Drivers/Imagick/Decoders/NativeObjectDecoder.php @@ -40,12 +40,12 @@ class NativeObjectDecoder extends SpecializableDecoder ); // discard animation depending on config - if (!$this->driver()->config()->decodeAnimation()) { + if (!$this->driver()->config()->option('decodeAnimation') === true) { $image->modify(new RemoveAnimationModifier()); } // adjust image rotatation - if ($this->driver()->config()->autoOrientation()) { + if ($this->driver()->config()->option('autoOrientation') === true) { $image->modify(new AlignRotationModifier()); } diff --git a/src/Image.php b/src/Image.php index 124af013..ba02c061 100644 --- a/src/Image.php +++ b/src/Image.php @@ -408,7 +408,7 @@ final class Image implements ImageInterface public function blendingColor(): ColorInterface { return $this->driver()->handleInput( - $this->driver()->config()->blendingColor() + $this->driver()->config()->option('blendingColor') ); } @@ -419,7 +419,8 @@ final class Image implements ImageInterface */ public function setBlendingColor(mixed $color): ImageInterface { - $this->driver()->config()->setBlendingColor( + $this->driver()->config()->setOption( + 'blendingColor', $this->driver()->handleInput($color) ); diff --git a/src/ImageManager.php b/src/ImageManager.php index 10327ca8..18fcf8dd 100644 --- a/src/ImageManager.php +++ b/src/ImageManager.php @@ -20,9 +20,9 @@ final class ImageManager implements ImageManagerInterface * @link https://image.intervention.io/v3/basics/image-manager#create-a-new-image-manager-instance * @param string|DriverInterface $driver */ - public function __construct(string|DriverInterface $driver) + public function __construct(string|DriverInterface $driver, mixed ...$options) { - $this->driver = $this->resolveDriver($driver); + $this->driver = $this->resolveDriver($driver, ...$options); } /** @@ -32,9 +32,9 @@ final class ImageManager implements ImageManagerInterface * @param string|DriverInterface $driver * @return ImageManager */ - public static function withDriver(string|DriverInterface $driver): self + public static function withDriver(string|DriverInterface $driver, mixed ...$options): self { - return new self(self::resolveDriver($driver)); + return new self(self::resolveDriver($driver, ...$options)); } /** @@ -47,7 +47,7 @@ final class ImageManager implements ImageManagerInterface */ public static function gd(mixed ...$options): self { - return self::withDriver(new GdDriver(new Config(...$options))); + return self::withDriver(new GdDriver(), ...$options); } /** @@ -60,7 +60,7 @@ final class ImageManager implements ImageManagerInterface */ public static function imagick(mixed ...$options): self { - return self::withDriver(new ImagickDriver(new Config(...$options))); + return self::withDriver(new ImagickDriver(), ...$options); } /** @@ -115,12 +115,11 @@ final class ImageManager implements ImageManagerInterface * @param string|DriverInterface $driver * @return DriverInterface */ - private static function resolveDriver(string|DriverInterface $driver): DriverInterface + private static function resolveDriver(string|DriverInterface $driver, mixed ...$options): DriverInterface { - if (is_object($driver)) { - return $driver; - } + $driver = is_string($driver) ? new $driver() : $driver; + $driver->config()->setOptions(...$options); - return new $driver(); + return $driver; } } diff --git a/src/Interfaces/ConfigInterface.php b/src/Interfaces/ConfigInterface.php index 67cedb06..0fe2ebff 100644 --- a/src/Interfaces/ConfigInterface.php +++ b/src/Interfaces/ConfigInterface.php @@ -4,13 +4,34 @@ declare(strict_types=1); namespace Intervention\Image\Interfaces; +use Intervention\Image\Exceptions\InputException; + interface ConfigInterface { - public function decodeAnimation(): bool; + /** + * Return value of given config option + * + * @param string $name + * @return mixed + */ + public function option(string $name, mixed $default = null): mixed; - public function autoOrientation(): bool; + /** + * Set value of given config option + * + * @param string $name + * @param mixed $value + * @throws InputException + * @return ConfigInterface + */ + public function setOption(string $name, mixed $value): self; - public function blendingColor(): mixed; - - public function setBlendingColor(mixed $color): mixed; + /** + * Set values of given config options + * + * @param mixed $options + * @throws InputException + * @return ConfigInterface + */ + public function setOptions(mixed ...$options): self; } diff --git a/tests/Unit/ConfigTest.php b/tests/Unit/ConfigTest.php index 45166c7e..700a6e2e 100644 --- a/tests/Unit/ConfigTest.php +++ b/tests/Unit/ConfigTest.php @@ -13,6 +13,57 @@ final class ConfigTest extends BaseTestCase { public function testConstructor(): void { - $this->assertInstanceOf(Config::class, new Config()); + $config = new Config(); + $this->assertInstanceOf(Config::class, $config); + + $this->assertTrue($config->option('autoOrientation')); + $this->assertTrue($config->option('decodeAnimation')); + $this->assertEquals('ffffff00', $config->option('blendingColor')); + + $config = new Config( + autoOrientation: false, + decodeAnimation: false, + blendingColor: 'f00', + ); + $this->assertInstanceOf(Config::class, $config); + + $this->assertFalse($config->option('autoOrientation')); + $this->assertFalse($config->option('decodeAnimation')); + $this->assertEquals('f00', $config->option('blendingColor')); + } + + public function testGetSetOptions(): void + { + $config = new Config(); + $this->assertTrue($config->option('autoOrientation')); + $this->assertTrue($config->option('decodeAnimation')); + $this->assertEquals('ffffff00', $config->option('blendingColor')); + + $result = $config->setOptions( + autoOrientation: false, + decodeAnimation: false, + blendingColor: 'f00', + ); + + $this->assertFalse($config->option('autoOrientation')); + $this->assertFalse($config->option('decodeAnimation')); + $this->assertEquals('f00', $config->option('blendingColor')); + + $this->assertFalse($result->option('autoOrientation')); + $this->assertFalse($result->option('decodeAnimation')); + $this->assertEquals('f00', $result->option('blendingColor')); + + $result = $config->setOption('blendingColor', '000'); + + $this->assertFalse($config->option('autoOrientation')); + $this->assertFalse($config->option('decodeAnimation')); + $this->assertEquals('000', $config->option('blendingColor')); + + $this->assertFalse($result->option('autoOrientation')); + $this->assertFalse($result->option('decodeAnimation')); + $this->assertEquals('000', $result->option('blendingColor')); + + $this->assertNull($config->option('unknown')); + $this->assertEquals('test', $config->option('unknown', 'test')); } }