Passed
Push — develop ( 280551...453ae8 )
by Andrew
05:36
created

OptimizedImage   D

Complexity

Total Complexity 59

Size/Duplication

Total Lines 622
Duplicated Lines 0 %

Importance

Changes 7
Bugs 0 Features 0
Metric Value
wmc 59
eloc 161
c 7
b 0
f 0
dl 0
loc 622
rs 4.08

32 Methods

Rating   Name   Duplication   Size   Complexity  
A maxSrcsetWidth() 0 12 2
A imgTag() 0 17 2
A srcsetWebp() 0 3 1
A srcsetMaxWidth() 0 5 1
A placeholderImage() 0 11 2
A srcsetWidthWebp() 0 5 1
B getSrcsetSubsetArray() 0 35 10
A srcset() 0 3 1
A srcsetMinWidthWebp() 0 5 1
A getPlaceholderImage() 0 3 1
A placeholderSilhouette() 0 11 2
A src() 0 7 2
A placeholderBox() 0 7 1
A getPlaceholderBox() 0 3 1
A rules() 0 16 1
A getSrcWebp() 0 3 1
A placeholderBoxSize() 0 6 2
A srcWebp() 0 7 2
A getSrcsetFromArray() 0 20 5
A getSrcset() 0 3 1
A getSrc() 0 3 1
A defaultPlaceholderImage() 0 7 1
A placeholderSilhouetteSize() 0 6 2
A placeholderImageSize() 0 6 2
A srcsetWidth() 0 5 1
A srcsetMaxWidthWebp() 0 5 1
A getPlaceholderSilhouette() 0 3 1
A colorPaletteRgb() 0 11 3
A srcsetMinWidth() 0 5 1
A getMaxSrcsetWidth() 0 3 1
A getRemoteFileSize() 0 27 4
A getSrcsetWebp() 0 3 1

How to fix   Complexity   

Complex Class

Complex classes like OptimizedImage often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use OptimizedImage, and based on these observations, apply Extract Interface, too.

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 array $options
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 false $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...
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($options = [], $lazyLoad = false)
388
    {
389
        $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...
390
                'class' => '',
391
                'src' => $this->src(),
392
                'srcset' => $this->srcset(),
393
                'sizes' => '100vw',
394
            ],
395
            $options
396
        );
397
        if ($lazyLoad) {
0 ignored issues
show
introduced by
The condition $lazyLoad is always false.
Loading history...
398
            $attrs['class'] += ' lazy';
399
            $attrs['lazyload'] = true;
400
        }
401
        $tag = Html::tag('img', $attrs);
0 ignored issues
show
Bug introduced by
$attrs of type array is incompatible with the type string expected by parameter $content of yii\helpers\BaseHtml::tag(). ( Ignorable by Annotation )

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

401
        $tag = Html::tag('img', /** @scrutinizer ignore-type */ $attrs);
Loading history...
402
403
        return Template::raw($tag);
404
    }
405
406
    /**
407
     * Return a base64-encoded placeholder image
408
     *
409
     * @return \Twig\Markup|null
410
     */
411
    public function placeholderImage()
412
    {
413
        $header = 'data:image/jpeg;base64,';
414
        if (!empty($this->placeholder)) {
415
            $content = $this->placeholder;
416
        } else {
417
            // At least return something
418
            return $this->defaultPlaceholderImage();
419
        }
420
421
        return Template::raw($header.rawurlencode($content));
422
    }
423
424
    /**
425
     * Getter for CraftQL
426
     *
427
     * @return string
428
     */
429
    public function getPlaceholderImage(): string
430
    {
431
        return (string)$this->placeholderImage();
432
    }
433
434
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
435
     * @return string
436
     */
437
    public function placeholderImageSize(): string
438
    {
439
        $placeholder = $this->placeholderImage();
440
        $contentLength = !empty(\strlen($placeholder)) ? \strlen($placeholder) : 0;
441
442
        return ImageOptimize::$plugin->optimize->humanFileSize($contentLength, 1);
443
    }
