Passed
Push — develop ( a3b096...881135 )
by Andrew
03:46
created

ImgixImageTransform::getTransformUrl()   F

Complexity

Conditions 24
Paths 2019

Size

Total Lines 102
Code Lines 63

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 63
dl 0
loc 102
rs 0
c 0
b 0
f 0
cc 24
nc 2019
nop 3

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
/**
3
 * ImageOptimize 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\imagetransforms;
12
13
use nystudio107\imageoptimize\ImageOptimize;
14
15
use craft\elements\Asset;
16
use craft\helpers\ArrayHelper;
17
use craft\helpers\Assets as AssetsHelper;
18
use craft\helpers\UrlHelper;
19
use craft\models\AssetTransform;
20
21
use Imgix\UrlBuilder;
22
use Psr\Http\Message\ResponseInterface;
23
24
use Craft;
25
26
/**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
27
 * @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 indented incorrectly; expected 2 spaces but found 4
Loading history...
28
 * @package   ImageOptimize
0 ignored issues
show
Coding Style introduced by
Tag value indented incorrectly; expected 1 spaces but found 3
Loading history...
29
 * @since     1.0.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 indented incorrectly; expected 3 spaces but found 5
Loading history...
30
 */
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...
31
class ImgixImageTransform extends ImageTransform
32
{
33
    // Constants
34
    // =========================================================================
35
36
    const TRANSFORM_ATTRIBUTES_MAP = [
37
        'width'   => 'w',
38
        'height'  => 'h',
39
        'quality' => 'q',
40
        'format'  => 'fm',
41
    ];
42
43
    const IMGIX_PURGE_ENDPOINT = 'https://api.imgix.com/v2/image/purger';
44
45
    // Static Methods
46
    // =========================================================================
47
48
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
49
     * @inheritdoc
50
     */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
51
    public static function displayName(): string
52
    {
53
        return Craft::t('image-optimize', 'Imgix');
54
    }
55
56
    // Public Methods
57
    // =========================================================================
58
59
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
60
     * @param Asset               $asset
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
61
     * @param AssetTransform|null $transform
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
62
     * @param array               $params
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
63
     *
64
     * @return string|null
65
     * @throws \yii\base\Exception
66
     * @throws \yii\base\InvalidConfigException
67
     */
68
    public function getTransformUrl(Asset $asset, $transform, array $params = [])
69
    {
70
        $url = null;
71
        $settings = ImageOptimize::$plugin->getSettings();
72
73
        $domain = $params['domain'] ?? 'demos.imgix.net';
74
        $builder = new UrlBuilder($domain);
75
        if ($asset && $builder) {
0 ignored issues
show
introduced by
$builder is of type Imgix\UrlBuilder, thus it always evaluated to true.
Loading history...
76
            $builder->setUseHttps(true);
77
            if ($transform) {
78
                // Map the transform properties
79
                foreach (self::TRANSFORM_ATTRIBUTES_MAP as $key => $value) {
80
                    if (!empty($transform[$key])) {
81
                        $params[$value] = $transform[$key];
82
                    }
83
                }
84
                // Remove any 'AUTO' settings
85
                ArrayHelper::removeValue($params, 'AUTO');
86
                // Handle the Imgix auto setting for compression/format
87
                $autoParams = [];
88
                if (empty($params['q'])) {
89
                    $autoParams[] = 'compress';
90
                }
91
                if (empty($params['fm'])) {
92
                    $autoParams[] = 'format';
93
                }
94
                if (!empty($autoParams)) {
95
                    $params['auto'] = implode(',', $autoParams);
96
                }
97
                // Handle interlaced images
98
                if (property_exists($transform, 'interlace')) {
99
                    if (($transform->interlace != 'none')
100
                        && (!empty($params['fm']))
101
                        && ($params['fm'] == 'jpg')
102
                    ) {
103
                        $params['fm'] = 'pjpg';
104
                    }
105
                }
106
                if ($settings->autoSharpenScaledImages) {
107
                    // See if the image has been scaled >= 50%
108
                    $widthScale = $asset->getWidth() / ($transform->width ?? $asset->getWidth());
109
                    $heightScale = $asset->getHeight() / ($transform->height ?? $asset->getHeight());
110
                    if (($widthScale >= 2.0) || ($heightScale >= 2.0)) {
111
                        $params['usm'] = 50.0;
112
                    }
113
                }
114
                // Handle the mode
115
                switch ($transform->mode) {
116
                    case 'fit':
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 16 spaces, found 20
Loading history...
117
                        $params['fit'] = 'clamp';
118
                        break;
119
120
                    case 'stretch':
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 16 spaces, found 20
Loading history...
121
                        $params['fit'] = 'scale';
122
                        break;
123
124
                    default:
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 16 spaces, found 20
Loading history...
125
                        // Set a sane default
126
                        if (empty($transform->position)) {
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 20 spaces, found 24
Loading history...
127
                            $transform->position = 'center-center';
128
                        }
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 20 spaces, found 24
Loading history...
129
                        // Fit mode
130
                        $params['fit'] = 'crop';
131
                        $cropParams = [];
132
                        // Handle the focal point
133
                        $focalPoint = $asset->getFocalPoint();
134
                        if (!empty($focalPoint)) {
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 20 spaces, found 24
Loading history...
135
                            $params['fp-x'] = $focalPoint['x'];
136
                            $params['fp-y'] = $focalPoint['y'];
137
                            $cropParams[] = 'focalpoint';
138
                        } elseif (preg_match('/(top|center|bottom)-(left|center|right)/', $transform->position)) {
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 20 spaces, found 24
Loading history...
139
                            // Imgix defaults to 'center' if no param is present
140
                            $filteredCropParams = explode('-', $transform->position);
141
                            $filteredCropParams = array_diff($filteredCropParams, ['center']);
142
                            $cropParams[] = $filteredCropParams;
143
                        }
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 20 spaces, found 24
Loading history...
144
                        // Imgix
145
                        if (!empty($cropParams) && $transform->position !== 'center-center') {
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 20 spaces, found 24
Loading history...
146
                            $params['crop'] = implode(',', $cropParams);
147
                        }
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 20 spaces, found 24
Loading history...
148
                        break;
149
                }
150
            } else {
151
                // No transform was passed in; so just auto all the things
152
                $params['auto'] = 'format,compress';
153
            }
154
            // Remove the api-key param
155
            unset($params['api-key']);
156
            // Apply the Security Token, if set
157
            if (!empty($settings->imgixSecurityToken)) {
0 ignored issues
show
Bug Best Practice introduced by
The property imgixSecurityToken does not exist on nystudio107\imageoptimize\models\Settings. Since you implemented __get, consider adding a @property annotation.
Loading history...
158
                $builder->setSignKey($settings->imgixSecurityToken);
159
            }
160
            // Finally, create the Imgix URL for this transformed image
161
            $assetUri = $this->getAssetUri($asset);
162
            $url = $builder->createURL($assetUri, $params);
163
            Craft::debug(
164
                'Imgix transform created for: '.$assetUri.' - Params: '.print_r($params, true).' - URL: '.$url,
165
                __METHOD__
166
            );
167
        }
168
169
        return $url;
170
    }
171
172
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
173
     * @param string              $url
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
174
     * @param Asset               $asset
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
175
     * @param AssetTransform|null $transform
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
176
     * @param array               $params
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
177
     *
178
     * @return string
179
     */
180
    public function getWebPUrl(string $url, Asset $asset, $transform, array $params = []): string
181
    {
182
        $url = preg_replace('/fm=[^&]*/', 'fm=webp', $url);
183
184
        return $url;
185
    }
186
187
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
188
     * @param Asset $asset
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
189
     * @param array $params
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
190
     *
191
     * @return null|string
192
     * @throws \yii\base\InvalidConfigException
193
     */
194
    public function getPurgeUrl(Asset $asset, array $params = [])
195
    {
196
        $url = null;
197
198
        $domain = isset($params['domain'])
199
            ? $params['domain']
200
            : 'demos.imgix.net';
201
        $builder = new UrlBuilder($domain);
202
        if ($asset && $builder) {
0 ignored issues
show
introduced by
$builder is of type Imgix\UrlBuilder, thus it always evaluated to true.
Loading history...
203
            $builder->setUseHttps(true);
204
            // Create the Imgix URL for purging this image
205
            $assetUri = $this->getAssetUri($asset);
206
            $url = $builder->createURL($assetUri, $params);
207
            // Strip the query string so we just pass in the raw URL
208
            $url = UrlHelper::stripQueryString($url);
209
        }
210
211
        return $url;
212
    }
213
214
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
215
     * @param string $url
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
216
     * @param array  $params
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
217
     *
218
     * @return bool
219
     */
220
    public function purgeUrl(string $url, array $params = []): bool
221
    {
222
        $result = false;
223
        $apiKey = isset($params['api-key'])
224
            ? $params['api-key']
225
            : '';
226
        // create new guzzle client
227
        $guzzleClient = Craft::createGuzzleClient(['timeout' => 120, 'connect_timeout' => 120]);
228
        // Submit the sitemap index to each search engine
229
        try {
230
            /** @var ResponseInterface $response */
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...
231
            $response = $guzzleClient->post(self::IMGIX_PURGE_ENDPOINT, [
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...
232
                'auth'        => [
233
                    $apiKey,
234
                    '',
235
                ],
236
                'form_params' => [
237
                    'url' => $url,
238
                ],
239
            ]);
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...
240
            // See if it succeeded
241
            if (($response->getStatusCode() >= 200)
242
                && ($response->getStatusCode() < 400)
243
            ) {
244
                $result = true;
245
            }
246
            Craft::info(
247
                'URL purged: '.$url.' - Response code: '.$response->getStatusCode(),
248
                __METHOD__
249
            );
250
        } catch (\Exception $e) {
251
            Craft::error(
252
                'Error purging URL: '.$url.' - '.$e->getMessage(),
253
                __METHOD__
254
            );
255
        }
256
257
        return $result;
258
    }
259
260
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
261
     * @return array
262
     */
263
    public function getTransformParams(): array
264
    {
265
        $settings = ImageOptimize::$plugin->getSettings();
266
        $params = [
267
            'domain'  => $settings->imgixDomain,
0 ignored issues
show
Bug Best Practice introduced by
The property imgixDomain does not exist on nystudio107\imageoptimize\models\Settings. Since you implemented __get, consider adding a @property annotation.
Loading history...
268
            'api-key' => $settings->imgixApiKey,
0 ignored issues
show
Bug Best Practice introduced by
The property imgixApiKey does not exist on nystudio107\imageoptimize\models\Settings. Since you implemented __get, consider adding a @property annotation.
Loading history...
269
        ];
270
271
        return $params;
272
    }
273
274
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
275
     * @param Asset $asset
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
276
     *
277
     * @return mixed
278
     * @throws \yii\base\InvalidConfigException
279
     */
280
    public function getAssetUri(Asset $asset)
281
    {
282
        $volume = $asset->getVolume();
283
284
        // If this is a local volume, it implies your are using a "Web Folder"
285
        // source in Imgix. We can then also infer that:
286
        // - This volume has URLs
287
        // - The "Base URL" in Imgix is set to your domain root, per the ImageOptimize docs.
288
        //
289
        // Therefore, we need to parse the path from the full URL, so that it
290
        // includes the path of the volume.
291
        if ($volume instanceof \craft\volumes\Local) {
292
            $assetUrl = AssetsHelper::generateUrl($volume, $asset);
293
            $assetUri = parse_url($assetUrl, PHP_URL_PATH);
294
295
            return $assetUri;
296
        }
297
298
        return parent::getAssetUri($asset);
299
    }
300
}
301