Passed
Push — develop ( c31290...9027f1 )
by Andrew
03:59
created

ImgixImageTransform::getAssetUri()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 7
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 4
dl 0
loc 7
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 1
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
     * @param Asset               $asset
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
50
     * @param AssetTransform|null $transform
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
51
     * @param array               $params
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
52
     *
53
     * @return string|null
54
     * @throws \yii\base\Exception
55
     * @throws \yii\base\InvalidConfigException
56
     */
57
    public static function getTransformUrl(Asset $asset, $transform, array $params = [])
58
    {
59
        $url = null;
60
        $settings = ImageOptimize::$plugin->getSettings();
61
62
        $domain = isset($params['domain'])
63
            ? $params['domain']
64
            : 'demos.imgix.net';
65
        $builder = new UrlBuilder($domain);
66
        if ($asset && $builder) {
0 ignored issues
show
introduced by
$builder is of type Imgix\UrlBuilder, thus it always evaluated to true.
Loading history...
67
            $builder->setUseHttps(true);
68
            if ($transform) {
69
                // Map the transform properties
70
                foreach (self::TRANSFORM_ATTRIBUTES_MAP as $key => $value) {
71
                    if (!empty($transform[$key])) {
72
                        $params[$value] = $transform[$key];
73
                    }
74
                }
75
                // Remove any 'AUTO' settings
76
                ArrayHelper::removeValue($params, 'AUTO');
77
                // Handle the Imgix auto setting for compression/format
78
                $autoParams = [];
79
                if (empty($params['q'])) {
80
                    $autoParams[] = 'compress';
81
                }
82
                if (empty($params['fm'])) {
83
                    $autoParams[] = 'format';
84
                }
85
                if (!empty($autoParams)) {
86
                    $params['auto'] = implode(',', $autoParams);
87
                }
88
                // Handle interlaced images
89
                if (property_exists($transform, 'interlace')) {
90
                    if (($transform->interlace != 'none')
91
                        && (!empty($params['fm']))
92
                        && ($params['fm'] == 'jpg')
93
                    ) {
94
                        $params['fm'] = 'pjpg';
95
                    }
96
                }
97
                if ($settings->autoSharpenScaledImages) {
98
                    // See if the image has been scaled >= 50%
99
                    $widthScale = $asset->getWidth() / ($transform->width ?? $asset->getWidth());
100
                    $heightScale = $asset->getHeight() / ($transform->height ?? $asset->getHeight());
101
                    if (($widthScale >= 2.0) || ($heightScale >= 2.0)) {
102
                        $params['usm'] = 50.0;
103
                    }
104
                }
105
                // Handle the mode
106
                switch ($transform->mode) {
107
                    case 'fit':
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 16 spaces, found 20
Loading history...
108
                        $params['fit'] = 'clamp';
109
                        break;
110
111
                    case 'stretch':
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 16 spaces, found 20
Loading history...
112
                        $params['fit'] = 'scale';
113
                        break;
114
115
                    default:
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 16 spaces, found 20
Loading history...
116
                        // Fit mode
117
                        $params['fit'] = 'crop';
118
                        $cropParams = [];
119
                        // Handle the focal point
120
                        $focalPoint = $asset->getFocalPoint();
121
                        if (!empty($focalPoint)) {
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 20 spaces, found 24
Loading history...
122
                            $params['fp-x'] = $focalPoint['x'];
123
                            $params['fp-y'] = $focalPoint['y'];
124
                            $cropParams[] = 'focalpoint';
125
                        } 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...
126
                            // Imgix defaults to 'center' if no param is present
127
                            $filteredCropParams = explode('-', $transform->position);
128
                            $filteredCropParams = array_diff($filteredCropParams, ['center']);
129
                            $cropParams[] = $filteredCropParams;
130
                        }
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 20 spaces, found 24
Loading history...
131
                        if (!empty($cropParams)) {
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 20 spaces, found 24
Loading history...
132
                            $params['crop'] = implode(',', $cropParams);
133
                        }
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 20 spaces, found 24
Loading history...
134
                        break;
135
                }
136
            } else {
137
                // No transform was passed in; so just auto all the things
138
                $params['auto'] = 'format,compress';
139
            }
140
            // Remove the api-key param
141
            unset($params['api-key']);
142
            // Apply the Security Token, if set
143
            if (!empty($settings->imgixSecurityToken)) {
144
                $builder->setSignKey($settings->imgixSecurityToken);
145
            }
146
            // Finally, create the Imgix URL for this transformed image
147
            $assetUri = self::getAssetUri($asset);
148
            $url = $builder->createURL($assetUri, $params);
149
            Craft::debug(
150
                'Imgix transform created for: '.$assetUri.' - Params: '.print_r($params, true).' - URL: '.$url,
151
                __METHOD__
152
            );
153
        }
