1 | <?php |
||||
2 | |||||
3 | namespace Compolomus\Compomage; |
||||
4 | |||||
5 | use Compolomus\Compomage\Interfaces\ImageInterface; |
||||
6 | use Exception; |
||||
7 | use InvalidArgumentException; |
||||
8 | use LogicException; |
||||
9 | use RuntimeException; |
||||
10 | use SplFileObject; |
||||
11 | |||||
12 | abstract class AbstractImage implements ImageInterface |
||||
13 | { |
||||
14 | protected const POSITIONS = [ |
||||
15 | 'NORTHWEST' => ['x' => 0, 'y' => 0, 'padX' => 10, 'padY' => 10], |
||||
16 | 'NORTH' => ['x' => 1, 'y' => 0, 'padX' => 0, 'padY' => 10], |
||||
17 | 'NORTHEAST' => ['x' => 2, 'y' => 0, 'padX' => -10, 'padY' => 10], |
||||
18 | 'WEST' => ['x' => 0, 'y' => 1, 'padX' => 10, 'padY' => 0], |
||||
19 | 'CENTER' => ['x' => 1, 'y' => 1, 'padX' => 0, 'padY' => 0], |
||||
20 | 'EAST' => ['x' => 2, 'y' => 1, 'padX' => -10, 'padY' => 0], |
||||
21 | 'SOUTHWEST' => ['x' => 0, 'y' => 2, 'padX' => 10, 'padY' => -10], |
||||
22 | 'SOUTH' => ['x' => 1, 'y' => 2, 'padX' => 0, 'padY' => -10], |
||||
23 | 'SOUTHEAST' => ['x' => 2, 'y' => 2, 'padX' => -10, 'padY' => -10] |
||||
24 | ]; |
||||
25 | |||||
26 | protected $image; |
||||
27 | |||||
28 | protected $width; |
||||
29 | |||||
30 | protected $height; |
||||
31 | |||||
32 | protected $orientation; |
||||
33 | |||||
34 | /** |
||||
35 | * @param int $value |
||||
36 | * @param int $range |
||||
37 | * @return bool |
||||
38 | */ |
||||
39 | protected function compareRangeValue(int $value, int $range): bool |
||||
40 | { |
||||
41 | return in_array(abs($value), range(0, $range), true); |
||||
42 | } |
||||
43 | |||||
44 | /** |
||||
45 | * @param int $width |
||||
46 | * @param int $height |
||||
47 | * @param Image $background |
||||
48 | * @return ImageInterface |
||||
49 | */ |
||||
50 | protected function setBackground(int $width, int $height, Image $background): ImageInterface |
||||
51 | { |
||||
52 | $this->orientation === 'vertical' |
||||
53 | ? $this->resizeByHeight($height) |
||||
54 | : $this->resizeByWidth($width); |
||||
55 | |||||
56 | $background->watermark($this, 'CENTER'); |
||||
57 | |||||
58 | $this->setImage($background->getImage()); |
||||
59 | $this->setSizes(); |
||||
60 | |||||
61 | return $this; |
||||
62 | } |
||||
63 | |||||
64 | 15 | protected function setOrientation(): void |
|||
65 | { |
||||
66 | 15 | $this->orientation = $this->getWidth() < $this->getHeight() ? 'vertical' : 'horizontal'; |
|||
67 | } |
||||
68 | |||||
69 | public function getOrientation(): string |
||||
70 | { |
||||
71 | return $this->orientation; |
||||
72 | } |
||||
73 | |||||
74 | /** |
||||
75 | * @param string $mode |
||||
76 | * @param int $param |
||||
77 | * @return ImageInterface |
||||
78 | * @throws InvalidArgumentException |
||||
79 | */ |
||||
80 | 2 | public function resizeBy(string $mode, int $param): ImageInterface |
|||
81 | { |
||||
82 | 2 | switch ($mode) { |
|||
83 | 2 | case 'width': |
|||
84 | 1 | return $this->resizeByWidth($param); |
|||
85 | 2 | case 'height': |
|||
86 | 1 | return $this->resizeByHeight($param); |
|||
87 | 2 | case 'percent': |
|||
88 | 1 | return $this->resizeByPercent($param); |
|||
89 | default: |
||||
90 | 1 | throw new InvalidArgumentException('Unsupported mode type by resize'); |
|||
91 | } |
||||
92 | } |
||||
93 | |||||
94 | /** |
||||
95 | * @param int $width |
||||
96 | * @return ImageInterface |
||||
97 | */ |
||||
98 | 1 | public function resizeByWidth(int $width): ImageInterface |
|||
99 | { |
||||
100 | 1 | return $this->resize($width, (int) ($this->getHeight() * ($width / $this->getWidth()))); |
|||
101 | } |
||||
102 | |||||
103 | /** |
||||
104 | * @return int |
||||
105 | */ |
||||
106 | 15 | public function getHeight(): int |
|||
107 | { |
||||
108 | 15 | return $this->height; |
|||
109 | } |
||||
110 | |||||
111 | /** |
||||
112 | * @param int $height |
||||
113 | */ |
||||
114 | 15 | protected function setHeight(int $height): void |
|||
115 | { |
||||
116 | 15 | $this->height = $height; |
|||
117 | } |
||||
118 | |||||
119 | /** |
||||
120 | * @return int |
||||
121 | */ |
||||
122 | 15 | public function getWidth(): int |
|||
123 | { |
||||
124 | 15 | return $this->width; |
|||
125 | } |
||||
126 | |||||
127 | /** |
||||
128 | * @param int $width |
||||
129 | */ |
||||
130 | 15 | protected function setWidth(int $width): void |
|||
131 | { |
||||
132 | 15 | $this->width = $width; |
|||
133 | } |
||||
134 | |||||
135 | /** |
||||
136 | * @param int $height |
||||
137 | * @return ImageInterface |
||||
138 | */ |
||||
139 | 1 | public function resizeByHeight(int $height): ImageInterface |
|||
140 | { |
||||
141 | 1 | return $this->resize((int) ($this->getWidth() * ($height / $this->getHeight())), $height); |
|||
142 | } |
||||
143 | |||||
144 | /** |
||||
145 | * @param int $percent |
||||
146 | * @return ImageInterface |
||||
147 | */ |
||||
148 | 1 | public function resizeByPercent(int $percent): ImageInterface |
|||
149 | { |
||||
150 | 1 | return $this->resize( |
|||
151 | 1 | (int) ($this->getWidth() * ($percent / 100)), |
|||
152 | 1 | (int) ($this->getHeight() * ($percent / 100)) |
|||
153 | ); |
||||
154 | } |
||||
155 | |||||
156 | abstract protected function newImage(int $width, int $height); |
||||
157 | |||||
158 | /** |
||||
159 | * @param ImageInterface|Image $watermark |
||||
160 | * @param string $position |
||||
161 | * @return ImageInterface |
||||
162 | * @throws InvalidArgumentException |
||||
163 | */ |
||||
164 | 1 | public function watermark($watermark, string $position): ImageInterface |
|||
165 | { |
||||
166 | 1 | if (!array_key_exists(strtoupper($position), self::POSITIONS)) { |
|||
167 | 1 | throw new InvalidArgumentException('Wrong position'); |
|||
168 | } |
||||
169 | |||||
170 | return $this->prepareWatermark( |
||||
171 | $watermark, |
||||
172 | (int) ((($this->getWidth() - $watermark->getWidth()) / 2) * self::POSITIONS[strtoupper($position)]['x']) + self::POSITIONS[strtoupper($position)]['padX'], |
||||
0 ignored issues
–
show
Bug
introduced
by
![]() |
|||||
173 | (int) ((($this->getHeight() - $watermark->getHeight()) / 2) * self::POSITIONS[strtoupper($position)]['y']) + self::POSITIONS[strtoupper($position)]['padY'] |
||||
0 ignored issues
–
show
The method
getHeight() does not exist on Compolomus\Compomage\Interfaces\ImageInterface . Since it exists in all sub-types, consider adding an abstract or default implementation to Compolomus\Compomage\Interfaces\ImageInterface .
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
174 | ); |
||||
175 | } |
||||
176 | |||||
177 | /** |
||||
178 | * @param ImageInterface|Image $watermark |
||||
179 | * @param int $x |
||||
180 | * @param int $y |
||||
181 | * @return ImageInterface |
||||
182 | */ |
||||
183 | abstract protected function prepareWatermark($watermark, int $x, int $y): ImageInterface; |
||||
184 | |||||
185 | /** |
||||
186 | * @param int $width |
||||
187 | * @param int $height |
||||
188 | * @return ImageInterface |
||||
189 | */ |
||||
190 | 2 | public function thumbnail(int $width, int $height): ImageInterface |
|||
191 | { |
||||
192 | 2 | $newHeight = $height; |
|||
193 | 2 | $newWidth = $width; |
|||
194 | |||||
195 | 2 | ($this->getWidth() / $this->getHeight()) >= ($width / $height) |
|||
196 | 1 | ? $newWidth = (int) ($this->getWidth() / ($this->getHeight() / $height)) |
|||
197 | 1 | : $newHeight = (int) ($this->getHeight() / ($this->getWidth() / $width)); |
|||
198 | |||||
199 | 2 | return $this->prepareThumbnail($width, $height, $newWidth, $newHeight); |
|||
200 | } |
||||
201 | |||||
202 | /** |
||||
203 | * @param int $width |
||||
204 | * @param int $height |
||||
205 | * @return ImageInterface |
||||
206 | */ |
||||
207 | abstract protected function prepareThumbnail(int $width, int $height): ImageInterface; |
||||
208 | |||||
209 | /** |
||||
210 | * @return string chunked base64 |
||||
211 | */ |
||||
212 | public function getBase64(): string |
||||
213 | { |
||||
214 | return base64_encode((string) $this); |
||||
215 | |||||
216 | } |
||||
217 | |||||
218 | /** |
||||
219 | * @param $image |
||||
220 | */ |
||||
221 | 15 | protected function setImage($image): void |
|||
222 | { |
||||
223 | 15 | $this->image = $image; |
|||
224 | } |
||||
225 | |||||
226 | 15 | public function getImage() |
|||
227 | { |
||||
228 | 15 | return $this->image; |
|||
229 | } |
||||
230 | |||||
231 | /** |
||||
232 | * System method |
||||
233 | * |
||||
234 | * @param void |
||||
235 | */ |
||||
236 | abstract protected function setSizes(): void; |
||||
237 | |||||
238 | /** |
||||
239 | * @param string $image |
||||
240 | * @throws Exception |
||||
241 | */ |
||||
242 | 17 | protected function init(string $image): void |
|||
243 | { |
||||
244 | switch ($image) { |
||||
245 | // base64 |
||||
246 | 17 | case base64_encode(base64_decode($image, true)) === $image: |
|||
247 | 3 | $this->getImageByBase64($image); |
|||
248 | 2 | break; |
|||
249 | // URL |
||||
250 | 16 | case (0 === strpos($image, 'http')): |
|||
251 | 3 | $this->getImageByURL($image); |
|||
252 | 2 | break; |
|||
253 | // Local file |
||||
254 | default: |
||||
255 | 15 | $this->tmp(file_get_contents($image)); |
|||
256 | } |
||||
257 | } |
||||
258 | |||||
259 | /** |
||||
260 | * @param string $base64 |
||||
261 | * @return void |
||||
262 | * @throws Exception |
||||
263 | */ |
||||
264 | 3 | protected function getImageByBase64(string $base64): void |
|||
265 | { |
||||
266 | 3 | $this->tmp(base64_decode($base64)); |
|||
267 | } |
||||
268 | |||||
269 | /** |
||||
270 | * @param string $source |
||||
271 | * @return ImageInterface |
||||
272 | */ |
||||
273 | abstract protected function tmp(string $source): ImageInterface; |
||||
274 | |||||
275 | /** |
||||
276 | * @param string $url |
||||
277 | * @return InvalidArgumentException|null |
||||
278 | * @throws Exception |
||||
279 | * @throws InvalidArgumentException |
||||
280 | * @throws LogicException |
||||
281 | * @throws RuntimeException |
||||
282 | */ |
||||
283 | 3 | protected function getImageByURL(string $url): ?InvalidArgumentException |
|||
284 | { |
||||
285 | 3 | if (@!getimagesize($url)) { |
|||
286 | 1 | throw new InvalidArgumentException('Unsupported image type'); |
|||
287 | } |
||||
288 | 2 | $upload = new SplFileObject($url, 'rb'); |
|||
289 | 2 | $image = ''; |
|||
290 | 2 | while (!$upload->eof()) { |
|||
291 | 2 | $image .= $upload->fgets(); |
|||
292 | } |
||||
293 | 2 | $this->tmp($image); |
|||
294 | |||||
295 | 2 | return null; |
|||
296 | } |
||||
297 | } |
||||
298 |