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 +277 -27 1.5.01.7.7 View file →
@@ -1,31 +1,32 @@
1 1 <?php
2 2 namespace ImageOptimization\Modules\Core;
3 3
4 -// TODO: Remove imports that are not used.
5 -use ImageOptimization\Modules\Oauth\{
6 - Classes\Data,
7 - Components\Connect,
8 - Rest\Activate,
9 - Rest\Connect_Init,
10 - Rest\Deactivate,
11 - Rest\Disconnect,
12 - Rest\Get_Subscriptions,
13 -};
14 -
15 4 use ImageOptimization\Modules\Optimization\{
5 + Classes\Validate_Image,
16 6 Rest\Cancel_Bulk_Optimization,
17 7 Rest\Optimize_Bulk,
18 8 };
9 +use ImageOptimization\Modules\Settings\Classes\Settings;
19 10 use ImageOptimization\Modules\Backups\Rest\{
20 11 Restore_All,
21 12 Remove_Backups,
22 13 };
23 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,
24 22 Module_Base,
25 23 Utils,
26 24 };
27 25
26 +use ImageOptimization\Modules\Connect\Module as Connect_Module;
27 +use ImageOptimization\Modules\Connect\Classes\Config;
28 +
28 29 use ImageOptimization\Plugin;
29 30
30 31 if ( ! defined( 'ABSPATH' ) ) {
31 32 exit; // Exit if accessed directly.
@@ -31,18 +32,25 @@
31 32 exit; // Exit if accessed directly.
32 33 }
33 34
34 35 class Module extends Module_Base {
36 +
37 + const ONE_MISMATCH_URL = '/wp-admin/admin.php?page=elementor-home#/home/url-mismatch';
38 +
35 39 public function get_name(): string {
36 40 return 'core';
37 41 }
38 42
39 - public static function component_list() : array {
43 + public static function component_list(): array {
40 44 return [
41 45 'Pointers',
46 + 'Migrations',
42 47 'Conflicts',
43 48 'User_Feedback',
44 49 'Not_Connected',
50 + 'Not_Connected_Modal',
51 + 'Renewal_Notice',
52 + 'Notificator',
45 53 ];
46 54 }
47 55
48 56 private function render_top_bar() {
@@ -61,10 +69,11 @@
61 69 public function maybe_add_quota_reached_notice() {
62 70
63 71 // @var ImageOptimizer/Modules/ConnectManager/Module
64 72 $module = Plugin::instance()->modules_manager->get_modules( 'connect-manager' );
73 + $upgrade_link = Utils::get_upgrade_link( 'https://go.elementor.com/io-quota-upgrade/' );
65 74
66 - if ( ! $module->connect_instance->is_activated() || $module->connect_instance->images_left() > 0 ) {
75 + if ( ! $module->connect_instance->get_connect_status() || $module->connect_instance->images_left() > 0 ) {
67 76 return;
68 77 }
69 78
70 79 ?>
@@ -82,9 +91,9 @@
82 91 'You have no images left to optimize in your current plan.',
83 92 'image-optimization'
84 93 ); ?>
85 94
86 - <a href="https://go.elementor.com/io-quota-upgrade/">
95 + <a href="<?php echo esc_url( $upgrade_link ); ?>">
87 96 <?php esc_html_e(
88 97 'Upgrade plan now',
89 98 'image-optimization'
90 99 ); ?>
@@ -94,11 +103,99 @@
94 103 </div>
95 104 <?php
96 105 }
97 106
98 - public function add_plugin_links( $links, $plugin_file_name ): array {
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 +
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 +
99 196 if ( ! str_ends_with( $plugin_file_name, '/image-optimization.php' ) ) {
100 - return (array) $links;
197 + return $links;
101 198 }
102 199
103 200 $custom_links = [
104 201 'settings' => sprintf(
@@ -105,14 +202,26 @@
105 202 '<a href="%s">%s</a>',
106 203 admin_url( 'admin.php?page=' . \ImageOptimization\Modules\Settings\Module::SETTING_BASE_SLUG ),
107 204 esc_html__( 'Settings', 'image-optimization' )
108 205 ),
109 - 'upgrade' => sprintf(
110 - '<a href="%s" style="color: #524CFF; font-weight: 700;" target="_blank" rel="noopener noreferrer">%s</a>',
111 - 'https://go.elementor.com/io-plugins-upgrade/',
206 + ];
207 + // @var ImageOptimizer/Modules/ConnectManager/Module
208 + $module = Plugin::instance()->modules_manager->get_modules( 'connect-manager' );
209 +
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/' ),
112 214 esc_html__( 'Upgrade', 'image-optimization' )
113 - ),
114 - ];
215 + );
216 + }
217 + if ( ! $module->connect_instance->is_connected() ) {
218 + $custom_links['connect'] = sprintf(
219 + '<a href="%s" style="color: #524cff; font-weight: 700;">%s</a>',
220 + admin_url( 'admin.php?page=' . \ImageOptimization\Modules\Settings\Module::SETTING_BASE_SLUG ),
221 + esc_html__( 'Connect', 'image-optimization' )
222 + );
223 + }
115 224
116 225 return array_merge( $custom_links, $links );
117 226 }
118 227
@@ -156,8 +265,10 @@
156 265 [
157 266 'siteUrl' => wp_parse_url( get_site_url(), PHP_URL_HOST ),
158 267 'thumbnailSizes' => wp_get_registered_image_subsizes(),
159 268 'isDevelopment' => defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG,
269 + 'isRTL' => is_rtl(),
270 + 'version' => IMAGE_OPTIMIZATION_VERSION,
160 271 ]
161 272 );
162 273
163 274 /**
@@ -163,23 +274,32 @@
163 274 /**
164 275 * @var ImageOptimizer\Modules\ConnectManager\Module $module
165 276 */
166 277 $module = Plugin::instance()->modules_manager->get_modules( 'connect-manager' );
167 - $is_connect_on_fly = $module->connect_instance->get_is_connect_on_fly();
168 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() );
169 281
170 282 wp_localize_script(
171 283 'image-optimization-admin',
172 284 'imageOptimizerUserData',
173 285 [
174 - 'isConnectOnFly' => $is_connect_on_fly,
286 + 'isConnectOnFly' => self::is_connect_on_fly(),
175 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,
176 292 'isActivated' => $module->connect_instance->is_activated(),
293 + 'isUrlMismatch' => ! $module->connect_instance->is_valid_home_url(),
177 294 'planData' => $module->connect_instance->is_activated() ? $module->connect_instance->get_connect_status() : null,
178 295 'licenseKey' => $module->connect_instance->is_activated() ? $module->connect_instance->get_activation_state() : null,
179 296 'imagesLeft' => $module->connect_instance->is_activated() ? $module->connect_instance->images_left() : null,
180 297 'isOwner' => $module->connect_instance->is_connected() ? $module->connect_instance->user_is_subscription_owner() : null,
181 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 ),
182 302
183 303 'wpRestNonce' => wp_create_nonce( 'wp_rest' ),
184 304 'disconnect' => wp_create_nonce( 'wp_rest' ),
185 305 'authInitNonce' => wp_create_nonce( $module->connect_instance->connect_init_nonce() ),
@@ -201,14 +321,138 @@
201 321 private function should_render(): bool {
202 322 return ( Utils::is_media_page() || Utils::is_plugin_page() ) && Utils::user_is_admin();
203 323 }
204 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 +
205 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 + /**
206 448 * Module constructor.
207 449 */
208 450 public function __construct() {
209 451 $this->register_components();
210 452
453 + add_action( 'action_scheduler_init', [ Migration_Manager::class, 'init' ] );
454 +
211 455 add_action( 'admin_enqueue_scripts', [ $this, 'enqueue_global_assets' ] );
212 456 add_filter( 'plugin_action_links', [ $this, 'add_plugin_links' ], 10, 2 );
213 457
214 458 add_action('current_screen', function () {
@@ -215,14 +459,16 @@
215 459 if ( ! $this->should_render() ) {
216 460 return;
217 461 }
218 462
219 - 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 + }
220 467
468 + add_action( 'admin_notices', [ $this, 'maybe_add_url_mismatch_notice' ] );
469 +
221 470 if ( Utils::is_media_page() ) {
222 - add_action('in_admin_header', function () {
223 - $this->render_top_bar();
224 - });
225 471
226 472 add_action('all_admin_notices', function () {
227 473 $this->render_app();
228 474 });
@@ -236,7 +482,11 @@
236 482
237 483 add_action('admin_enqueue_scripts', function () {
238 484 $this->enqueue_scripts();
239 485 });
486 +
487 + if ( Utils::is_media_page() ) {
488 + add_action( 'admin_enqueue_scripts', [ $this, 'add_bulk_optimization_links' ] );
489 + }
240 490 });
241 491 }
242 492 }