Passed
Push — develop ( 264027...658993 )
by Andrew
03:35
created

ImageOptimize::getSettingsResponse()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 13
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 13
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 9
nc 1
nop 0
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
8
 * @copyright Copyright (c) 2017 nystudio107
9
 */
10
11
namespace nystudio107\imageoptimize;
12
13
use nystudio107\imageoptimize\fields\OptimizedImages;
14
use nystudio107\imageoptimize\imagetransforms\ImageTransformInterface;
15
use nystudio107\imageoptimize\models\Settings;
16
use nystudio107\imageoptimize\services\Optimize as OptimizeService;
17
use nystudio107\imageoptimize\services\OptimizedImages as OptimizedImagesService;
18
use nystudio107\imageoptimize\services\Placeholder as PlaceholderService;
19
use nystudio107\imageoptimize\variables\ImageOptimizeVariable;
20
21
use Craft;
22
use craft\base\Element;
23
use craft\base\Field;
24
use craft\base\Plugin;
25
use craft\base\Volume;
26
use craft\console\Application as ConsoleApplication;
27
use craft\elements\Asset;
28
use craft\events\AssetTransformImageEvent;
29
use craft\events\ElementEvent;
30
use craft\events\FieldEvent;
31
use craft\events\GetAssetUrlEvent;
32
use craft\events\GenerateTransformEvent;
33
use craft\events\PluginEvent;
34
use craft\events\RegisterComponentTypesEvent;
35
use craft\events\ReplaceAssetEvent;
36
use craft\events\VolumeEvent;
37
use craft\helpers\UrlHelper;
38
use craft\models\FieldLayout;
39
use craft\services\Assets;
40
use craft\services\AssetTransforms;
41
use craft\services\Elements;
42
use craft\services\Fields;
43
use craft\services\Plugins;
44
use craft\services\Volumes;
45
use craft\web\twig\variables\CraftVariable;
46
use craft\web\Controller;
47
48
use yii\base\Event;
49
50
/** @noinspection MissingPropertyAnnotationsInspection */
51
52
/**
53
 * Class ImageOptimize
54
 *
55
 * @author    nystudio107
56
 * @package   ImageOptimize
57
 * @since     1.0.0
58
 *
59
 * @property OptimizeService        optimize
60
 * @property PlaceholderService     placeholder
61
 * @property OptimizedImagesService optimizedImages
62
 * @property Settings               $settings
63
 * @method   Settings               getSettings()
64
 */
