Passed
Push — master ( 753522...c7a79d )
by Robson
01:29
created

Cropper::imageDestroy()   A

Complexity

Conditions 3
Paths 2

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 2
nc 2
nop 1
dl 0
loc 4
rs 10
c 0
b 0
f 0
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
    /**
32
     * Allow jpg and png to thumb and cache generate
33
     *
34
     * @var array allowed media types
35
     */
36
    private static $allowedExt = ['image/jpeg', "image/png"];
37
38
    /**
39
     * Cropper constructor.
40
     *
41
     * @param string $cachePath
42
     * @param int $jpgQuality
43
     * @param int $pngCompressor
44
     * @throws \Exception
45
     */
46
    public function __construct(string $cachePath, int $jpgQuality = 75, int $pngCompressor = 5)
47
    {
48
        $this->cachePath = $cachePath;
49
        $this->cacheSize = [$jpgQuality, $pngCompressor];
50
51
        if (!file_exists($this->cachePath) || !is_dir($this->cachePath)) {
52
            if (!mkdir($this->cachePath, 0755)) {
53
                throw new \Exception("Could not create cache folder");
54
            }
55
        }
56
    }
57
58
    /**
59
     * Make an thumb image
60
     *
61
     * @param string $imagePath
62
     * @param int $width
63
     * @param int|null $height
64
     * @return null|string
65
     */
66
    public function make(string $imagePath, int $width, int $height = null): ?string
67
    {
68
        if (!file_exists($imagePath)) {
69
            return "Image not found";
70
        }
71
72
        $this->imagePath = $imagePath;
73
        $this->imageMime = mime_content_type($this->imagePath);
74
        $this->imageInfo = pathinfo($this->imagePath);
75
        $this->imageName = hash("crc32", $this->imageInfo['basename']) . hash("crc32",
76
                "{$width}{$height}") . ($this->imageMime == "image/jpeg" ? ".jpg" : ".png");
77
78
        if (!in_array($this->imageMime, self::$allowedExt)) {
79
            return "Not a valid JPG or PNG image";
80
        }
81
82
        if (file_exists("{$this->cachePath}/{$this->imageName}") && is_file("{$this->cachePath}/{$this->imageName}")) {
83
            return "{$this->cachePath}/{$this->imageName}";
84
        }
85
86
        return $this->imageCache($width, $height);
87
    }
88
89
    /**
90
     * Clear cache
91
     *
92
     * @param string|null $imageName
93
     * @example $t->flush("images/image.jpg"); clear image name and variations size
94
     * @example $t->flush(); clear all image cache folder
95
     */
96
    public function flush(string $imageName = null): void
97
    {
98
        $scan = scandir($this->cachePath);
99
        $name = ($imageName ? hash("crc32", pathinfo($imageName)['basename']) : null);
100
101
        foreach ($scan as $file) {
102
            $file = "{$this->cachePath}/{$file}";
103
            if ($imageName && strpos($file, $name)) {
104
                $this->imageDestroy($file);
105
            } elseif (!$imageName) {
106
                $this->imageDestroy($file);
107
            }
108
        }
109
    }
110
111
    /**
112
     * @param int $width
113
     * @param int|null $height
114
     * @return null|string
115
     */
116
    private function imageCache(int $width, int $height = null): ?string
117
    {
118
        list($src_w, $src_h) = getimagesize($this->imagePath);
119
        $height = ($height ?? ($width * $src_h) / $src_w);
120
121
        $src_x = 0;
122
        $src_y = 0;
123
124
        $cmp_x = $src_w / $width;
125
        $cmp_y = $src_h / $height;
126
127
        if ($cmp_x > $cmp_y) {
128
            $src_w = round($src_w / $cmp_x * $cmp_y);
129
            $src_x = round(($src_w - ($src_w / $cmp_x * $cmp_y))); //2
130
        } elseif ($cmp_y > $cmp_x) {
131
            $src_h = round($src_h / $cmp_y * $cmp_x);
132
            $src_y = round(($src_h - ($src_h / $cmp_y * $cmp_x))); //2
133
        }
134
135
        $src_x = (int)$src_x;
136
        $src_h = (int)$src_h;
137
        $src_y = (int)$src_y;
138
        $src_y = (int)$src_y;
139
140
        if ($this->imageMime == "image/jpeg") {
141
            return $this->fromJpg($width, $height, $src_x, $src_y, $src_w, $src_h);
142
        }
143
144
        if ($this->imageMime == "image/png") {
145
            return $this->fromPng($width, $height, $src_x, $src_y, $src_w, $src_h);
146
        }
147
148
        return null;
149
    }
150
151
    /**
152
     * @param string $imagePatch
153
     */
154
    private function imageDestroy(string $imagePatch): void
155
    {
156
        if (file_exists($imagePatch) && is_file($imagePatch)) {
157
            unlink($imagePatch);
158
        }
159
    }
160
161
    /**
162
     * @param int $width
163
     * @param int $height
164
     * @param int $src_x
165
     * @param int $src_y
166
     * @param int $src_w
167
     * @param int $src_h
168
     * @return string
169
     */
170
    private function fromJpg(int $width, int $height, int $src_x, int $src_y, int $src_w, int $src_h): string
171
    {
172
        $thumb = imagecreatetruecolor($width, $height);
173
        $source = imagecreatefromjpeg($this->imagePath);
174
        imagecopyresized($thumb, $source, 0, 0, $src_x, $src_y, $width, $height, $src_w, $src_h);
175
        imagejpeg($thumb, "{$this->cachePath}/{$this->imageName}", $this->cacheSize[0]);
176
177
        imagedestroy($thumb);
178
        imagedestroy($source);
179
180
        return "{$this->cachePath}/{$this->imageName}";
181
    }
182
183
    /**
184
     * @param int $width
185
     * @param int $height
186
     * @param int $src_x
187
     * @param int $src_y
188
     * @param int $src_w
189
     * @param int $src_h
190
     * @return string
191
     */
192
    private function fromPng(int $width, int $height, int $src_x, int $src_y, int $src_w, int $src_h): string
193
    {
194
        $thumb = imagecreatetruecolor($width, $height);
195
        $source = imagecreatefrompng($this->imagePath);
196
197
        imagealphablending($thumb, false);
198
        imagesavealpha($thumb, true);
199
        imagecopyresized($thumb, $source, 0, 0, $src_x, $src_y, $width, $height, $src_w, $src_h);
200
        imagepng($thumb, "{$this->cachePath}/{$this->imageName}", $this->cacheSize[1]);
201
202
        imagedestroy($thumb);
203
        imagedestroy($source);
204
205
        return "{$this->cachePath}/{$this->imageName}";
206
    }
207
}