Completed
Push — master ( b8b745...32257f )
by
unknown
08:12
created

AbstractResizeEffect::size()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 4
rs 10
c 0
b 0
f 0
cc 1
eloc 2
nc 1
nop 0
1
<?php
2
3
namespace Charcoal\Image\Effect;
4
5
use \Exception;
6
use \InvalidArgumentException;
7
8
use \Charcoal\Image\AbstractEffect;
9
10
/**
11
 * Resize an image to given dimensions
12
 */
13
abstract class AbstractResizeEffect extends AbstractEffect
14
{
15
    /**
16
     * @var string $mode
17
     */
18
    private $mode = 'auto';
19
20
    /**
21
     * @var mixed $size
22
     */
23
    private $size;
24
25
    /**
26
     * @var integer $width
27
     */
28
    private $width = 0;
29
30
    /**
31
     * @var integer $height
32
     */
33
    private $height = 0;
34
35
    /**
36
     * @var integer $minWidth
37
     */
38
    private $minWidth = 0;
39
40
    /**
41
     * @var integer $minHeight
42
     */
43
    private $minHeight = 0;
44
45
    /**
46
     * @var integer $maxWidth
47
     */
48
    private $maxWidth = 0;
49
50
    /**
51
     * @var integer $maxHeight
52
     */
53
    private $maxHeight = 0;
54
55
    /**
56
     * @var string $gravity
57
     */
58
    private $gravity = 'center';
59
60
    /**
61
     * @var string $backgroundColor
62
     */
63
    private $backgroundColor = 'rgba(100%, 100%, 100%, 0)';
64
65
    /**
66
     * @var boolean $adaptive
67
     */
68
    private $adaptive = false;
69
70
    /**
71
     * @param string $mode The resize mode.
72
     * @throws InvalidArgumentException If the mode argument is not a valid resize mode.
73
     * @return AbstractResizeEffect Chainable
74
     */
75
    public function setMode($mode)
76
    {
77
        $allowedModes = [
78
            'auto',
79
            'exact',
80
            'width',
81
            'height',
82
            'best_fit',
83
            'crop',
84
            'fill',
85
            'none'
86
        ];
87
        if (!is_string($mode) || (!in_array($mode, $allowedModes))) {
88
            throw new InvalidArgumentException(
89
                'Mode is not valid'
90
            );
91
        }
92
        $this->mode = $mode;
93
        return $this;
94
    }
95
96
    /**
97
     * @return string
98
     */
99
    public function mode()
100
    {
101
        return $this->mode;
102
    }
103
104
    /**
105
     * Set a complex resize value.
106
     *
107
     * @param  mixed $size The size.
108
     * @throws InvalidArgumentException If the size argument is not valid.
109
     * @return Rotate Chainable
110
     */
111
    public function setSize($size)
112
    {
113
        if ($size !== null && !is_string($size) && (!is_numeric($width) || ($width < 0))) {
0 ignored issues
show
Bug introduced by
The variable $width does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
114
            throw new InvalidArgumentException(
115
                'Size must be a valid scale'
116
            );
117
        }
118
119
        $this->size = $size;
120
121
        return $this;
122
    }
123
124
    /**
125
     * Retrieve the complex resize value.
126
     *
127
     * @return mixed
128
     */
129
    public function size()
130
    {
131
        return $this->size;
132
    }
133
134
    /**
135
     * @param integer $width The target resize width.
136
     * @throws InvalidArgumentException If the width argument is not numeric or lower than 0.
137
     * @return Rotate Chainable
138
     */
139
    public function setWidth($width)
140
    {
141
        if (!is_numeric($width) || ($width < 0)) {
142
            throw new InvalidArgumentException(
143
                'Width must be a positive integer'
144
            );
145
        }
146
        $this->width = (int)$width;
147
        return $this;
148
    }
149
150
    /**
151
     * @return float
152
     */
153
    public function width()
154
    {
155
        return $this->width;
156
    }
157
158
    /**
159
     * @param integer $height The target resize height.
160
     * @throws InvalidArgumentException If the height argument is not numeric or lower than 0.
161
     * @return Rotate Chainable
162
     */
163 View Code Duplication
    public function setHeight($height)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
164
    {
165
        if (!is_int($height) || ($height < 0)) {
166
            throw new InvalidArgumentException(
167
                'Height must be a positive integer'
168
            );
169
        }
170
        $this->height = (int)$height;
171
        return $this;
172
    }
173
174
    /**
175
     * @return float
176
     */
177
    public function height()
178
    {
179
        return $this->height;
180
    }
181
182
    /**
183
     * @param integer $minWidth The resize minimal width.
184
     * @throws InvalidArgumentException If the argument is not numeric or lower than 0.
185
     * @return Rotate Chainable
186
     */
187
    public function setMinWidth($minWidth)
188
    {
189
        if (!is_numeric($minWidth) || ($minWidth < 0)) {
190
            throw new InvalidArgumentException(
191
                'Min Width must be a positive integer'
192
            );
193
        }
194
        $this->minWidth = (int)$minWidth;
195
        return $this;
196
    }
197
198
    /**
199
     * @return float
200
     */
201
    public function minWidth()
202
    {
203
        return $this->minWidth;
204
    }
205
206
    /**
207
     * @param integer $minHeight The resize minimal height.
208
     * @throws InvalidArgumentException If the argument is not numeric or lower than 0.
209
     * @return Rotate Chainable
210
     */
211
    public function setMinHeight($minHeight)
212
    {
213
        if (!is_numeric($minHeight) || ($minHeight < 0)) {
214
            throw new InvalidArgumentException(
215
                'Min Height must be a positive integer'
216
            );
217
        }
218
        $this->minHeight = (int)$minHeight;
219
        return $this;
220
    }
221
222
    /**
223
     * @return float
224
     */
225
    public function minHeight()
226
    {
227
        return $this->minHeight;
228
    }
229
230
    /**
231
     * @param integer $maxWidth The resize max width.
232
     * @throws InvalidArgumentException If the argument is not numeric or lower than 0.
233
     * @return Rotate Chainable
234
     */
235
    public function setMaxWidth($maxWidth)
236
    {
237
        if (!is_numeric($maxWidth) || ($maxWidth < 0)) {
238
            throw new InvalidArgumentException(
239
                'Max Width must be a positive integer'
240
            );
241
        }
242
        $this->maxWidth = (int)$maxWidth;
243
        return $this;
244
    }
245
246
    /**
247
     * @return float
248
     */
249
    public function maxWidth()
250
    {
251
        return $this->maxWidth;
252
    }
253
254
    /**
255
     * @param integer $maxHeight The resize max height.
256
     * @throws InvalidArgumentException If the argument is not numeric or lower than 0.
257
     * @return Rotate Chainable
258
     */
259
    public function setMaxHeight($maxHeight)
260
    {
261
        if (!is_numeric($maxHeight) || ($maxHeight < 0)) {
262
            throw new InvalidArgumentException(
263
                'Height must be a positive integer'
264
            );
265
        }
266
        $this->maxHeight = (int)$maxHeight;
267
        return $this;
268
    }
269
270
    /**
271
     * @return float
272
     */
273
    public function maxHeight()
274
    {
275
        return $this->maxHeight;
276
    }
277
278
    /**
279
     * @param string $gravity The resize gravity.
280
     * @throws InvalidArgumentException If the argument is not a valid gravity name.
281
     * @return AbstractWatermarkEffect Chainable
282
     */
283
    public function setGravity($gravity)
284
    {
285
        if (!in_array($gravity, $this->image()->availableGravities())) {
286
            throw new InvalidArgumentException(
287
                'Gravity is not valid'
288
            );
289
        }
290
        $this->gravity = $gravity;
291
        return $this;
292
    }
293
294
    /**
295
     * @return string
296
     */
297
    public function gravity()
298
    {
299
        return $this->gravity;
300
    }
301
302
    /**
303
     * @param string $color The resize background color.
304
     * @throws InvalidArgumentException If the color argument is not a string.
305
     * @return AbstractRotateEffect Chainable
306
     */
307
    public function setBackgroundColor($color)
308
    {
309
        if (!is_string($color)) {
310
            throw new InvalidArgumentException(
311
                'Color must be a string'
312
            );
313
        }
314
        $this->backgroundColor = $color;
315
        return $this;
316
    }
317
318
    /**
319
     * @return string
320
     */
321
    public function backgroundColor()
322
    {
323
        return $this->backgroundColor;
324
    }
325
326
327
    /**
328
     * @param boolean $adaptive The adaptative resize flag.
329
     * @return AbstractRotateEffect Chainable
330
     */
331
    public function setAdaptive($adaptive)
332
    {
333
        $this->adaptive = !!$adaptive;
334
        return $this;
335
    }
336
337
    /**
338
     * @return boolean
339
     */
340
    public function adaptive()
341
    {
342
        return $this->adaptive;
343
    }
344
345
    /**
346
     * @return string
347
     */
348
    public function autoMode()
349
    {
350
        $width = $this->width();
351
        $height = $this->height();
352
353
        if ($width > 0 && $height > 0) {
354
            return 'exact';
355
        } elseif ($width > 0) {
356
            return 'width';
357
        } elseif ($height > 0) {
358
            return 'height';
359
        } else {
360
            if ($this->minWidth() || $this->minHeight() || $this->maxWidth() || $this->maxHeight()) {
361
                return 'constraints';
362
            } else {
363
                return 'none';
364
            }
365
        }
366
    }
367
368
    /**
369
     * @param array $data The effect data, if available.
370
     * @throws Exception If the effect data is invalid for its resize mode.
371
     * @return AbstractResizeEffect Chainable
372
     */
373
    public function process(array $data = null)
374
    {
375
        if ($data !== null) {
376
            $this->setData($data);
377
        }
378
379
        $mode = $this->mode();
380
        if ($mode == 'auto') {
381
            $mode = $this->autoMode();
382
        }
383
384
        if ($mode == 'none') {
385
            // Noting to do.
386
            return $this;
387
        }
388
389
        $imageWidth  = $this->image()->width();
390
        $imageHeight = $this->image()->height();
391
392
        switch ($mode) {
393 View Code Duplication
            case 'exact':
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
394
                if (($this->width() <= 0) || ($this->height() <= 0)) {
395
                    throw new Exception(
396
                        'Missing parameters to perform exact resize'
397
                    );
398
                }
399
                if ($imageWidth != $this->width() || $imageHeight != $this->height()) {
400
                    $this->doResize($this->width(), $this->height(), false);
401
                }
402
                break;
403
404
            case 'width':
405
                if ($this->width() <= 0) {
406
                    throw new Exception(
407
                        'Missing parameters to perform exact width resize'
408
                    );
409
                }
410
                if ($imageWidth != $this->width()) {
411
                    $this->doResize($this->width(), 0, false);
412
                }
413
                break;
414
415
            case 'height':
416
                if ($this->height() <= 0) {
417
                    throw new Exception(
418
                        'Missing parameters to perform exact height resize'
419
                    );
420
                }
421
                if ($imageHeight != $this->height()) {
422
                    $this->doResize(0, $this->height(), false);
423
                }
424
                break;
425
426 View Code Duplication
            case 'best_fit':
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
427
                if (($this->width() <= 0) || ($this->height() <= 0)) {
428
                    throw new Exception(
429
                        'Missing parameters to perform "best fit" resize'
430
                    );
431
                }
432
                if ($imageWidth != $this->width() || $imageHeight != $this->height()) {
433
                    $this->doResize($this->width(), $this->height(), true);
434
                }
435
                break;
436
437
            case 'constraints':
438
                $minW = $this->minWidth();
439
                $minH = $this->minHeight();
440
                $maxW = $this->maxWidth();
441
                $maxH = $this->maxHeight();
442
443
                if (array_sum([$minW, $minH, $maxW, $maxH]) == 0) {
444
                    throw new Exception(
445
                        'Missing parameter(s) to perform "constraints" resize'
446
                    );
447
                }
448
449 View Code Duplication
                if (($minW && ($minW > $imageWidth)) || ($minH && ($minH > $imageHeight))) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
450
                    // Must scale up, keeping ratio
451
                    $this->doResize($minW, $minH, true);
452
                    break;
453
                }
454
455 View Code Duplication
                if (($maxW && ($maxW < $imageWidth)) || ($maxH && ($maxH < $imageHeight))) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
456
                    // Must scale down. keeping ratio
457
                    $this->doResize($maxW, $maxH, true);
458
                    break;
459
                }
460
                break;
461
462
            case 'crop':
463
                throw new Exception(
464
                    'Crop resize mode is not (yet) supported'
465
                );
466
467
            case 'fill':
468
                $imgClass = get_class($this->image());
469
                $canvas = new $imgClass;
470
                $canvas->create($this->width(), $this->width(), $this->backgroundColor());
471
                throw new Exception(
472
                    'Crop resize mode is not (yet) supported'
473
                );
474
        }
475
476
        return $this;
477
    }
478
479
    /**
480
     * @param integer $width   The target width.
481
     * @param integer $height  The target height.
482
     * @param boolean $bestFit The "best_fit" flag.
483
     * @return void
484
     */
485
    abstract protected function doResize($width, $height, $bestFit = false);
486
}
487