Passed
Push — develop ( dadb8b...e89f4d )
by Andrew
08:19
created

ImageOptimize::checkForOptimizedImagesField()   B

Complexity

Conditions 7
Paths 9

Size

Total Lines 21
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 13
dl 0
loc 21
rs 8.8333
c 0
b 0
f 0
cc 7
nc 9
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;
12
13
use nystudio107\imageoptimize\fields\OptimizedImages;
14
use nystudio107\imageoptimize\imagetransforms\CraftImageTransform;
15
use nystudio107\imageoptimize\imagetransforms\ImageTransformInterface;
16
use nystudio107\imageoptimize\listeners\GetCraftQLSchema;
17
use nystudio107\imageoptimize\models\Settings;
18
use nystudio107\imageoptimize\services\Optimize as OptimizeService;
19
use nystudio107\imageoptimize\services\OptimizedImages as OptimizedImagesService;
20
use nystudio107\imageoptimize\services\Placeholder as PlaceholderService;
21
use nystudio107\imageoptimize\utilities\ImageOptimizeUtility;
22
use nystudio107\imageoptimize\variables\ImageOptimizeVariable;
23
24
use Craft;
25
use craft\base\Field;
26
use craft\base\Plugin;
27
use craft\base\Volume;
28
use craft\elements\Asset;
29
use craft\events\AssetTransformImageEvent;
30
use craft\events\ElementEvent;
31
use craft\events\FieldEvent;
32
use craft\events\GetAssetThumbUrlEvent;
33
use craft\events\GetAssetUrlEvent;
34
use craft\events\GenerateTransformEvent;
35
use craft\events\PluginEvent;
36
use craft\events\RegisterComponentTypesEvent;
37
use craft\events\RegisterTemplateRootsEvent;
38
use craft\events\RegisterUrlRulesEvent;
39
use craft\events\ReplaceAssetEvent;
40
use craft\events\VolumeEvent;
41
use craft\helpers\ArrayHelper;
42
use craft\helpers\UrlHelper;
43
use craft\models\FieldLayout;
44
use craft\services\Assets;
45
use craft\services\AssetTransforms;
46
use craft\services\Elements;
47
use craft\services\Fields;
48
use craft\services\Plugins;
49
use craft\services\Utilities;
50
use craft\services\Volumes;
51
use craft\web\twig\variables\CraftVariable;
52
use craft\web\Controller;
53
use craft\web\UrlManager;
54
use craft\web\View;
55
56
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...
57
58
use yii\base\Event;
59
use yii\base\Exception;
60
use yii\base\InvalidConfigException;
61
62
/** @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...
63
64
/**
65
 * Class ImageOptimize
66
 *
67
 * @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...
68
 * @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...
69
 * @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...
70
 *
71
 * @property OptimizeService         $optimize
72
 * @property PlaceholderService      $placeholder
73
 * @property OptimizedImagesService  $optimizedImages
74
 * @property ImageTransformInterface $transformMethod
75
 * @property Settings                $settings
76
 * @method   Settings                getSettings()
77
 */
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...
78
class ImageOptimize extends Plugin
79
{
80
81
    // Constants
82
    // =========================================================================
83
84
    const CRAFTQL_PLUGIN_HANDLE = 'craftql';
85
86
    // Static Properties
87
    // =========================================================================
88
89
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
90
     * @var ImageOptimize
91
     */
92
    public static $plugin;
93
94
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
95
     * @var bool
96
     */
97
    public static $generatePlaceholders = true;
98
99
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
100
     * @var bool
101
     */
102
    public static $craft31 = false;
103
104
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
105
     * @var bool
106
     */
107
    public static $craft35 = false;
108
109
    // Static Methods
110
    // =========================================================================
111
112
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
Coding Style introduced by
Parameter $config should have a doc-comment as per coding-style.
Loading history...
Coding Style introduced by
Parameter $id should have a doc-comment as per coding-style.
Loading history...
Coding Style introduced by
Parameter $parent should have a doc-comment as per coding-style.
Loading history...
113
     * @inheritdoc
114
     */
115
    public function __construct($id, $parent = null, array $config = [])
116
    {
117
        $config['components'] = [
118
            'optimize' => OptimizeService::class,
119
            'optimizedImages' => OptimizedImagesService::class,
120
            'placeholder' => PlaceholderService::class,
121
        ];
122
123
        parent::__construct($id, $parent, $config);
124
    }
125
126
    // Public Properties
127
    // =========================================================================
128
129
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
130
     * @var string
131
     */
132
    public $schemaVersion = '1.0.0';
133
134
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
135
     * @var bool
136
     */
137
    public $hasCpSection = false;
138
139
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
140
     * @var bool
141
     */
142
    public $hasCpSettings = true;
143
144
    // Public Methods
145
    // =========================================================================
146
147
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
148
     * @inheritdoc
149
     */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
150
    public function init()
151
    {
152
        parent::init();
153
        self::$plugin = $this;
154
        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...
155
        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...
156
        // Handle any console commands
157
        $request = Craft::$app->getRequest();
158
        if ($request->getIsConsoleRequest()) {
159
            $this->controllerNamespace = 'nystudio107\imageoptimize\console\controllers';
160
        }
161
        // Set the image transform component
162
        $this->setImageTransformComponent();
163
        // Add in our Craft components
164
        $this->addComponents();
165
        // Install our global event handlers
166
        $this->installEventHandlers();
167
        // Log that the plugin has loaded
168
        Craft::info(
169
            Craft::t(
170
                'image-optimize',
171
                '{name} plugin loaded',
172
                ['name' => $this->name]
173
            ),
174
            __METHOD__
175
        );
176
    }
177
178
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
179
     * @inheritdoc
180
     */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
181
    public function getSettingsResponse()
182
    {
183
        $view = Craft::$app->getView();
184
        $namespace = $view->getNamespace();
185
        $view->setNamespace('settings');
186
        $settingsHtml = $this->settingsHtml();
187
        $view->setNamespace($namespace);
188
        /** @var Controller $controller */
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
Coding Style introduced by
The open comment tag must be the only content on the line
Loading history...
Coding Style introduced by
The close comment tag must be the only content on the line
Loading history...
189
        $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...
190
191
        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...
192
            'plugin'       => $this,
193
            'settingsHtml' => $settingsHtml,
194
        ]);
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...
195
    }
