OptimizedImage   F
last analyzed

Complexity

Total Complexity 61

Size/Duplication

Total Lines 636
Duplicated Lines 0 %

Importance

Changes 15
Bugs 2 Features 0
Metric Value
wmc 61
eloc 154
c 15
b 2
f 0
dl 0
loc 636
rs 3.52

34 Methods

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

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
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;
14
use craft\base\Model;
15
use craft\helpers\Template;
16
use craft\validators\ArrayValidator;
17
use nystudio107\imageoptimize\helpers\Color as ColorHelper;
18
use nystudio107\imageoptimize\helpers\UrlHelper;
19
use nystudio107\imageoptimize\ImageOptimize;
20
use function strlen;
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
Tag value for @author tag indented incorrectly; expected 2 spaces but found 4
Loading history...
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...
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 ?array An array of optimized image variant URLs
34
     */
35
    public ?array $optimizedImageUrls = [];
36
37
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
38
     * @var ?array An array of optimized .webp image variant URLs
39
     */
40
    public ?array $optimizedWebPImageUrls = [];
41
42
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
43
     * @var ?array An array of the widths of the optimized image variants
44
     */
45
    public ?array $variantSourceWidths = [];
46
47
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
48
     * @var ?array An array of the heights of the optimized image variants
49
     */
50
    public ?array $variantHeights = [];
51
52
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
53
     * @var array An array of the x,y image focal point coords, ranging from 0.0 to 1.0
54
     */
55
    public ?array $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 ?int $originalImageWidth = 0;
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 ?int $originalImageHeight = 0;
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 ?string $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 ?string $placeholderSvg = '';
76
77
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
78
     * @var ?array An array the 5 most dominant colors in the image
79
     */
80
    public ?array $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 ?int $lightness = 0;
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 ?int $placeholderWidth = 0;
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 ?int $placeholderHeight = 0;
96
97
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
98
     * @var ?array An array of errors logged when generating the image transforms
99
     */
100
    public ?array $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 string
134
     */
135
    public function src(int $width = 0): string