65
class ImageOptimize extends Plugin
66
{
67
    // Static Properties
68
    // =========================================================================
69
70
    /**
71
     * @var ImageOptimize
72
     */
73
    public static $plugin;
74
75
    /**
76
     * @var ImageTransformInterface
77
     */
78
    public static $transformClass;
79
80
    /**
81
     * @var array
82
     */
83
    public static $transformParams;
84
85
    /**
86
     * @var bool
87
     */
88
    public static $generatePlacholders = true;
89
90
    // Public Methods
91
    // =========================================================================
92
93
    /**
94
     * @inheritdoc
95
     */
96
    public function init()
97
    {
98
        parent::init();
99
        self::$plugin = $this;
100
        // Handle any console commands
101
        if (Craft::$app instanceof ConsoleApplication) {
102
            $this->controllerNamespace = 'nystudio107\imageoptimize\console\controllers';
103
        }
104
        // Cache some settings
105
        $settings = $this->getSettings();
106
        self::$transformClass = ImageTransformInterface::IMAGE_TRANSFORM_MAP[$settings->transformMethod];
107
        self::$transformParams = self::$transformClass::getTransformParams();
108
        // Add in our Craft components
109
        $this->addComponents();
110
        // Install our global event handlers
111
        $this->installEventHandlers();
112
        // Log that the plugin has loaded
113
        Craft::info(
114
            Craft::t(
115
                'image-optimize',
116
                '{name} plugin loaded',
117
                ['name' => $this->name]
118
            ),
119
            __METHOD__
120
        );
121
    }
122
123
    /**
124
     * @inheritdoc
125
     */
126
    public function getSettingsResponse()
127
    {
128
        $view = Craft::$app->getView();
129
        $namespace = $view->getNamespace();
130
        $view->setNamespace('settings');
131
        $settingsHtml = $this->settingsHtml();
132
        $view->setNamespace($namespace);
133
        /** @var Controller $controller */
134
        $controller = Craft::$app->controller;
135
136
        return $controller->renderTemplate('image-optimize/_settings', [
137
            'plugin'       => $this,
138
            'settingsHtml' => $settingsHtml,
139
        ]);
140
    }
141
142
    /**
143
     * @inheritdoc
144
     */
145
    public function settingsHtml()
146
    {
147
        $imageProcessors = ImageOptimize::$plugin->optimize->getActiveImageProcessors();
148
        $variantCreators = ImageOptimize::$plugin->optimize->getActiveVariantCreators();
149
        // Get only the user-editable settings
150
        $settings = $this->getSettings();
151
152
        // Render the settings template
153
        return Craft::$app->getView()->renderTemplate(
154
            'image-optimize/settings',
155
            [
156
                'settings'        => $settings,
157
                'imageProcessors' => $imageProcessors,
158
                'variantCreators' => $variantCreators,
159
                'gdInstalled'     => function_exists('imagecreatefromjpeg'),
160
            ]
161
        );
162
    }
163
164
    // Protected Methods
165
    // =========================================================================
166
167
    /**
168
     * @inheritdoc
169
     */
170
    protected function createSettingsModel()
171
    {
172
        return new Settings();
173
    }
174
175
    /**
176
     * Add in our Craft components
177
     */
178
    protected function addComponents()
179
    {
180
        // Register our variables
181
        Event::on(
182
            CraftVariable::class,
183
            CraftVariable::EVENT_INIT,
184
            function (Event $event) {
185
                /** @var CraftVariable $variable */
186
                $variable = $event->sender;
187
                $variable->set('imageOptimize', ImageOptimizeVariable::class);
188
            }
189
        );
190
191
        // Register our Field
192
        Event::on(
193
            Fields::class,
194
            Fields::EVENT_REGISTER_FIELD_TYPES,
195
            function (RegisterComponentTypesEvent $event) {
196
                Craft::debug(
197
                    'Fields::EVENT_REGISTER_FIELD_TYPES',
198
                    __METHOD__
199
                );
200
                $event->types[] = OptimizedImages::class;
201
            }
202
        );
203
    }
204
205
    /**
206
     * Install our event handlers
207
     */
208
    protected function installEventHandlers()
209
    {
210
        $this->installAssetEventHandlers();
211
        $this->installElementEventHandlers();
212
        $this->installMiscEventHandlers();
213
    }
214
215
    /**
216
     * Install our miscellaneous event handlers
217
     */
218
    protected function installMiscEventHandlers()
219
    {
220
        // Handler: Fields::EVENT_AFTER_SAVE_FIELD
221
        Event::on(
222
            Fields::class,
223
            Fields::EVENT_AFTER_SAVE_FIELD,
224
            function (FieldEvent $event) {
225
                Craft::debug(
226
                    'Fields::EVENT_AFTER_SAVE_FIELD',
227
                    __METHOD__
228
                );
229
                $settings = $this->getSettings();
230
                /** @var Field $field */
231
                if (!$event->isNew && $settings->automaticallyResaveImageVariants) {
232
                    $thisField = $event->field;
233
                    if ($thisField instanceof OptimizedImages) {
234
                        $volumes = Craft::$app->getVolumes()->getAllVolumes();
235
                        foreach ($volumes as $volume) {
236
                            $needToReSave = false;
237
                            /** @var FieldLayout $fieldLayout */
238
                            /** @var Volume $volume */
239
                            $fieldLayout = $volume->getFieldLayout();
240
                            // Loop through the fields in the layout to see if it contains our field
241
                            if ($fieldLayout) {
242
                                $fields = $fieldLayout->getFields();
243
                                foreach ($fields as $field) {
244
                                    if ($thisField->handle == $field->handle) {
245
                                        $needToReSave = true;
246
                                    }
247
                                }
248
                                if ($needToReSave) {
249
                                    ImageOptimize::$plugin->optimizedImages->resaveVolumeAssets($volume);
250
                                }
251
                            }
252
                        }
253
                    }
254
                }
255
            }
256
        );
257
258
        // Handler: Plugins::EVENT_AFTER_SAVE_PLUGIN_SETTINGS
259
        Event::on(
260
            Plugins::class,
261
            Plugins::EVENT_AFTER_SAVE_PLUGIN_SETTINGS,
262
            function (PluginEvent $event) {
263
                if ($event->plugin === $this) {
264
                    Craft::debug(
265
                        'Plugins::EVENT_AFTER_SAVE_PLUGIN_SETTINGS',
266
                        __METHOD__
267
                    );
268
                    $settings = $this->getSettings();
269
                    if ($settings->automaticallyResaveImageVariants) {
270
                        // After they have changed the settings, resave all of the assets
271
                        ImageOptimize::$plugin->optimizedImages->resaveAllVolumesAssets();
272
                    }
273
                }
274
            }
275
        );
276
277
        // Handler: Volumes::EVENT_AFTER_SAVE_VOLUME
278
        Event::on(
279
            Volumes::class,
280
            Volumes::EVENT_AFTER_SAVE_VOLUME,
281
            function (VolumeEvent $event) {
282
                Craft::debug(
283
                    'Volumes::EVENT_AFTER_SAVE_VOLUME',
284
                    __METHOD__
285
                );
286
                $settings = $this->getSettings();
287
                // Only worry about this volume if it's not new
288
                if (!$event->isNew && $settings->automaticallyResaveImageVariants) {
289
                    /** @var Volume $volume */
290
                    $volume = $event->volume;
291
                    if (is_subclass_of($volume, Volume::class)) {
292
                        ImageOptimize::$plugin->optimizedImages->resaveVolumeAssets($volume);
293
                    }
294
                }
295
            }
296
        );
297
298
        // Do something after we're installed
299
        Event::on(
300
            Plugins::class,
301
            Plugins::EVENT_AFTER_INSTALL_PLUGIN,
302
            function (PluginEvent $event) {
303
                if ($event->plugin === $this) {
304
                    $request = Craft::$app->getRequest();
305
                    if (($request->isCpRequest) && (!$request->isConsoleRequest)) {
306
                        Craft::$app->getResponse()->redirect(UrlHelper::cpUrl('image-optimize/welcome'))->send();
307
                    }
308
                }
309
            }
310
        );
311
    }
312
313
    /**
314
     * Install our Asset event handlers
315
     */
316
    protected function installAssetEventHandlers()
317
    {
318
319
        // Handler: Assets::EVENT_GET_ASSET_URL
320
        Event::on(
321
            Assets::class,
322
            Assets::EVENT_GET_ASSET_URL,
323
            function (GetAssetUrlEvent $event) {
324
                Craft::debug(
325
                    'Assets::EVENT_GET_ASSET_URL',
326
                    __METHOD__
327
                );
328
                // Return the URL to the asset URL or null to let Craft handle it
329
                $event->url = ImageOptimize::$plugin->optimize->handleGetAssetUrlEvent(
330
                    $event
331
                );
332
            }
333
        );
334
335
        // Handler: AssetTransforms::EVENT_GENERATE_TRANSFORM
336
        Event::on(
337
            AssetTransforms::class,
338
            AssetTransforms::EVENT_GENERATE_TRANSFORM,
339
            function (GenerateTransformEvent $event) {
340
                Craft::debug(
341
                    'AssetTransforms::EVENT_GENERATE_TRANSFORM',
342
                    __METHOD__
343
                );
344
                // Return the path to the optimized image to _createTransformForAsset()
345
                $event->tempPath = ImageOptimize::$plugin->optimize->handleGenerateTransformEvent(
346
                    $event
347
                );
348
            }
349
        );
350
351
        // Handler: AssetTransforms::EVENT_AFTER_DELETE_TRANSFORMS
352
        Event::on(
353
            AssetTransforms::class,
354
            AssetTransforms::EVENT_AFTER_DELETE_TRANSFORMS,
355
            function (AssetTransformImageEvent $event) {
356
                Craft::debug(
357
                    'AssetTransforms::EVENT_AFTER_DELETE_TRANSFORMS',
358
                    __METHOD__
359
                );
360
                // Clean up any stray variant files
361
                ImageOptimize::$plugin->optimize->handleAfterDeleteTransformsEvent(
362
                    $event
363
                );
364
            }
365
        );
366
367
        // Handler: Assets::EVENT_BEFORE_REPLACE_ASSET
368
        Event::on(
369
            Assets::class,
370
            Assets::EVENT_BEFORE_REPLACE_ASSET,
371
            function (ReplaceAssetEvent $event) {
372
                Craft::debug(
373
                    'Assets::EVENT_BEFORE_REPLACE_ASSET',
374
                    __METHOD__
375
                );
376
                /** @var Asset $element */
377
                $element = $event->asset;
378
                // Purge the URL
379
                $purgeUrl = ImageOptimize::$transformClass::getPurgeUrl(
380
                    $element,
381
                    ImageOptimize::$transformParams
382
                );
383
                if ($purgeUrl) {
384
                    ImageOptimize::$transformClass::purgeUrl($purgeUrl, ImageOptimize::$transformParams);
385
                }
386
            }
387
        );
388
389
        // Handler: Assets::EVENT_AFTER_REPLACE_ASSET
390
        Event::on(
391
            Assets::class,
392
            Assets::EVENT_AFTER_REPLACE_ASSET,
393
            function (ReplaceAssetEvent $event) {
394
                Craft::debug(
395
                    'Assets::EVENT_AFTER_REPLACE_ASSET',
396
                    __METHOD__
397
                );
398
                /** @var Asset $element */
399
                $element = $event->asset;
400
                if (!empty($element->id)) {
401
                    ImageOptimize::$plugin->optimizedImages->resaveAsset($element->id);
402
                }
403
            }
404
        );
405
    }
406
407
    /**
408
     * Install our Element event handlers
409
     */
410
    protected function installElementEventHandlers()
411
    {
412
        // Handler: Elements::EVENT_BEFORE_SAVE_ELEMENT
413
        Event::on(
414
            Assets::class,
415
            Elements::EVENT_BEFORE_SAVE_ELEMENT,
416
            function (ElementEvent $event) {
417
                Craft::debug(
418
                    'Elements::EVENT_BEFORE_SAVE_ELEMENT',
419
                    __METHOD__
420
                );
421
                /** @var Asset $asset */
422
                $asset = $event->element;
423
                if (!$event->isNew) {
424
                    // Purge the URL
425
                    $purgeUrl = ImageOptimize::$transformClass::getPurgeUrl(
426
                        $asset,
427
                        ImageOptimize::$transformParams
428
                    );
429
                    if ($purgeUrl) {
430
                        ImageOptimize::$transformClass::purgeUrl($purgeUrl, ImageOptimize::$transformParams);
431
                    }
432
                }
433
            }
434
        );
435
436
        // Handler: Elements::EVENT_BEFORE_DELETE_ELEMENT
437
        Event::on(
438
            Asset::class,
439
            Elements::EVENT_BEFORE_DELETE_ELEMENT,
440
            function (ElementEvent $event) {
441
                Craft::debug(
442
                    'Elements::EVENT_BEFORE_DELETE_ELEMENT',
443
                    __METHOD__
444
                );
445
                /** @var Asset $asset */
446
                $asset = $event->element;
447
                // Purge the URL
448
                $purgeUrl = ImageOptimize::$transformClass::getPurgeUrl(
449
                    $asset,
450
                    ImageOptimize::$transformParams
451
                );
452
                if ($purgeUrl) {
453
                    ImageOptimize::$transformClass::purgeUrl($purgeUrl, ImageOptimize::$transformParams);
454
                }
455
            }
456
        );
457
    }
458
}
459