ImageResizerService::cropAndResize()   A
last analyzed

Complexity

Conditions 5
Paths 8

Size

Total Lines 25
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 5
eloc 9
c 1
b 0
f 0
nc 8
nop 8
dl 0
loc 25
rs 9.6111

How to fix   Many Parameters   

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

1
<?php
2
3
namespace Rvdlee\ZfImageResizer\Service;
4
5
use Exception;
6
use Rvdlee\ZfImageResizer\Exception\InvalidArgumentException;
7
use Rvdlee\ZfImageResizer\Interfaces\ImageResizerInterface;
8
use Rvdlee\ZfImageResizer\Model\Image;
9
use Zend\Log\LoggerInterface;
10
11
class ImageResizerService
12
{
13
    /**
14
     * @var ImageResizerInterface
15
     */
16
    protected $adapter;
17
18
    /**
19
     * @var LoggerInterface
20
     */
21
    protected $logger;
22
23
    /**
24
     * @param ImageResizerInterface $adapter
25
     *
26
     * @throws InvalidArgumentException
27
     */
28
    public function __construct(ImageResizerInterface $adapter, LoggerInterface $logger)
29
    {
30
        $this->setLogger($logger);
31
        $this->getLogger()->info('Constucting ImageResizerService');
32
        $this->setAdapter($adapter);
33
    }
34
35
    /**
36
     * @param string $imagePath
37
     * @param int    $newWidth
38
     * @param int    $newHeight
39
     * @param bool   $returnBase64
40
     * @return string
41
     * @throws InvalidArgumentException
42
     */
43
    public function resizeImage(string $imagePath, int $newWidth = 0, int $newHeight = 0, bool $returnBase64 = false): string
44
    {
45
        /** @var Image $image */
46
        $image = new Image($imagePath, $newWidth, $newHeight);
47
48
        /**
49
         * If the image already exists, return the path and notify via logger
50
         */
51
        if (file_exists($image->getTargetPath())) {
52
            $this->getLogger()->info('Image already exists, not resizing...');
53
            return $image->getTargetPath();
54
        }
55
56
        try {
57
            if ($this->getAdapter()->canHandle($imagePath)) {
58
                /** @var string $command */
59
                $command = $this->getAdapter()->resizeCommand($image, $returnBase64);
60
61
                $this->getLogger()->info(sprintf('Handling %s via %s', $imagePath, get_class($this->getAdapter())));
62
                $output = shell_exec(sprintf('%s 2>&1', $command));
63
                $this->getLogger()->info($output);
64
            }
65
        } catch (Exception $exception) {
66
            $this->getLogger()->err(
67
                sprintf('Exception when handling %s to via %s', $imagePath, get_class($this->getAdapter()))
68
            );
69
        }
70
71
        return $image->getTargetPath();
72
    }
73
74
    /**
75
     * @param string $imagePath
76
     * @param int    $cropWidth
77
     * @param int    $cropHeight
78
     * @param string $mode
79
     * @param int    $x
80
     * @param int    $y
81
     * @return string
82
     * @throws InvalidArgumentException
83
     */
84
    public function cropImage(string $imagePath, int $cropWidth, int $cropHeight, string $mode = Image::MANUAL_CROP, int $x = 0, int $y = 0): string
85
    {
86
        /** @var Image $image */
87
        $image = new Image($imagePath, $cropWidth, $cropHeight, $mode, $x, $y);
88
89
        /**
90
         * If the image already exists, return the path and notify via logger
91
         */
92
        if (file_exists($image->getTargetPath())) {
93
            $this->getLogger()->info('Image already exists, not resizing...');
94
            return $image->getTargetPath();
95
        }
96
97
        try {
98
            if ($this->getAdapter()->canHandle($imagePath)) {
99
                /** @var string $command */
100
                $command = $this->getAdapter()->cropCommand($image, $mode, $x, $y);
101
102
                $this->getLogger()->info(sprintf('Handling %s via %s', $imagePath, get_class($this->getAdapter())));
103
                $output = shell_exec(sprintf('%s 2>&1', $command));
104
                $this->getLogger()->info($output);
105
            }
106
        } catch (Exception $exception) {
107
            $this->getLogger()->err(
108
                sprintf('Exception when handling %s to via %s', $imagePath, get_class($this->getAdapter()))
109
            );
110
        }
111
112
        return $image->getTargetPath();
113
    }
114
115
    /**
116
     * @param string $imagePath
117
     * @param int    $cropWidth
118
     * @param int    $cropHeight
119
     * @param int    $finalWidth
120
     * @param int    $finalHeight
121
     * @param string $mode
122
     * @param int    $x
123
     * @param int    $y
124
     * @return string
125
     * @throws InvalidArgumentException
126
     */
127
    public function cropAndResize(string $imagePath, int $cropWidth, int $cropHeight, int $finalWidth, int $finalHeight, string $mode = Image::MANUAL_CROP, int $x = 0, int $y = 0): string
128
    {
129
        // If final width has not been set, set it to the cropWidth as a fallback
130
        if ($finalWidth === 0) {
131
            $finalWidth = $cropWidth;
132
        }
133
        // If final width has not been set, set it to the cropHeight as a fallback
134
        if ($finalWidth === 0) {
135
            $finalWidth = $cropWidth;
136
        }
137
138
        // First crop the image at the highest possible resolution for best effect
139
        $resized = $resizedCropped = $this->cropImage($imagePath, $cropWidth, $cropHeight, $mode, $x, $y);
140
141
        // Resize if the final height or width differs from the cropped width and height
142
        if ($cropWidth !== $finalWidth || $cropHeight !== $finalHeight) {
143
            // Resize that image to the desired final width and height
144
            $resizedCropped = $this->resizeImage($resized, $finalWidth, $finalHeight);
145
146
            // Delete the resized image, we dont need it anymore
147
            unlink($resized);
148
        }
149
150
        // Return the cropped and resized image
151
        return $resizedCropped;
152
    }
153
154
    /**
155
     * @param string $filepath
156
     * @param int $width
157
     * @param int $height
158
     * @return string
159
     * @throws \Gumlet\ImageResizeException
160
     */
161
    public function scaleAndCropThumbnail(string $filepath, int $width, int $height): string
162
    {
163
        [$orginalWidth, $originalHeight] = getimagesize($filepath);
164
        $ratio = ($orginalWidth > $originalHeight ? $orginalWidth : $originalHeight) / ($orginalWidth < $originalHeight ? $orginalWidth : $originalHeight);
165
166
        if ($orginalWidth > $originalHeight) {
167
            $targetWidth = round($height * $ratio);
168
            $scaledImage = $this->scaleThumbnail($filepath, (int) $targetWidth, $height);
169
        } else {
170
            $targetHeight = round($width * $ratio);
171
            $scaledImage = $this->scaleThumbnail($filepath, $width, (int) $targetHeight);
172
        }
173
174
        $thumbpath = $this->generateThumbFilepath($filepath);
0 ignored issues
show
Unused Code introduced by
The assignment to $thumbpath is dead and can be removed.
Loading history...
175
176
        // Crop the scaled image for best result
177
        $croppedImage = $this->cropImage($scaledImage, $width, $height, Image::CENTERED_CROP);
178
179
        // Delete the scaled image, this only served for improved thumb quality
180
        unlink($scaledImage);
181
182
        return $croppedImage;
183
    }
184
185
    /**
186
     * Scale by ratio, width or height is optional but one needs to be provided, it will calculate the
187
     * ratio by either one of these.
188
     *
189
     * @param string $filepath
190
     * @param int $targetWidth
191
     * @param int $targetHeight
192
     * @return string
193
     * @throws \Gumlet\ImageResizeException
194
     */
195
    public function scaleThumbnail(string $filepath, int $targetWidth = 0, int $targetHeight = 0)
196
    {
197
        if (!file_exists($filepath) && is_file($filepath)) {
198
            throw new InvalidArgumentException('File does not exist!');
199
        }
200
201
        if ($targetHeight >! 0 || $targetWidth >! 0) {
202
            throw new InvalidArgumentException('targetWidth or targetHeight needs to be defined.');
203
        }
204
205
        return $this->resizeImage($filepath, $targetWidth, $targetHeight);
206
    }
207
208
    public function generateThumbFilepath(string $filepath): string
209
    {
210
        // Extract the basename out of the path
211
        $filename = basename($filepath);
212
        // Get the filepath
213
        $explodedFilepath = explode(DIRECTORY_SEPARATOR, $filepath);
214
        // Reconstruct the base file path
215
        $baseFilepath = implode(DIRECTORY_SEPARATOR, array_slice($explodedFilepath, 0, count($explodedFilepath)-1));
216
        // Explode the filename
217
        $explodedFilename = explode('.', $filename);
218
        // Generate new name
219
        $thumbname = sprintf(
220
            '%s.%s',
221
            bin2hex(random_bytes(64)),
222
            end($explodedFilename)
223
        );
224
225
        return $baseFilepath . DIRECTORY_SEPARATOR . $thumbname;
226
    }
227
228
    /**
229
     * @return ImageResizerInterface
230
     */
231
    public function getAdapter(): ImageResizerInterface
232
    {
233
        return $this->adapter;
234
    }
235
236
    /**
237
     * @param ImageResizerInterface $adapter
238
     * @return ImageResizerService
239
     */
240
    public function setAdapter(ImageResizerInterface $adapter): ImageResizerService
241
    {
242
        $this->adapter = $adapter;
243
        return $this;
244
    }
245
246
    /**
247
     * @return LoggerInterface
248
     */
249
    public function getLogger(): LoggerInterface
250
    {
251
        return $this->logger;
252
    }
253
254
    /**
255
     * @param LoggerInterface $logger
256
     *
257
     * @return ImageResizerService
258
     */
259
    public function setLogger(LoggerInterface $logger): ImageResizerService
260
    {
261
        $this->logger = $logger;
262
263
        return $this;
264
    }
265
}