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