Passed
Push — v1 ( b5a719...67f63c )
by Andrew
12:46 queued 05:01
created

ImageOptimize   B

Complexity

Total Complexity 49

Size/Duplication

Total Lines 584
Duplicated Lines 0 %

Importance

Changes 5
Bugs 0 Features 0
Metric Value
wmc 49
eloc 262
c 5
b 0
f 0
dl 0
loc 584
rs 8.48

15 Methods

Rating   Name   Duplication   Size   Complexity  
A init() 0 26 2
A createSettingsModel() 0 3 1
A settingsHtml() 0 39 5
A installElementEventHandlers() 0 38 4
A customFrontendRoutes() 0 3 1
A installCpEventListeners() 0 19 3
A setImageTransformComponent() 0 11 2
A installCraftQLEventHandlers() 0 7 2
B installMiscEventHandlers() 0 68 10
A installSiteEventListeners() 0 15 1
B installAssetEventHandlers() 0 98 3
A installEventHandlers() 0 14 5
A getSettingsResponse() 0 13 1
A addComponents() 0 36 2
B checkForOptimizedImagesField() 0 21 7

How to fix   Complexity   

Complex Class

Complex classes like ImageOptimize 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 ImageOptimize, and based on these observations, apply Extract Interface, too.

1
<?php
2
/**
3
 * ImageOptimize 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;
12
13
use Craft;
14
use craft\base\Field;
15
use craft\base\Plugin;
16
use craft\base\Volume;
17
use craft\elements\Asset;
18
use craft\events\AssetTransformImageEvent;
19
use craft\events\ElementEvent;
20
use craft\events\FieldEvent;
21
use craft\events\GenerateTransformEvent;
22
use craft\events\GetAssetThumbUrlEvent;
23
use craft\events\GetAssetUrlEvent;
24
use craft\events\PluginEvent;
25
use craft\events\RegisterComponentTypesEvent;
26
use craft\events\RegisterTemplateRootsEvent;
27
use craft\events\RegisterUrlRulesEvent;
28
use craft\events\ReplaceAssetEvent;
29
use craft\events\VolumeEvent;
30
use craft\helpers\ArrayHelper;
31
use craft\helpers\UrlHelper;
32
use craft\models\FieldLayout;
33
use craft\services\Assets;
34
use craft\services\AssetTransforms;
35
use craft\services\Elements;
36
use craft\services\Fields;
37
use craft\services\Plugins;
38
use craft\services\Utilities;
39
use craft\services\Volumes;
40
use craft\web\Controller;
41
use craft\web\twig\variables\CraftVariable;
42
use craft\web\UrlManager;
43
use craft\web\View;
44
use markhuot\CraftQL\CraftQL;
0 ignored issues
show
Bug introduced by
The type markhuot\CraftQL\CraftQL was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
45
use nystudio107\imageoptimize\fields\OptimizedImages;
46
use nystudio107\imageoptimize\imagetransforms\CraftImageTransform;
47
use nystudio107\imageoptimize\imagetransforms\ImageTransformInterface;
48
use nystudio107\imageoptimize\listeners\GetCraftQLSchema;
49
use nystudio107\imageoptimize\models\Settings;
50
use nystudio107\imageoptimize\services\ServicesTrait;
51
use nystudio107\imageoptimize\utilities\ImageOptimizeUtility;
52
use nystudio107\imageoptimize\variables\ImageOptimizeVariable;
53
use yii\base\Event;
54
use yii\base\Exception;
55
use yii\base\InvalidConfigException;
56
57
/** @noinspection MissingPropertyAnnotationsInspection */
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...
58
59
/**
60
 * Class ImageOptimize
61
 *
62
 * @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...
63
 * @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...
64
 * @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 for @since tag indented incorrectly; expected 3 spaces but found 5
Loading history...
65
 *
66
 * @property ImageTransformInterface $transformMethod
67
 */
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...
68
class ImageOptimize extends Plugin
69
{
70
    // Traits
71
    // =========================================================================
72
73
    use ServicesTrait;
74
75
    // Constants
76
    // =========================================================================
77
78
    const CRAFTQL_PLUGIN_HANDLE = 'craftql';
79
80
    // Static Properties
81
    // =========================================================================
82
83
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
84
     * @var ImageOptimize
85
     */
86
    public static $plugin;
87
88
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
89
     * @var bool
90
     */
91
    public static $generatePlaceholders = true;
92
93
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
94
     * @var bool
95
     */
96
    public static $craft31 = false;
97
98
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
99
     * @var bool
100
     */
101
    public static $craft35 = false;
102
103
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
104
     * @var bool
105
     */
106
    public static $craft37 = false;
107
108
    // Public Properties
109
    // =========================================================================
110
111
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
112
     * @var string
113
     */
114
    public $schemaVersion = '1.0.0';
115
116
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
117
     * @var bool
118
     */
119
    public $hasCpSection = false;
120
121
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
122
     * @var bool
123
     */
124
    public $hasCpSettings = true;
125
126
    // Public Methods
127
    // =========================================================================
128
129
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
130
     * @inheritdoc
131
     */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
132
    public function init()
133
    {
134
        parent::init();
135
        self::$plugin = $this;
136
        self::$craft31 = version_compare(Craft::$app->getVersion(), '3.1', '>=');
0 ignored issues
show
Documentation Bug introduced by
It seems like version_compare(Craft::a...Version(), '3.1', '>=') can also be of type integer. However, the property $craft31 is declared as type boolean. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
137
        self::$craft35 = version_compare(Craft::$app->getVersion(), '3.5', '>=');
0 ignored issues
show
Documentation Bug introduced by
It seems like version_compare(Craft::a...Version(), '3.5', '>=') can also be of type integer. However, the property $craft35 is declared as type boolean. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
138
        self::$craft37 = version_compare(Craft::$app->getVersion(), '3.7', '>=');
0 ignored issues
show
Documentation Bug introduced by
It seems like version_compare(Craft::a...Version(), '3.7', '>=') can also be of type integer. However, the property $craft37 is declared as type boolean. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
139
        // Handle any console commands
140
        $request = Craft::$app->getRequest();
141
        if ($request->getIsConsoleRequest()) {
142
            $this->controllerNamespace = 'nystudio107\imageoptimize\console\controllers';
143
        }
144
        // Set the image transform component
145
        $this->setImageTransformComponent();
146
        // Add in our Craft components
147
        $this->addComponents();
148
        // Install our global event handlers
149
        $this->installEventHandlers();
150
        // Log that the plugin has loaded
151
        Craft::info(
152
            Craft::t(
153
                'image-optimize',
154
                '{name} plugin loaded',
155
                ['name' => $this->name]
156
            ),
157
            __METHOD__
158
        );
159
    }
160
161
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
162
     * @inheritdoc
163
     */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
164
    public function getSettingsResponse()
165
    {
166
        $view = Craft::$app->getView();
167
        $namespace = $view->getNamespace();
168
        $view->setNamespace('settings');
169
        $settingsHtml = $this->settingsHtml();
170
        $view->setNamespace($namespace);
171
        /** @var Controller $controller */
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...
172
        $controller = Craft::$app->controller;
0 ignored issues
show
Documentation Bug introduced by
It seems like Craft::app->controller can also be of type yii\web\Controller. However, the property $controller is declared as type yii\console\Controller. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
173
174
        return $controller->renderTemplate('image-optimize/settings/index.twig', [
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...
175
            'plugin' => $this,
176
            'settingsHtml' => $settingsHtml,
177
        ]);
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...
178
    }
179
180
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
181
     * @inheritdoc
182
     */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
183
    public function settingsHtml()
184
    {
185
        // Get only the user-editable settings
186
        $settings = $this->getSettings();
187
188
        // Get the image transform types
189
        $allImageTransformTypes = ImageOptimize::$plugin->optimize->getAllImageTransformTypes();
190
        $imageTransformTypeOptions = [];
191
        /** @var ImageTransformInterface $class */
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...
192
        foreach ($allImageTransformTypes as $class) {
193
            if ($class::isSelectable()) {
194
                $imageTransformTypeOptions[] = [
195
                    'value' => $class,
196
                    'label' => $class::displayName(),
197
                ];
198
            }
199
        }
200
        // Sort them by name
201
        ArrayHelper::multisort($imageTransformTypeOptions, 'label');
202
203
        // Render the settings template
204
        try {
205
            return Craft::$app->getView()->renderTemplate(
206
                'image-optimize/settings/_settings.twig',
207
                [
208
                    'settings' => $settings,
209
                    'gdInstalled' => \function_exists('imagecreatefromjpeg'),
210
                    'imageTransformTypeOptions' => $imageTransformTypeOptions,
211
                    'allImageTransformTypes' => $allImageTransformTypes,
212
                    'imageTransform' => ImageOptimize::$plugin->transformMethod,
213
                ]
214
            );
215
        } catch (\Twig\Error\LoaderError $e) {
216
            Craft::error($e->getMessage(), __METHOD__);
217
        } catch (Exception $e) {
218
            Craft::error($e->getMessage(), __METHOD__);
219
        }
220
221
        return '';
222
    }
223
224
    // Protected Methods
225
    // =========================================================================
226
227
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
228
     * @inheritdoc
229
     */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
230
    protected function createSettingsModel()
231
    {
232
        return new Settings();
233
    }
234
235
    /**
236
     * Set the transformMethod component
237
     */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
238
    protected function setImageTransformComponent()
239
    {
240
        $settings = $this->getSettings();
241
        $definition = array_merge(
242
            $settings->imageTransformTypeSettings[$settings->transformClass] ?? [],
243
            ['class' => $settings->transformClass]
244
        );
245
        try {
246
            $this->set('transformMethod', $definition);
247
        } catch (InvalidConfigException $e) {
248
            Craft::error($e->getMessage(), __METHOD__);
249
        }
250
    }
251
252
    /**
253
     * Add in our Craft components
254
     */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
255
    protected function addComponents()
256
    {
257
        // Register our variables
258
        Event::on(
259
            CraftVariable::class,
260
            CraftVariable::EVENT_INIT,
261
            function (Event $event) {
262
                /** @var CraftVariable $variable */
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...
263
                $variable = $event->sender;
264
                $variable->set('imageOptimize', [
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...
265
                    'class' => ImageOptimizeVariable::class,
266
                    'viteService' => $this->vite,
267
                ]);
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...
268
            }
269
        );
270
271
        // Register our Field
272
        Event::on(
273
            Fields::class,
274
            Fields::EVENT_REGISTER_FIELD_TYPES,
275
            function (RegisterComponentTypesEvent $event) {
276
                Craft::debug(
277
                    'Fields::EVENT_REGISTER_FIELD_TYPES',
278
                    __METHOD__
279
                );
280
                $event->types[] = OptimizedImages::class;
281
            }
282
        );
283
284
        // Register our Utility only if they are using the CraftImageTransform method
285
        if (ImageOptimize::$plugin->transformMethod instanceof CraftImageTransform) {
286
            Event::on(
287
                Utilities::class,
288
                Utilities::EVENT_REGISTER_UTILITY_TYPES,
289
                function (RegisterComponentTypesEvent $event) {
290
                    $event->types[] = ImageOptimizeUtility::class;
291
                }
292
            );
293
        }
294
    }
295
296
    /**
297
     * Install our event handlers
298
     */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
299
    protected function installEventHandlers()
300
    {
301
        $this->installAssetEventHandlers();
302
        $this->installElementEventHandlers();
303
        $this->installMiscEventHandlers();
304
        $this->installCraftQLEventHandlers();
305
        $request = Craft::$app->getRequest();
306
        // Install only for non-console site requests
307
        if ($request->getIsSiteRequest() && !$request->getIsConsoleRequest()) {
308
            $this->installSiteEventListeners();
309
        }
310
        // Install only for non-console cp requests
311
        if ($request->getIsCpRequest() && !$request->getIsConsoleRequest()) {
312
            $this->installCpEventListeners();
313
        }
314
    }
315
316
    /**
317
     * Install our Asset event handlers
318
     */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
319
    protected function installAssetEventHandlers()
320
    {
321
        // Handler: Assets::EVENT_GET_ASSET_URL
322
        Event::on(
323
            Assets::class,
324
            Assets::EVENT_GET_ASSET_URL,
325
            function (GetAssetUrlEvent $event) {
326
                Craft::debug(
327
                    'Assets::EVENT_GET_ASSET_URL',
328
                    __METHOD__
329
                );
330
                // Return the URL to the asset URL or null to let Craft handle it
331
                $event->url = ImageOptimize::$plugin->optimize->handleGetAssetUrlEvent(
332
                    $event
333
                );
334
            }
335
        );
336
337
        // Handler: Assets::EVENT_GET_ASSET_THUMB_URL
338
        Event::on(
339
            Assets::class,
340
            Assets::EVENT_GET_ASSET_THUMB_URL,
341
            function (GetAssetThumbUrlEvent $event) {
342
                Craft::debug(
343
                    'Assets::EVENT_GET_ASSET_THUMB_URL',
344
                    __METHOD__
345
                );
346
                // Return the URL to the asset URL or null to let Craft handle it
347
                $event->url = ImageOptimize::$plugin->optimize->handleGetAssetThumbUrlEvent(
348
                    $event
349
                );
350
            }
351
        );
352
353
        // Handler: AssetTransforms::EVENT_GENERATE_TRANSFORM
354
        Event::on(
355
            AssetTransforms::class,
356
            AssetTransforms::EVENT_GENERATE_TRANSFORM,
357
            function (GenerateTransformEvent $event) {
358
                Craft::debug(
359
                    'AssetTransforms::EVENT_GENERATE_TRANSFORM',
360
                    __METHOD__
361
                );
362
                // Return the path to the optimized image to _createTransformForAsset()
363
                $event->tempPath = ImageOptimize::$plugin->optimize->handleGenerateTransformEvent(
364
                    $event
365
                );
366
            }
367
        );
368
369
        // Handler: AssetTransforms::EVENT_AFTER_DELETE_TRANSFORMS
370
        Event::on(
371
            AssetTransforms::class,
372
            AssetTransforms::EVENT_AFTER_DELETE_TRANSFORMS,
373
            function (AssetTransformImageEvent $event) {
374
                Craft::debug(
375
                    'AssetTransforms::EVENT_AFTER_DELETE_TRANSFORMS',
376
                    __METHOD__
377
                );
378
                // Clean up any stray variant files
379
                ImageOptimize::$plugin->optimize->handleAfterDeleteTransformsEvent(
380
                    $event
381
                );
382
            }
383
        );
384
385
        // Handler: Assets::EVENT_BEFORE_REPLACE_ASSET
386
        Event::on(
387
            Assets::class,
388
            Assets::EVENT_BEFORE_REPLACE_ASSET,
389
            function (ReplaceAssetEvent $event) {
390
                Craft::debug(
391
                    'Assets::EVENT_BEFORE_REPLACE_ASSET',
392
                    __METHOD__
393
                );
394
                /** @var Asset $element */
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...
395
                $element = $event->asset;
396
                // Purge the URL
397
                $purgeUrl = ImageOptimize::$plugin->transformMethod->getPurgeUrl($element);
398
                if ($purgeUrl) {
399
                    ImageOptimize::$plugin->transformMethod->purgeUrl($purgeUrl);
400
                }
401
            }
402
        );
403
404
        // Handler: Assets::EVENT_AFTER_REPLACE_ASSET
405
        Event::on(
406
            Assets::class,
407
            Assets::EVENT_AFTER_REPLACE_ASSET,
408
            function (ReplaceAssetEvent $event) {
409
                Craft::debug(
410
                    'Assets::EVENT_AFTER_REPLACE_ASSET',
411
                    __METHOD__
412
                );
413
                /** @var Asset $element */
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...
414
                $element = $event->asset;
415
                if ($element->id !== null) {
416
                    ImageOptimize::$plugin->optimizedImages->resaveAsset($element->id, true);
417
                }
418
            }
419
        );
420
    }
421
422
    /**
423
     * Install our Element event handlers
424
     */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
425
    protected function installElementEventHandlers()
426
    {
427
        // Handler: Elements::EVENT_BEFORE_SAVE_ELEMENT
428
        Event::on(
429
            Assets::class,
430
            Elements::EVENT_BEFORE_SAVE_ELEMENT,
431
            function (ElementEvent $event) {
432
                Craft::debug(
433
                    'Elements::EVENT_BEFORE_SAVE_ELEMENT',
434
                    __METHOD__
435
                );
436
                /** @var Asset $asset */
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...
437
                $asset = $event->element;
438
                if (!$event->isNew) {
439
                    // Purge the URL
440
                    $purgeUrl = ImageOptimize::$plugin->transformMethod->getPurgeUrl($asset);
441
                    if ($purgeUrl) {
442
                        ImageOptimize::$plugin->transformMethod->purgeUrl($purgeUrl);
443
                    }
444
                }
445
            }
446
        );
447
448
        // Handler: Elements::EVENT_BEFORE_DELETE_ELEMENT
449
        Event::on(
450
            Asset::class,
451
            Elements::EVENT_BEFORE_DELETE_ELEMENT,
452
            function (ElementEvent $event) {
453
                Craft::debug(
454
                    'Elements::EVENT_BEFORE_DELETE_ELEMENT',
455
                    __METHOD__
456
                );
457
                /** @var Asset $asset */
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...
458
                $asset = $event->element;
459
                // Purge the URL
460
                $purgeUrl = ImageOptimize::$plugin->transformMethod->getPurgeUrl($asset);
461
                if ($purgeUrl) {
462
                    ImageOptimize::$plugin->transformMethod->purgeUrl($purgeUrl);
463
                }
464
            }
465
        );
466
    }
467
468
    /**
469
     * Install our miscellaneous event handlers
470
     */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
471
    protected function installMiscEventHandlers()
472
    {
473
        // Handler: Fields::EVENT_AFTER_SAVE_FIELD
474
        Event::on(
475
            Fields::class,
476
            Fields::EVENT_AFTER_SAVE_FIELD,
477
            function (FieldEvent $event) {
478
                Craft::debug(
479
                    'Fields::EVENT_AFTER_SAVE_FIELD',
480
                    __METHOD__
481
                );
482
                $settings = $this->getSettings();
483
                /** @var Field $field */
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...
484
                if (!$event->isNew && $settings->automaticallyResaveImageVariants) {
485
                    $this->checkForOptimizedImagesField($event);
486
                }
487
            }
488
        );
489
490
        // Handler: Plugins::EVENT_AFTER_SAVE_PLUGIN_SETTINGS
491
        Event::on(
492
            Plugins::class,
493
            Plugins::EVENT_AFTER_SAVE_PLUGIN_SETTINGS,
494
            function (PluginEvent $event) {
495
                if ($event->plugin === $this) {
496
                    Craft::debug(
497
                        'Plugins::EVENT_AFTER_SAVE_PLUGIN_SETTINGS',
498
                        __METHOD__
499
                    );
500
                    $settings = $this->getSettings();
501
                    if ($settings->automaticallyResaveImageVariants) {
502
                        // After they have changed the settings, resave all of the assets
503
                        ImageOptimize::$plugin->optimizedImages->resaveAllVolumesAssets();
504
                    }
505
                }
506
            }
507
        );
508
509
        // Handler: Volumes::EVENT_AFTER_SAVE_VOLUME
510
        Event::on(
511
            Volumes::class,
512
            Volumes::EVENT_AFTER_SAVE_VOLUME,
513
            function (VolumeEvent $event) {
514
                Craft::debug(
515
                    'Volumes::EVENT_AFTER_SAVE_VOLUME',
516
                    __METHOD__
517
                );
518
                $settings = $this->getSettings();
519
                // Only worry about this volume if it's not new
520
                if (!$event->isNew && $settings->automaticallyResaveImageVariants) {
521
                    /** @var Volume $volume */
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...
522
                    $volume = $event->volume;
523
                    if ($volume !== null) {
524
                        ImageOptimize::$plugin->optimizedImages->resaveVolumeAssets($volume);
525
                    }
526
                }
527
            }
528
        );
529
530
        // Handler: Plugins::EVENT_AFTER_INSTALL_PLUGIN
531
        Event::on(
532
            Plugins::class,
533
            Plugins::EVENT_AFTER_INSTALL_PLUGIN,
534
            function (PluginEvent $event) {
535
                if ($event->plugin === $this) {
536
                    $request = Craft::$app->getRequest();
537
                    if ($request->isCpRequest) {
538
                        Craft::$app->getResponse()->redirect(UrlHelper::cpUrl('image-optimize/welcome'))->send();
539
                    }
540
                }
541
            }
542
        );
543
    }
544
545
    /**
546
     * Install our CraftQL event handlers
547
     */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
548
    protected function installCraftQLEventHandlers()
549
    {
550
        if (class_exists(CraftQL::class)) {
551
            Event::on(
552
                OptimizedImages::class,
553
                GetCraftQLSchema::EVENT_GET_FIELD_SCHEMA,
554
                [new GetCraftQLSchema, 'handle']
555
            );
556
        }
557
    }
558
559
    /**
560
     * Install site event listeners for site requests only
561
     */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
562
    protected function installSiteEventListeners()
563
    {
564
        // Handler: UrlManager::EVENT_REGISTER_SITE_URL_RULES
565
        Event::on(
566
            UrlManager::class,
567
            UrlManager::EVENT_REGISTER_SITE_URL_RULES,
568
            function (RegisterUrlRulesEvent $event) {
569
                Craft::debug(
570
                    'UrlManager::EVENT_REGISTER_SITE_URL_RULES',
571
                    __METHOD__
572
                );
573
                // Register our Control Panel routes
574
                $event->rules = array_merge(
575
                    $event->rules,
576
                    $this->customFrontendRoutes()
577
                );
578
            }
579
        );
580
    }
581
582
    /**
583
     * Install site event listeners for cp requests only
584
     */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
585
    protected function installCpEventListeners()
586
    {
587
        // Handler: Plugins::EVENT_AFTER_LOAD_PLUGINS
588
        Event::on(
589
            Plugins::class,
590
            Plugins::EVENT_AFTER_LOAD_PLUGINS,
591
            function () {
592
                // Install these only after all other plugins have loaded
593
                Event::on(
594
                    View::class,
595
                    View::EVENT_REGISTER_CP_TEMPLATE_ROOTS,
596
                    function (RegisterTemplateRootsEvent $e) {
597
                        // Register the root directodies
598
                        $allImageTransformTypes = ImageOptimize::$plugin->optimize->getAllImageTransformTypes();
599
                        /** @var ImageTransformInterface $imageTransformType */
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...
600
                        foreach ($allImageTransformTypes as $imageTransformType) {
601
                            list($id, $baseDir) = $imageTransformType::getTemplatesRoot();
602
                            if (is_dir($baseDir)) {
603
                                $e->roots[$id] = $baseDir;
604
                            }
605
                        }
606
                    }
607
                );
608
            }
609
        );
610
    }
611
612
    /**
613
     * Return the custom frontend routes
614
     *
615
     * @return array
616
     */
617
    protected function customFrontendRoutes(): array
618
    {
619
        return [
620
        ];
621
    }
622
623
    /**
624
     * If the Field being saved is an OptimizedImages field, re-save the
625
     * responsive image variants automatically
626
     *
627
     * @param FieldEvent $event
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
628
     *
629
     * @throws \yii\base\InvalidConfigException
630
     */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
631
    protected function checkForOptimizedImagesField(FieldEvent $event)
632
    {
633
        $thisField = $event->field;
634
        if ($thisField instanceof OptimizedImages) {
635
            $volumes = Craft::$app->getVolumes()->getAllVolumes();
636
            foreach ($volumes as $volume) {
637
                $needToReSave = false;
638
                /** @var FieldLayout $fieldLayout */
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...
639
                /** @var Volume $volume */
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...
640
                $fieldLayout = $volume->getFieldLayout();
641
                // Loop through the fields in the layout to see if it contains our field
642
                if ($fieldLayout) {
643
                    $fields = $fieldLayout->getFields();
644
                    foreach ($fields as $field) {
645
                        /** @var Field $field */
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...
646
                        if ($thisField->handle === $field->handle) {
647
                            $needToReSave = true;
648
                        }
649
                    }
650
                    if ($needToReSave) {
651
                        ImageOptimize::$plugin->optimizedImages->resaveVolumeAssets($volume, $thisField->id);
0 ignored issues
show
Bug introduced by
It seems like $thisField->id can also be of type string; however, parameter $fieldId of nystudio107\imageoptimiz...s::resaveVolumeAssets() does only seem to accept integer|null, 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

651
                        ImageOptimize::$plugin->optimizedImages->resaveVolumeAssets($volume, /** @scrutinizer ignore-type */ $thisField->id);
Loading history...
652
                    }
653
                }
654
            }
655
        }
656
    }
657
}
658