PluginProbe
Image Optimizer – Compress Images and Convert to WebP or AVIF / 1.7.7
Image Optimizer – Compress Images and Convert to WebP or AVIF v1.7.7
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 +301 -62 1.1.01.7.7 View file →
@@ -1,42 +1,56 @@
1 1 <?php
2 2 namespace ImageOptimization\Modules\Core;
3 3
4 -use ImageOptimization\Modules\Oauth\{
5 - Classes\Data,
6 - Components\Connect,
7 - Rest\Activate,
8 - Rest\Connect_Init,
9 - Rest\Deactivate,
10 - Rest\Disconnect,
11 - Rest\Get_Subscriptions,
12 -};
13 4 use ImageOptimization\Modules\Optimization\{
5 + Classes\Validate_Image,
14 6 Rest\Cancel_Bulk_Optimization,
15 7 Rest\Optimize_Bulk,
16 8 };
9 +use ImageOptimization\Modules\Settings\Classes\Settings;
17 10 use ImageOptimization\Modules\Backups\Rest\{
18 11 Restore_All,
19 12 Remove_Backups,
20 13 };
21 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,
21 + Migration\Migration_Manager,
22 22 Module_Base,
23 23 Utils,
24 24 };
25 25
26 +use ImageOptimization\Modules\Connect\Module as Connect_Module;
27 +use ImageOptimization\Modules\Connect\Classes\Config;
28 +
29 +use ImageOptimization\Plugin;
30 +
26 31 if ( ! defined( 'ABSPATH' ) ) {
27 32 exit; // Exit if accessed directly.
28 33 }
29 34
30 35 class Module extends Module_Base {
36 +
37 + const ONE_MISMATCH_URL = '/wp-admin/admin.php?page=elementor-home#/home/url-mismatch';
38 +
31 39 public function get_name(): string {
32 40 return 'core';
33 41 }
34 42
35 - public static function component_list() : array {
43 + public static function component_list(): array {
36 44 return [
37 45 'Pointers',
46 + 'Migrations',
38 47 'Conflicts',
48 + 'User_Feedback',
49 + 'Not_Connected',
50 + 'Not_Connected_Modal',
51 + 'Renewal_Notice',
52 + 'Notificator',
39 53 ];
40 54 }
41 55
42 56 private function render_top_bar() {
@@ -52,9 +66,14 @@
52 66 <?php
53 67 }
54 68
55 69 public function maybe_add_quota_reached_notice() {
56 - if ( ! Connect::is_activated() || Data::images_left() > 0 ) {
70 +
71 + // @var ImageOptimizer/Modules/ConnectManager/Module
72 + $module = Plugin::instance()->modules_manager->get_modules( 'connect-manager' );
73 + $upgrade_link = Utils::get_upgrade_link( 'https://go.elementor.com/io-quota-upgrade/' );
74 +
75 + if ( ! $module->connect_instance->get_connect_status() || $module->connect_instance->images_left() > 0 ) {
57 76 return;
58 77 }
59 78
60 79 ?>
@@ -72,9 +91,9 @@
72 91 'You have no images left to optimize in your current plan.',
73 92 'image-optimization'
74 93 ); ?>
75 94
76 - <a href="https://go.elementor.com/io-panel-upgrade/">
95 + <a href="<?php echo esc_url( $upgrade_link ); ?>">
77 96 <?php esc_html_e(
78 97 'Upgrade plan now',
79 98 'image-optimization'
80 99 ); ?>
@@ -84,13 +103,101 @@
84 103 </div>
85 104 <?php
86 105 }
87 106
88 - public function add_plugin_links( $links, $plugin_file_name ): array {
89 - if ( false === strpos( $plugin_file_name, '/image-optimization.php' ) ) {
90 - return (array) $links;
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;
91 115 }
92 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 +
153 + public function maybe_add_url_mismatch_notice() {
154 + // @var ImageOptimizer/Modules/ConnectManager/Module
155 + $module = Plugin::instance()->modules_manager->get_modules( 'connect-manager' );
156 +
157 + if ( $module->connect_instance->is_valid_home_url() ) {
158 + return;
159 + }
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 +
163 + ?>
164 + <div class="notice notice-error notice image-optimizer__notice image-optimizer__notice--error">
165 + <p>
166 + <b>
167 + <?php esc_html_e(
168 + 'Your license key does not match your current domain, causing a mismatch.',
169 + 'image-optimization'
170 + ); ?>
171 + </b>
172 +
173 + <span>
174 + <?php esc_html_e(
175 + 'This is most likely due to a change in the domain URL of your site (including HTTP/SSL migration).',
176 + 'image-optimization'
177 + ); ?>
178 +
179 + <button type="button" onclick="<?php echo esc_js( $onclick ); ?>">
180 + <?php esc_html_e(
181 + 'Fix mismatched URL',
182 + 'image-optimization'
183 + ); ?>
184 + </button>
185 + </span>
186 + </p>
187 + </div>
188 + <?php
189 + }
190 +
191 + public function add_plugin_links( $links, $plugin_file_name ) {
192 + if ( ! is_array( $links ) ) {
193 + return $links;
194 + }
195 +
196 + if ( ! str_ends_with( $plugin_file_name, '/image-optimization.php' ) ) {
197 + return $links;
198 + }
199 +
93 200 $custom_links = [
94 201 'settings' => sprintf(
95 202 '<a href="%s">%s</a>',
96 203 admin_url( 'admin.php?page=' . \ImageOptimization\Modules\Settings\Module::SETTING_BASE_SLUG ),
@@ -96,42 +203,26 @@
96 203 admin_url( 'admin.php?page=' . \ImageOptimization\Modules\Settings\Module::SETTING_BASE_SLUG ),
97 204 esc_html__( 'Settings', 'image-optimization' )
98 205 ),
99 206 ];
207 + // @var ImageOptimizer/Modules/ConnectManager/Module
208 + $module = Plugin::instance()->modules_manager->get_modules( 'connect-manager' );
100 209
101 - if ( ! Connect::is_connected() ) {
102 - $custom_links['connect'] = sprintf(
103 - '<a href="%s" style="color: #524CFF; font-weight: 700;">%s</a>',
104 - admin_url( 'admin.php?page=' . \ImageOptimization\Modules\Settings\Module::SETTING_BASE_SLUG . '&action=connect' ),
105 - esc_html__( 'Connect', 'image-optimization' )
210 + if ( $module->connect_instance->is_connected() && ! self::is_elementor_one() ) {
211 + $custom_links['upgrade'] = sprintf(
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/' ),
214 + esc_html__( 'Upgrade', 'image-optimization' )
106 215 );
107 216 }
108 -
109 - if ( Connect::is_connected() && ! Connect::is_activated() ) {
110 - $custom_links['activate'] = sprintf(
111 - '<a href="%s" style="color: #524CFF; font-weight: 700;">%s</a>',
217 + if ( ! $module->connect_instance->is_connected() ) {
218 + $custom_links['connect'] = sprintf(
219 + '<a href="%s" style="color: #524cff; font-weight: 700;">%s</a>',
112 220 admin_url( 'admin.php?page=' . \ImageOptimization\Modules\Settings\Module::SETTING_BASE_SLUG ),
113 - esc_html__( 'Activate', 'image-optimization' )
221 + esc_html__( 'Connect', 'image-optimization' )
114 222 );
115 223 }
116 224
117 - if ( Connect::is_connected() && Connect::is_activated() ) {
118 - $plan_data = Connect::check_connect_status();
119 - $usage_percentage = 0;
120 -
121 - if ( ! empty( $plan_data ) ) {
122 - $usage_percentage = $plan_data->used_quota / $plan_data->quota * 100;
123 - }
124 -
125 - if ( $usage_percentage >= 80 ) {
126 - $custom_links['upgrade'] = sprintf(
127 - '<a href="%s" style="color: #524CFF; font-weight: 700;">%s</a>',
128 - 'https://go.elementor.com/io-panel-upgrade/',
129 - esc_html__( 'Upgrade', 'image-optimization' )
130 - );
131 - }
132 - }
133 -
134 225 return array_merge( $custom_links, $links );
135 226 }
136 227
137 228 public function enqueue_global_assets() {
@@ -143,9 +234,9 @@
143 234 );
144 235
145 236 wp_enqueue_style(
146 237 'image-optimization-core-style-admin',
147 - $this->get_css_assets_url( 'style-admin', '/assets/build/' ),
238 + $this->get_css_assets_url( 'style-admin', 'assets/build/' ),
148 239 [],
149 240 IMAGE_OPTIMIZATION_VERSION,
150 241 );
151 242 }
@@ -153,9 +244,9 @@
153 244 /**
154 245 * Enqueue styles and scripts
155 246 */
156 247 private function enqueue_scripts() {
157 - $asset_file = include IMAGE_OPTIMIZATION_ASSETS_PATH . 'build/admin.asset.php';
248 + $asset_file = require IMAGE_OPTIMIZATION_ASSETS_PATH . 'build/admin.asset.php';
158 249
159 250 foreach ( $asset_file['dependencies'] as $style ) {
160 251 wp_enqueue_style( $style );
161 252 }
@@ -163,9 +254,9 @@
163 254 wp_enqueue_script(
164 255 'image-optimization-admin',
165 256 $this->get_js_assets_url( 'admin' ),
166 257 array_merge( $asset_file['dependencies'], [ 'wp-util' ] ),
167 - IMAGE_OPTIMIZATION_VERSION,
258 + $asset_file['version'],
168 259 true
169 260 );
170 261
171 262 wp_localize_script(
@@ -174,32 +265,50 @@
174 265 [
175 266 'siteUrl' => wp_parse_url( get_site_url(), PHP_URL_HOST ),
176 267 'thumbnailSizes' => wp_get_registered_image_subsizes(),
177 268 'isDevelopment' => defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG,
269 + 'isRTL' => is_rtl(),
270 + 'version' => IMAGE_OPTIMIZATION_VERSION,
178 271 ]
179 272 );
180 273
181 - $connect_data = Data::get_connect_data();
274 + /**
275 + * @var ImageOptimizer\Modules\ConnectManager\Module $module
276 + */
277 + $module = Plugin::instance()->modules_manager->get_modules( 'connect-manager' );
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() );
182 281
183 282 wp_localize_script(
184 283 'image-optimization-admin',
185 284 'imageOptimizerUserData',
186 285 [
187 - 'isConnected' => Connect::is_connected(),
188 - 'isActivated' => Connect::is_activated(),
189 - 'planData' => Connect::is_activated() ? Connect::check_connect_status() : null,
190 - 'licenseKey' => Connect::is_activated() ? Data::get_activation_state() : null,
191 - 'imagesLeft' => Connect::is_activated() ? Data::images_left() : null,
192 - 'isOwner' => Connect::is_connected() ? Data::user_is_subscription_owner() : null,
193 - 'subscriptionEmail' => $connect_data['user']['email'] ?? null,
286 + 'isConnectOnFly' => self::is_connect_on_fly(),
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,
292 + 'isActivated' => $module->connect_instance->is_activated(),
293 + 'isUrlMismatch' => ! $module->connect_instance->is_valid_home_url(),
294 + 'planData' => $module->connect_instance->is_activated() ? $module->connect_instance->get_connect_status() : null,
295 + 'licenseKey' => $module->connect_instance->is_activated() ? $module->connect_instance->get_activation_state() : null,
296 + 'imagesLeft' => $module->connect_instance->is_activated() ? $module->connect_instance->images_left() : null,
297 + 'isOwner' => $module->connect_instance->is_connected() ? $module->connect_instance->user_is_subscription_owner() : null,
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 ),
194 302
195 303 'wpRestNonce' => wp_create_nonce( 'wp_rest' ),
196 304 'disconnect' => wp_create_nonce( 'wp_rest' ),
197 - 'authInitNonce' => wp_create_nonce( Connect_Init::NONCE_NAME ),
198 - 'authDisconnectNonce' => wp_create_nonce( Disconnect::NONCE_NAME ),
199 - 'authDeactivateNonce' => wp_create_nonce( Deactivate::NONCE_NAME ),
200 - 'authGetSubscriptionsNonce' => wp_create_nonce( Get_Subscriptions::NONCE_NAME ),
201 - 'authActivateNonce' => wp_create_nonce( Activate::NONCE_NAME ),
305 + 'authInitNonce' => wp_create_nonce( $module->connect_instance->connect_init_nonce() ),
306 + 'authDisconnectNonce' => wp_create_nonce( $module->connect_instance->disconnect_nonce() ),
307 + 'authDeactivateNonce' => wp_create_nonce( $module->connect_instance->deactivate_nonce() ),
308 + 'authGetSubscriptionsNonce' => wp_create_nonce( $module->connect_instance->get_subscriptions_nonce() ),
309 + 'authActivateNonce' => wp_create_nonce( $module->connect_instance->activate_nonce() ),
310 + 'versionNonce' => wp_create_nonce( $module->connect_instance->version_nonce() ),
202 311 'removeBackupsNonce' => wp_create_nonce( Remove_Backups::NONCE_NAME ),
203 312 'restoreAllImagesNonce' => wp_create_nonce( Restore_All::NONCE_NAME ),
204 313 'optimizeBulkNonce' => wp_create_nonce( Optimize_Bulk::NONCE_NAME ),
205 314 'cancelBulkOptimizationNonce' => wp_create_nonce( Cancel_Bulk_Optimization::NONCE_NAME ),
@@ -212,14 +321,138 @@
212 321 private function should_render(): bool {
213 322 return ( Utils::is_media_page() || Utils::is_plugin_page() ) && Utils::user_is_admin();
214 323 }
215 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 +
216 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 + /**
217 448 * Module constructor.
218 449 */
219 450 public function __construct() {
220 451 $this->register_components();
221 452
453 + add_action( 'action_scheduler_init', [ Migration_Manager::class, 'init' ] );
454 +
222 455 add_action( 'admin_enqueue_scripts', [ $this, 'enqueue_global_assets' ] );
223 456 add_filter( 'plugin_action_links', [ $this, 'add_plugin_links' ], 10, 2 );
224 457
225 458 add_action('current_screen', function () {
@@ -226,14 +459,16 @@
226 459 if ( ! $this->should_render() ) {
227 460 return;
228 461 }
229 462
230 - 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 + }
231 467
468 + add_action( 'admin_notices', [ $this, 'maybe_add_url_mismatch_notice' ] );
469 +
232 470 if ( Utils::is_media_page() ) {
233 - add_action('in_admin_header', function () {
234 - $this->render_top_bar();
235 - });
236 471
237 472 add_action('all_admin_notices', function () {
238 473 $this->render_app();
239 474 });
@@ -247,7 +482,11 @@
247 482
248 483 add_action('admin_enqueue_scripts', function () {
249 484 $this->enqueue_scripts();
250 485 });
486 +
487 + if ( Utils::is_media_page() ) {
488 + add_action( 'admin_enqueue_scripts', [ $this, 'add_bulk_optimization_links' ] );
489 + }
251 490 });
252 491 }
253 492 }