PluginProbe
WPFunnels – Funnel Builder for WooCommerce with Checkout & One Click Upsell / 3.12.12
WPFunnels – Funnel Builder for WooCommerce with Checkout & One Click Upsell v3.12.12
3.13.4 3.13.3 3.13.2 3.13.1 3.13.0 3.12.13 3.12.12 3.12.11 3.12.10 3.12.9 3.12.8 3.12.7 3.12.6 3.12.5 3.12.4 3.12.3 3.12.1 3.12.2 3.12.0 3.11.1 3.11.0 3.10.9 3.10.8 3.10.7 3.10.6 All 262 releases
wpfunnels / vendor / spatie / image / src / Manipulations.php

Manipulations.php in WPFunnels – Funnel Builder for WooCommerce with Checkout & One Click Upsell 3.12.12, at vendor/spatie/image/src/Manipulations.php

609 lines 17.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace Spatie\Image;
4
5 use League\Glide\Filesystem\FileNotFoundException;
6 use ReflectionClass;
7 use Spatie\Image\Exceptions\InvalidManipulation;
8
9 class Manipulations
10 {
11 public const CROP_TOP_LEFT = 'crop-top-left';
12 public const CROP_TOP = 'crop-top';
13 public const CROP_TOP_RIGHT = 'crop-top-right';
14 public const CROP_LEFT = 'crop-left';
15 public const CROP_CENTER = 'crop-center';
16 public const CROP_RIGHT = 'crop-right';
17 public const CROP_BOTTOM_LEFT = 'crop-bottom-left';
18 public const CROP_BOTTOM = 'crop-bottom';
19 public const CROP_BOTTOM_RIGHT = 'crop-bottom-right';
20
21 public const ORIENTATION_AUTO = 'auto';
22 public const ORIENTATION_0 = 0;
23 public const ORIENTATION_90 = 90;
24 public const ORIENTATION_180 = 180;
25 public const ORIENTATION_270 = 270;
26
27 public const FLIP_HORIZONTALLY = 'h';
28 public const FLIP_VERTICALLY = 'v';
29 public const FLIP_BOTH = 'both';
30
31 public const FIT_CONTAIN = 'contain';
32 public const FIT_MAX = 'max';
33 public const FIT_FILL = 'fill';
34 public const FIT_FILL_MAX = 'fill-max';
35 public const FIT_STRETCH = 'stretch';
36 public const FIT_CROP = 'crop';
37
38 public const BORDER_OVERLAY = 'overlay';
39 public const BORDER_SHRINK = 'shrink';
40 public const BORDER_EXPAND = 'expand';
41
42 public const FORMAT_JPG = 'jpg';
43 public const FORMAT_PJPG = 'pjpg';
44 public const FORMAT_PNG = 'png';
45 public const FORMAT_GIF = 'gif';
46 public const FORMAT_WEBP = 'webp';
47 public const FORMAT_AVIF = 'avif';
48 public const FORMAT_TIFF = 'tiff';
49
50 public const FILTER_GREYSCALE = 'greyscale';
51 public const FILTER_SEPIA = 'sepia';
52
53 public const UNIT_PIXELS = 'px';
54 public const UNIT_PERCENT = '%';
55
56 public const POSITION_TOP_LEFT = 'top-left';
57 public const POSITION_TOP = 'top';
58 public const POSITION_TOP_RIGHT = 'top-right';
59 public const POSITION_LEFT = 'left';
60 public const POSITION_CENTER = 'center';
61 public const POSITION_RIGHT = 'right';
62 public const POSITION_BOTTOM_LEFT = 'bottom-left';
63 public const POSITION_BOTTOM = 'bottom';
64 public const POSITION_BOTTOM_RIGHT = 'bottom-right';
65
66 protected ManipulationSequence $manipulationSequence;
67
68 public function __construct(array $manipulations = [])
69 {
70 if (! $this->hasMultipleConversions($manipulations)) {
71 $manipulations = [$manipulations];
72 }
73
74 foreach ($manipulations as $manipulation) {
75 $this->manipulationSequence = new ManipulationSequence($manipulation);
76 }
77 }
78
79 public static function create(array $manipulations = []): Manipulations
80 {
81 return new self($manipulations);
82 }
83
84 /**
85 * @throws InvalidManipulation
86 */
87 public function orientation(string $orientation): static
88 {
89 if (! $this->validateManipulation($orientation, 'orientation')) {
90 throw InvalidManipulation::invalidParameter(
91 'orientation',
92 $orientation,
93 $this->getValidManipulationOptions('orientation')
94 );
95 }
96
97 return $this->addManipulation('orientation', $orientation);
98 }
99
100 /**
101 * @throws InvalidManipulation
102 */
103 public function flip(string $orientation): static
104 {
105 if (! $this->validateManipulation($orientation, 'flip')) {
106 throw InvalidManipulation::invalidParameter(
107 'flip',
108 $orientation,
109 $this->getValidManipulationOptions('flip')
110 );
111 }
112
113 return $this->addManipulation('flip', $orientation);
114 }
115
116 /**
117 * @throws InvalidManipulation
118 */
119 public function crop(string $cropMethod, int $width, int $height): static
120 {
121 if (! $this->validateManipulation($cropMethod, 'crop')) {
122 throw InvalidManipulation::invalidParameter(
123 'cropmethod',
124 $cropMethod,
125 $this->getValidManipulationOptions('crop')
126 );
127 }
128
129 $this->width($width);
130 $this->height($height);
131
132 return $this->addManipulation('crop', $cropMethod);
133 }
134
135 /**
136 * @param int $focalX Crop center X in percent
137 * @param int $focalY Crop center Y in percent
138 *
139 * @throws InvalidManipulation
140 */
141 public function focalCrop(int $width, int $height, int $focalX, int $focalY, float $zoom = 1): static
142 {
143 if ($zoom < 1 || $zoom > 100) {
144 throw InvalidManipulation::valueNotInRange('zoom', $zoom, 1, 100);
145 }
146
147 $this->width($width);
148 $this->height($height);
149
150 return $this->addManipulation('crop', "crop-{$focalX}-{$focalY}-{$zoom}");
151 }
152
153 /**
154 * @throws InvalidManipulation
155 */
156 public function manualCrop(int $width, int $height, int $x, int $y): static
157 {
158 if ($width < 0) {
159 throw InvalidManipulation::invalidWidth($width);
160 }
161
162 if ($height < 0) {
163 throw InvalidManipulation::invalidWidth($height);
164 }
165
166 return $this->addManipulation('manualCrop', "{$width},{$height},{$x},{$y}");
167 }
168
169 /**
170 * @throws InvalidManipulation
171 */
172 public function width(int $width): static
173 {
174 if ($width < 0) {
175 throw InvalidManipulation::invalidWidth($width);
176 }
177
178 return $this->addManipulation('width', (string)$width);
179 }
180
181 /**
182 * @throws InvalidManipulation
183 */
184 public function height(int $height): static
185 {
186 if ($height < 0) {
187 throw InvalidManipulation::invalidHeight($height);
188 }
189
190 return $this->addManipulation('height', (string)$height);
191 }
192
193 /**
194 * @throws InvalidManipulation
195 */
196 public function fit(string $fitMethod, ?int $width = null, ?int $height = null): static
197 {
198 if (! $this->validateManipulation($fitMethod, 'fit')) {
199 throw InvalidManipulation::invalidParameter(
200 'fit',
201 $fitMethod,
202 $this->getValidManipulationOptions('fit')
203 );
204 }
205
206 if ($width === null && $height === null) {
207 throw new InvalidManipulation('Width or height or both must be provided');
208 }
209
210 if ($width !== null) {
211 $this->width($width);
212 }
213
214 if ($height !== null) {
215 $this->height($height);
216 }
217
218 return $this->addManipulation('fit', $fitMethod);
219 }
220
221 /**
222 * @param int $ratio A value between 1 and 8
223 *
224 * @throws InvalidManipulation
225 */
226 public function devicePixelRatio(int $ratio): static
227 {
228 if ($ratio < 1 || $ratio > 8) {
229 throw InvalidManipulation::valueNotInRange('ratio', $ratio, 1, 8);
230 }
231
232 return $this->addManipulation('devicePixelRatio', (string)$ratio);
233 }
234
235 /**
236 * @param int $brightness A value between -100 and 100
237 *
238 * @throws InvalidManipulation
239 */
240 public function brightness(int $brightness): static
241 {
242 if ($brightness < -100 || $brightness > 100) {
243 throw InvalidManipulation::valueNotInRange('brightness', $brightness, -100, 100);
244 }
245
246 return $this->addManipulation('brightness', (string)$brightness);
247 }
248
249 /**
250 * @param float $gamma A value between 0.01 and 9.99
251 *
252 * @throws InvalidManipulation
253 */
254 public function gamma(float $gamma): static
255 {
256 if ($gamma < 0.01 || $gamma > 9.99) {
257 throw InvalidManipulation::valueNotInRange('gamma', $gamma, 0.01, 9.00);
258 }
259
260 return $this->addManipulation('gamma', (string)$gamma);
261 }
262
263 /**
264 * @param int $contrast A value between -100 and 100
265 *
266 * @throws InvalidManipulation
267 */
268 public function contrast(int $contrast): static
269 {
270 if ($contrast < -100 || $contrast > 100) {
271 throw InvalidManipulation::valueNotInRange('contrast', $contrast, -100, 100);
272 }
273
274 return $this->addManipulation('contrast', (string)$contrast);
275 }
276
277 /**
278 * @param int $sharpen A value between 0 and 100
279 *
280 * @throws InvalidManipulation
281 */
282 public function sharpen(int $sharpen): static
283 {
284 if ($sharpen < 0 || $sharpen > 100) {
285 throw InvalidManipulation::valueNotInRange('sharpen', $sharpen, 0, 100);
286 }
287
288 return $this->addManipulation('sharpen', (string)$sharpen);
289 }
290
291 /**
292 * @param int $blur A value between 0 and 100
293 *
294 * @throws InvalidManipulation
295 */
296 public function blur(int $blur): static
297 {
298 if ($blur < 0 || $blur > 100) {
299 throw InvalidManipulation::valueNotInRange('blur', $blur, 0, 100);
300 }
301
302 return $this->addManipulation('blur', (string)$blur);
303 }
304
305 /**
306 * @param int $pixelate A value between 0 and 1000
307 *
308 * @throws InvalidManipulation
309 */
310 public function pixelate(int $pixelate): static
311 {
312 if ($pixelate < 0 || $pixelate > 1000) {
313 throw InvalidManipulation::valueNotInRange('pixelate', $pixelate, 0, 1000);
314 }
315
316 return $this->addManipulation('pixelate', (string)$pixelate);
317 }
318
319 /**
320 * @throws InvalidManipulation
321 */
322 public function greyscale(): static
323 {
324 return $this->filter('greyscale');
325 }
326
327 /**
328 * @throws InvalidManipulation
329 */
330 public function sepia(): static
331 {
332 return $this->filter('sepia');
333 }
334
335 public function background(string $colorName): static
336 {
337 return $this->addManipulation('background', $colorName);
338 }
339
340 /**
341 * @throws InvalidManipulation
342 */
343 public function border(int $width, string $color, string $borderType = 'overlay'): static
344 {
345 if ($width < 0) {
346 throw InvalidManipulation::invalidWidth($width);
347 }
348
349 if (! $this->validateManipulation($borderType, 'border')) {
350 throw InvalidManipulation::invalidParameter(
351 'border',
352 $borderType,
353 $this->getValidManipulationOptions('border')
354 );
355 }
356
357 return $this->addManipulation('border', "{$width},{$color},{$borderType}");
358 }
359
360 /**
361 * @throws InvalidManipulation
362 */
363 public function quality(int $quality): static
364 {
365 if ($quality < 0 || $quality > 100) {
366 throw InvalidManipulation::valueNotInRange('quality', $quality, 0, 100);
367 }
368
369 return $this->addManipulation('quality', (string)$quality);
370 }
371
372 /**
373 * @throws InvalidManipulation
374 */
375 public function format(string $format): static
376 {
377 if (! $this->validateManipulation($format, 'format')) {
378 throw InvalidManipulation::invalidParameter(
379 'format',
380 $format,
381 $this->getValidManipulationOptions('format')
382 );
383 }
384
385 return $this->addManipulation('format', $format);
386 }
387
388 /**
389 * @throws InvalidManipulation
390 */
391 protected function filter(string $filterName): static
392 {
393 if (! $this->validateManipulation($filterName, 'filter')) {
394 throw InvalidManipulation::invalidParameter(
395 'filter',
396 $filterName,
397 $this->getValidManipulationOptions('filter')
398 );
399 }
400
401 return $this->addManipulation('filter', $filterName);
402 }
403
404 /**
405 * @throws FileNotFoundException
406 */
407 public function watermark(string $filePath): static
408 {
409 if (! file_exists($filePath)) {
410 throw new FileNotFoundException($filePath);
411 }
412
413 $this->addManipulation('watermark', $filePath);
414
415 return $this;
416 }
417
418 /**
419 * @param int $width The width of the watermark in pixels (default) or percent.
420 * @param string $unit The unit of the `$width` parameter. Use `Manipulations::UNIT_PERCENT` or `Manipulations::UNIT_PIXELS`.
421 */
422 public function watermarkWidth(int $width, string $unit = 'px'): static
423 {
424 $width = ($unit === static::UNIT_PERCENT ? $width.'w' : $width);
425
426 return $this->addManipulation('watermarkWidth', (string)$width);
427 }
428
429 /**
430 * @param int $height The height of the watermark in pixels (default) or percent.
431 * @param string $unit The unit of the `$height` parameter. Use `Manipulations::UNIT_PERCENT` or `Manipulations::UNIT_PIXELS`.
432 */
433 public function watermarkHeight(int $height, string $unit = 'px'): static
434 {
435 $height = ($unit === static::UNIT_PERCENT ? $height.'h' : $height);
436
437 return $this->addManipulation('watermarkHeight', (string)$height);
438 }
439
440 /**
441 * @param string $fitMethod How is the watermark fitted into the watermarkWidth and watermarkHeight properties.
442 *
443 * @throws InvalidManipulation
444 */
445 public function watermarkFit(string $fitMethod): static
446 {
447 if (! $this->validateManipulation($fitMethod, 'fit')) {
448 throw InvalidManipulation::invalidParameter(
449 'watermarkFit',
450 $fitMethod,
451 $this->getValidManipulationOptions('fit')
452 );
453 }
454
455 return $this->addManipulation('watermarkFit', $fitMethod);
456 }
457
458 /**
459 * @param int $xPadding How far is the watermark placed from the left and right edges of the image.
460 * @param int|null $yPadding How far is the watermark placed from the top and bottom edges of the image.
461 * @param string $unit Unit of the padding values. Use `Manipulations::UNIT_PERCENT` or `Manipulations::UNIT_PIXELS`.
462 */
463 public function watermarkPadding(int $xPadding, int $yPadding = null, string $unit = 'px'): static
464 {
465 $yPadding = $yPadding ?? $xPadding;
466
467 $xPadding = ($unit === static::UNIT_PERCENT ? $xPadding.'w' : $xPadding);
468 $yPadding = ($unit === static::UNIT_PERCENT ? $yPadding.'h' : $yPadding);
469
470 $this->addManipulation('watermarkPaddingX', (string)$xPadding);
471 $this->addManipulation('watermarkPaddingY', (string)$yPadding);
472
473 return $this;
474 }
475
476 /**
477 * @throws InvalidManipulation
478 */
479 public function watermarkPosition(string $position): static
480 {
481 if (! $this->validateManipulation($position, 'position')) {
482 throw InvalidManipulation::invalidParameter(
483 'watermarkPosition',
484 $position,
485 $this->getValidManipulationOptions('position')
486 );
487 }
488
489 return $this->addManipulation('watermarkPosition', $position);
490 }
491
492 /**
493 * Sets the opacity of the watermark. Only works with the `imagick` driver.
494 *
495 * @param int $opacity A value between 0 and 100.
496 *
497 * @throws InvalidManipulation
498 */
499 public function watermarkOpacity(int $opacity): static
500 {
501 if ($opacity < 0 || $opacity > 100) {
502 throw InvalidManipulation::valueNotInRange('opacity', $opacity, 0, 100);
503 }
504
505 return $this->addManipulation('watermarkOpacity', (string)$opacity);
506 }
507
508 /**
509 * Shave off some kilobytes by optimizing the image.
510 */
511 public function optimize(array $optimizationOptions = []): static
512 {
513 return $this->addManipulation('optimize', json_encode($optimizationOptions));
514 }
515
516 public function apply(): static
517 {
518 $this->manipulationSequence->startNewGroup();
519
520 return $this;
521 }
522
523 public function toArray(): array
524 {
525 return $this->manipulationSequence->toArray();
526 }
527
528 /**
529 * Checks if the given manipulations has arrays inside or not.
530 */
531 private function hasMultipleConversions(array $manipulations): bool
532 {
533 foreach ($manipulations as $manipulation) {
534 if (isset($manipulation[0]) && is_array($manipulation[0])) {
535 return true;
536 }
537 }
538
539 return false;
540 }
541
542 public function removeManipulation(string $name): void
543 {
544 $this->manipulationSequence->removeManipulation($name);
545 }
546
547 public function hasManipulation(string $manipulationName): bool
548 {
549 return ! is_null($this->getManipulationArgument($manipulationName));
550 }
551
552 public function getManipulationArgument(string $manipulationName)
553 {
554 foreach ($this->manipulationSequence->getGroups() as $manipulationSet) {
555 if (array_key_exists($manipulationName, $manipulationSet)) {
556 return $manipulationSet[$manipulationName];
557 }
558 }
559 }
560
561 protected function addManipulation(string $manipulationName, string $manipulationArgument): static
562 {
563 $this->manipulationSequence->addManipulation($manipulationName, $manipulationArgument);
564
565 return $this;
566 }
567
568 public function mergeManipulations(self $manipulations): static
569 {
570 $this->manipulationSequence->merge($manipulations->manipulationSequence);
571
572 return $this;
573 }
574
575 public function getManipulationSequence(): ManipulationSequence
576 {
577 return $this->manipulationSequence;
578 }
579
580 protected function validateManipulation(string $value, string $constantNamePrefix): bool
581 {
582 return in_array($value, $this->getValidManipulationOptions($constantNamePrefix));
583 }
584
585 protected function getValidManipulationOptions(string $manipulation): array
586 {
587 $options = (new ReflectionClass(static::class))->getConstants();
588
589 return array_filter($options, function ($value, $name) use ($manipulation) {
590 return str_starts_with($name, mb_strtoupper($manipulation));
591 }, ARRAY_FILTER_USE_BOTH);
592 }
593
594 public function isEmpty(): bool
595 {
596 return $this->manipulationSequence->isEmpty();
597 }
598
599 /*
600 * Get the first manipulation with the given name.
601 *
602 * @return mixed
603 */
604 public function getFirstManipulationArgument(string $manipulationName)
605 {
606 return $this->manipulationSequence->getFirstManipulationArgument($manipulationName);
607 }
608 }
609