PluginProbe
Image Optimizer – Compress Images and Convert to WebP or AVIF / trunk
Image Optimizer – Compress Images and Convert to WebP or AVIF vtrunk
1.7.7 1.7.6 1.7.5 1.7.4 trunk 1.0.0 1.0.1 1.0.2 1.1.0 1.2.0 1.2.1 1.3.0 1.4.0 1.4.1 1.5.0 1.5.1 1.5.2 1.5.3 1.5.4 1.6.0 1.6.1 1.6.2 1.6.3 1.6.4 1.6.5 All 33 releases
← All changes | modules/core/module.php +225 -17 1.5.2 → trunk View file →
@@ -1,21 +1,32 @@
1 1 <?php
2 2 namespace ImageOptimization\Modules\Core;
3 3
4 4 use ImageOptimization\Modules\Optimization\{
5 + Classes\Validate_Image,
5 6 Rest\Cancel_Bulk_Optimization,
6 7 Rest\Optimize_Bulk,
7 8 };
9 +use ImageOptimization\Modules\Settings\Classes\Settings;
8 10 use ImageOptimization\Modules\Backups\Rest\{
9 11 Restore_All,
10 12 Remove_Backups,
11 13 };
12 14 use ImageOptimization\Classes\{
15 + Async_Operation\Async_Operation,
16 + Async_Operation\Async_Operation_Queue,
17 + Async_Operation\Queries\Operation_Query,
18 + Image\Image_Meta,
19 + Image\Image_Optimization_Error_Type,
20 + Image\Image_Status,
13 21 Migration\Migration_Manager,
14 22 Module_Base,
15 - Utils
23 + Utils,
16 24 };
17 25
26 +use ImageOptimization\Modules\Connect\Module as Connect_Module;
27 +use ImageOptimization\Modules\Connect\Classes\Config;
28 +
18 29 use ImageOptimization\Plugin;
19 30
20 31 if ( ! defined( 'ABSPATH' ) ) {
21 32 exit; // Exit if accessed directly.
@@ -21,13 +32,16 @@
21 32 exit; // Exit if accessed directly.
22 33 }
23 34
24 35 class Module extends Module_Base {
36 +
37 + const ONE_MISMATCH_URL = '/wp-admin/admin.php?page=elementor-home#/home/url-mismatch';
38 +
25 39 public function get_name(): string {
26 40 return 'core';
27 41 }
28 42
29 - public static function component_list() : array {
43 + public static function component_list(): array {
30 44 return [
31 45 'Pointers',
32 46 'Migrations',
33 47 'Conflicts',
@@ -32,8 +46,11 @@
32 46 'Migrations',
33 47 'Conflicts',
34 48 'User_Feedback',
35 49 'Not_Connected',
50 + 'Not_Connected_Modal',
51 + 'Renewal_Notice',
52 + 'Notificator',
36 53 ];
37 54 }
38 55
39 56 private function render_top_bar() {
@@ -52,8 +69,9 @@
52 69 public function maybe_add_quota_reached_notice() {
53 70
54 71 // @var ImageOptimizer/Modules/ConnectManager/Module
55 72 $module = Plugin::instance()->modules_manager->get_modules( 'connect-manager' );
73 + $upgrade_link = Utils::get_upgrade_link( 'https://go.elementor.com/io-quota-upgrade/' );
56 74
57 75 if ( ! $module->connect_instance->get_connect_status() || $module->connect_instance->images_left() > 0 ) {
58 76 return;
59 77 }
@@ -73,9 +91,9 @@
73 91 'You have no images left to optimize in your current plan.',
74 92 'image-optimization'
75 93 ); ?>
76 94
77 - <a href="https://go.elementor.com/io-quota-upgrade/">
95 + <a href="<?php echo esc_url( $upgrade_link ); ?>">
78 96 <?php esc_html_e(
79 97 'Upgrade plan now',
80 98 'image-optimization'
81 99 ); ?>
@@ -85,8 +103,54 @@
85 103 </div>
86 104 <?php
87 105 }
88 106
107 + public function maybe_add_80_quota_reached_notice() {
108 + // @var ImageOptimizer/Modules/ConnectManager/Module
109 + $module = Plugin::instance()->modules_manager->get_modules( 'connect-manager' );
110 +
111 + $connect_status = $module->connect_instance->get_connect_status();
112 +
113 + if ( ! isset( $connect_status->quota ) || ! isset( $connect_status->used_quota ) ) {
114 + return;
115 + }
116 +
117 + $usage = $connect_status->used_quota / $connect_status->quota * 100;
118 +
119 + if ( $usage < 80 || 100 === $usage ) {
120 + return;
121 + }
122 +
123 + $upgrade_link = Utils::get_upgrade_link( 'https://go.elementor.com/io-quota-upgrade/' );
124 +
125 + ?>
126 + <div class="notice notice-warning notice image-optimizer__notice image-optimizer__notice--warning">
127 + <p>
128 + <b>
129 + <?php esc_html_e(
130 + 'You’ve used 80% of your plan quota.',
131 + 'image-optimization'
132 + ); ?>
133 + </b>
134 +
135 + <span>
136 + <?php esc_html_e(
137 + 'Upgrade now to avoid interruptions.',
138 + 'image-optimization'
139 + ); ?>
140 +
141 + <a href="<?php echo esc_url( $upgrade_link ); ?>">
142 + <?php esc_html_e(
143 + 'Upgrade plan now',
144 + 'image-optimization'
145 + ); ?>
146 + </a>
147 + </span>
148 + </p>
149 + </div>
150 + <?php
151 + }
152 +
89 153 public function maybe_add_url_mismatch_notice() {
90 154 // @var ImageOptimizer/Modules/ConnectManager/Module
91 155 $module = Plugin::instance()->modules_manager->get_modules( 'connect-manager' );
92 156
@@ -93,8 +157,10 @@
93 157 if ( $module->connect_instance->is_valid_home_url() ) {
94 158 return;
95 159 }
96 160
161 + $onclick = self::is_elementor_one() ? 'window.location.href = "' . self::ONE_MISMATCH_URL . '";' : 'document.dispatchEvent( new Event( "image-optimizer/auth/url-mismatch-modal/open" ) );';
162 +
97 163 ?>
98 164 <div class="notice notice-error notice image-optimizer__notice image-optimizer__notice--error">
99 165 <p>
100 166 <b>
@@ -109,9 +175,9 @@
109 175 'This is most likely due to a change in the domain URL of your site (including HTTP/SSL migration).',
110 176 'image-optimization'
111 177 ); ?>
112 178
113 - <button type="button" onclick="document.dispatchEvent( new Event( 'image-optimizer/auth/url-mismatch-modal/open' ) );">
179 + <button type="button" onclick="<?php echo esc_js( $onclick ); ?>">
114 180 <?php esc_html_e(
115 181 'Fix mismatched URL',
116 182 'image-optimization'
117 183 ); ?>
@@ -121,11 +187,15 @@
121 187 </div>
122 188 <?php
123 189 }
124 190
125 - public function add_plugin_links( $links, $plugin_file_name ): array {
191 + public function add_plugin_links( $links, $plugin_file_name ) {
192 + if ( ! is_array( $links ) ) {
193 + return $links;
194 + }
195 +
126 196 if ( ! str_ends_with( $plugin_file_name, '/image-optimization.php' ) ) {
127 - return (array) $links;
197 + return $links;
128 198 }
129 199
130 200 $custom_links = [
131 201 'settings' => sprintf(
@@ -136,17 +206,18 @@
136 206 ];
137 207 // @var ImageOptimizer/Modules/ConnectManager/Module
138 208 $module = Plugin::instance()->modules_manager->get_modules( 'connect-manager' );
139 209
140 - if ( $module->connect_instance->is_connected() ) {
210 + if ( $module->connect_instance->is_connected() && ! self::is_elementor_one() ) {
141 211 $custom_links['upgrade'] = sprintf(
142 - '<a href="%s" style="color: #524CFF; font-weight: 700;" target="_blank" rel="noopener noreferrer">%s</a>',
143 - 'https://go.elementor.com/io-plugins-upgrade/',
212 + '<a href="%s" style="color: #524cff; font-weight: 700;" target="_blank" rel="noopener noreferrer">%s</a>',
213 + Utils::get_upgrade_link( 'https://go.elementor.com/io-plugins-upgrade/' ),
144 214 esc_html__( 'Upgrade', 'image-optimization' )
145 215 );
146 - } else {
216 + }
217 + if ( ! $module->connect_instance->is_connected() ) {
147 218 $custom_links['connect'] = sprintf(
148 - '<a href="%s" style="color: #524CFF; font-weight: 700;">%s</a>',
219 + '<a href="%s" style="color: #524cff; font-weight: 700;">%s</a>',
149 220 admin_url( 'admin.php?page=' . \ImageOptimization\Modules\Settings\Module::SETTING_BASE_SLUG ),
150 221 esc_html__( 'Connect', 'image-optimization' )
151 222 );
152 223 }
@@ -194,8 +265,10 @@
194 265 [
195 266 'siteUrl' => wp_parse_url( get_site_url(), PHP_URL_HOST ),
196 267 'thumbnailSizes' => wp_get_registered_image_subsizes(),
197 268 'isDevelopment' => defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG,
269 + 'isRTL' => is_rtl(),
270 + 'version' => IMAGE_OPTIMIZATION_VERSION,
198 271 ]
199 272 );
200 273
201 274 /**
@@ -201,17 +274,22 @@
201 274 /**
202 275 * @var ImageOptimizer\Modules\ConnectManager\Module $module
203 276 */
204 277 $module = Plugin::instance()->modules_manager->get_modules( 'connect-manager' );
205 - $is_connect_on_fly = $module->connect_instance->get_is_connect_on_fly();
206 278 $connect_email = $module->connect_instance->get_connect_data()['user']['email'] ?? null;
279 + $show_reset = ! $module->connect_instance->is_connected()
280 + && ( $module->connect_instance->get_client_id() || $module->connect_instance->get_client_secret() );
207 281
208 282 wp_localize_script(
209 283 'image-optimization-admin',
210 284 'imageOptimizerUserData',
211 285 [
212 - 'isConnectOnFly' => $is_connect_on_fly,
286 + 'isConnectOnFly' => self::is_connect_on_fly(),
213 287 'isConnected' => $module->connect_instance->is_connected(),
288 + 'isElementorOne' => self::is_elementor_one(),
289 + 'hasElementorOneSubscription' => self::has_elementor_one_subscription(),
290 + 'isMigrationPopupDismissed' => (bool) Settings::get( Settings::MIGRATION_POPUP_DISMISSED ),
291 + 'currentPage' => get_current_screen()->base,
214 292 'isActivated' => $module->connect_instance->is_activated(),
215 293 'isUrlMismatch' => ! $module->connect_instance->is_valid_home_url(),
216 294 'planData' => $module->connect_instance->is_activated() ? $module->connect_instance->get_connect_status() : null,
217 295 'licenseKey' => $module->connect_instance->is_activated() ? $module->connect_instance->get_activation_state() : null,
@@ -217,8 +295,11 @@
217 295 'licenseKey' => $module->connect_instance->is_activated() ? $module->connect_instance->get_activation_state() : null,
218 296 'imagesLeft' => $module->connect_instance->is_activated() ? $module->connect_instance->images_left() : null,
219 297 'isOwner' => $module->connect_instance->is_connected() ? $module->connect_instance->user_is_subscription_owner() : null,
220 298 'subscriptionEmail' => $connect_email ? $connect_email : null,
299 + 'showResetButton' => $show_reset,
300 + 'maxFileSize' => Validate_Image::get_max_file_size(),
301 + 'helpVideos' => Settings::get( Settings::HELP_VIDEOS ),
221 302
222 303 'wpRestNonce' => wp_create_nonce( 'wp_rest' ),
223 304 'disconnect' => wp_create_nonce( 'wp_rest' ),
224 305 'authInitNonce' => wp_create_nonce( $module->connect_instance->connect_init_nonce() ),
@@ -240,9 +321,131 @@
240 321 private function should_render(): bool {
241 322 return ( Utils::is_media_page() || Utils::is_plugin_page() ) && Utils::user_is_admin();
242 323 }
243 324
325 + private static function is_connect_on_fly(): bool {
326 + /**
327 + * @var ImageOptimizer\Modules\ConnectManager\Module $module
328 + */
329 + $module = Plugin::instance()->modules_manager->get_modules( 'connect-manager' );
330 + return $module->connect_instance->get_is_connect_on_fly();
331 + }
332 +
333 + public static function is_elementor_one(): bool {
334 +
335 + if ( ! self::is_connect_on_fly() ) {
336 + return false;
337 + }
338 +
339 + $connect = Connect_Module::get_connect();
340 +
341 + if ( ! $connect ) {
342 + return false;
343 + }
344 +
345 + return Connect_Module::get_connect()->get_config( 'app_type' ) !== Config::APP_TYPE;
346 + }
347 +
244 348 /**
349 + * Check if user generally has an active Elementor One subscription.
350 + * @return bool
351 + */
352 + public static function has_elementor_one_subscription(): bool {
353 + $one_facade = \ElementorOne\Admin\Helpers\Utils::get_one_connect();
354 + return $one_facade && $one_facade->utils()->is_connected();
355 + }
356 +
357 + public static function on_deactivation(): void {
358 + $optimization_query = ( new Operation_Query() )
359 + ->set_queue( Async_Operation_Queue::OPTIMIZE )
360 + ->set_status( [ Async_Operation::OPERATION_STATUS_PENDING, Async_Operation::OPERATION_STATUS_RUNNING ] )
361 + ->set_limit( -1 );
362 +
363 + $restoring_query = ( new Operation_Query() )
364 + ->set_queue( Async_Operation_Queue::RESTORE )
365 + ->set_status( [ Async_Operation::OPERATION_STATUS_PENDING, Async_Operation::OPERATION_STATUS_RUNNING ] )
366 + ->set_limit( -1 );
367 +
368 + $optimization_operations = Async_Operation::get( $optimization_query );
369 + $restoring_operations = Async_Operation::get( $restoring_query );
370 +
371 + foreach ( $optimization_operations as $operation ) {
372 + $image_id = $operation->get_args()['attachment_id'];
373 +
374 + if ( ! $image_id ) {
375 + continue;
376 + }
377 +
378 + Async_Operation::remove( [ $operation->get_id() ] );
379 +
380 + $image_meta = new Image_Meta( $image_id );
381 +
382 + if ( empty( $image_meta->get_optimized_sizes() ) ) {
383 + $image_meta->delete();
384 + } else {
385 + $image_meta
386 + ->set_status( Image_Status::OPTIMIZATION_FAILED )
387 + ->set_error_type( Image_Optimization_Error_Type::PLUGIN_DEACTIVATION )
388 + ->save();
389 + }
390 + }
391 +
392 + foreach ( $restoring_operations as $operation ) {
393 + $image_id = $operation->get_args()['attachment_id'];
394 +
395 + if ( ! $image_id ) {
396 + continue;
397 + }
398 +
399 + Async_Operation::remove( [ $operation->get_id() ] );
400 +
401 + $image_meta = new Image_Meta( $image_id );
402 +
403 + $image_meta
404 + ->set_status( Image_Status::RESTORING_FAILED )
405 + ->set_error_type( Image_Optimization_Error_Type::PLUGIN_DEACTIVATION )
406 + ->save();
407 + }
408 + }
409 +
410 + /**
411 + * Renders the Bulk Optimization link on the media pages.
412 + *
413 + * @return void
414 + */
415 + public function add_bulk_optimization_links(): void {
416 + $page_url = add_query_arg(
417 + [
418 + 'page' => 'image-optimization-settings',
419 + 'tab' => 'image-optimization-bulk-optimization',
420 + ],
421 + admin_url( 'admin.php' )
422 + );
423 +
424 + ?>
425 + <script>
426 + document.addEventListener( 'DOMContentLoaded', function () {
427 + // Grid media is rendered by JS, so the timeout is required
428 + setTimeout( () => {
429 + const targetButton = document.querySelector( '.filter-items .actions input[type=submit]' ) ||
430 + document.querySelector( '.media-toolbar-secondary .select-mode-toggle-button' );
431 +
432 + if ( targetButton ) {
433 + const link = document.createElement('a');
434 +
435 + link.href = '<?php echo esc_js( $page_url ); ?>';
436 + link.innerText = '<?php echo esc_js( __( 'Bulk Optimization', 'image-optimization' ) ); ?>';
437 + link.className = 'button button-compact is-primary image-optimizer__button image-optimizer__button--pink';
438 +
439 + targetButton.insertAdjacentElement( 'afterend', link );
440 + }
441 + }, 100 )
442 + } );
443 + </script>
444 + <?php
445 + }
446 +
447 + /**
245 448 * Module constructor.
246 449 */
247 450 public function __construct() {
248 451 $this->register_components();
@@ -256,15 +459,16 @@
256 459 if ( ! $this->should_render() ) {
257 460 return;
258 461 }
259 462
260 - add_action( 'admin_notices', [ $this, 'maybe_add_quota_reached_notice' ] );
463 + if ( ! self::is_elementor_one() ) {
464 + add_action( 'admin_notices', [ $this, 'maybe_add_quota_reached_notice' ] );
465 + add_action( 'admin_notices', [ $this, 'maybe_add_80_quota_reached_notice' ] );
466 + }
467 +
261 468 add_action( 'admin_notices', [ $this, 'maybe_add_url_mismatch_notice' ] );
262 469
263 470 if ( Utils::is_media_page() ) {
264 - add_action('in_admin_header', function () {
265 - $this->render_top_bar();
266 - });
267 471
268 472 add_action('all_admin_notices', function () {
269 473 $this->render_app();
270 474 });
@@ -278,7 +482,11 @@
278 482
279 483 add_action('admin_enqueue_scripts', function () {
280 484 $this->enqueue_scripts();
281 485 });
486 +
487 + if ( Utils::is_media_page() ) {
488 + add_action( 'admin_enqueue_scripts', [ $this, 'add_bulk_optimization_links' ] );
489 + }
282 490 });
283 491 }
284 492 }