Passed
Pull Request — master (#4)
by Robson
01:46
created

Cropper::imageName()   A

Complexity

Conditions 5
Paths 6

Size

Total Lines 11
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 5
eloc 7
c 1
b 0
f 0
nc 6
nop 2
dl 0
loc 11
rs 9.6111
1
<?php
2
3
namespace CoffeeCode\Cropper;
4
5
/**
6
 * Class CoffeeCode Cropper
7
 *
8
 * @author Robson V. Leite <https://github.com/robsonvleite>
9
 * @package CoffeeCode\Cropper
10
 */
11
class Cropper
12
{
13
    /** @var string */
14
    private $cachePath;
15
16
    /** @var array */
17
    private $cacheSize;
18
19
    /** @var string */
20
    private $imagePath;
21
22
    /** @var string */
23
    private $imageName;
24
25
    /** @var string */
26
    private $imageMime;
27
28
    /** @var string */
29
    private $imageInfo;
30
31
    /** @var bool */
32
    private $imageNameisHash;
33
    /**
34
     * Allow jpg and png to thumb and cache generate
35
     *
36
     * @var array allowed media types
37
     */
38
    private static $allowedExt = ['image/jpeg', "image/png"];
39
40
    /**
41
     * Cropper constructor.
42
     *
43
     * @param string $cachePath
44
     * @param int $jpgQuality
45
     * @param int $pngCompressor
46
     * @throws \Exception
47
     */
48
    public function __construct(string $cachePath, int $jpgQuality = 75, int $pngCompressor = 5)
49
    {
50
        $this->cachePath = $cachePath;
51
        $this->cacheSize = [$jpgQuality, $pngCompressor];
52
53
        if (!file_exists($this->cachePath) || !is_dir($this->cachePath)) {
54
            if (!mkdir($this->cachePath, 0755)) {
55
                throw new \Exception("Could not create cache folder");
56
            }
57
        }
58
    }
59
60
    /**
61
     * Make an thumb image
62
     *
63
     * @param string $imagePath
64
     * @param int $width
65
     * @param int|null $height
66
     * @return null|string
67
     */
68
    public function make(string $imagePath, int $width, int $height = null, bool $isHash = true): ?string
69
    {
70
        if (!file_exists($imagePath)) {
71
            return "Image not found";
72
        }
73
74
        $this->imageNameisHash = $isHash;
75
76
        $this->imagePath = $imagePath;
77
        $this->imageMime = mime_content_type($this->imagePath);
78
        $this->imageInfo = pathinfo($this->imagePath);
79
80
        $this->imageName($width, $height);
81
82
        if (!in_array($this->imageMime, self::$allowedExt)) {
83
            return "Not a valid JPG or PNG image";
84
        }
85
86
        if (file_exists("{$this->cachePath}/{$this->imageName}") && is_file("{$this->cachePath}/{$this->imageName}")) {
87
            return "{$this->cachePath}/{$this->imageName}";
88
        }
89
90
        return $this->imageCache($width, $height);
91
    }
92
93
    /**
94
     * Clear cache
95
     *
96
     * @param string|null $imageName
97
     * @example $t->flush("images/image.jpg"); clear image name and variations size
98
     * @example $t->flush(); clear all image cache folder
99
     */
100
    public function flush(string $imageName = null): void
101
    {
102
        $scan = scandir($this->cachePath);
103
        $name = ($imageName ? hash("crc32", pathinfo($imageName)['basename']) : null);
104
105
        foreach ($scan as $file) {
106
            $file = "{$this->cachePath}/{$file}";
107
            if ($imageName && strpos($file, $name)) {
108
                $this->imageDestroy($file);
109
            } elseif (!$imageName) {
110
                $this->imageDestroy($file);
111
            }
112
        }
113
    }
114
115
    /**
116
     * @param int $width
117
     * @param int|null $height
118
     */
119
    private function imageName(int $width, int $height = null): void
120
    {
121
        if ($this->imageNameisHash) {
122
            $this->imageName = hash("crc32", $this->imageInfo['basename']) . date("Ymd") . hash("crc32",
123
                    "{$width}{$height}") . ($this->imageMime == "image/jpeg" ? ".jpg" : ".png");;
124
            return;
125
        }
126
127
        $this->imageName = $this->imageInfo['filename'] . '-' . $width .
128
            ($height ? '-' . $height : "") . date("-Ymdhsi") .
129
            ($this->imageMime == "image/jpeg" ? ".jpg" : ".png");
130
    }
131
132
    /**
133
     * @param int $width
134
     * @param int|null $height
135
     * @return null|string
136
     */
137
    private function imageCache(int $width, int $height = null): ?string
138
    {
139
        list($src_w, $src_h) = getimagesize($this->imagePath);
140
        $height = ($height ?? ($width * $src_h) / $src_w);
141
142
        $src_x = 0;
143
        $src_y = 0;
144
145
        $cmp_x = $src_w / $width;
146
        $cmp_y = $src_h / $height;
147
148
        if ($cmp_x > $cmp_y) {
149
            $src_w = round($src_w / $cmp_x * $cmp_y);
150
            $src_x = round(($src_w - ($src_w / $cmp_x * $cmp_y))); //2
151
        } elseif ($cmp_y > $cmp_x) {
152
            $src_h = round($src_h / $cmp_y * $cmp_x);
153
            $src_y = round(($src_h - ($src_h / $cmp_y * $cmp_x))); //2
154
        }
155
156
        $src_x = (int)$src_x;
157
        $src_h = (int)$src_h;
158
        $src_y = (int)$src_y;
159
        $src_y = (int)$src_y;
160
161
        if ($this->imageMime == "image/jpeg") {
162
            return $this->fromJpg($width, $height, $src_x, $src_y, $src_w, $src_h);
163
        }
164
165
        if ($this->imageMime == "image/png") {
166
            return $this->fromPng($width, $height, $src_x, $src_y, $src_w, $src_h);
167
        }
168
169
        return null;
170
    }
171
172
    /**
173
     * @param string $imagePatch
174
     */
175
    private function imageDestroy(string $imagePatch): void
176
    {
177
        if (file_exists($imagePatch) && is_file($imagePatch)) {
178
            unlink($imagePatch);
179
        }
180
    }
181
182
    /**
183
     * @param int $width
184
     * @param int $height
185
     * @param int $src_x
186
     * @param int $src_y
187
     * @param int $src_w
188
     * @param int $src_h
189
     * @return string
190
     */
191
    private function fromJpg(int $width, int $height, int $src_x, int $src_y, int $src_w, int $src_h): string
192
    {
193
        $thumb = imagecreatetruecolor($width, $height);
194
        $source = imagecreatefromjpeg($this->imagePath);
195
        imagecopyresized($thumb, $source, 0, 0, $src_x, $src_y, $width, $height, $src_w, $src_h);
0 ignored issues
show
Bug introduced by
It seems like $thumb can also be of type false; however, parameter $dst_image of imagecopyresized() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

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

195
        imagecopyresized(/** @scrutinizer ignore-type */ $thumb, $source, 0, 0, $src_x, $src_y, $width, $height, $src_w, $src_h);
Loading history...
Bug introduced by
It seems like $source can also be of type false; however, parameter $src_image of imagecopyresized() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

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

195
        imagecopyresized($thumb, /** @scrutinizer ignore-type */ $source, 0, 0, $src_x, $src_y, $width, $height, $src_w, $src_h);
Loading history...
196
        imagejpeg($thumb, "{$this->cachePath}/{$this->imageName}", $this->cacheSize[0]);
0 ignored issues
show
Bug introduced by
It seems like $thumb can also be of type false; however, parameter $image of imagejpeg() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

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

196
        imagejpeg(/** @scrutinizer ignore-type */ $thumb, "{$this->cachePath}/{$this->imageName}", $this->cacheSize[0]);
Loading history...
197
198
        imagedestroy($thumb);
0 ignored issues
show
Bug introduced by
It seems like $thumb can also be of type false; however, parameter $image of imagedestroy() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

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

198
        imagedestroy(/** @scrutinizer ignore-type */ $thumb);
Loading history...
199
        imagedestroy($source);
200
201
        return "{$this->cachePath}/{$this->imageName}";
202
    }
203
204
    /**
205
     * @param int $width
206
     * @param int $height
207
     * @param int $src_x
208
     * @param int $src_y
209
     * @param int $src_w
210
     * @param int $src_h
211
     * @return string
212
     */
213
    private function fromPng(int $width, int $height, int $src_x, int $src_y, int $src_w, int $src_h): string
214
    {
215
        $thumb = imagecreatetruecolor($width, $height);
216
        $source = imagecreatefrompng($this->imagePath);
217
218
        imagealphablending($thumb, false);
0 ignored issues
show
Bug introduced by
It seems like $thumb can also be of type false; however, parameter $image of imagealphablending() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

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

218
        imagealphablending(/** @scrutinizer ignore-type */ $thumb, false);
Loading history...
219
        imagesavealpha($thumb, true);
0 ignored issues
show
Bug introduced by
It seems like $thumb can also be of type false; however, parameter $image of imagesavealpha() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

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

219
        imagesavealpha(/** @scrutinizer ignore-type */ $thumb, true);
Loading history...
220
        imagecopyresized($thumb, $source, 0, 0, $src_x, $src_y, $width, $height, $src_w, $src_h);
0 ignored issues
show
Bug introduced by
It seems like $source can also be of type false; however, parameter $src_image of imagecopyresized() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

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

220
        imagecopyresized($thumb, /** @scrutinizer ignore-type */ $source, 0, 0, $src_x, $src_y, $width, $height, $src_w, $src_h);
Loading history...
Bug introduced by
It seems like $thumb can also be of type false; however, parameter $dst_image of imagecopyresized() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

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

220
        imagecopyresized(/** @scrutinizer ignore-type */ $thumb, $source, 0, 0, $src_x, $src_y, $width, $height, $src_w, $src_h);
Loading history...
221
        imagepng($thumb, "{$this->cachePath}/{$this->imageName}", $this->cacheSize[1]);
0 ignored issues
show
Bug introduced by
It seems like $thumb can also be of type false; however, parameter $image of imagepng() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

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

221
        imagepng(/** @scrutinizer ignore-type */ $thumb, "{$this->cachePath}/{$this->imageName}", $this->cacheSize[1]);
Loading history...
222
223
        imagedestroy($thumb);
0 ignored issues
show
Bug introduced by
It seems like $thumb can also be of type false; however, parameter $image of imagedestroy() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

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

223
        imagedestroy(/** @scrutinizer ignore-type */ $thumb);
Loading history...
224
        imagedestroy($source);
225
226
        return "{$this->cachePath}/{$this->imageName}";
227
    }
228
}