Passed
Push — develop ( fff86a...02dcc0 )
by Andrew
94:48
created

OptimizedImage::swapLazyLoadAttrs()   A

Complexity

Conditions 5
Paths 16

Size

Total Lines 20
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 13
c 1
b 0
f 0
dl 0
loc 20
rs 9.5222
cc 5
nc 16
nop 2
1
<?php
2
/**
3
 * Image Optimize plugin for Craft CMS 3.x
4
 *
5
 * Automatically optimize images after they've been transformed
6
 *
7
 * @link      https://nystudio107.com
0 ignored issues
show
Coding Style introduced by
The tag in position 1 should be the @copyright tag
Loading history...
8
 * @copyright Copyright (c) 2017 nystudio107
0 ignored issues
show
Coding Style introduced by
@copyright tag must contain a year and the name of the copyright holder
Loading history...
9
 */
0 ignored issues
show
Coding Style introduced by
PHP version not specified
Loading history...
Coding Style introduced by
Missing @category tag in file comment
Loading history...
Coding Style introduced by
Missing @package tag in file comment
Loading history...
Coding Style introduced by
Missing @author tag in file comment
Loading history...
Coding Style introduced by
Missing @license tag in file comment
Loading history...
10
11
namespace nystudio107\imageoptimize\models;
12
13
use craft\helpers\Html;
14
use nystudio107\imageoptimize\ImageOptimize;
15
use nystudio107\imageoptimize\helpers\UrlHelper;
16
use nystudio107\imageoptimize\helpers\Color as ColorHelper;
17
18
use craft\helpers\Template;
19
use craft\base\Model;
20
use craft\validators\ArrayValidator;
21
22
/**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
23
 * @author    nystudio107
0 ignored issues
show
Coding Style introduced by
The tag in position 1 should be the @package tag
Loading history...
Coding Style introduced by
Content of the @author tag must be in the form "Display Name <[email protected]>"
Loading history...
Coding Style introduced by
Tag value for @author tag indented incorrectly; expected 2 spaces but found 4
Loading history...
24
 * @package   ImageOptimize
0 ignored issues
show
Coding Style introduced by
Tag value for @package tag indented incorrectly; expected 1 spaces but found 3
Loading history...
25
 * @since     1.2.0
0 ignored issues
show
Coding Style introduced by
The tag in position 3 should be the @author tag
Loading history...
Coding Style introduced by
Tag value for @since tag indented incorrectly; expected 3 spaces but found 5
Loading history...
26
 */