136
    {
137
        if (empty($width)) {
138
            return Template::raw(reset($this->optimizedImageUrls));
0 ignored issues
show
Bug introduced by
It seems like $this->optimizedImageUrls can also be of type null; however, parameter $array of reset() does only seem to accept array|object, 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

138
            return Template::raw(reset(/** @scrutinizer ignore-type */ $this->optimizedImageUrls));
Loading history...
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 string
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 string
163
     */
164
    public function srcset(bool $dpr = false): string
165
    {
166
        return Template::raw($this->getSrcsetFromArray($this->optimizedImageUrls, $dpr));
0 ignored issues
show
Bug introduced by
It seems like $this->optimizedImageUrls can also be of type null; however, parameter $array of nystudio107\imageoptimiz...e::getSrcsetFromArray() does only seem to accept array, 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

166
        return Template::raw($this->getSrcsetFromArray(/** @scrutinizer ignore-type */ $this->optimizedImageUrls, $dpr));
Loading history...
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
    /**
182
     * Return a string of image URLs and their sizes that match $width
183
     *
184
     * @param int $width
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...
185
     * @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...
186
     *                  srcsets
187
     *
188
     * @return string
189
     */
190
    public function srcsetWidth(int $width, bool $dpr = false): string
191
    {
192
        $subset = $this->getSrcsetSubsetArray($this->optimizedImageUrls, $width, 'width');
0 ignored issues
show
Bug introduced by
It seems like $this->optimizedImageUrls can also be of type null; however, parameter $set of nystudio107\imageoptimiz...:getSrcsetSubsetArray() does only seem to accept array, 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

192
        $subset = $this->getSrcsetSubsetArray(/** @scrutinizer ignore-type */ $this->optimizedImageUrls, $width, 'width');
Loading history...
193
194
        return Template::raw($this->getSrcsetFromArray($subset, $dpr));
195
    }
196
197
    /**
198
     * Return a string of image URLs and their sizes that are at least $width
199
     * or larger
200
     *
201
     * @param int $width
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...
202
     * @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...
203
     *                  srcsets
204
     *
205
     * @return string
206
     */
207
    public function srcsetMinWidth(int $width, bool $dpr = false): string
208
    {
209
        $subset = $this->getSrcsetSubsetArray($this->optimizedImageUrls, $width, 'minwidth');
0 ignored issues
show
Bug introduced by
It seems like $this->optimizedImageUrls can also be of type null; however, parameter $set of nystudio107\imageoptimiz...:getSrcsetSubsetArray() does only seem to accept array, 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

209
        $subset = $this->getSrcsetSubsetArray(/** @scrutinizer ignore-type */ $this->optimizedImageUrls, $width, 'minwidth');
Loading history...
210
211
        return Template::raw($this->getSrcsetFromArray($subset, $dpr));
212
    }
213
214
    /**
215
     * Return a string of image URLs and their sizes that are $width or smaller
216
     *
217
     * @param int $width
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...
218
     * @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...
219
     *                  srcsets
220
     *
221
     * @return string
222
     */
223
    public function srcsetMaxWidth(int $width, bool $dpr = false): string
224
    {
225
        $subset = $this->getSrcsetSubsetArray($this->optimizedImageUrls, $width, 'maxwidth');
0 ignored issues
show
Bug introduced by
It seems like $this->optimizedImageUrls can also be of type null; however, parameter $set of nystudio107\imageoptimiz...:getSrcsetSubsetArray() does only seem to accept array, 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

225
        $subset = $this->getSrcsetSubsetArray(/** @scrutinizer ignore-type */ $this->optimizedImageUrls, $width, 'maxwidth');
Loading history...
226
227
        return Template::raw($this->getSrcsetFromArray($subset, $dpr));
228
    }
229
230
    /**
231
     * Return the first webp image variant URL or the specific one passed in
232
     * via $width
233
     *
234
     * @param int $width
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
235
     *
236
     * @return string
237
     */
238
    public function srcWebp(int $width = 0): string
239
    {
240
        if (empty($width)) {
241
            return Template::raw(reset($this->optimizedWebPImageUrls));
0 ignored issues
show
Bug introduced by
It seems like $this->optimizedWebPImageUrls can also be of type null; however, parameter $array of reset() does only seem to accept array|object, 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

241
            return Template::raw(reset(/** @scrutinizer ignore-type */ $this->optimizedWebPImageUrls));
Loading history...
242
        }
243
244
        return Template::raw($this->optimizedWebPImageUrls[$width] ?? '');
245
    }
246
247
    /**
248
     * Getter for CraftQL
249
     *
250
     * @param int $width
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
251
     *
252
     * @return string
253
     */
254
    public function getSrcWebp(int $width = 0): string
255
    {
256
        return $this->srcWebp($width);
257
    }
258
259
    /**
260
     * Return a string of webp image URLs and their sizes
261
     *
262
     * @param bool $dpr Whether to generate 1x, 2x srcsets vs the normal XXXw
263
     *                  srcsets
264
     *
265
     * @return string
266
     */
267
    public function srcsetWebp(bool $dpr = false): string
268
    {
269
        return Template::raw($this->getSrcsetFromArray($this->optimizedWebPImageUrls, $dpr));
0 ignored issues
show
Bug introduced by
It seems like $this->optimizedWebPImageUrls can also be of type null; however, parameter $array of nystudio107\imageoptimiz...e::getSrcsetFromArray() does only seem to accept array, 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

269
        return Template::raw($this->getSrcsetFromArray(/** @scrutinizer ignore-type */ $this->optimizedWebPImageUrls, $dpr));
Loading history...
270
    }
271
272
    /**
273
     * Getter for CraftQL
274
     *
275
     * @param bool $dpr
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
276
     *
277
     * @return string
278
     */
279
    public function getSrcsetWebp(bool $dpr = false): string
280
    {
281
        return $this->srcsetWebp($dpr);
282
    }
283
284
    /**
285
     * Return a string of webp image URLs and their sizes that match $width
286
     *
287
     * @param int $width
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...
288
     * @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...
289
     *                  srcsets
290
     *
291
     * @return string
292
     */
293
    public function srcsetWidthWebp(int $width, bool $dpr = false): string
294
    {
295
        $subset = $this->getSrcsetSubsetArray($this->optimizedWebPImageUrls, $width, 'width');
0 ignored issues
show
Bug introduced by
It seems like $this->optimizedWebPImageUrls can also be of type null; however, parameter $set of nystudio107\imageoptimiz...:getSrcsetSubsetArray() does only seem to accept array, 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

295
        $subset = $this->getSrcsetSubsetArray(/** @scrutinizer ignore-type */ $this->optimizedWebPImageUrls, $width, 'width');
Loading history...
296
297
        return Template::raw($this->getSrcsetFromArray($subset, $dpr));
298
    }
299
300
    /**
301
     * Return a string of webp image URLs and their sizes that are at least
302
     * $width or larger
303
     *
304
     * @param int $width
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...
305
     * @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...
306
     *                  srcsets
307
     *
308
     * @return string
309
     */
310
    public function srcsetMinWidthWebp(int $width, bool $dpr = false): string
311
    {
312
        $subset = $this->getSrcsetSubsetArray($this->optimizedWebPImageUrls, $width, 'minwidth');
0 ignored issues
show
Bug introduced by
It seems like $this->optimizedWebPImageUrls can also be of type null; however, parameter $set of nystudio107\imageoptimiz...:getSrcsetSubsetArray() does only seem to accept array, 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

312
        $subset = $this->getSrcsetSubsetArray(/** @scrutinizer ignore-type */ $this->optimizedWebPImageUrls, $width, 'minwidth');
Loading history...
313
314
        return Template::raw($this->getSrcsetFromArray($subset, $dpr));
315
    }
316
317
    /**
318
     * Return a string of webp image URLs and their sizes that are $width or
319
     * smaller
320
     *
321
     * @param int $width
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...
322
     * @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...
323
     *                  srcsets
324
     *
325
     * @return string
326
     */
327
    public function srcsetMaxWidthWebp(int $width, bool $dpr = false): string
328
    {
329
        $subset = $this->getSrcsetSubsetArray($this->optimizedWebPImageUrls, $width, 'maxwidth');
0 ignored issues
show
Bug introduced by
It seems like $this->optimizedWebPImageUrls can also be of type null; however, parameter $set of nystudio107\imageoptimiz...:getSrcsetSubsetArray() does only seem to accept array, 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

329
        $subset = $this->getSrcsetSubsetArray(/** @scrutinizer ignore-type */ $this->optimizedWebPImageUrls, $width, 'maxwidth');
Loading history...
330
331
        return Template::raw($this->getSrcsetFromArray($subset, $dpr));
332
    }
333
334
    /**
335
     * Work around issues with `<img srcset>` returning sizes larger than are
336
     * available as per:
337
     * https://medium.com/@MRWwebDesign/responsive-images-the-sizes-attribute-and-unexpected-image-sizes-882a2eadb6db
338
     *
339
     * @return int
340
     */
341
    public function maxSrcsetWidth(): int
342
    {
343
        $result = 0;
344
        if (!empty($this->optimizedImageUrls)) {
345
            $tempArray = $this->optimizedImageUrls;
346
            ksort($tempArray, SORT_NUMERIC);
347
348
            $keys = array_keys($tempArray);
349
            $result = end($keys);
350
        }
351
352
        return $result;
353
    }
354
355
    /**
356
     * Getter for CraftQL
357
     *
358
     * @return int
359
     */
360
    public function getMaxSrcsetWidth(): int
361
    {
362
        return $this->maxSrcsetWidth();
363
    }
364
365
    /**
366
     * Return the colors as an array of RGB colors
367
     */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
368
    public function colorPaletteRgb(): array
369
    {
370
        $colors = [];
371
372
        foreach ($this->colorPalette as $color) {
373
            if (!empty($color)) {
374
                $colors[] = ColorHelper::HTMLToRGB($color);
375
            }
376
        }
377
378
        return $colors;
379
    }
380
381
    /**
382
     * Generate a complete <link rel="preload"> tag for this OptimizedImages model
383
     * ref: https://web.dev/preload-responsive-images/#imagesrcset-and-imagesizes
384
     *
385
     * @param array $config
0 ignored issues
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
Coding Style introduced by
Missing parameter comment
Loading history...
386
     * @return LinkPreloadTag
0 ignored issues
show
Coding Style introduced by
Tag @return cannot be grouped with parameter tags in a doc comment
Loading history...
387
     */
388
    public function linkPreloadTag(array $config = []): LinkPreloadTag
389
    {
390
        return new LinkPreloadTag(array_merge($config, ['optimizedImage' => $this]));
391
    }
392
393
    /**
394
     * Generate a complete <img> tag for this OptimizedImage model
395
     *
396
     * @param array $config
0 ignored issues
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
Coding Style introduced by
Missing parameter comment
Loading history...
397
     * @return ImgTag
0 ignored issues
show
Coding Style introduced by
Tag @return cannot be grouped with parameter tags in a doc comment
Loading history...
398
     */
399
    public function imgTag(array $config = []): ImgTag
400
    {
401
        return new ImgTag(array_merge($config, ['optimizedImage' => $this]));
402
    }
403
404
    /**
405
     * Generate a complete <picture> tag for this OptimizedImage model
406
     *
407
     * @param array $config
0 ignored issues
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
Coding Style introduced by
Missing parameter comment
Loading history...
408
     * @return PictureTag
0 ignored issues
show
Coding Style introduced by
Tag @return cannot be grouped with parameter tags in a doc comment
Loading history...
409
     */
410
    public function pictureTag(array $config = []): PictureTag
411
    {
412
        return new PictureTag(array_merge($config, ['optimizedImage' => $this]));
413
    }
414
415
    /**
416
     * Return a base64-encoded placeholder image
417
     *
418
     * @return string
419
     */
420
    public function placeholderImage(): string
421
    {
422
        $header = 'data:image/jpeg;base64,';
423
        if (!empty($this->placeholder)) {
424
            $content = $this->placeholder;
425
        } else {
426
            // At least return something
427
            return $this->defaultPlaceholderImage();
428
        }
429
430
        return Template::raw($header . rawurlencode($content));
431
    }
432
433
    /**
434
     * Getter for CraftQL
435
     *
436
     * @return string
437
     */
438
    public function getPlaceholderImage(): string
439
    {
440
        return $this->placeholderImage();
441
    }
442
443
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
444
     * @return string
445
     */
446
    public function placeholderImageSize(): string
447
    {
448
        $placeholder = $this->placeholderImage();
449
        $contentLength = !empty(strlen($placeholder)) ? strlen($placeholder) : 0;
450
451
        return ImageOptimize::$plugin->optimize->humanFileSize($contentLength, 1);
452
    }
453
454
    /**
455
     * Return an SVG box as a placeholder image
456
     *
457
     * @param string|null $color
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
458
     *
459
     * @return string
460
     */
461
    public function placeholderBox(?string $color = null): string
462
    {
463
        $width = $this->placeholderWidth ?? 1;
464
        $height = $this->placeholderHeight ?? 1;
465
        $color = $color ?? $this->colorPalette[0] ?? '#CCC';
466
467
        return Template::raw(ImageOptimize::$plugin->placeholder->generatePlaceholderBox($width, $height, $color));
468
    }
469
470
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
471
     * @param string|null $color
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
472
     *
473
     * @return string
474
     */
475
    public function getPlaceholderBox(string $color = null): string
476
    {
477
        return $this->placeholderBox($color);
478
    }
479
480
    /**
481
     * Getter for CraftQL
482
     *
483
     * @return string
484
     */
485
    public function placeholderBoxSize(): string
486
    {
487
        $placeholder = $this->placeholderBox();
488
        $contentLength = !empty(strlen($placeholder)) ? strlen($placeholder) : 0;
489
490
        return ImageOptimize::$plugin->optimize->humanFileSize($contentLength, 1);
491
    }
492
493
    /**
494
     * Return a silhouette of the image as an SVG placeholder
495
     *
496
     * @return string
497
     */
498
    public function placeholderSilhouette(): string
499
    {
500
        $header = 'data:image/svg+xml,';
501
        if (!empty($this->placeholderSvg)) {
502
            $content = $this->placeholderSvg;
503
        } else {
504
            // At least return something
505
            return $this->defaultPlaceholderImage();
506
        }
507
508
        return Template::raw($header . $content);
509
    }
510
511
    /**
512
     * Getter for CraftQL
513
     *
514
     * @return string
515
     */
516
    public function getPlaceholderSilhouette(): string
517
    {
518
        return $this->placeholderSilhouette();
519
    }
520
521
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
522
     * @return string
523
     */
524
    public function placeholderSilhouetteSize(): string
525
    {
526
        $placeholder = $this->placeholderSilhouette();
527
        $contentLength = !empty(strlen($placeholder)) ? strlen($placeholder) : 0;
528
529
        return ImageOptimize::$plugin->optimize->humanFileSize($contentLength, 1);
530
    }
531
532
    /**
533
     *  Get the file size of any remote resource (using curl),
534
     *  either in bytes or - default - as human-readable formatted string.
535
     *
536
     * @param string $url Takes the remote object's URL.
0 ignored issues
show
Coding Style introduced by
Expected 8 spaces after parameter name; 1 found
Loading history...
537
     * @param bool $formatSize Whether to return size in bytes or
0 ignored issues
show
Coding Style introduced by
Expected 3 spaces after parameter type; 1 found
Loading history...
538
     *                              formatted.
0 ignored issues
show
Coding Style introduced by
Parameter comment not aligned correctly; expected 25 spaces but found 30
Loading history...
539
     * @param bool $useHead Whether to use HEAD requests. If false,
0 ignored issues
show
Coding Style introduced by
Expected 3 spaces after parameter type; 1 found
Loading history...
Coding Style introduced by
Expected 4 spaces after parameter name; 1 found
Loading history...
540
     *                              uses GET.
0 ignored issues
show
Coding Style introduced by
Parameter comment not aligned correctly; expected 22 spaces but found 30
Loading history...
541
     *
542
     * @return  mixed    Returns human-readable formatted size
0 ignored issues
show
Coding Style introduced by
Tag value for @return tag indented incorrectly; expected 7 spaces but found 2
Loading history...
543
     *                              or size in bytes (default: formatted).
544
     * @noinspection PhpComposerExtensionStubsInspection*@author  Stephan Schmitz <[email protected]>
545
     * @license MIT <http://eyecatchup.mit-license.org/>
0 ignored issues
show
Coding Style introduced by
Tag value for @license tag indented incorrectly; expected 6 spaces but found 1
Loading history...
546
     * @url     <https://gist.github.com/eyecatchup/f26300ffd7e50a92bc4d>
0 ignored issues
show
Coding Style introduced by
Tag value for @url tag indented incorrectly; expected 10 spaces but found 5
Loading history...
547
     *
548
     * @noinspection PhpComposerExtensionStubsInspection
0 ignored issues
show
Coding Style introduced by
Tags must be grouped together in a doc comment
Loading history...
549
     */
550
    public function getRemoteFileSize(string $url, bool $formatSize = true, bool $useHead = true): mixed
551
    {
552
        // Get an absolute URL with protocol that curl will be happy with
553
        $url = UrlHelper::absoluteUrlWithProtocol($url);
554
        $ch = curl_init($url);
555
        /** @noinspection CurlSslServerSpoofingInspection */
0 ignored issues
show
Coding Style introduced by
The open comment tag must be the only content on the line
Loading history...
Coding Style introduced by
Missing short description in doc comment
Loading history...
Coding Style introduced by
The close comment tag must be the only content on the line
Loading history...
556
        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...
557
            CURLOPT_RETURNTRANSFER => 1,
558
            CURLOPT_FOLLOWLOCATION => 1,
559
            CURLOPT_SSL_VERIFYPEER => 0,
560
        ]);
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...
561
        if ($useHead) {
562
            curl_setopt($ch, CURLOPT_NOBODY, 1);
563
        }
564
        curl_exec($ch);
565
        // content-length of download (in bytes), read from Content-Length: field
566
        $contentLength = curl_getinfo($ch, CURLINFO_CONTENT_LENGTH_DOWNLOAD);
567
        $error = curl_error($ch);
568
        if (!empty($error)) {
569
            Craft::error($error, __METHOD__);
570
        }
571
        curl_close($ch);
572
        // cannot retrieve file size, return "-1"
573
        if (!$contentLength) {
574
            return -1;
575
        }
576
        // return size in bytes
577
        if (!$formatSize) {
578
            return $contentLength;
579
        }
580
581
        return ImageOptimize::$plugin->optimize->humanFileSize($contentLength, 1);
582
    }
583
584
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
585
     * @param array $array
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
586
     * @param bool $dpr
0 ignored issues
show
Coding Style introduced by
Expected 2 spaces after parameter type; 1 found
Loading history...
Coding Style introduced by
Missing parameter comment
Loading history...
587
     *
588
     * @return string
589
     */
590
    public function getSrcsetFromArray(array $array, bool $dpr = false): string
591
    {
592
        $srcset = '';
593
        foreach ($array as $key => $value) {
594
            if ($dpr) {
595
                $descriptor = '1x';
596
                if (!empty($array[(int)$key / 2])) {
597
                    $descriptor = '2x';
598
                }
599
                if (!empty($array[(int)$key / 3])) {
600
                    $descriptor = '3x';
601
                }
602
            } else {
603
                $descriptor = $key . 'w';
604
            }
605
            $srcset .= $value . ' ' . $descriptor . ', ';
606
        }
607
608
        return rtrim($srcset, ', ');
609
    }
610
611
    // Protected Methods
612
    // =========================================================================
613
614
    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...
615
    {
616
        $subset = [];
617
        $index = 0;
618
        if (empty($this->variantSourceWidths)) {
619
            return $subset;
620
        }
621
        foreach ($this->variantSourceWidths as $variantSourceWidth) {
622
            $match = false;
623
            switch ($comparison) {
624
                case 'width':
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 12 spaces, found 16
Loading history...
625
                    if ($variantSourceWidth == $width) {
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 16 spaces, found 20
Loading history...
626
                        $match = true;
627
                    }
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 16 spaces, found 20
Loading history...
628
                    break;
629
630
                case 'minwidth':
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 12 spaces, found 16
Loading history...
631
                    if ($variantSourceWidth >= $width) {
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 16 spaces, found 20
Loading history...
632
                        $match = true;
633
                    }
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 16 spaces, found 20
Loading history...
634
                    break;
635
636
                case 'maxwidth':
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 12 spaces, found 16
Loading history...
637
                    if ($variantSourceWidth <= $width) {
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 16 spaces, found 20
Loading history...
638
                        $match = true;
639
                    }
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 16 spaces, found 20
Loading history...
640
                    break;
641
            }
642
            if ($match) {
643
                $subset += array_slice($set, $index, 1, true);
644
            }
645
            $index++;
646
        }
647
648
        return $subset;
649
    }
650
651
    /**
652
     * Return a default placeholder image
653
     *
654
     * @return string
655
     */
656
    protected function defaultPlaceholderImage(): string
657
    {
658
        $width = 1;
659
        $height = 1;
660
        $color = '#CCC';
661
662
        return Template::raw(ImageOptimize::$plugin->placeholder->generatePlaceholderBox($width, $height, $color));
663
    }
664
}
665