154
155
        return $url;
156
    }
157
158
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
159
     * @param string              $url
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
160
     * @param Asset               $asset
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
161
     * @param AssetTransform|null $transform
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
162
     * @param array               $params
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
163
     *
164
     * @return string
165
     */
166
    public static function getWebPUrl(string $url, Asset $asset, $transform, array $params = []): string
167
    {
168
        $url = preg_replace('/fm=[^&]*/', 'fm=webp', $url);
169
170
        return $url;
171
    }
172
173
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
174
     * @param Asset $asset
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
175
     * @param array $params
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
176
     *
177
     * @return null|string
178
     * @throws \yii\base\InvalidConfigException
179
     */
180
    public static function getPurgeUrl(Asset $asset, array $params = [])
181
    {
182
        $url = null;
183
184
        $domain = isset($params['domain'])
185
            ? $params['domain']
186
            : 'demos.imgix.net';
187
        $builder = new UrlBuilder($domain);
188
        if ($asset && $builder) {
0 ignored issues
show
introduced by
$builder is of type Imgix\UrlBuilder, thus it always evaluated to true.
Loading history...
189
            $builder->setUseHttps(true);
190
            // Create the Imgix URL for purging this image
191
            $assetUri = self::getAssetUri($asset);
192
            $url = $builder->createURL($assetUri, $params);
193
            // Strip the query string so we just pass in the raw URL
194
            $url = UrlHelper::stripQueryString($url);
195
        }
196
197
        return $url;
198
    }
199
200
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
201
     * @param string $url
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
202
     * @param array  $params
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
203
     *
204
     * @return bool
205
     */
206
    public static function purgeUrl(string $url, array $params = []): bool
207
    {
208
        $result = false;
209
        $apiKey = isset($params['api-key'])
210
            ? $params['api-key']
211
            : '';
212
        // create new guzzle client
213
        $guzzleClient = Craft::createGuzzleClient(['timeout' => 120, 'connect_timeout' => 120]);
214
        // Submit the sitemap index to each search engine
215
        try {
216
            /** @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...
217
            $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...
218
                'auth'        => [
219
                    $apiKey,
220
                    '',
221
                ],
222
                'form_params' => [
223
                    'url' => $url,
224
                ],
225
            ]);
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...
226
            // See if it succeeded
227
            if (($response->getStatusCode() >= 200)
228
                && ($response->getStatusCode() < 400)
229
            ) {
230
                $result = true;
231
            }
232
            Craft::info(
233
                'URL purged: '.$url.' - Response code: '.$response->getStatusCode(),
234
                __METHOD__
235
            );
236
        } catch (\Exception $e) {
237
            Craft::error(
238
                'Error purging URL: '.$url.' - '.$e->getMessage(),
239
                __METHOD__
240
            );
241
        }
242
243
        return $result;
244
    }
245
246
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
247
     * @return array
248
     */
249
    public static function getTransformParams(): array
250
    {
251
        $settings = ImageOptimize::$plugin->getSettings();
252
        $params = [
253
            'domain'  => $settings->imgixDomain,
254
            'api-key' => $settings->imgixApiKey,
255
        ];
256
257
        return $params;
258
    }
259
260
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
261
     * @param Asset $asset
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
262
     *
263
     * @return mixed
264
     * @throws \yii\base\InvalidConfigException
265
     */
266
    public static function getAssetUri(Asset $asset)
267
    {
268
        $volume = $asset->getVolume();
269
        $assetUrl = AssetsHelper::generateUrl($volume, $asset);
270
        $assetUri = parse_url($assetUrl, PHP_URL_PATH);
271
272
        return $assetUri;
273
    }
274
}
275