196
197
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
198
     * @inheritdoc
199
     */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
200
    public function settingsHtml()
201
    {
202
        // Get only the user-editable settings
203
        $settings = $this->getSettings();
204
205
        // Get the image transform types
206
        $allImageTransformTypes = ImageOptimize::$plugin->optimize->getAllImageTransformTypes();
207
        $imageTransformTypeOptions = [];
208
        /** @var ImageTransformInterface $class */
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
Coding Style introduced by
The open comment tag must be the only content on the line
Loading history...
Coding Style introduced by
The close comment tag must be the only content on the line
Loading history...
209
        foreach ($allImageTransformTypes as $class) {
210
            if ($class::isSelectable()) {
211
                $imageTransformTypeOptions[] = [
212
                    'value' => $class,
213
                    'label' => $class::displayName(),
214
                ];
215
            }
216
        }
217
        // Sort them by name
218
        ArrayHelper::multisort($imageTransformTypeOptions, 'label');
219
220
        // Render the settings template
221
        try {
222
            return Craft::$app->getView()->renderTemplate(
223
                'image-optimize/settings/_settings.twig',
224
                [
225
                    'settings'        => $settings,
226
                    'gdInstalled'     => \function_exists('imagecreatefromjpeg'),
227
                    'imageTransformTypeOptions' => $imageTransformTypeOptions,
228
                    'allImageTransformTypes' => $allImageTransformTypes,
229
                    'imageTransform' => ImageOptimize::$plugin->transformMethod,
230
                ]
231
            );
232
        } catch (\Twig\Error\LoaderError $e) {
233
            Craft::error($e->getMessage(), __METHOD__);
234
        } catch (Exception $e) {
235
            Craft::error($e->getMessage(), __METHOD__);
236
        }
237
238
        return '';
239
    }