444
445
    /**
446
     * Return an SVG box as a placeholder image
447
     *
448
     * @param string|null $color
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
449
     *
450
     * @return \Twig\Markup|null
451
     */
452
    public function placeholderBox(string $color = null)
453
    {
454
        $width = $this->placeholderWidth ?? 1;
455
        $height = $this->placeholderHeight ?? 1;
456
        $color = $color ?? $this->colorPalette[0] ?? '#CCC';
457
458
        return Template::raw(ImageOptimize::$plugin->placeholder->generatePlaceholderBox($width, $height, $color));
459
    }
460
461
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
462
     * @param string|null $color
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
463
     *
464
     * @return string
465
     */
466
    public function getPlaceholderBox(string $color = null): string
467
    {
468
        return (string)$this->placeholderBox($color);
469
    }
470
471
    /**
472
     * Getter for CraftQL
473
     *
474
     * @return string
475
     */
476
    public function placeholderBoxSize(): string
477
    {
478
        $placeholder = $this->placeholderBox();
479
        $contentLength = !empty(\strlen($placeholder)) ? \strlen($placeholder) : 0;
480
481
        return ImageOptimize::$plugin->optimize->humanFileSize($contentLength, 1);
482
    }
483
484
    /**
485
     * Return a silhouette of the image as an SVG placeholder
486
     *
487
     * @return \Twig\Markup|null
488
     */
489
    public function placeholderSilhouette()
490
    {
491
        $header = 'data:image/svg+xml,';
492
        if (!empty($this->placeholderSvg)) {
493
            $content = $this->placeholderSvg;
494
        } else {
495
            // At least return something
496
            return $this->defaultPlaceholderImage();
497
        }
498
499
        return Template::raw($header.$content);
500
    }
501
502
    /**
503
     * Getter for CraftQL
504
     *
505
     * @return string
506
     */
507
    public function getPlaceholderSilhouette(): string
508
    {
509
        return (string)$this->placeholderSilhouette();
510
    }
511
512
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
513
     * @return string
514
     */
515
    public function placeholderSilhouetteSize(): string
516
    {
517
        $placeholder = $this->placeholderSilhouette();
518
        $contentLength = !empty(\strlen($placeholder)) ? \strlen($placeholder) : 0;
519
520
        return ImageOptimize::$plugin->optimize->humanFileSize($contentLength, 1);
521
    }
522
523
    /**
524
     *  Get the file size of any remote resource (using curl),
525
     *  either in bytes or - default - as human-readable formatted string.
526
     *
527
     * @author  Stephan Schmitz <[email protected]>
528
     * @license MIT <http://eyecatchup.mit-license.org/>
529
     * @url     <https://gist.github.com/eyecatchup/f26300ffd7e50a92bc4d>
530
     *
531
     * @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...
532
     * @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...
533
     *                              formatted.
534
     * @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...
535
     *                              uses GET.
536
     *
537
     * @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...
538
     *                              or size in bytes (default: formatted).
539
     */
540
    public function getRemoteFileSize($url, $formatSize = true, $useHead = true)
