PluginProbe
Imagify Image Optimization: Optimize Images | Compress & Convert to WebP/AVIF / 2.2.3.1
Imagify Image Optimization: Optimize Images | Compress & Convert to WebP/AVIF v2.2.3.1
2.3.4 2.3.3 2.3.2 2.3.1 2.3.0 2.2.9 2.2.8 trunk 1.10 1.3.3 1.3.4 1.3.5 1.3.5.1 1.3.5.2 1.3.6 1.3.6.1 1.4 1.4.1 1.4.2 1.4.3 1.4.4 1.4.5 1.4.6 1.4.7 1.5 All 103 releases
imagify / classes / Notices / Notices.php

Notices.php in Imagify Image Optimization: Optimize Images | Compress & Convert to WebP/AVIF 2.2.3.1, at classes/Notices/Notices.php

910 lines 22.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 declare(strict_types=1);
3
4 namespace Imagify\Notices;
5
6 use Imagify\Traits\InstanceGetterTrait;
7 use Imagify\User\User;
8
9 /**
10 * Class that handles the admin notices.
11 *
12 * @since 1.6.10
13 */
14 class Notices {
15 use InstanceGetterTrait;
16
17 /**
18 * Class version.
19 *
20 * @var string
21 */
22 const VERSION = '1.0.1';
23
24 /**
25 * Name of the transient storing temporary notices.
26 *
27 * @var string
28 */
29 const TEMPORARY_NOTICES_TRANSIENT_NAME = 'imagify_temporary_notices';
30
31 /**
32 * Name of the user meta that stores the dismissed notice IDs.
33 *
34 * @var string
35 */
36 const DISMISS_META_NAME = '_imagify_ignore_notices';
37
38 /**
39 * Action used in the nonce to dismiss a notice.
40 *
41 * @var string
42 */
43 const DISMISS_NONCE_ACTION = 'imagify-dismiss-notice';
44
45 /**
46 * Action used in the nonce to deactivate a plugin.
47 *
48 * @var string
49 */
50 const DEACTIVATE_PLUGIN_NONCE_ACTION = 'imagify-deactivate-plugin';
51
52 /**
53 * List of notice IDs.
54 * They correspond to method names and IDs stored in the "dismissed" transient.
55 * Only use "-" character, not "_".
56 *
57 * @var array
58 */
59 protected static $notice_ids = [
60 // This warning is displayed when the API key is empty. Dismissible.
61 'welcome-steps',
62 // This warning is displayed when the API key is wrong. Dismissible.
63 'wrong-api-key',
64 // This warning is displayed if some plugins are active. NOT dismissible.
65 'plugins-to-deactivate',
66 // This notice is displayed when external HTTP requests are blocked via the WP_HTTP_BLOCK_EXTERNAL constant. Dismissible.
67 'http-block-external',
68 // This warning is displayed when the grid view is active on the library. Dismissible.
69 'grid-view',
70 // This warning is displayed if the backup folder is not writable. NOT dismissible.
71 'backup-folder-not-writable',
72 // This notice is displayed to rate the plugin after 100 optimizations & 7 days after the first installation. Dismissible.
73 'rating',
74 // Add a message about WP Rocket on the "Bulk Optimization" screen. Dismissible.
75 'wp-rocket',
76 'bulk-optimization-complete',
77 'bulk-optimization-running',
78 'upsell-banner',
79 'upsell-admin-bar',
80 ];
81
82 /**
83 * List of user capabilities to use for each notice.
84 * Default value 'manage' is not listed.
85 *
86 * @var array
87 */
88 protected static $capabilities = [
89 'grid-view' => 'optimize',
90 'backup-folder-not-writable' => 'bulk-optimize',
91 'rating' => 'bulk-optimize',
92 'wp-rocket' => 'bulk-optimize',
93 'bulk-optimization-complete' => 'bulk-optimize',
94 'bulk-optimization-running' => 'bulk-optimize',
95 ];
96
97 /**
98 * List of plugins that conflict with Imagify.
99 *
100 * @var array
101 */
102 protected static $conflicting_plugins = [
103 'wp-smush' => 'wp-smushit/wp-smush.php', // WP Smush.
104 'wp-smush-pro' => 'wp-smush-pro/wp-smush.php', // WP Smush Pro.
105 'kraken' => 'kraken-image-optimizer/kraken.php', // Kraken.io.
106 'tinypng' => 'tiny-compress-images/tiny-compress-images.php', // TinyPNG.
107 'shortpixel' => 'shortpixel-image-optimiser/wp-shortpixel.php', // Shortpixel.
108 'ewww' => 'ewww-image-optimizer/ewww-image-optimizer.php', // EWWW Image Optimizer.
109 'ewww-cloud' => 'ewww-image-optimizer-cloud/ewww-image-optimizer-cloud.php', // EWWW Image Optimizer Cloud.
110 'imagerecycle' => 'imagerecycle-pdf-image-compression/wp-image-recycle.php', // ImageRecycle.
111 ];
112
113 /**
114 * The constructor.
115 *
116 * @return void
117 */
118 protected function __construct() {}
119
120
121 /** ----------------------------------------------------------------------------------------- */
122 /** INIT ==================================================================================== */
123 /** ----------------------------------------------------------------------------------------- */
124
125 /**
126 * Launch the hooks.
127 *
128 * @since 1.6.10
129 */
130 public function init() {
131 // For generic purpose.
132 add_action( 'all_admin_notices', [ $this, 'render_notices' ] );
133 add_action( 'wp_ajax_imagify_dismiss_notice', [ $this, 'admin_post_dismiss_notice' ] );
134 add_action( 'admin_post_imagify_dismiss_notice', [ $this, 'admin_post_dismiss_notice' ] );
135 // For specific notices.
136 add_action( 'imagify_dismiss_notice', [ $this, 'clear_scheduled_rating' ] );
137 add_action( 'admin_post_imagify_deactivate_plugin', [ $this, 'deactivate_plugin' ] );
138 add_action( 'imagify_not_almost_over_quota_anymore', [ $this, 'renew_almost_over_quota_notice' ] );
139 }
140
141
142 /** ----------------------------------------------------------------------------------------- */
143 /** HOOKS =================================================================================== */
144 /** ----------------------------------------------------------------------------------------- */
145
146 /**
147 * Maybe display some notices.
148 *
149 * @since 1.6.10
150 */
151 public function render_notices() {
152 foreach ( $this->get_notice_ids() as $notice_id ) {
153 // Get the name of the method that will tell if this notice should be displayed.
154 $callback = 'display_' . str_replace( '-', '_', $notice_id );
155
156 if ( ! method_exists( $this, $callback ) ) {
157 continue;
158 }
159
160 $data = call_user_func( [ $this, $callback ] );
161
162 if ( $data ) {
163 // The notice must be displayed: render the view.
164 \Imagify_Views::get_instance()->print_template( 'notice-' . $notice_id, $data );
165 }
166 }
167
168 // Temporary notices.
169 $this->render_temporary_notices();
170 }
171
172 /**
173 * Process a dismissed notice.
174 *
175 * @since 1.6.10
176 * @see _do_admin_post_imagify_dismiss_notice()
177 */
178 public function admin_post_dismiss_notice() {
179 imagify_check_nonce( self::DISMISS_NONCE_ACTION );
180
181 $notice = ! empty( $_GET['notice'] ) ? esc_html( wp_unslash( $_GET['notice'] ) ) : false;
182 $notices = $this->get_notice_ids();
183 $notices = array_flip( $notices );
184
185 if ( ! $notice || ! isset( $notices[ $notice ] ) || ! $this->user_can( $notice ) ) {
186 imagify_die();
187 }
188
189 self::dismiss_notice( $notice );
190
191 /**
192 * Fires when a notice is dismissed.
193 *
194 * @since 1.4.2
195 *
196 * @param int $notice The notice slug
197 */
198 do_action( 'imagify_dismiss_notice', $notice );
199
200 imagify_maybe_redirect();
201 wp_send_json_success();
202 }
203
204 /**
205 * Stop the rating cron when the notice is dismissed.
206 *
207 * @since 1.6.10
208 * @see _imagify_clear_scheduled_rating()
209 *
210 * @param string $notice The notice name.
211 */
212 public function clear_scheduled_rating( $notice ) {
213 if ( 'rating' === $notice ) {
214 set_site_transient( 'do_imagify_rating_cron', 'no' );
215 \Imagify_Cron_Rating::get_instance()->unschedule_event();
216 }
217 }
218
219 /**
220 * Disable a plugin which can be in conflict with Imagify.
221 *
222 * @since 1.6.10
223 * @see _imagify_deactivate_plugin()
224 */
225 public function deactivate_plugin() {
226 imagify_check_nonce( self::DEACTIVATE_PLUGIN_NONCE_ACTION );
227
228 if ( empty( $_GET['plugin'] ) || ! $this->user_can( 'plugins-to-deactivate' ) ) {
229 imagify_die();
230 }
231
232 $plugin = esc_html( wp_unslash( $_GET['plugin'] ) );
233 $plugins = $this->get_conflicting_plugins();
234 $plugins = array_flip( $plugins );
235
236 if ( empty( $plugins[ $plugin ] ) ) {
237 imagify_die();
238 }
239
240 deactivate_plugins( $plugin );
241
242 imagify_maybe_redirect();
243 wp_send_json_success();
244 }
245
246 /**
247 * Renew the "almost-over-quota" notice when the consumed quota percent decreases back below 80%.
248 *
249 * @since 1.7
250 */
251 public function renew_almost_over_quota_notice() {
252 global $wpdb;
253
254 $results = $wpdb->get_results( $wpdb->prepare( "SELECT umeta_id, user_id FROM $wpdb->usermeta WHERE meta_key = %s AND meta_value LIKE %s", self::DISMISS_META_NAME, '%upsell%' ) );
255
256 if ( ! $results ) {
257 return;
258 }
259
260 // Prevent multiple queries to the DB by caching user metas.
261 $not_cached = [];
262
263 foreach ( $results as $result ) {
264 if ( ! wp_cache_get( $result->umeta_id, 'user_meta' ) ) {
265 $not_cached[] = $result->umeta_id;
266 }
267 }
268
269 if ( $not_cached ) {
270 update_meta_cache( 'user', $not_cached );
271 }
272
273 // Renew the notice for all users.
274 foreach ( $results as $result ) {
275 self::renew_notice( 'upsell-banner', $result->user_id );
276 self::renew_notice( 'upsell-admin-bar', $result->user_id );
277 }
278 }
279
280
281 /** ----------------------------------------------------------------------------------------- */
282 /** NOTICES ================================================================================= */
283 /** ----------------------------------------------------------------------------------------- */
284
285 /**
286 * Tell if the 'welcome-steps' notice should be displayed.
287 *
288 * @since 1.6.10
289 *
290 * @return bool
291 */
292 public function display_welcome_steps() {
293 static $display;
294
295 if ( isset( $display ) ) {
296 return $display;
297 }
298
299 $display = false;
300
301 if ( ! $this->user_can( 'welcome-steps' ) ) {
302 return $display;
303 }
304
305 if ( imagify_is_screen( 'imagify-settings' ) ) {
306 return $display;
307 }
308
309 if ( self::notice_is_dismissed( 'welcome-steps' ) || get_imagify_option( 'api_key' ) ) {
310 return $display;
311 }
312
313 $display = true;
314 return $display;
315 }
316
317 /**
318 * Tell if the 'wrong-api-key' notice should be displayed.
319 *
320 * @since 1.6.10
321 *
322 * @return bool
323 */
324 public function display_wrong_api_key() {
325 static $display;
326
327 if ( isset( $display ) ) {
328 return $display;
329 }
330
331 $display = false;
332
333 if ( ! $this->user_can( 'wrong-api-key' ) ) {
334 return $display;
335 }
336
337 if ( ! imagify_is_screen( 'bulk' ) ) {
338 return $display;
339 }
340
341 if ( self::notice_is_dismissed( 'wrong-api-key' ) || ! get_imagify_option( 'api_key' ) || \Imagify_Requirements::is_api_key_valid() ) {
342 return $display;
343 }
344
345 $display = true;
346 return $display;
347 }
348
349 /**
350 * Tell if the 'plugins-to-deactivate' notice should be displayed.
351 *
352 * @since 1.6.10
353 *
354 * @return array An array of plugins to deactivate.
355 */
356 public function display_plugins_to_deactivate() {
357 static $display;
358
359 if ( isset( $display ) ) {
360 return $display;
361 }
362
363 if ( ! $this->user_can( 'plugins-to-deactivate' ) ) {
364 $display = false;
365 return $display;
366 }
367
368 $display = $this->get_conflicting_plugins();
369 return $display;
370 }
371
372 /**
373 * Tell if the 'plugins-to-deactivate' notice should be displayed.
374 *
375 * @since 1.6.10
376 *
377 * @return bool
378 */
379 public function display_http_block_external() {
380 static $display;
381
382 if ( isset( $display ) ) {
383 return $display;
384 }
385
386 $display = false;
387
388 if ( ! $this->user_can( 'http-block-external' ) ) {
389 return $display;
390 }
391
392 if ( imagify_is_screen( 'imagify-settings' ) ) {
393 return $display;
394 }
395
396 if ( self::notice_is_dismissed( 'http-block-external' ) || ! \Imagify_Requirements::is_imagify_blocked() ) {
397 return $display;
398 }
399
400 $display = true;
401 return $display;
402 }
403
404 /**
405 * Tell if the 'grid-view' notice should be displayed.
406 *
407 * @since 1.6.10
408 *
409 * @return bool
410 */
411 public function display_grid_view() {
412 global $wp_version;
413 static $display;
414
415 if ( isset( $display ) ) {
416 return $display;
417 }
418
419 $display = false;
420
421 if ( ! $this->user_can( 'grid-view' ) ) {
422 return $display;
423 }
424
425 if ( ! imagify_is_screen( 'library' ) ) {
426 return $display;
427 }
428
429 $media_library_mode = get_user_option( 'media_library_mode', get_current_user_id() );
430
431 if ( 'list' === $media_library_mode || self::notice_is_dismissed( 'grid-view' ) || version_compare( $wp_version, '4.0' ) < 0 ) {
432 return $display;
433 }
434
435 // Don't display the notice if the API key isn't valid.
436 if ( ! \Imagify_Requirements::is_api_key_valid() ) {
437 return $display;
438 }
439
440 $display = true;
441 return $display;
442 }
443
444 /**
445 * Tell if the 'backup-folder-not-writable' notice should be displayed.
446 *
447 * @since 1.6.10
448 *
449 * @return bool
450 */
451 public function display_backup_folder_not_writable() {
452 static $display;
453
454 if ( isset( $display ) ) {
455 return $display;
456 }
457
458 $display = false;
459
460 if ( ! $this->user_can( 'backup-folder-not-writable' ) ) {
461 return $display;
462 }
463
464 // Every places where images can be optimized, automatically or not (+ the settings page).
465 if ( ! imagify_is_screen( 'imagify-settings' ) && ! imagify_is_screen( 'library' ) && ! imagify_is_screen( 'upload' ) && ! imagify_is_screen( 'bulk' ) && ! imagify_is_screen( 'media-modal' ) ) {
466 return $display;
467 }
468
469 if ( ! get_imagify_option( 'backup' ) ) {
470 return $display;
471 }
472
473 if ( \Imagify_Requirements::attachments_backup_dir_is_writable() ) {
474 return $display;
475 }
476
477 $display = true;
478 return $display;
479 }
480
481 /**
482 * Tell if the 'rating' notice should be displayed.
483 *
484 * @since 1.6.10
485 *
486 * @return bool|int
487 */
488 public function display_rating() {
489 static $display;
490
491 if ( isset( $display ) ) {
492 return $display;
493 }
494
495 $display = false;
496
497 if ( ! $this->user_can( 'rating' ) ) {
498 return $display;
499 }
500
501 if ( ! imagify_is_screen( 'bulk' ) && ! imagify_is_screen( 'library' ) && ! imagify_is_screen( 'upload' ) ) {
502 return $display;
503 }
504
505 if ( self::notice_is_dismissed( 'rating' ) ) {
506 return $display;
507 }
508
509 $user_images_count = (int) get_site_transient( 'imagify_user_images_count' );
510
511 if ( ! $user_images_count || get_site_transient( 'imagify_seen_rating_notice' ) ) {
512 return $display;
513 }
514
515 $display = $user_images_count;
516 return $display;
517 }
518
519 /**
520 * Tell if the 'wp-rocket' notice should be displayed.
521 *
522 * @since 1.6.10
523 *
524 * @return bool
525 */
526 public function display_wp_rocket() {
527 static $display;
528
529 if ( isset( $display ) ) {
530 return $display;
531 }
532
533 $display = false;
534
535 if ( ! $this->user_can( 'wp-rocket' ) ) {
536 return $display;
537 }
538
539 if ( ! imagify_is_screen( 'bulk' ) ) {
540 return $display;
541 }
542
543 $plugins = get_plugins();
544
545 if ( isset( $plugins['wp-rocket/wp-rocket.php'] ) || self::notice_is_dismissed( 'wp-rocket' ) ) {
546 return $display;
547 }
548
549 $display = true;
550 return $display;
551 }
552
553 /**
554 * Tell if the bulk optimization complete notice should be displayed
555 *
556 * @since 2.1
557 *
558 * @return array
559 */
560 public function display_bulk_optimization_complete(): array {
561 if ( ! $this->user_can( 'bulk-optimization-complete' ) ) {
562 return [];
563 }
564
565 if ( imagify_is_screen( 'bulk' ) ) {
566 return [];
567 }
568
569 if ( self::notice_is_dismissed( 'bulk-optimization-complete' ) ) {
570 return [];
571 }
572
573 if ( false === get_transient( 'imagify_bulk_optimization_complete' ) ) {
574 return [];
575 }
576
577 $data = get_transient( 'imagify_bulk_optimization_result' );
578
579 if ( empty( $data ) ) {
580 return [];
581 }
582
583 $global_gain = $data['original_size'] - $data['optimized_size'];
584
585 $data['original_size'] = imagify_size_format( $data['original_size'], 2 );
586 $data['optimized_size'] = imagify_size_format( $global_gain, 2 );
587 $data['bulk_page_url'] = admin_url( 'upload.php?page=imagify-bulk-optimization' );
588
589 return $data;
590 }
591
592 /**
593 * Tell if the bulk optimization running notice should be displayed
594 *
595 * @since 2.1
596 *
597 * @return array
598 */
599 public function display_bulk_optimization_running(): array {
600 if ( ! $this->user_can( 'bulk-optimization-running' ) ) {
601 return [];
602 }
603
604 if ( imagify_is_screen( 'bulk' ) ) {
605 return [];
606 }
607
608 if ( self::notice_is_dismissed( 'bulk-optimization-running' ) ) {
609 return [];
610 }
611
612 $custom_folders = get_transient( 'imagify_custom-folders_optimize_running' );
613 $library_wp = get_transient( 'imagify_wp_optimize_running' );
614
615 if (
616 ! $custom_folders
617 &&
618 ! $library_wp
619 ) {
620 return [];
621 }
622
623 $data = [];
624
625 $data['bulk_page_url'] = admin_url( 'upload.php?page=imagify-bulk-optimization' );
626
627 return $data;
628 }
629
630 /** ----------------------------------------------------------------------------------------- */
631 /** TEMPORARY NOTICES ======================================================================= */
632 /** ----------------------------------------------------------------------------------------- */
633
634 /**
635 * Maybe display some notices.
636 *
637 * @since 1.7
638 */
639 protected function render_temporary_notices() {
640 if ( is_network_admin() ) {
641 $notices = $this->get_network_temporary_notices();
642 } else {
643 $notices = $this->get_site_temporary_notices();
644 }
645
646 if ( ! $notices ) {
647 return;
648 }
649
650 $views = \Imagify_Views::get_instance();
651
652 foreach ( $notices as $i => $notice_data ) {
653 $notices[ $i ]['type'] = ! empty( $notice_data['type'] ) ? $notice_data['type'] : 'error';
654 }
655
656 $views->print_template( 'notice-temporary', $notices );
657 }
658
659 /**
660 * Get temporary notices for the network.
661 *
662 * @since 1.7
663 *
664 * @return array
665 */
666 protected function get_network_temporary_notices() {
667 $notices = get_site_transient( self::TEMPORARY_NOTICES_TRANSIENT_NAME );
668
669 if ( false === $notices ) {
670 return [];
671 }
672
673 delete_site_transient( self::TEMPORARY_NOTICES_TRANSIENT_NAME );
674
675 return $notices && is_array( $notices ) ? $notices : [];
676 }
677
678 /**
679 * Create a temporary notice for the network.
680 *
681 * @since 1.7
682 *
683 * @param array|object|string $notice_data Some data, with the message to display.
684 */
685 public function add_network_temporary_notice( $notice_data ) {
686 $notices = get_site_transient( self::TEMPORARY_NOTICES_TRANSIENT_NAME );
687 $notices = is_array( $notices ) ? $notices : [];
688
689 if ( is_wp_error( $notice_data ) ) {
690 $notice_data = $notice_data->get_error_messages();
691 $notice_data = implode( '<br/>', $notice_data );
692 }
693
694 if ( is_string( $notice_data ) ) {
695 $notice_data = [
696 'message' => $notice_data,
697 ];
698 } elseif ( is_object( $notice_data ) ) {
699 $notice_data = (array) $notice_data;
700 }
701
702 if ( ! is_array( $notice_data ) || empty( $notice_data['message'] ) ) {
703 return;
704 }
705
706 $notices[] = $notice_data;
707
708 set_site_transient( self::TEMPORARY_NOTICES_TRANSIENT_NAME, $notices, 30 );
709 }
710
711 /**
712 * Get temporary notices for the current site.
713 *
714 * @since 1.7
715 *
716 * @return array
717 */
718 protected function get_site_temporary_notices() {
719 $notices = get_transient( self::TEMPORARY_NOTICES_TRANSIENT_NAME );
720
721 if ( false === $notices ) {
722 return [];
723 }
724
725 delete_transient( self::TEMPORARY_NOTICES_TRANSIENT_NAME );
726
727 return $notices && is_array( $notices ) ? $notices : [];
728 }
729
730 /**
731 * Create a temporary notice for the current site.
732 *
733 * @since 1.7
734 *
735 * @param array|string $notice_data Some data, with the message to display.
736 */
737 public function add_site_temporary_notice( $notice_data ) {
738 $notices = get_transient( self::TEMPORARY_NOTICES_TRANSIENT_NAME );
739 $notices = is_array( $notices ) ? $notices : [];
740
741 if ( is_string( $notice_data ) ) {
742 $notice_data = [
743 'message' => $notice_data,
744 ];
745 } elseif ( is_object( $notice_data ) ) {
746 $notice_data = (array) $notice_data;
747 }
748
749 if ( ! is_array( $notice_data ) || empty( $notice_data['message'] ) ) {
750 return;
751 }
752
753 $notices[] = $notice_data;
754
755 set_transient( self::TEMPORARY_NOTICES_TRANSIENT_NAME, $notices, 30 );
756 }
757
758
759 /** ----------------------------------------------------------------------------------------- */
760 /** PUBLIC TOOLS ============================================================================ */
761 /** ----------------------------------------------------------------------------------------- */
762
763 /**
764 * Renew a dismissed Imagify notice.
765 *
766 * @since 1.6.10
767 *
768 * @param string $notice A notice ID.
769 * @param int $user_id A user ID.
770 */
771 public static function renew_notice( $notice, $user_id = 0 ) {
772 $user_id = $user_id ? (int) $user_id : get_current_user_id();
773 $notices = get_user_meta( $user_id, self::DISMISS_META_NAME, true );
774 $notices = $notices && is_array( $notices ) ? array_flip( $notices ) : [];
775
776 if ( ! isset( $notices[ $notice ] ) ) {
777 return;
778 }
779
780 unset( $notices[ $notice ] );
781 $notices = array_flip( $notices );
782 $notices = array_filter( $notices );
783 $notices = array_values( $notices );
784
785 update_user_meta( $user_id, self::DISMISS_META_NAME, $notices );
786 }
787
788 /**
789 * Dismiss an Imagify notice.
790 *
791 * @since 1.6.10
792 * @see imagify_dismiss_notice()
793 *
794 * @param string $notice A notice ID.
795 * @param int $user_id A user ID.
796 */
797 public static function dismiss_notice( $notice, $user_id = 0 ) {
798 $user_id = $user_id ? (int) $user_id : get_current_user_id();
799 $notices = get_user_meta( $user_id, self::DISMISS_META_NAME, true );
800 $notices = $notices && is_array( $notices ) ? array_flip( $notices ) : [];
801
802 if ( isset( $notices[ $notice ] ) ) {
803 return;
804 }
805
806 $notices = array_flip( $notices );
807 $notices[] = $notice;
808 $notices = array_filter( $notices );
809 $notices = array_values( $notices );
810
811 update_user_meta( $user_id, self::DISMISS_META_NAME, $notices );
812 }
813
814 /**
815 * Tell if an Imagify notice is dismissed.
816 *
817 * @since 1.6.10
818 * @see imagify_notice_is_dismissed()
819 *
820 * @param string $notice A notice ID.
821 * @param int $user_id A user ID.
822 * @return bool
823 */
824 public static function notice_is_dismissed( $notice, $user_id = 0 ) {
825 $user_id = $user_id ? (int) $user_id : get_current_user_id();
826 $notices = get_user_meta( $user_id, self::DISMISS_META_NAME, true );
827 $notices = $notices && is_array( $notices ) ? array_flip( $notices ) : [];
828
829 return isset( $notices[ $notice ] );
830 }
831
832 /**
833 * Tell if one or more notices will be displayed later in the page.
834 *
835 * @since 1.6.10
836 *
837 * @return bool
838 */
839 public function has_notices() {
840 foreach ( self::$notice_ids as $notice_id ) {
841 $callback = 'display_' . str_replace( '-', '_', $notice_id );
842
843 if ( method_exists( $this, $callback ) && call_user_func( [ $this, $callback ] ) ) {
844 return true;
845 }
846 }
847
848 return false;
849 }
850
851
852 /** ----------------------------------------------------------------------------------------- */
853 /** INTERNAL TOOLS ========================================================================== */
854 /** ----------------------------------------------------------------------------------------- */
855
856 /**
857 * Get all notice IDs.
858 *
859 * @since 1.6.10
860 * @since 1.10 Cast return value to array.
861 *
862 * @return array The filtered notice ids.
863 */
864 protected function get_notice_ids() {
865 /**
866 * Filter the notices Imagify can display.
867 *
868 * @since 1.6.10
869 *
870 * @param array $notice_ids An array of notice "IDs".
871 */
872 return (array) apply_filters( 'imagify_notices', self::$notice_ids );
873 }
874
875 /**
876 * Tell if the current user can see the notices.
877 * Notice IDs that are not listed in self::$capabilities are assumed as 'manage'.
878 *
879 * @since 1.6.10
880 *
881 * @param string $notice_id A notice ID.
882 * @return bool
883 */
884 protected function user_can( $notice_id ) {
885 $capability = isset( self::$capabilities[ $notice_id ] ) ? self::$capabilities[ $notice_id ] : 'manage';
886
887 return imagify_get_context( 'wp' )->current_user_can( $capability );
888 }
889
890 /**
891 * Get a list of plugins that can conflict with Imagify.
892 *
893 * @since 1.6.10
894 *
895 * @return array
896 */
897 protected function get_conflicting_plugins() {
898 /**
899 * Filter the recommended plugins to deactivate to prevent conflicts.
900 *
901 * @since 1.0
902 *
903 * @param string $plugins List of recommended plugins to deactivate.
904 */
905 $plugins = apply_filters( 'imagify_plugins_to_deactivate', self::$conflicting_plugins );
906
907 return array_filter( $plugins, 'is_plugin_active' );
908 }
909 }
910