0 ignored issues
show
Coding Style introduced by
Missing @category tag in class comment
Loading history...
Coding Style introduced by
Missing @license tag in class comment
Loading history...
Coding Style introduced by
Missing @link tag in class comment
Loading history...
27
class OptimizedImage extends Model
28
{
29
    // Public Properties
30
    // =========================================================================
31
32
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
33
     * @var string[] An array of optimized image variant URLs
34
     */
35
    public $optimizedImageUrls = [];
36
37
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
38
     * @var string[] An array of optimized .webp image variant URLs
39
     */
40
    public $optimizedWebPImageUrls = [];
41
42
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
43
     * @var int[] An array of the widths of the optimized image variants
44
     */
45
    public $variantSourceWidths = [];
46
47
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
48
     * @var int[] An array of the heights of the optimized image variants
49
     */
50
    public $variantHeights = [];
51
52
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
53
     * @var float[] An array of the x,y image focal point coords, ranging from 0.0 to 1.0
54
     */
55
    public $focalPoint;
56
57
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
58
     * @var int The width of the original source image
59
     */
60
    public $originalImageWidth;
61
62
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
63
     * @var int The height of the original source image
64
     */
65
    public $originalImageHeight;
66
67
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
68
     * @var string The base64 encoded placeholder LQIP image
69
     */
70
    public $placeholder = '';
71
72
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
73
     * @var string The base64 encoded placeholder LQIP SVG image
74
     */
75
    public $placeholderSvg = '';
76
77
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
78
     * @var string[] An array the 5 most dominant colors in the image
79
     */
80
    public $colorPalette = [];
81
82
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
83
     * @var int The overall lightness of the image, from 0..100
84
     */
85
    public $lightness;
86
87
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
88
     * @var int The width of the placeholder image
89
     */
90
    public $placeholderWidth;
91
92
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
93
     * @var int The height of the placeholder image
94
     */
95
    public $placeholderHeight;
96
97
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
98
     * @var string[] An array of errors logged when generating the image transforms
99
     */
100
    public $stickyErrors = [];
101
102
    // Public Methods
103
    // =========================================================================
104
105
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
106
     * @inheritdoc
107
     */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
108
    public function rules(): array
109
    {
110
        return [
111
            ['optimizedImageUrls', ArrayValidator::class],
112
            ['optimizedWebPImageUrls', ArrayValidator::class],
113
            ['variantSourceWidths', ArrayValidator::class],
114
            ['variantHeights', ArrayValidator::class],
115
            ['focalPoint', 'safe'],
116
            ['originalImageWidth', 'integer'],
117
            ['originalImageHeight', 'integer'],
118
            ['placeholder', 'string'],
119
            ['placeholderSvg', 'string'],
120
            ['colorPalette', ArrayValidator::class],
121
            ['placeholderWidth', 'integer'],
122
            ['placeholderHeight', 'integer'],
123
            ['stickyErrors', ArrayValidator::class],
124
        ];
125
    }
126
127
    /**
128
     * Return the first image variant URL or the specific one passed in via
129
     * $width
130
     *
131
     * @param int $width
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
132
     *
133
     * @return \Twig\Markup|null
134
     */
135
    public function src(int $width = 0): string
136
    {
137
        if (empty($width)) {
138
            return Template::raw(reset($this->optimizedImageUrls));
139
        }
140
141
        return Template::raw($this->optimizedImageUrls[$width] ?? '');
142
    }
143
144
    /**
145
     * Getter for CraftQL
146
     *
147
     * @param int $width
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
148
     *
149
     * @return null|string|\Twig\Markup
150
     */
151
    public function getSrc(int $width = 0): string
152
    {
153
        return $this->src($width);
154
    }
155
156
    /**
157
     * Return a string of image URLs and their sizes
158
     *
159
     * @param bool $dpr Whether to generate 1x, 2x srcsets vs the normal XXXw
160
     *                  srcsets
161
     *
162
     * @return \Twig\Markup|null
163
     */
164
    public function srcset(bool $dpr = false): string
165
    {
166
        return Template::raw($this->getSrcsetFromArray($this->optimizedImageUrls, $dpr));
167
    }
168
169
    /**
170
     * Getter for CraftQL
171
     *
172
     * @param bool $dpr
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
173
     *
174
     * @return string
175
     */
176
    public function getSrcset(bool $dpr = false): string
177
    {
178
        return $this->srcset($dpr);
179
    }
180
    /**
181
     * Return a string of image URLs and their sizes that match $width
182
     *
183
     * @param int  $width
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
184
     * @param bool $dpr Whether to generate 1x, 2x srcsets vs the normal XXXw
0 ignored issues
show
Coding Style introduced by
Expected 3 spaces after parameter name; 1 found
Loading history...
185
     *                  srcsets
186
     *
187
     * @return \Twig\Markup|null
188
     */
189
    public function srcsetWidth(int $width, bool $dpr = false): string
190
    {
191
        $subset = $this->getSrcsetSubsetArray($this->optimizedImageUrls, $width, 'width');
192
193
        return Template::raw($this->getSrcsetFromArray($subset, $dpr));
194
    }
195
196
    /**
197
     * Return a string of image URLs and their sizes that are at least $width
198
     * or larger
199
     *
200
     * @param int  $width
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
201
     * @param bool $dpr Whether to generate 1x, 2x srcsets vs the normal XXXw
0 ignored issues
show
Coding Style introduced by
Expected 3 spaces after parameter name; 1 found
Loading history...
202
     *                  srcsets
203
     *
204
     * @return \Twig\Markup|null
205
     */
206
    public function srcsetMinWidth(int $width, bool $dpr = false): string
207
    {
208
        $subset = $this->getSrcsetSubsetArray($this->optimizedImageUrls, $width, 'minwidth');
209
210
        return Template::raw($this->getSrcsetFromArray($subset, $dpr));
211
    }
212
213
    /**
214
     * Return a string of image URLs and their sizes that are $width or smaller
215
     *
216
     * @param int  $width
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
217
     * @param bool $dpr Whether to generate 1x, 2x srcsets vs the normal XXXw
0 ignored issues
show
Coding Style introduced by
Expected 3 spaces after parameter name; 1 found
Loading history...
218
     *                  srcsets
219
     *
220
     * @return \Twig\Markup|null
221
     */
222
    public function srcsetMaxWidth(int $width, bool $dpr = false): string
223
    {
224
        $subset = $this->getSrcsetSubsetArray($this->optimizedImageUrls, $width, 'maxwidth');
225
226
        return Template::raw($this->getSrcsetFromArray($subset, $dpr));
227
    }
228
229
    /**
230
     * Return the first webp image variant URL or the specific one passed in
231
     * via $width
232
     *
233
     * @param int $width
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
234
     *
235
     * @return \Twig\Markup|null
236
     */
237
    public function srcWebp(int $width = 0): string
238
    {
239
        if (empty($width)) {
240
            return Template::raw(reset($this->optimizedWebPImageUrls));
241
        }
242
243
        return Template::raw($this->optimizedWebPImageUrls[$width] ?? '');
244
    }
245
246
    /**
247
     * Getter for CraftQL
248
     *
249
     * @param int $width
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
250
     *
251
     * @return string
252
     */
253
    public function getSrcWebp(int $width = 0): string
254
    {
255
        return $this->srcWebp($width);
256
    }
257
258
    /**
259
     * Return a string of webp image URLs and their sizes
260
     *
261
     * @param bool $dpr Whether to generate 1x, 2x srcsets vs the normal XXXw
262
     *                  srcsets
263
     *
264
     * @return \Twig\Markup|null
265
     */
266
    public function srcsetWebp(bool $dpr = false): string
267
    {
268
        return Template::raw($this->getSrcsetFromArray($this->optimizedWebPImageUrls, $dpr));
269
    }
270
271
    /**
272
     * Getter for CraftQL
273
     *
274
     * @param bool $dpr
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
275
     *
276
     * @return string
277
     */
278
    public function getSrcsetWebp(bool $dpr = false): string
279
    {
280
        return $this->srcsetWebp($dpr);
281
    }
282
283
    /**
284
     * Return a string of webp image URLs and their sizes that match $width
285
     *
286
     * @param int  $width
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
287
     * @param bool $dpr Whether to generate 1x, 2x srcsets vs the normal XXXw
0 ignored issues
show
Coding Style introduced by
Expected 3 spaces after parameter name; 1 found
Loading history...
288
     *                  srcsets
289
     *
290
     * @return \Twig\Markup|null
291
     */
292
    public function srcsetWidthWebp(int $width, bool $dpr = false): string
293
    {
294
        $subset = $this->getSrcsetSubsetArray($this->optimizedWebPImageUrls, $width, 'width');
295
296
        return Template::raw($this->getSrcsetFromArray($subset, $dpr));
297
    }
298
299
    /**
300
     * Return a string of webp image URLs and their sizes that are at least
301
     * $width or larger
302
     *
303
     * @param int  $width
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
304
     * @param bool $dpr Whether to generate 1x, 2x srcsets vs the normal XXXw
0 ignored issues
show
Coding Style introduced by
Expected 3 spaces after parameter name; 1 found
Loading history...
305
     *                  srcsets
306
     *
307
     * @return \Twig\Markup|null
308
     */
309
    public function srcsetMinWidthWebp(int $width, bool $dpr = false): string
310
    {
311
        $subset = $this->getSrcsetSubsetArray($this->optimizedWebPImageUrls, $width, 'minwidth');
312
313
        return Template::raw($this->getSrcsetFromArray($subset, $dpr));
314
    }
315
316
    /**
317
     * Return a string of webp image URLs and their sizes that are $width or
318
     * smaller
319
     *
320
     * @param int  $width
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
321
     * @param bool $dpr Whether to generate 1x, 2x srcsets vs the normal XXXw
0 ignored issues
show
Coding Style introduced by
Expected 3 spaces after parameter name; 1 found
Loading history...
322
     *                  srcsets
323
     *
324
     * @return \Twig\Markup|null
325
     */
326
    public function srcsetMaxWidthWebp(int $width, bool $dpr = false): string
327
    {
328
        $subset = $this->getSrcsetSubsetArray($this->optimizedWebPImageUrls, $width, 'maxwidth');
329
330
        return Template::raw($this->getSrcsetFromArray($subset, $dpr));
331
    }
332
333
    /**
334
     * Work around issues with `<img srcset>` returning sizes larger than are
335
     * available as per:
336
     * https://medium.com/@MRWwebDesign/responsive-images-the-sizes-attribute-and-unexpected-image-sizes-882a2eadb6db
337
     *
338
     * @return int
339
     */
340
    public function maxSrcsetWidth(): int
341
    {
342
        $result = 0;
343
        if (!empty($this->optimizedImageUrls)) {
344
            $tempArray = $this->optimizedImageUrls;
345
            ksort($tempArray, SORT_NUMERIC);
346
347
            $keys = array_keys($tempArray);
348
            $result = end($keys);
349
        }
350
351
        return $result;
352
    }
353
354
    /**
355
     * Getter for CraftQL
356
     *
357
     * @return int
358
     */
359
    public function getMaxSrcsetWidth(): int
360
    {
361
        return $this->maxSrcsetWidth();
362
    }
363
364
    /**
365
     * Return the colors as an array of RGB colors
366
     */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
367
    public function colorPaletteRgb(): array
368
    {
369
        $colors = [];
370
371
        foreach ($this->colorPalette as $color) {
372
            if (!empty($color)) {
373
                $colors[] = ColorHelper::HTMLToRGB($color);
374
            }
375
        }
376
377
        return $colors;
378
    }
379
380
    /**
381
     * Generate a complete <img> tag for this OptimizedImages model
382
     *
383
     * @param false|string $lazyLoad
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
384
     * @param array $imgAttrs
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
Coding Style introduced by
Expected 8 spaces after parameter type; 1 found
Loading history...
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
385
     * @return \Twig\Markup
0 ignored issues
show
Coding Style introduced by
Tag @return cannot be grouped with parameter tags in a doc comment
Loading history...
386
     */
387
    public function imgTag($lazyLoad = false, $imgAttrs = [])
388
    {
389
        // Merge the passed in options with the tag attributes
390
        $attrs = array_merge([
0 ignored issues
show
Coding Style introduced by
The opening parenthesis of a multi-line function call should be the last content on the line.
Loading history...
391
                'class' => '',
392
                'src' => reset($this->optimizedImageUrls),
393
                'srcset' => $this->getSrcsetFromArray($this->optimizedImageUrls),
394
                'sizes' => '100vw',
395
                'loading' => $lazyLoad,
396
            ],
397
            $imgAttrs
398
        );
399
        // Handle lazy loading
400
        if ($lazyLoad) {
401
            $attrs = $this->swapLazyLoadAttrs($lazyLoad, $attrs);
402
        }
403
        // Remove any empty attributes
404
        $attrs = array_filter($attrs);
405
        // Render the tag
406
        $tag = Html::tag('img', '', $attrs);
407
408
        return Template::raw($tag);
409
    }
410
411
    /**
412
     * Return a base64-encoded placeholder image
413
     *
414
     * @return \Twig\Markup|null
415
     */
416
    public function placeholderImage()
417
    {
418
        $header = 'data:image/jpeg;base64,';
419
        if (!empty($this->placeholder)) {
420
            $content = $this->placeholder;
421
        } else {
422
            // At least return something
423
            return $this->defaultPlaceholderImage();
424
        }
425
426
        return Template::raw($header.rawurlencode($content));
427
    }
428
429
    /**
430
     * Getter for CraftQL
431
     *
432
     * @return string
433
     */
434
    public function getPlaceholderImage(): string
435
    {
436
        return (string)$this->placeholderImage();
437
    }
438
439
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
440
     * @return string
441
     */
442
    public function placeholderImageSize(): string
443
    {
444
        $placeholder = $this->placeholderImage();
445
        $contentLength = !empty(\strlen($placeholder)) ? \strlen($placeholder) : 0;
446
447
        return ImageOptimize::$plugin->optimize->humanFileSize($contentLength, 1);
448
    }
449
450
    /**
451
     * Return an SVG box as a placeholder image
452
     *
453
     * @param string|null $color
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
454
     *
455
     * @return \Twig\Markup|null
456
     */
457
    public function placeholderBox(string $color = null)
458
    {
459
        $width = $this->placeholderWidth ?? 1;
460
        $height = $this->placeholderHeight ?? 1;
461
        $color = $color ?? $this->colorPalette[0] ?? '#CCC';
462
463
        return Template::raw(ImageOptimize::$plugin->placeholder->generatePlaceholderBox($width, $height, $color));
464
    }
465
466
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
467
     * @param string|null $color
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
468
     *
469
     * @return string
470
     */
471
    public function getPlaceholderBox(string $color = null): string
472
    {
473
        return (string)$this->placeholderBox($color);
474
    }
475
476
    /**
477
     * Getter for CraftQL
478
     *
479
     * @return string
480
     */
481
    public function placeholderBoxSize(): string
482
    {
483
        $placeholder = $this->placeholderBox();
484
        $contentLength = !empty(\strlen($placeholder)) ? \strlen($placeholder) : 0;
485
486
        return ImageOptimize::$plugin->optimize->humanFileSize($contentLength, 1);
487
    }
488
489
    /**
490
     * Return a silhouette of the image as an SVG placeholder
491
     *
492
     * @return \Twig\Markup|null
493
     */
494
    public function placeholderSilhouette()
495
    {
496
        $header = 'data:image/svg+xml,';
497
        if (!empty($this->placeholderSvg)) {
498
            $content = $this->placeholderSvg;
499
        } else {
500
            // At least return something
501
            return $this->defaultPlaceholderImage();
502
        }
503
504
        return Template::raw($header.$content);
505
    }
506
507
    /**
508
     * Getter for CraftQL
509
     *
510
     * @return string
511
     */
512
    public function getPlaceholderSilhouette(): string
513
    {
514
        return (string)$this->placeholderSilhouette();
515
    }
516
517
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
518
     * @return string
519
     */
520
    public function placeholderSilhouetteSize(): string
521
    {
522
        $placeholder = $this->placeholderSilhouette();
523
        $contentLength = !empty(\strlen($placeholder)) ? \strlen($placeholder) : 0;
524
525
        return ImageOptimize::$plugin->optimize->humanFileSize($contentLength, 1);
526
    }
527
528
    /**
529
     *  Get the file size of any remote resource (using curl),
530
     *  either in bytes or - default - as human-readable formatted string.
531
     *
532
     * @author  Stephan Schmitz <[email protected]>
533
     * @license MIT <http://eyecatchup.mit-license.org/>
534
     * @url     <https://gist.github.com/eyecatchup/f26300ffd7e50a92bc4d>
535
     *
536
     * @param   string  $url        Takes the remote object's URL.
0 ignored issues
show
Coding Style introduced by
Parameter tags must be defined first in a doc comment
Loading history...
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 1 spaces but found 3
Loading history...
537
     * @param   boolean $formatSize Whether to return size in bytes or
0 ignored issues
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 1 spaces but found 3
Loading history...
538
     *                              formatted.
539
     * @param   boolean $useHead    Whether to use HEAD requests. If false,
0 ignored issues
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 1 spaces but found 3
Loading history...
540
     *                              uses GET.
541
     *
542
     * @return  int|mixed|string    Returns human-readable formatted size
0 ignored issues
show
Coding Style introduced by
Tag value for @return tag indented incorrectly; expected 1 spaces but found 2
Loading history...
543
     *                              or size in bytes (default: formatted).
544
     */
545
    public function getRemoteFileSize($url, $formatSize = true, $useHead = true)
546
    {
547
        // Get an absolute URL with protocol that curl will be happy with
548
        $url = UrlHelper::absoluteUrlWithProtocol($url);
549
        $ch = curl_init($url);
550
        curl_setopt_array($ch, [
0 ignored issues
show
Coding Style introduced by
The opening parenthesis of a multi-line function call should be the last content on the line.
Loading history...
551
            CURLOPT_RETURNTRANSFER => 1,
552
            CURLOPT_FOLLOWLOCATION => 1,
553
            CURLOPT_SSL_VERIFYPEER => 0,
554
        ]);
0 ignored issues
show
Coding Style introduced by
For multi-line function calls, the closing parenthesis should be on a new line.

If a function call spawns multiple lines, the coding standard suggests to move the closing parenthesis to a new line:

someFunctionCall(
    $firstArgument,
    $secondArgument,
    $thirdArgument
); // Closing parenthesis on a new line.
Loading history...
555
        if ($useHead) {
556
            curl_setopt($ch, CURLOPT_NOBODY, 1);
557
        }
558
        curl_exec($ch);
559
        // content-length of download (in bytes), read from Content-Length: field
560
        $contentLength = curl_getinfo($ch, CURLINFO_CONTENT_LENGTH_DOWNLOAD);
561
        curl_close($ch);
562
        // cannot retrieve file size, return "-1"
563
        if (!$contentLength) {
564
            return -1;
565
        }
566
        // return size in bytes
567
        if (!$formatSize) {
568
            return $contentLength;
569
        }
570
571
        return ImageOptimize::$plugin->optimize->humanFileSize($contentLength, 1);
572
    }
573
574
    // Protected Methods
575
    // =========================================================================
576
577
    protected function getSrcsetSubsetArray(array $set, int $width, string $comparison): array
0 ignored issues
show
Coding Style introduced by
You must use "/**" style comments for a function comment
Loading history...
578
    {
579
        $subset = [];
580
        $index = 0;
581
        if (empty($this->variantSourceWidths)) {
582
            return $subset;
583
        }
584
        foreach ($this->variantSourceWidths as $variantSourceWidth) {
585
            $match = false;
586
            switch ($comparison) {
587
                case 'width':
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 12 spaces, found 16
Loading history...
588
                    if ($variantSourceWidth == $width) {
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 16 spaces, found 20
Loading history...
589
                        $match = true;
590
                    }
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 16 spaces, found 20
Loading history...
591
                    break;
592
593
                case 'minwidth':
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 12 spaces, found 16
Loading history...
594
                    if ($variantSourceWidth >= $width) {
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 16 spaces, found 20
Loading history...
595
                        $match = true;
596
                    }
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 16 spaces, found 20
Loading history...
597
                    break;
598
599
                case 'maxwidth':
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 12 spaces, found 16
Loading history...
600
                    if ($variantSourceWidth <= $width) {
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 16 spaces, found 20
Loading history...
601
                        $match = true;
602
                    }
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 16 spaces, found 20
Loading history...
603
                    break;
604
            }
605
            if ($match) {
606
                $subset += array_slice($set, $index, 1, true);
607
            }
608
            $index++;
609
        }
610
611
        return $subset;
612
    }
613
614
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
615
     * @param array $array
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
616
     * @param bool  $dpr
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
617
     *
618
     * @return string
619
     */
620
    protected function getSrcsetFromArray(array $array, bool $dpr = false): string
621
    {
622
        $srcset = '';
623
        foreach ($array as $key => $value) {
624
            if ($dpr) {
625
                $descriptor = '1x';
626
                if (!empty($array[(int)$key / 2])) {
627
                    $descriptor = '2x';
628
                }
629
                if (!empty($array[(int)$key / 3])) {
630
                    $descriptor = '3x';
631
                }
632
            } else {
633
                $descriptor = $key.'w';
634
            }
635
            $srcset .= $value.' '.$descriptor.', ';
636
        }
637
        $srcset = rtrim($srcset, ', ');
638
639
        return $srcset;
640
    }
641
642
    /**
643
     * Return a default placeholder image
644
     *
645
     * @return \Twig\Markup
646
     */
647
    protected function defaultPlaceholderImage(): \Twig\Markup
648
    {
649
        $width = 1;
650
        $height = 1;
651
        $color = '#CCC';
652
653
        return Template::raw(ImageOptimize::$plugin->placeholder->generatePlaceholderBox($width, $height, $color));
654
    }
655
656
    /**
657
     * Swap the tag attributes to work with lazy loading
658
     *
659
     * @param array $attrs
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
Coding Style introduced by
Expected 2 spaces after parameter type; 1 found
Loading history...
Coding Style introduced by
Doc comment for parameter $attrs does not match actual variable name $lazyLoad
Loading history...
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
660
     * @param string $lazyLoad
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
Coding Style introduced by
Doc comment for parameter $lazyLoad does not match actual variable name $attrs
Loading history...
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
661
     * @return array
0 ignored issues
show
Coding Style introduced by
Tag @return cannot be grouped with parameter tags in a doc comment
Loading history...
662
     */
663
    protected function swapLazyLoadAttrs(string $lazyLoad, array $attrs): array
664
    {
665
        if (!empty($attrs['class'])) {
666
            $attrs['class'] .= ' lazyload';
667
        }
668
        if (!empty($attrs['loading'])) {
669
            $attrs['loading'] = 'lazy';
670
        }
671
        if (!empty($attrs['srcset'])) {
672
            $attrs['data-srcset'] = $attrs['srcset'];
673
            $attrs['srcset'] = '';
674
        }
675
        if (!empty($attrs['src'])) {
676
            $attrs['data-src'] = $attrs['src'];
677
        }
678
        $attrs['src'] = $this->getLazyLoadSrc($lazyLoad);
679
        $attrs['height'] = $this->placeholderHeight;
680
        $attrs['width'] = $this->placeholderWidth;
681
682
        return $attrs;
683
    }
684
685
    /**
686
     * Return a lazy loading placeholder image based on the passed in $lazyload setting
687
     *
688
     * @param string $lazyLoad
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
689
     * @param array $attrs
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
Coding Style introduced by
Expected 2 spaces after parameter type; 1 found
Loading history...
Coding Style introduced by
Superfluous parameter comment
Loading history...
690
     *
691
     * @return array
692
     */
693
    protected function getLazyLoadSrc(string $lazyLoad): string
694
    {
695
        $result = '';
696
        if (is_string($lazyLoad)) {
0 ignored issues
show
introduced by
The condition is_string($lazyLoad) is always true.
Loading history...
697
            $lazyLoad = strtolower($lazyLoad);
698
        }
699
        switch ($lazyLoad) {
700
            case 'image':
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 8 spaces, found 12
Loading history...
701
                $result = $this->getPlaceholderImage();
702
                break;
703
            case 'silhouette':
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 8 spaces, found 12
Loading history...
704
                $result = $this->getPlaceholderSilhouette();
705
                break;
706
            case 'color':
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 8 spaces, found 12
Loading history...
707
                $result = $this->getPlaceholderBox($this->colorPalette[0] ?? null);
708
                break;
709
            default:
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 8 spaces, found 12
Loading history...
710
                $result = $this->getPlaceholderBox();
711
                break;
712
        }
713
714
        return $result;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $result returns the type string which is incompatible with the documented return type array.
Loading history...
715
    }
716
}
717