541
    {
542
        // Get an absolute URL with protocol that curl will be happy with
543
        $url = UrlHelper::absoluteUrlWithProtocol($url);
544
        $ch = curl_init($url);
545
        curl_setopt_array($ch, [
0 ignored issues
show
Bug introduced by
It seems like $ch can also be of type false; however, parameter $ch of curl_setopt_array() 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

545
        curl_setopt_array(/** @scrutinizer ignore-type */ $ch, [
Loading history...
Coding Style introduced by
The opening parenthesis of a multi-line function call should be the last content on the line.
Loading history...
546
            CURLOPT_RETURNTRANSFER => 1,
547
            CURLOPT_FOLLOWLOCATION => 1,
548
            CURLOPT_SSL_VERIFYPEER => 0,
549
        ]);
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...
550
        if ($useHead) {
551
            curl_setopt($ch, CURLOPT_NOBODY, 1);
0 ignored issues
show
Bug introduced by
It seems like $ch can also be of type false; however, parameter $ch of curl_setopt() 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

551
            curl_setopt(/** @scrutinizer ignore-type */ $ch, CURLOPT_NOBODY, 1);
Loading history...
552
        }
553
        curl_exec($ch);
0 ignored issues
show
Bug introduced by
It seems like $ch can also be of type false; however, parameter $ch of curl_exec() 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

553
        curl_exec(/** @scrutinizer ignore-type */ $ch);
Loading history...
554
        // content-length of download (in bytes), read from Content-Length: field
555
        $contentLength = curl_getinfo($ch, CURLINFO_CONTENT_LENGTH_DOWNLOAD);
0 ignored issues
show
Bug introduced by
It seems like $ch can also be of type false; however, parameter $ch of curl_getinfo() 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

555
        $contentLength = curl_getinfo(/** @scrutinizer ignore-type */ $ch, CURLINFO_CONTENT_LENGTH_DOWNLOAD);
Loading history...
556
        curl_close($ch);
0 ignored issues
show
Bug introduced by
It seems like $ch can also be of type false; however, parameter $ch of curl_close() 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

556
        curl_close(/** @scrutinizer ignore-type */ $ch);
Loading history...
557
        // cannot retrieve file size, return "-1"
558
        if (!$contentLength) {
559
            return -1;
560
        }
561
        // return size in bytes
562
        if (!$formatSize) {
563
            return $contentLength;
564
        }
565
566
        return ImageOptimize::$plugin->optimize->humanFileSize($contentLength, 1);
567
    }
568
569
    // Protected Methods
570
    // =========================================================================
571
572
    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...
573
    {
574
        $subset = [];
575
        $index = 0;
576
        if (empty($this->variantSourceWidths)) {
577
            return $subset;
578
        }
579
        foreach ($this->variantSourceWidths as $variantSourceWidth) {
580
            $match = false;
581
            switch ($comparison) {
582
                case 'width':
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 12 spaces, found 16
Loading history...
583
                    if ($variantSourceWidth == $width) {
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 16 spaces, found 20
Loading history...
584
                        $match = true;
585
                    }
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 16 spaces, found 20
Loading history...
586
                    break;
587
588
                case 'minwidth':
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 12 spaces, found 16
Loading history...
589
                    if ($variantSourceWidth >= $width) {
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 16 spaces, found 20
Loading history...
590
                        $match = true;
591
                    }
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 16 spaces, found 20
Loading history...
592
                    break;
593
594
                case 'maxwidth':
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 12 spaces, found 16
Loading history...
595
                    if ($variantSourceWidth <= $width) {
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 16 spaces, found 20
Loading history...
596
                        $match = true;
597
                    }
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 16 spaces, found 20
Loading history...
598
                    break;
599
            }
600
            if ($match) {
601
                $subset += array_slice($set, $index, 1, true);
602
            }
603
            $index++;
604
        }
605
606
        return $subset;
607
    }
608
609
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
610
     * @param array $array
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
611
     * @param bool  $dpr
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
612
     *
613
     * @return string
614
     */
615
    protected function getSrcsetFromArray(array $array, bool $dpr = false): string
616
    {
617
        $srcset = '';
618
        foreach ($array as $key => $value) {
619
            if ($dpr) {
620
                $descriptor = '1x';
621
                if (!empty($array[(int)$key / 2])) {
622
                    $descriptor = '2x';
623
                }
624
                if (!empty($array[(int)$key / 3])) {
625
                    $descriptor = '3x';
626
                }
627
            } else {
628
                $descriptor = $key.'w';
629
            }
630
            $srcset .= $value.' '.$descriptor.', ';
631
        }
632
        $srcset = rtrim($srcset, ', ');
633
634
        return $srcset;
635
    }
636
637
    /**
638
     * Return a default placeholder image
639
     *
640
     * @return \Twig\Markup
641
     */
642
    protected function defaultPlaceholderImage(): \Twig\Markup
643
    {
644
        $width = 1;
645
        $height = 1;
646
        $color = '#CCC';
647
648
        return Template::raw(ImageOptimize::$plugin->placeholder->generatePlaceholderBox($width, $height, $color));
649
    }
650
}
651