240
241
    // Protected Methods
242
    // =========================================================================
243
244
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
245
     * @inheritdoc
246
     */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
247
    protected function createSettingsModel()
248
    {
249
        return new Settings();
250
    }
251
252
    /**
253
     * Set the transformMethod component
254
     */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
255
    protected function setImageTransformComponent()
256
    {
257
        $settings = $this->getSettings();
258
        $definition = array_merge(
259
            $settings->imageTransformTypeSettings[$settings->transformClass] ?? [],
260
            ['class' => $settings->transformClass]
261
        );
262
        try {
263
            $this->set('transformMethod', $definition);
264
        } catch (InvalidConfigException $e) {
265
            Craft::error($e->getMessage(), __METHOD__);
266
        }
267
    }
268
269
    /**
270
     * Add in our Craft components
271
     */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
272
    protected function addComponents()
273
    {
274
        // Register our variables
275
        Event::on(
276
            CraftVariable::class,
277
            CraftVariable::EVENT_INIT,
278
            function (Event $event) {
279
                /** @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...
280
                $variable = $event->sender;
281
                $variable->set('imageOptimize', ImageOptimizeVariable::class);
282
            }
283
        );
284
285
        // Register our Field
286
        Event::on(
287
            Fields::class,
288
            Fields::EVENT_REGISTER_FIELD_TYPES,
289
            function (RegisterComponentTypesEvent $event) {
290
                Craft::debug(
291
                    'Fields::EVENT_REGISTER_FIELD_TYPES',
292
                    __METHOD__
293
                );
294
                $event->types[] = OptimizedImages::class;
295
            }
296
        );
297
298
        // Register our Utility only if they are using the CraftImageTransform method
299
        if (ImageOptimize::$plugin->transformMethod instanceof CraftImageTransform) {
300
            Event::on(
301
                Utilities::class,
302
                Utilities::EVENT_REGISTER_UTILITY_TYPES,
303
                function (RegisterComponentTypesEvent $event) {
304
                    $event->types[] = ImageOptimizeUtility::class;
305
                }
306
            );
307
        }
308
    }
309
310
    /**
311
     * Install our event handlers
312
     */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
313
    protected function installEventHandlers()
314
    {
315
        $this->installAssetEventHandlers();
316
        $this->installElementEventHandlers();
317
        $this->installMiscEventHandlers();
318
        $this->installCraftQLEventHandlers();
319
        $request = Craft::$app->getRequest();
320
        // Install only for non-console site requests
321
        if ($request->getIsSiteRequest() && !$request->getIsConsoleRequest()) {
322
            $this->installSiteEventListeners();
323
        }
324
        // Install only for non-console cp requests
325
        if ($request->getIsCpRequest() && !$request->getIsConsoleRequest()) {
326
            $this->installCpEventListeners();
327
        }
328
    }
329
330
    /**
331
     * Install our Asset event handlers
332
     */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
333
    protected function installAssetEventHandlers()
334
    {
335
        // Handler: Assets::EVENT_GET_ASSET_URL
336
        Event::on(
337
            Assets::class,
338
            Assets::EVENT_GET_ASSET_URL,
339
            function (GetAssetUrlEvent $event) {
340
                Craft::debug(
341
                    'Assets::EVENT_GET_ASSET_URL',
342
                    __METHOD__
343
                );
344
                // Return the URL to the asset URL or null to let Craft handle it
345
                $event->url = ImageOptimize::$plugin->optimize->handleGetAssetUrlEvent(
346
                    $event
347
                );
348
            }
349
        );
350
351
        // Handler: Assets::EVENT_GET_ASSET_THUMB_URL
352
        Event::on(
353
            Assets::class,
354
            Assets::EVENT_GET_ASSET_THUMB_URL,
355
            function (GetAssetThumbUrlEvent $event) {
356
                Craft::debug(
357
                    'Assets::EVENT_GET_ASSET_THUMB_URL',
358
                    __METHOD__
359
                );
360
                // Return the URL to the asset URL or null to let Craft handle it
361
                $event->url = ImageOptimize::$plugin->optimize->handleGetAssetThumbUrlEvent(
362
                    $event
363
                );
364
            }
365
        );
366
367
        // Handler: AssetTransforms::EVENT_GENERATE_TRANSFORM
368
        Event::on(
369
            AssetTransforms::class,
370
            AssetTransforms::EVENT_GENERATE_TRANSFORM,
371
            function (GenerateTransformEvent $event) {
372
                Craft::debug(
373
                    'AssetTransforms::EVENT_GENERATE_TRANSFORM',
374
                    __METHOD__
375
                );
376
                // Return the path to the optimized image to _createTransformForAsset()
377
                $event->tempPath = ImageOptimize::$plugin->optimize->handleGenerateTransformEvent(
378
                    $event
379
                );
380
            }
381
        );
382
383
        // Handler: AssetTransforms::EVENT_AFTER_DELETE_TRANSFORMS
384
        Event::on(
385
            AssetTransforms::class,
386
            AssetTransforms::EVENT_AFTER_DELETE_TRANSFORMS,
387
            function (AssetTransformImageEvent $event) {
388
                Craft::debug(
389
                    'AssetTransforms::EVENT_AFTER_DELETE_TRANSFORMS',
390
                    __METHOD__
391
                );
392
                // Clean up any stray variant files
393
                ImageOptimize::$plugin->optimize->handleAfterDeleteTransformsEvent(
394
                    $event
395
                );
396
            }
397
        );
398
399
        // Handler: Assets::EVENT_BEFORE_REPLACE_ASSET
400
        Event::on(
401
            Assets::class,
402
            Assets::EVENT_BEFORE_REPLACE_ASSET,
403
            function (ReplaceAssetEvent $event) {
404
                Craft::debug(
405
                    'Assets::EVENT_BEFORE_REPLACE_ASSET',
406
                    __METHOD__
407
                );
408
                /** @var Asset $element */
0 ignored issues
show
Coding Style introduced by
The close comment tag must be the only content on the line
Loading history...
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...
409
                $element = $event->asset;
410
                // Purge the URL
411
                $purgeUrl = ImageOptimize::$plugin->transformMethod->getPurgeUrl($element);
412
                if ($purgeUrl) {
413
                    ImageOptimize::$plugin->transformMethod->purgeUrl($purgeUrl);
414
                }
415
            }
416
        );
417
418
        // Handler: Assets::EVENT_AFTER_REPLACE_ASSET
419
        Event::on(
420
            Assets::class,
421
            Assets::EVENT_AFTER_REPLACE_ASSET,
422
            function (ReplaceAssetEvent $event) {
423
                Craft::debug(
424
                    'Assets::EVENT_AFTER_REPLACE_ASSET',
425
                    __METHOD__
426
                );
427
                /** @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...
428
                $element = $event->asset;
429
                if ($element->id !== null) {
430
                    ImageOptimize::$plugin->optimizedImages->resaveAsset($element->id);
431
                }
432
            }
433
        );
434
    }
435
436
    /**
437
     * Install our Element event handlers
438
     */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
439
    protected function installElementEventHandlers()
440
    {
441
        // Handler: Elements::EVENT_BEFORE_SAVE_ELEMENT
442
        Event::on(
443
            Assets::class,
444
            Elements::EVENT_BEFORE_SAVE_ELEMENT,
445
            function (ElementEvent $event) {
446
                Craft::debug(
447
                    'Elements::EVENT_BEFORE_SAVE_ELEMENT',
448
                    __METHOD__
449
                );
450
                /** @var Asset $asset */
0 ignored issues
show
Coding Style introduced by
The close 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 open comment tag must be the only content on the line
Loading history...
451
                $asset = $event->element;
452
                if (!$event->isNew) {
453
                    // Purge the URL
454
                    $purgeUrl = ImageOptimize::$plugin->transformMethod->getPurgeUrl($asset);
455
                    if ($purgeUrl) {
456
                        ImageOptimize::$plugin->transformMethod->purgeUrl($purgeUrl);
457
                    }
458
                }
459
            }
460
        );
461
462
        // Handler: Elements::EVENT_BEFORE_DELETE_ELEMENT
463
        Event::on(
464
            Asset::class,
465
            Elements::EVENT_BEFORE_DELETE_ELEMENT,
466
            function (ElementEvent $event) {
467
                Craft::debug(
468
                    'Elements::EVENT_BEFORE_DELETE_ELEMENT',
469
                    __METHOD__
470
                );
471
                /** @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...
472
                $asset = $event->element;
473
                // Purge the URL
474
                $purgeUrl = ImageOptimize::$plugin->transformMethod->getPurgeUrl($asset);
475
                if ($purgeUrl) {
476
                    ImageOptimize::$plugin->transformMethod->purgeUrl($purgeUrl);
477
                }
478
            }
479
        );
480
    }
481
482
    /**
483
     * Install our miscellaneous event handlers
484
     */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
485
    protected function installMiscEventHandlers()
486
    {
487
        // Handler: Fields::EVENT_AFTER_SAVE_FIELD
488
        Event::on(
489
            Fields::class,
490
            Fields::EVENT_AFTER_SAVE_FIELD,
491
            function (FieldEvent $event) {
492
                Craft::debug(
493
                    'Fields::EVENT_AFTER_SAVE_FIELD',
494
                    __METHOD__
495
                );
496
                $settings = $this->getSettings();
497
                /** @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...
498
                if (!$event->isNew && $settings->automaticallyResaveImageVariants) {
499
                    $this->checkForOptimizedImagesField($event);
500
                }
501
            }
502
        );
503
504
        // Handler: Plugins::EVENT_AFTER_SAVE_PLUGIN_SETTINGS
505
        Event::on(
506
            Plugins::class,
507
            Plugins::EVENT_AFTER_SAVE_PLUGIN_SETTINGS,
508
            function (PluginEvent $event) {
509
                if ($event->plugin === $this) {
510
                    Craft::debug(
511
                        'Plugins::EVENT_AFTER_SAVE_PLUGIN_SETTINGS',
512
                        __METHOD__
513
                    );
514
                    $settings = $this->getSettings();
515
                    if ($settings->automaticallyResaveImageVariants) {
516
                        // After they have changed the settings, resave all of the assets
517
                        ImageOptimize::$plugin->optimizedImages->resaveAllVolumesAssets();
518
                    }
519
                }
520
            }
521
        );
522
523
        // Handler: Volumes::EVENT_AFTER_SAVE_VOLUME
524
        Event::on(
525
            Volumes::class,
526
            Volumes::EVENT_AFTER_SAVE_VOLUME,
527
            function (VolumeEvent $event) {
528
                Craft::debug(
529
                    'Volumes::EVENT_AFTER_SAVE_VOLUME',
530
                    __METHOD__
531
                );
532
                $settings = $this->getSettings();
533
                // Only worry about this volume if it's not new
534
                if (!$event->isNew && $settings->automaticallyResaveImageVariants) {
535
                    /** @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...
536
                    $volume = $event->volume;
537
                    if ($volume !== null) {
538
                        ImageOptimize::$plugin->optimizedImages->resaveVolumeAssets($volume);
539
                    }
540
                }
541
            }
542
        );
543
544
        // Handler: Plugins::EVENT_AFTER_INSTALL_PLUGIN
545
        Event::on(
546
            Plugins::class,
547
            Plugins::EVENT_AFTER_INSTALL_PLUGIN,
548
            function (PluginEvent $event) {
549
                if ($event->plugin === $this) {
550
                    $request = Craft::$app->getRequest();
551
                    if ($request->isCpRequest) {
552
                        Craft::$app->getResponse()->redirect(UrlHelper::cpUrl('image-optimize/welcome'))->send();
553
                    }
554
                }
555
            }
556
        );
557
    }
558
559
    /**
560
     * Install our CraftQL event handlers
561
     */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
562
    protected function installCraftQLEventHandlers()
563
    {
564
        if (class_exists(CraftQL::class)) {
565
            Event::on(
566
                OptimizedImages::class,
567
                GetCraftQLSchema::EVENT_GET_FIELD_SCHEMA,
568
                [new GetCraftQLSchema, 'handle']
569
            );
570
        }
571
    }
572
573
    /**
574
     * Install site event listeners for site requests only
575
     */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
576
    protected function installSiteEventListeners()
577
    {
578
        // Handler: UrlManager::EVENT_REGISTER_SITE_URL_RULES
579
        Event::on(
580
            UrlManager::class,
581
            UrlManager::EVENT_REGISTER_SITE_URL_RULES,
582
            function (RegisterUrlRulesEvent $event) {
583
                Craft::debug(
584
                    'UrlManager::EVENT_REGISTER_SITE_URL_RULES',
585
                    __METHOD__
586
                );
587
                // Register our Control Panel routes
588
                $event->rules = array_merge(
589
                    $event->rules,
590
                    $this->customFrontendRoutes()
591
                );
592
            }
593
        );
594
    }
595
596
    /**
597
     * Install site event listeners for cp requests only
598
     */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
599
    protected function installCpEventListeners()
600
    {
601
        // Handler: Plugins::EVENT_AFTER_LOAD_PLUGINS
602
        Event::on(
603
            Plugins::class,
604
            Plugins::EVENT_AFTER_LOAD_PLUGINS,
605
            function () {
606
                    // Install these only after all other plugins have loaded
607
                    Event::on(
608
                        View::class,
609
                        View::EVENT_REGISTER_CP_TEMPLATE_ROOTS,
610
                        function (RegisterTemplateRootsEvent $e) {
611
                            // Register the root directodies
612
                            $allImageTransformTypes = ImageOptimize::$plugin->optimize->getAllImageTransformTypes();
613
                            /** @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
The close comment tag must be the only content on the line
Loading history...
Coding Style introduced by
Missing short description in doc comment
Loading history...
614
                            foreach ($allImageTransformTypes as $imageTransformType) {
615
                                list($id, $baseDir) = $imageTransformType::getTemplatesRoot();
616
                                if (is_dir($baseDir)) {
617
                                    $e->roots[$id] = $baseDir;
618
                                }
619
                            }
620
                        }
621
                    );
622
            }
623
        );
624
    }
625
626
    /**
627
     * Return the custom frontend routes
628
     *
629
     * @return array
630
     */
631
    protected function customFrontendRoutes(): array
632
    {
633
        return [
634
        ];
635
    }
636
637
    /**
638
     * If the Field being saved is an OptimizedImages field, re-save the
639
     * responsive image variants automatically
640
     *
641
     * @param FieldEvent $event
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
642
     *
643
     * @throws \yii\base\InvalidConfigException
644
     */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
645
    protected function checkForOptimizedImagesField(FieldEvent $event)
646
    {
647
        $thisField = $event->field;
648
        if ($thisField instanceof OptimizedImages) {
649
            $volumes = Craft::$app->getVolumes()->getAllVolumes();
650
            foreach ($volumes as $volume) {
651
                $needToReSave = false;
652
                /** @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
The close comment tag must be the only content on the line
Loading history...
Coding Style introduced by
Missing short description in doc comment
Loading history...
653
                /** @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
The close comment tag must be the only content on the line
Loading history...
Coding Style introduced by
Missing short description in doc comment
Loading history...
654
                $fieldLayout = $volume->getFieldLayout();
655
                // Loop through the fields in the layout to see if it contains our field
656
                if ($fieldLayout) {
657
                    $fields = $fieldLayout->getFields();
658
                    foreach ($fields as $field) {
659
                        /** @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
The close comment tag must be the only content on the line
Loading history...
Coding Style introduced by
Missing short description in doc comment
Loading history...
660
                        if ($thisField->handle === $field->handle) {
661
                            $needToReSave = true;
662
                        }
663
                    }
664
                    if ($needToReSave) {
665
                        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

665
                        ImageOptimize::$plugin->optimizedImages->resaveVolumeAssets($volume, /** @scrutinizer ignore-type */ $thisField->id);
Loading history...
666
                    }
667
                }
668
            }
669
        }
670
    }
671
}
672