Passed
Push — master ( e24b23...32beb9 )
by kicaj
03:56
created

FileBehavior::_prepareThumbs()   F

Complexity

Conditions 56
Paths 3141

Size

Total Lines 178
Code Lines 110

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 110
dl 0
loc 178
rs 0
c 0
b 0
f 0
cc 56
nc 3141
nop 2

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
namespace File\Model\Behavior;
3
4
use Cake\ORM\Behavior;
5
use Cake\Utility\Text;
6
use Cake\Event\Event;
7
use Cake\Datasource\EntityInterface;
8
use File\Exception\LibraryException;
9
use File\Exception\ThumbsException;
10
11
class FileBehavior extends Behavior
12
{
13
14
    /**
15
     * {@inheritDoc}
16
     */
17
    protected $_defaultConfig = [
18
        'library' => 'gd',
19
        'types' => [ // Default allowed types
20
            'image/bmp',
21
            'image/gif',
22
            'image/jpeg',
23
            'image/jpg',
24
            'image/pjpeg',
25
            'image/pjpg',
26
            'image/png',
27
            'image/x-png',
28
            'image/webp',
29
        ],
30
        'extensions' => [ // Default allowed extensions
31
            'bmp',
32
            'gif',
33
            'jpeg',
34
            'jpg',
35
            'pjpg',
36
            'pjpeg',
37
            'png',
38
            'webp',
39
        ],
40
        'path' => 'files',
41
        'background' => [255, 255, 255, 127],
42
        'watermark' => '',
43
        'thumbs' => [],
44
    ];
45
46
    /**
47
     * Array of files to upload
48
     *
49
     * @var array
50
     */
51
    protected $_files = [];
52
53
    /**
54
     * {@inheritDoc}
55
     */
56
    public function initialize(array $config)
57
    {
58
        $this->_config = [];
59
60
        foreach ($config as $field => $fieldOptions) {
61
            if (is_array($fieldOptions)) {
62
                $this->_config[$this->getTable()->getAlias()][$field] = array_merge($this->_defaultConfig, $fieldOptions);
63
            } else {
64
                $field = $fieldOptions;
65
66
                $this->_config[$this->getTable()->getAlias()][$field] = $this->_defaultConfig;
67
            }
68
        }
69
    }
70
71
    /**
72
     * {@inheritDoc}
73
     */
74
    public function beforeMarshal(Event $event, $data = [], $options = [])
75
    {
76
        if (!empty($config = $this->getConfig($this->getTable()->getAlias()))) {
77
            foreach ($config as $field => $fieldOptions) {
78
                if (array_key_exists($field, $data)) {
79
                    // Save file array to suffixed field
80
                    $data['_' . $field] = $data[$field];
81
82
                    // Detect multiple files by array keys
83
                    if (is_numeric(key($data[$field]))) {
84
                        foreach (array_keys($data[$field]) as $key) {
85
                            if (!empty($data[$field][$key]['tmp_name'])) {
86
                                $this->_files[$field . '_' . $key] = array_merge($fieldOptions, [
87
                                    'name' => $this->_prepareName($data[$field][$key]['name']),
88
                                    'source' => $data[$field][$key]['tmp_name'],
89
                                ]);
90
91
                                $data[$field][$key] = $this->_files[$field . '_' . $key]['name'];
92
                            } else {
93
                                unset($data[$field][$key]);
94
                            }
95
                        }
96
                    } else {
97
                        if (!empty($data[$field]['tmp_name'])) {
98
                            $this->_files[$field] = array_merge($fieldOptions, [
99
                                'name' => $this->_prepareName($data[$field]['name']),
100
                                'source' => $data[$field]['tmp_name'],
101
                            ]);
102
103
                            $data[$field] = $this->_files[$field]['name'];
104
                        } else {
105
                            unset($data[$field]);
106
                        }
107
                    }
108
                }
109
            }
110
        }
111
    }
112
113
    /**
114
     * {@inheritDoc}
115
     */
116
    public function afterSave(Event $event, EntityInterface $entity, $options = [])
117
    {
118
        $this->_prepareFile($entity);
119
    }
120
121
    /**
122
     * {@inheritDoc}
123
     */
124
    public function beforeDelete(Event $event, EntityInterface $entity)
125
    {
126
        return $this->deleteFile($event);
127
    }
128
129
    /**
130
     * Copy source file to destination and if field (image) has configurations for thumbs, then create them.
131
     *
132
     * @param EntityInterface $entity Entity
133
     */
134
    protected function _prepareFile(EntityInterface $entity)
135
    {
136
        foreach ($this->_files as $field => $fieldOptions) {
137
            if (!is_dir($fieldOptions['path'])) {
138
                $this->_prepareDir($fieldOptions['path']);
139
            }
140
141
            $file = $fieldOptions['path'] . DS . $fieldOptions['name'];
142
143
            if (move_uploaded_file($fieldOptions['source'], $file) || (file_exists($fieldOptions['source']) && rename($fieldOptions['source'], $file))) {
144
                $fileType = mb_strtolower(getimagesize($fieldOptions['source'])['mime']);
145
146
                $fieldTypes = array_map(function ($fieldType) {
147
                    return mb_strtolower($fieldType);
148
                }, $fieldOptions['types']);
149
150
                // Create thumbs
151
                if (mb_strpos($fileType, 'image/') !== false && in_array($fileType, $fieldTypes)) {
152
                    $this->_prepareThumbs($file, $fieldOptions);
153
                }
154
            }
155
        }
156
    }
157
158
    /**
159
     * Delete file with created thumbs
160
     *
161
     * @param Event $event Reference to event
162
     * @return boolean True if is success
163
     */
164
    public function deleteFile(Event $event)
165
    {
166
        // Get field list of model schema
167
        $modelSchema = $model->schema();
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $model does not exist. Did you maybe mean $modelSchema?
Loading history...
168
169
        foreach ($this->settings[$model->alias] as $fieldName => $fieldOptions) {
170
            // Check is field in model schema
171
            if (isset($modelSchema[$fieldName])) {
172
                $dataField = $model->findById($model->id);
173
174
                if (is_array($dataField) && !empty($dataField[$model->alias][$fieldName])) {
175
                    // Pattern for original file with thumbs
176
                    $filePattern = $this->settings[$model->alias][$fieldName]['path'] . DS . substr($dataField[$model->alias][$fieldName], 0, 14);
0 ignored issues
show
Bug Best Practice introduced by
The property settings does not exist on File\Model\Behavior\FileBehavior. Did you maybe forget to declare it?
Loading history...
177
178
                    foreach (glob($filePattern . '*') as $fileName) {
179
                        // Remove file
180
                        @unlink($fileName);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition for unlink(). This can introduce security issues, and is generally not recommended. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unhandled  annotation

180
                        /** @scrutinizer ignore-unhandled */ @unlink($fileName);

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
181
                    }
182
                }
183
            }
184
        }
185
186
        return true;
187
    }
188
189
    /**
190
     * Generate thumbs by names with parameters
191
     *
192
     * @param string $originalFile Path to original file
193
     * @param array $thumbParams Settings for uploaded files
194
     * @return boolean Output image to save file
195
     */
196
    protected function _prepareThumbs($originalFile, $settingParams)
197
    {
198
        if (is_file($originalFile) && is_array($settingParams)) {
199
            // Check image library
200
            if (!extension_loaded($settingParams['library'])) {
201
                throw new LibraryException(__d('file', 'The library identified by {0} is not loaded!', $settingParams['library']));
202
            }
203
204
            // Get extension from original file
205
            $fileExtension = $this->getExtension($originalFile);
206
207
            switch ($settingParams['library']) {
208
                // Get image resource
209
                case 'gd':
210
                    switch ($fileExtension) {
211
                        case 'bmp':
212
                            $sourceImage = imagecreatefrombmp($originalFile);
213
214
                            break;
215
                        case 'gif':
216
                            $sourceImage = imagecreatefromgif($originalFile);
217
218
                            break;
219
                        case 'png':
220
                            $sourceImage = imagecreatefrompng($originalFile);
221
222
                            break;
223
                        case 'webp':
224
                            $sourceImage = imagecreatefromwebp($originalFile);
0 ignored issues
show
Bug introduced by
The function imagecreatefromwebp was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

224
                            $sourceImage = /** @scrutinizer ignore-call */ imagecreatefromwebp($originalFile);
Loading history...
225
226
                            break;
227
                        default:
228
                            ini_set('gd.jpeg_ignore_warning', 1);
229
230
                            $sourceImage = imagecreatefromjpeg($originalFile);
231
232
                            break;
233
                    }
234
235
                    // Get original width and height
236
                    $originalWidth = imagesx($sourceImage);
237
                    $originalHeight = imagesy($sourceImage);
238
239
                    break;
240
                case 'imagick':
241
                    $sourceImage = new \Imagick($originalFile);
242
243
                    // Get original width and height
244
                    $originalWidth = $sourceImage->getimagewidth();
245
                    $originalHeight = $sourceImage->getimageheight();
246
247
                    break;
248
                default:
249
                    throw new LibraryException(__d('file', 'The library identified by {0} it is not known as image processing!', $settingParams['library']));
250
            }
251
252
            $offsetX = 0;
253
            $offsetY = 0;
254
255
            $cropX = 0;
256
            $cropY = 0;
257
258
            foreach ($settingParams['thumbs'] as $thumbName => $thumbParam) {
259
                if (is_array($thumbParam)) {
260
                    if (isset($thumbParam['width']) && is_array($thumbParam['width']) && count($thumbParam['width']) === 1) {
261
                        list($newWidth, $newHeight) = $this->_byWidth($originalWidth, $originalHeight, $thumbParam['width'][0]);
262
                    } elseif (isset($thumbParam['height']) && is_array($thumbParam['height']) && count($thumbParam['height']) === 1) {
263
                        list($newWidth, $newHeight) = $this->_byHeight($originalWidth, $originalHeight, $thumbParam['height'][0]);
264
                    } elseif (isset($thumbParam['shorter']) && is_array($thumbParam['shorter']) && count($thumbParam['shorter']) === 2) {
265
                        list($newWidth, $newHeight) = $this->_byShorter($originalWidth, $originalHeight, $thumbParam['shorter'][0], $thumbParam['shorter'][1]);
266
                    } elseif (isset($thumbParam['longer']) && is_array($thumbParam['longer']) && count($thumbParam['longer']) === 2) {
267
                        list($newWidth, $newHeight) = $this->_byLonger($originalWidth, $originalHeight, $thumbParam['longer'][0], $thumbParam['longer'][1]);
268
                    } elseif (isset($thumbParam['fit']) && is_array($thumbParam['fit']) && count($thumbParam['fit']) === 2) {
269
                        list($newWidth, $newHeight, $offsetX, $offsetY, $cropX, $cropY) = $this->_byFit($originalWidth, $originalHeight, $thumbParam['fit'][0], $thumbParam['fit'][1]);
270
                    } elseif (isset($thumbParam['fit']) && is_array($thumbParam['fit']) && count($thumbParam['fit']) === 3) {
271
                        list($newWidth, $newHeight, $offsetX, $offsetY, $cropX, $cropY) = $this->_byFit($originalWidth, $originalHeight, $thumbParam['fit'][0], $thumbParam['fit'][1], $thumbParam['fit'][2]);
272
                    } elseif (isset($thumbParam['square']) && is_array($thumbParam['square']) && count($thumbParam['square']) === 1) {
273
                        list($newWidth, $newHeight, $offsetX, $offsetY, $cropX, $cropY) = $this->_bySquare($originalWidth, $originalHeight, $thumbParam['square'][0]);
274
                    } elseif (isset($thumbParam['square']) && is_array($thumbParam['square']) && count($thumbParam['square']) === 2) {
275
                        list($newWidth, $newHeight, $offsetX, $offsetY, $cropX, $cropY) = $this->_bySquare($originalWidth, $originalHeight, $thumbParam['square'][0], $thumbParam['square'][1]);
276
                    } else {
277
                        throw new ThumbsException(__d('file', 'Unknown type of creating thumbnails!'));
278
                    }
279
280
                    $thumbFile = str_replace('default', $thumbName, $originalFile);
281
282
                    switch ($settingParams['library']) {
283
                        // Get image resource
284
                        case 'gd':
285
                            $newImage = imagecreatetruecolor($newWidth, $newHeight);
286
287
                            if (is_array($settingParams['background'])) {
288
                                // Set background color and transparent indicates
289
                                imagefill($newImage, 0, 0, imagecolorallocatealpha($newImage, $settingParams['background'][0], $settingParams['background'][1], $settingParams['background'][2], $settingParams['background'][3]));
290
                            }
291
292
                            imagecopyresampled($newImage, $sourceImage, 0, 0, 0, 0, $newWidth, $newHeight, $originalWidth, $originalHeight);
293
294
                            if ((isset($thumbParam['square']) && is_array($thumbParam['square'])) || (isset($thumbParam['fit']) && is_array($thumbParam['fit']))) {
295
                                $fitImage = imagecreatetruecolor($newWidth + (2 * $offsetX) - (2 * $cropX), $newHeight + (2 * $offsetY) - (2 * $cropY));
296
297
                                if (is_array($settingParams['background'])) {
298
                                    // Set background color and transparent indicates
299
                                    imagefill($fitImage, 0, 0, imagecolorallocatealpha($fitImage, $settingParams['background'][0], $settingParams['background'][1], $settingParams['background'][2], $settingParams['background'][3]));
300
                                }
301
302
                                imagecopyresampled($fitImage, $newImage, $offsetX, $offsetY, $cropX, $cropY, $newWidth, $newHeight, $newWidth, $newHeight);
303
304
                                $newImage = $fitImage;
305
                            }
306
307
                            imagealphablending($newImage, false);
308
                            imagesavealpha($newImage, true);
309
310
                            // Watermark
311
                            if (isset($thumbParam['watermark']) && ($watermarkSource = file_get_contents($settingParams['watermark'])) !== false) {
312
                                $watermarkImage = imagecreatefromstring($watermarkSource);
313
314
                                list($watermarkPositionX, $watermarkPositionY) = $this->getPosition(imagesx($newImage), imagesy($newImage), imagesx($watermarkImage), imagesy($watermarkImage), $offsetX, $offsetY, $thumbParam['watermark']);
315
316
                                // Set transparent
317
                                imagealphablending($newImage, true);
318
                                imagecopy($newImage, $watermarkImage, $watermarkPositionX, $watermarkPositionY, 0, 0, imagesx($watermarkImage), imagesy($watermarkImage));
319
                            }
320
321
                            // Set resource file type
322
                            switch ($fileExtension) {
323
                                case 'bmp':
324
                                    imagebmp($newImage, $thumbFile);
325
326
                                    break;
327
                                case 'gif':
328
                                    imagegif($newImage, $thumbFile);
329
330
                                    break;
331
                                case 'png':
332
                                    imagepng($newImage, $thumbFile);
333
334
                                    break;
335
                                case 'webp':
336
                                    imagewebp($newImage, $thumbFile);
337
338
                                    break;
339
                                default:
340
                                    imagejpeg($newImage, $thumbFile, 100);
341
342
                                    break;
343
                            }
344
345
                            break;
346
                        case 'imagick':
347
                            $newImage = $sourceImage->clone();
348
349
                            $newImage->scaleimage($newWidth, $newHeight);
350
                            $newImage->setimagebackgroundcolor('transparent');
351
                            $newImage->extentimage($newWidth + (2 * $offsetX), $newHeight + (2 * $offsetY), -$offsetX, -$offsetY);
352
353
                            if ((isset($thumbParam['square']) && is_array($thumbParam['square'])) || (isset($thumbParam['fit']) && is_array($thumbParam['fit']))) {
354
                                $newImage->cropimage($newWidth + (2 * $offsetX) - (2 * $cropX), $newHeight + (2 * $offsetY) - (2 * $cropY), $cropX, $cropY);
355
                            }
356
357
                            // Watermark
358
                            if (isset($thumbParam['watermark']) && ($watermarkSource = file_get_contents($settingParams['watermark'])) !== false) {
359
                                $watermarkImage = new \Imagick();
360
                                $watermarkImage->readimageblob($watermarkSource);
361
362
                                list($watermarkPositionX, $watermarkPositionY) = $this->getPosition($newWidth, $newHeight, $watermarkImage->getimagewidth(), $watermarkImage->getimageheight(), $offsetX, $offsetY, $thumbParam['watermark']);
363
364
                                $newImage->compositeimage($watermarkImage, \Imagick::COMPOSITE_OVER, $watermarkPositionX, $watermarkPositionY);
365
                            }
366
367
                            // Set object file type
368
                            $newImage->setImageFormat($fileExtension);
369
370
                            $newImage->writeimage($thumbFile);
371
                            $newImage->clear();
372
373
                            break;
374
                    }
375
                }
376
            }
377
        }
378
    }
379
380
    /**
381
     * Get extension from original name
382
     *
383
     * @param string $originalName Name of original file
384
     * @return string Extension of uploaded file
385
     */
386
    public function getExtension($originalName)
387
    {
388
        $fileExtension = pathinfo(mb_strtolower($originalName), PATHINFO_EXTENSION);
389
390
        switch ($fileExtension) {
391
            case 'jpg':
392
            case 'jpeg':
393
            case 'pjpg':
394
            case 'pjpeg':
395
                // Standarize JPEG image file extension
396
                return 'jpg';
397
398
                break;
0 ignored issues
show
Unused Code introduced by
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
399
            default:
400
                return $fileExtension;
401
402
                break;
403
        }
404
    }
405
406
    /**
407
     * Get position of watermark image
408
     *
409
     * @param integer $newWidth New width of uploaded image
410
     * @param integer $newHeight New height of uploaded image
411
     * @param integer $watermarkWidth Original width of watermark image
412
     * @param integer $watermarkHeight Original height of watermark image
413
     * @param integer $offsetX Horizontal offset
414
     * @param integer $offsetY Vertical offset
415
     * @param integer $positionValue Value for position watermark, value between 1 and 9
416
     * @return array Coordinates of position watermark
417
     */
418
    public function getPosition($newWidth, $newHeight, $watermarkWidth, $watermarkHeight, $offsetX = 0, $offsetY = 0, $positionValue = 1)
419
    {
420
        switch (intval($positionValue)) {
421
            case 1: // Top left
422
                return [$offsetX, $offsetY];
423
424
                break;
0 ignored issues
show
Unused Code introduced by
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
425
            case 2: // Top center
426
                return [($newWidth / 2) - ($watermarkWidth / 2), 0 + $offsetY];
427
428
                break;
429
            case 3: // Top right
430
                return [($newWidth - $watermarkWidth) - $offsetX, 0 + $offsetY];
431
432
                break;
433
            case 4: // Middle left
434
                return [$offsetX, ($newHeight / 2) - ($watermarkHeight / 2)];
435
436
                break;
437
            case 5: // Middle center
438
                return [($newWidth / 2) - ($watermarkWidth / 2), ($newHeight / 2) - ($watermarkHeight / 2)];
439
440
                break;
441
            case 6: // Middle right
442
                return [($newWidth - $watermarkWidth) - $offsetX, ($newHeight / 2) - ($watermarkHeight / 2)];
443
444
                break;
445
            case 7: // Bottom left
446
                return [$offsetX, ($newHeight - $watermarkHeight) - $offsetY];
447
448
                break;
449
            case 8: // Bottom center
450
                return [($newWidth / 2) - ($watermarkWidth / 2), ($newHeight - $watermarkHeight) - $offsetY];
451
452
                break;
453
            case 9: // Bottom right
454
                return [($newWidth - $watermarkWidth) - $offsetX, ($newHeight - $watermarkHeight) - $offsetY];
455
456
                break;
457
            default:
458
                return [$offsetX, $offsetY];
459
460
                break;
461
        }
462
    }
463
464
    /**
465
     * Generate random name of uploaded file.
466
     * If action is for update with not used file then it will be removed.
467
     *
468
     * @todo Prepare method for working without primary key field
469
     * @todo Generate names of files by user method
470
     * @param string $fieldName Name of file field
471
     * @return string New name of file
472
     */
473
    protected function _prepareName($fieldName)
474
    {
475
        return Text::uuid() . '_default.' . $this->getExtension($fieldName);
476
    }
477
478
    /**
479
     * Set path to directory for save uploaded files.
480
     * If directory isn't exists, will be created with full privileges.
481
     *
482
     * @param string $dirPath Path to directory
483
     * @return string Path to directory
484
     */
485
    protected function _prepareDir($dirPath)
486
    {
487
        $dirPath = WWW_ROOT . str_replace('/', DS, $dirPath);
488
489
        if (!is_dir($dirPath) && mb_strlen($dirPath) > 0) {
490
            mkdir($dirPath, 0777, true);
491
        }
492
493
        chmod($dirPath, 0777);
494
495
        return $dirPath;
496
    }
497
498
    /**
499
     * Create image dimension by new width.
500
     *
501
     * @param integer $originalWidth Original width of uploaded image
502
     * @param integer $originalHeight Original height of uploaded image
503
     * @param integer $newWidth Set new image width
504
     * @return array New width and height
505
     */
506
    protected function _byWidth($originalWidth, $originalHeight, $newWidth)
507
    {
508
        $newWidth = intval($newWidth);
509
510
        if ($newWidth > $originalWidth) {
511
            $newWidth = $originalWidth;
512
            $newHeight = $originalHeight;
513
        } else {
514
            $newHeight = intval($newWidth * ($originalHeight / $originalWidth));
515
        }
516
517
        return [$newWidth, $newHeight];
518
    }
519
520
    /**
521
     * Create image dimension by new height.
522
     *
523
     * @param integer $originalWidth Original width of uploaded image
524
     * @param integer $originalHeight Original height of uploaded image
525
     * @param integer $newHeight Set new image height
526
     * @return array New width and height
527
     */
528
    protected function _byHeight($originalWidth, $originalHeight, $newHeight)
529
    {
530
        $newHeight = intval($newHeight);
531
532
        if ($newHeight > $originalHeight) {
533
            $newHeight = $originalHeight;
534
            $newWidth = $originalWidth;
535
        } else {
536
            $newWidth = intval($newHeight * ($originalWidth / $originalHeight));
537
        }
538
539
        return [$newWidth, $newHeight];
540
    }
541
542
    /**
543
     * Create image dimension by shorter side.
544
     *
545
     * @param integer $originalWidth Original width of uploaded image
546
     * @param integer $originalHeight Original height of uploaded image
547
     * @param integer $newWidth Set new image min width
548
     * @param integer $newHeight Set new image min height
549
     * @return array New width and height
550
     */
551
    protected function _byShorter($originalWidth, $originalHeight, $newWidth, $newHeight)
552
    {
553
        $newWidth = intval($newWidth);
554
        $newHeight = intval($newHeight);
555
556
        if ($originalWidth < $originalHeight) {
557
            list($newWidth, $newHeight) = $this->_byWidth($originalWidth, $originalHeight, $newWidth);
558
        } else {
559
            list($newWidth, $newHeight) = $this->_byHeight($originalWidth, $originalHeight, $newHeight);
560
        }
561
562
        return [$newWidth, $newHeight];
563
    }
564
565
    /**
566
     * Create image dimension by longer side.
567
     *
568
     * @param integer $originalWidth Original width of uploaded image
569
     * @param integer $originalHeight Original height of uploaded image
570
     * @param integer $newWidth Set new image max width
571
     * @param integer $newHeight Set new image max height
572
     * @return array New width and height
573
     */
574
    protected function _byLonger($originalWidth, $originalHeight, $newWidth, $newHeight)
575
    {
576
        $newWidth = intval($newWidth);
577
        $newHeight = intval($newHeight);
578
579
        if ($originalWidth > $originalHeight) {
580
            list($newWidth, $newHeight) = $this->_byWidth($originalWidth, $originalHeight, $newWidth);
581
        } else {
582
            list($newWidth, $newHeight) = $this->_byHeight($originalWidth, $originalHeight, $newHeight);
583
        }
584
585
        return [$newWidth, $newHeight];
586
    }
587
588
    /**
589
     * Create image dimension by fit.
590
     *
591
     * @param integer $originalWidth Original width of uploaded image
592
     * @param integer $originalHeight Original height of uploaded image
593
     * @param integer $newWidth Set new image width
594
     * @param integer $newHeight Set new image height
595
     * @param boolean $originalKeep Save original shape
596
     * @return array New width and height and offsets of position with keeping original shape
597
     */
598
    protected function _byFit($originalWidth, $originalHeight, $newWidth, $newHeight, $originalKeep = false)
599
    {
600
        $newWidth = intval($newWidth);
601
        $newHeight = intval($newHeight);
602
603
        $offsetX = 0;
604
        $offsetY = 0;
605
        $cropX = 0;
606
        $cropY = 0;
607
608
        if ($originalKeep === true) {
609
            if ($originalWidth == $originalHeight) {
610
                $newSizes = $this->_byLonger($originalWidth, $originalHeight, min($newWidth, $newHeight), min($newWidth, $newHeight));
611
            } else {
612
                $newSizes = $this->_byLonger($originalWidth, $originalHeight, $newWidth, $newHeight);
613
614
                if ($newWidth < $newSizes[0] || $newHeight < $newSizes[1]) {
615
                    $newSizes = $this->_byShorter($originalWidth, $originalHeight, $newWidth, $newHeight);
616
                }
617
            }
618
        } else {
619
            if ($originalWidth == $originalHeight) {
620
                $newSizes = $this->_byShorter($originalWidth, $originalHeight, max($newWidth, $newHeight), max($newWidth, $newHeight));
621
            } else {
622
                $newSizes = $this->_byShorter($originalWidth, $originalHeight, $newWidth, $newHeight);
623
624
                if ($newWidth > $newSizes[0] || $newHeight > $newSizes[1]) {
625
                    $newSizes = $this->_byLonger($originalWidth, $originalHeight, $newWidth, $newHeight);
626
                }
627
            }
628
        }
629
630
        if ($newWidth < $newSizes[0]) {
631
            $cropX = ($newSizes[0] - $newWidth) / 2;
632
        } else {
633
            $offsetX = ($newWidth - $newSizes[0]) / 2;
634
        }
635
636
        if ($newHeight < $newSizes[1]) {
637
            $cropY = ($newSizes[1] - $newHeight) / 2;
638
        } else {
639
            $offsetY = ($newHeight - $newSizes[1]) / 2;
640
        }
641
642
        return [$newSizes[0], $newSizes[1], $offsetX, $offsetY, $cropX, $cropY];
643
    }
644
645
    /**
646
     * Create image dimension to square
647
     *
648
     * @param integer $originalWidth Original width of uploaded image
649
     * @param integer $originalHeight Original height of uploaded image
650
     * @param integer $newSide Set new image side
651
     * @param boolean $originalKeep Save original shape
652
     * @return array New width and height with coordinates of crop or offsets of position
653
     */
654
    protected function _bySquare($originalWidth, $originalHeight, $newSide, $originalKeep = false)
655
    {
656
        $newSide = intval($newSide);
657
658
        $offsetX = 0;
659
        $offsetY = 0;
660
        $cropX = 0;
661
        $cropY = 0;
662
663
        if ($originalKeep === true) {
664
            list($newWidth, $newHeight) = $this->_byLonger($originalWidth, $originalHeight, $newSide, $newSide);
665
666
            if ($newSide > $newWidth) {
667
                $offsetX = ($newSide - $newWidth) / 2;
668
            }
669
670
            if ($newSide > $newHeight) {
671
                $offsetY = ($newSide - $newHeight) / 2;
672
            }
673
        } else {
674
            list($newWidth, $newHeight) = $this->_byShorter($originalWidth, $originalHeight, $newSide, $newSide);
675
676
            if ($newSide < $newWidth) {
677
                $cropX = ($newWidth - $newSide) / 2;
678
            } else {
679
                $offsetX = ($newSide - $newWidth) / 2;
680
            }
681
682
            if ($newSide < $newHeight) {
683
                $cropY = ($newHeight - $newSide) / 2;
684
            } else {
685
                $offsetY = ($newSide - $newHeight) / 2;
686
            }
687
        }
688
689
        return [$newWidth, $newHeight, $offsetX, $offsetY, $cropX, $cropY];
690
    }
691
}