From e8d9f9f496cef23751406abc6ca9c37ae3ffb43a Mon Sep 17 00:00:00 2001 From: Dennis van Dalen Date: Mon, 15 Jul 2024 11:48:31 +0200 Subject: [PATCH] Check for enum instances when applying manipulations (#3661) * Switch match to switch-case in apply method and check for enum instances * Add tests --- src/Conversions/Manipulations.php | 69 +++++++++++++--- tests/Conversions/ImageManipulationTest.php | 90 +++++++++++++++++++++ 2 files changed, 147 insertions(+), 12 deletions(-) create mode 100644 tests/Conversions/ImageManipulationTest.php diff --git a/src/Conversions/Manipulations.php b/src/Conversions/Manipulations.php index 6c528b842..637682901 100644 --- a/src/Conversions/Manipulations.php +++ b/src/Conversions/Manipulations.php @@ -5,7 +5,6 @@ use Spatie\Image\Drivers\ImageDriver; use Spatie\Image\Enums\AlignPosition; use Spatie\Image\Enums\BorderType; -use Spatie\Image\Enums\ColorFormat; use Spatie\Image\Enums\Constraint; use Spatie\Image\Enums\CropPosition; use Spatie\Image\Enums\Fit; @@ -59,17 +58,7 @@ public function isEmpty(): bool public function apply(ImageDriver $image): void { foreach ($this->manipulations as $manipulationName => $parameters) { - match ($manipulationName) { - 'border' => (isset($parameters['type'])) && $parameters['type'] = BorderType::from($parameters['type']), - 'watermark' => (isset($parameters['fit'])) && $parameters['fit'] = Fit::from($parameters['fit']), - 'watermark','resizeCanvas','insert' => (isset($parameters['position'])) && $parameters['position'] = AlignPosition::from($parameters['position']), - 'pickColor' => (isset($parameters['colorFormat'])) && $parameters['colorFormat'] = ColorFormat::from($parameters['colorFormat']), - 'resize','width','height' => (isset($parameters['constraints'])) && $parameters['constraints'] = Constraint::from($parameters['constraints']), - 'crop' => (isset($parameters['position'])) && $parameters['position'] = CropPosition::from($parameters['position']), - 'fit' => (isset($parameters['fit'])) && $parameters['fit'] = Fit::from($parameters['fit']), - 'flip' => (isset($parameters['flip'])) && $parameters['flip'] = FlipDirection::from($parameters['flip']), - default => '' - }; + $parameters = $this->transformParameters($manipulationName, $parameters); $image->$manipulationName(...$parameters); } } @@ -94,4 +83,60 @@ public function toArray(): array { return $this->manipulations; } + + /** + * @param int|string $manipulationName + * @param mixed $parameters + * @return mixed + */ + public function transformParameters(int|string $manipulationName, mixed $parameters): mixed + { + switch ($manipulationName) { + case 'border': + if (isset($parameters['type']) && !$parameters['type'] instanceof BorderType) { + $parameters['type'] = BorderType::from($parameters['type']); + } + break; + case 'watermark': + if (isset($parameters['fit']) && !$parameters['fit'] instanceof Fit) { + $parameters['fit'] = Fit::from($parameters['fit']); + } + // Fallthrough intended for position + case 'resizeCanvas': + case 'insert': + if (isset($parameters['position']) && !$parameters['position'] instanceof AlignPosition) { + $parameters['position'] = AlignPosition::from($parameters['position']); + } + break; + case 'resize': + case 'width': + case 'height': + if (isset($parameters['constraints']) && is_array($parameters['constraints'])) { + foreach ($parameters['constraints'] as &$constraint) { + if (!$constraint instanceof Constraint) { + $constraint = Constraint::from($constraint); + } + } + } + break; + case 'crop': + if (isset($parameters['position']) && !$parameters['position'] instanceof CropPosition) { + $parameters['position'] = CropPosition::from($parameters['position']); + } + break; + case 'fit': + if (isset($parameters['fit']) && !$parameters['fit'] instanceof Fit) { + $parameters['fit'] = Fit::from($parameters['fit']); + } + break; + case 'flip': + if (isset($parameters['flip']) && !$parameters['flip'] instanceof FlipDirection) { + $parameters['flip'] = FlipDirection::from($parameters['flip']); + } + break; + default: + break; + } + return $parameters; + } } diff --git a/tests/Conversions/ImageManipulationTest.php b/tests/Conversions/ImageManipulationTest.php new file mode 100644 index 000000000..6904602f1 --- /dev/null +++ b/tests/Conversions/ImageManipulationTest.php @@ -0,0 +1,90 @@ +getTestJpg()); + + // Define manipulations + $manipulations = [ + 'border' => ['width' => 10, 'type' => 'expand'], + 'watermark' => ['fit' => 'contain', 'watermarkImage' => $this->getTestPng()], + 'resizeCanvas' => ['position' => 'center'], + 'resize' => ['constraints' => ['preserveAspectRatio'], 'width' => 100, 'height' => 100], + 'crop' => ['width' => 50, 'height'=> 50, 'position' => 'topLeft'], + 'fit' => ['fit' => 'contain'], + 'flip' => ['flip' => 'horizontal'], + ]; + + $transformedParameters = []; + + // Create an instance of the class containing the logic + $manipulator = new Manipulations($manipulations); + + foreach ($manipulations as $manipulationName => $parameters) { + $parameters = $manipulator->transformParameters($manipulationName, $parameters); + + // Apply the manipulation + $image->$manipulationName(...$parameters); + + // Store the transformed parameters for assertions + $transformedParameters[$manipulationName] = $parameters; + } + + // Assertions to check if parameters have been correctly transformed + expect($transformedParameters['border']['type'])->toBeInstanceOf(BorderType::class) + ->and($transformedParameters['watermark']['fit'])->toBeInstanceOf(Fit::class) + ->and($transformedParameters['resizeCanvas']['position'])->toBeInstanceOf(AlignPosition::class) + ->and($transformedParameters['resize']['constraints'][0])->toBeInstanceOf(Constraint::class) + ->and($transformedParameters['crop']['position'])->toBeInstanceOf(CropPosition::class) + ->and($transformedParameters['fit']['fit'])->toBeInstanceOf(Fit::class) + ->and($transformedParameters['flip']['flip'])->toBeInstanceOf(FlipDirection::class); +}); + +it('handles parameters that are already enum instances', function () { + // Mock the image object + $image = Image::load(pathToImage: $this->getTestJpg()); + + // Define manipulations with parameters already as enum instances + $manipulations = [ + 'border' => ['width' => 10, 'type' => BorderType::Expand], + 'watermark' => ['fit' => Fit::Contain, 'watermarkImage' => $this->getTestPng()], + 'resizeCanvas' => ['position' => AlignPosition::Center], + 'resize' => ['constraints' => [Constraint::PreserveAspectRatio], 'width' => 100, 'height' => 100], + 'crop' => ['width' => 50, 'height'=> 50, 'position' => CropPosition::TopLeft], + 'fit' => ['fit' => Fit::Contain], + 'flip' => ['flip' => FlipDirection::Horizontal], + ]; + + $transformedParameters = []; + + // Create an instance of the class containing the logic + $manipulator = new Manipulations($manipulations); + + foreach ($manipulations as $manipulationName => $parameters) { + $parameters = $manipulator->transformParameters($manipulationName, $parameters); + + // Apply the manipulation + $image->$manipulationName(...$parameters); + + // Store the transformed parameters for assertions + $transformedParameters[$manipulationName] = $parameters; + } + + // Assertions to check if parameters remain unchanged + expect($transformedParameters['border']['type'])->toBeInstanceOf(BorderType::class) + ->and($transformedParameters['watermark']['fit'])->toBeInstanceOf(Fit::class) + ->and($transformedParameters['resizeCanvas']['position'])->toBeInstanceOf(AlignPosition::class) + ->and($transformedParameters['resize']['constraints'][0])->toBeInstanceOf(Constraint::class) + ->and($transformedParameters['crop']['position'])->toBeInstanceOf(CropPosition::class) + ->and($transformedParameters['fit']['fit'])->toBeInstanceOf(Fit::class) + ->and($transformedParameters['flip']['flip'])->toBeInstanceOf(FlipDirection::class); +});