PluginProbe
Elementor Website Builder – more than just a page builder / 4.3.0-beta2
Elementor Website Builder – more than just a page builder v4.3.0-beta2
4.3.0-beta2 4.3.0-beta1 4.2.4 4.2.3 4.2.2 4.2.1 4.2.0 4.1.5 4.2.0-beta2 4.2.0-dev2 4.2.0-beta1 4.1.4 4.1.3 4.1.2 4.1.1 4.1.0 4.1.0-beta3 4.1.0-dev3 4.0.9 4.1.0-beta2 4.1.0-dev2 4.0.8 4.1.0-beta1 4.1.0-dev1 4.0.7 All 451 releases
elementor / core / admin / admin-notices.php

admin-notices.php in Elementor Website Builder – more than just a page builder 4.3.0-beta2, at core/admin/admin-notices.php

876 lines 26.0 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 namespace Elementor\Core\Admin;
3
4 use Elementor\Api;
5 use Elementor\Core\Admin\UI\Components\Button;
6 use Elementor\Core\Base\Module;
7 use Elementor\Core\Utils\Hints;
8 use Elementor\Core\Utils\Promotions\Filtered_Promotions_Manager;
9 use Elementor\Plugin;
10 use Elementor\Tracker;
11 use Elementor\User;
12 use Elementor\Utils;
13 use Elementor\Core\Admin\Notices\Base_Notice;
14
15 if ( ! defined( 'ABSPATH' ) ) {
16 exit; // Exit if accessed directly.
17 }
18
19 class Admin_Notices extends Module {
20
21 const DEFAULT_EXCLUDED_PAGES = [ 'plugins.php', 'plugin-install.php', 'plugin-editor.php' ];
22
23 const EXIT_EARLY_FOR_BACKWARD_COMPATIBILITY = false;
24
25 private $plain_notices = [
26 'api_notice',
27 'api_upgrade_plugin',
28 'tracker',
29 'tracker_last_update',
30 'rate_us_feedback',
31 'role_manager_promote',
32 'plugin_image_optimization',
33 'ally_pages_promotion',
34 ];
35
36 private $elementor_pages_count = null;
37
38 private $install_time = null;
39
40 private $current_screen_id = null;
41
42 private function get_notices() {
43 /**
44 * Admin notices.
45 *
46 * Filters Elementor admin notices.
47 *
48 * This hook can be used by external developers to manage existing
49 * admin notice or to add new notices for Elementor add-ons.
50 *
51 * @param array $notices A list of notice classes.
52 */
53 $notices = apply_filters( 'elementor/core/admin/notices', [] );
54
55 return $notices;
56 }
57
58 private function get_install_time() {
59 if ( null === $this->install_time ) {
60 $this->install_time = Plugin::$instance->get_install_time();
61 }
62
63 return $this->install_time;
64 }
65
66 private function get_elementor_pages_count() {
67 if ( null === $this->elementor_pages_count ) {
68 $elementor_pages = new \WP_Query( [
69 'no_found_rows' => true,
70 'post_type' => 'any',
71 'post_status' => 'publish',
72 'fields' => 'ids',
73 'update_post_meta_cache' => false,
74 'update_post_term_cache' => false,
75 'meta_key' => '_elementor_edit_mode',
76 'meta_value' => 'builder',
77 ] );
78
79 $this->elementor_pages_count = $elementor_pages->post_count;
80 }
81
82 return $this->elementor_pages_count;
83 }
84
85 private function notice_api_upgrade_plugin() {
86 $upgrade_notice = Api::get_upgrade_notice();
87 if ( empty( $upgrade_notice ) ) {
88 return false;
89 }
90
91 if ( ! current_user_can( 'update_plugins' ) ) {
92 return false;
93 }
94
95 if ( ! $this->is_elementor_admin_screen_with_system_info() ) {
96 return false;
97 }
98
99 // Check for upgrades.
100 $update_plugins = get_site_transient( 'update_plugins' );
101
102 $has_remote_update_package = ! ( empty( $update_plugins ) || empty( $update_plugins->response[ ELEMENTOR_PLUGIN_BASE ] ) || empty( $update_plugins->response[ ELEMENTOR_PLUGIN_BASE ]->package ) );
103
104 if ( ! $has_remote_update_package && empty( $upgrade_notice['update_link'] ) ) {
105 return false;
106 }
107
108 if ( $has_remote_update_package ) {
109 $product = $update_plugins->response[ ELEMENTOR_PLUGIN_BASE ];
110
111 $details_url = self_admin_url( 'plugin-install.php?tab=plugin-information&plugin=' . $product->slug . '&section=changelog&TB_iframe=true&width=600&height=800' );
112 $upgrade_url = wp_nonce_url( self_admin_url( 'update.php?action=upgrade-plugin&plugin=' . ELEMENTOR_PLUGIN_BASE ), 'upgrade-plugin_' . ELEMENTOR_PLUGIN_BASE );
113 $new_version = $product->new_version;
114 } else {
115 $upgrade_url = $upgrade_notice['update_link'];
116 $details_url = $upgrade_url;
117
118 $new_version = $upgrade_notice['version'];
119 }
120
121 // Check if upgrade messages should be shown.
122 if ( version_compare( ELEMENTOR_VERSION, $upgrade_notice['version'], '>=' ) ) {
123 return false;
124 }
125
126 $notice_id = 'upgrade_notice_' . $upgrade_notice['version'];
127 if ( User::is_user_notice_viewed( $notice_id ) ) {
128 return false;
129 }
130
131 $message = sprintf(
132 /* translators: 1: Details URL, 2: Accessibility text, 3: Version number, 4: Update URL, 5: Accessibility text. */
133 __( 'There is a new version of Elementor Page Builder available. <a href="%1$s" class="thickbox open-plugin-details-modal" aria-label="%2$s">View version %3$s details</a> or <a href="%4$s" class="update-link" aria-label="%5$s">update now</a>.', 'elementor' ),
134 esc_url( $details_url ),
135 sprintf(
136 /* translators: %s: Elementor version. */
137 esc_attr__( 'View Elementor version %s details', 'elementor' ),
138 $new_version
139 ),
140 $new_version,
141 esc_url( $upgrade_url ),
142 esc_attr__( 'Update Now', 'elementor' )
143 );
144
145 $options = [
146 'title' => esc_html__( 'Update Notification', 'elementor' ),
147 'description' => $message,
148 'button' => [
149 'icon_classes' => 'dashicons dashicons-update',
150 'text' => esc_html__( 'Update Now', 'elementor' ),
151 'url' => $upgrade_url,
152 ],
153 'id' => $notice_id,
154 ];
155
156 $this->print_admin_notice( $options );
157
158 return true;
159 }
160
161 private function notice_api_notice() {
162 $admin_notice = Api::get_admin_notice();
163 if ( empty( $admin_notice ) ) {
164 return false;
165 }
166
167 if ( ! current_user_can( 'manage_options' ) ) {
168 return false;
169 }
170
171 if ( ! $this->is_elementor_admin_screen_with_system_info() ) {
172 return false;
173 }
174
175 $notice_id = 'admin_notice_api_' . $admin_notice['notice_id'];
176 if ( User::is_user_notice_viewed( $notice_id ) ) {
177 return false;
178 }
179
180 $options = [
181 'title' => esc_html__( 'Update Notification', 'elementor' ),
182 'description' => $admin_notice['notice_text'],
183 'id' => $notice_id,
184 ];
185
186 $this->print_admin_notice( $options );
187
188 return true;
189 }
190
191 private function notice_tracker() {
192 if ( ! current_user_can( 'manage_options' ) ) {
193 return false;
194 }
195
196 // Show tracker notice after 24 hours from installed time.
197 if ( strtotime( '+24 hours', $this->get_install_time() ) > time() ) {
198 return false;
199 }
200
201 if ( '1' === get_option( 'elementor_tracker_notice' ) ) {
202 return false;
203 }
204
205 if ( Tracker::is_allow_track() ) {
206 return false;
207 }
208
209 if ( 2 > $this->get_elementor_pages_count() ) {
210 return false;
211 }
212
213 // TODO: Skip for development env.
214 $optin_url = wp_nonce_url( add_query_arg( 'elementor_tracker', 'opt_into' ), 'opt_into' );
215 $optout_url = wp_nonce_url( add_query_arg( 'elementor_tracker', 'opt_out' ), 'opt_out' );
216
217 $tracker_description_text = esc_html__( 'Become a super contributor by helping us understand how you use our service to enhance your experience and improve our product.', 'elementor' );
218
219 /**
220 * Tracker admin description text.
221 *
222 * Filters the admin notice text for non-sensitive data collection.
223 *
224 * @since 1.0.0
225 *
226 * @param string $tracker_description_text Description text displayed in admin notice.
227 */
228 $tracker_description_text = apply_filters( 'elementor/tracker/admin_description_text', $tracker_description_text );
229
230 $message = esc_html( $tracker_description_text ) . ' <a href="https://go.elementor.com/usage-data-tracking/" target="_blank">' . esc_html__( 'Learn more.', 'elementor' ) . '</a>';
231
232 $options = [
233 'title' => esc_html__( 'Want to shape the future of web creation?', 'elementor' ),
234 'description' => $message,
235 'dismissible' => false,
236 'button' => [
237 'text' => esc_html__( 'Sure! I\'d love to help', 'elementor' ),
238 'url' => $optin_url,
239 'type' => 'cta',
240 ],
241 'button_secondary' => [
242 'text' => esc_html__( 'No thanks', 'elementor' ),
243 'url' => $optout_url,
244 'variant' => 'outline',
245 'type' => 'cta',
246 ],
247 ];
248
249 $this->print_admin_notice( $options );
250
251 return true;
252 }
253
254 private function notice_tracker_last_update() {
255 if ( ! current_user_can( 'manage_options' ) ) {
256 return false;
257 }
258
259 if ( ! Tracker::has_terms_changed() ) {
260 return false;
261 }
262
263 $notice_id = 'tracker_last_update_' . Tracker::LAST_TERMS_UPDATED;
264
265 if ( User::is_user_notice_viewed( $notice_id ) ) {
266 return false;
267 }
268
269 $optin_url = wp_nonce_url( add_query_arg( 'elementor_tracker', 'opt_into' ), 'opt_into' );
270
271 $message = esc_html__( 'We\'re updating our Terms and Conditions to include the collection of usage and behavioral data. This information helps us understand how you use Elementor so we can make informed improvements to the product.', 'elementor' );
272
273 $options = [
274 'id' => $notice_id,
275 'title' => esc_html__( 'Update regarding usage data collection', 'elementor' ),
276 'description' => $message,
277 'button' => [
278 'text' => esc_html__( 'Opt in', 'elementor' ),
279 'url' => $optin_url,
280 'type' => 'cta',
281 ],
282 'button_secondary' => [
283 'text' => esc_html__( 'Learn more', 'elementor' ),
284 'url' => 'https://go.elementor.com/wp-dash-update-usage-notice/',
285 'new_tab' => true,
286 'type' => 'cta',
287 ],
288 ];
289
290 $this->print_admin_notice( $options );
291
292 return true;
293 }
294
295 private function notice_rate_us_feedback() {
296 $notice_id = 'rate_us_feedback';
297
298 if ( ! current_user_can( 'manage_options' ) ) {
299 return false;
300 }
301
302 if ( 'dashboard' !== $this->current_screen_id || User::is_user_notice_viewed( $notice_id ) ) {
303 return false;
304 }
305
306 if ( 10 >= $this->get_elementor_pages_count() ) {
307 return false;
308 }
309
310 $dismiss_url = add_query_arg( [
311 'action' => 'elementor_set_admin_notice_viewed',
312 'notice_id' => esc_attr( $notice_id ),
313 '_wpnonce' => wp_create_nonce( 'elementor_set_admin_notice_viewed' ),
314 ], admin_url( 'admin-post.php' ) );
315
316 $options = [
317 'title' => esc_html__( 'Congrats!', 'elementor' ),
318 'description' => esc_html__( 'You created over 10 pages with Elementor. Great job! If you can spare a minute, please help us by leaving a five star review on WordPress.org.', 'elementor' ),
319 'id' => $notice_id,
320 'button' => [
321 'text' => esc_html__( 'Happy To Help', 'elementor' ),
322 'url' => 'https://go.elementor.com/admin-review/',
323 'new_tab' => true,
324 'type' => 'cta',
325 ],
326 'button_secondary' => [
327 'text' => esc_html__( 'Hide Notification', 'elementor' ),
328 'classes' => [ 'e-notice-dismiss' ],
329 'url' => esc_url_raw( $dismiss_url ),
330 'new_tab' => true,
331 'type' => 'cta',
332 ],
333 ];
334
335 $this->print_admin_notice( $options );
336
337 return true;
338 }
339
340 private function notice_role_manager_promote() {
341 $notice_id = 'role_manager_promote';
342
343 if ( Utils::has_pro() ) {
344 return false;
345 }
346
347 if ( ! current_user_can( 'manage_options' ) ) {
348 return false;
349 }
350
351 if ( 'elementor_page_elementor-role-manager' !== $this->current_screen_id || User::is_user_notice_viewed( $notice_id ) ) {
352 return false;
353 }
354
355 $users = new \WP_User_Query( [
356 'fields' => 'ID',
357 'number' => 10,
358 ] );
359
360 if ( 5 > $users->get_total() ) {
361 return false;
362 }
363
364 $options = [
365 'title' => esc_html__( 'Managing a multi-user site?', 'elementor' ),
366 'description' => esc_html__( 'With Elementor Pro, you can control user access and make sure no one messes up your design.', 'elementor' ),
367 'id' => $notice_id,
368
369 'button' => [
370 'text' => esc_html__( 'Learn More', 'elementor' ),
371 'url' => 'https://go.elementor.com/plugin-promotion-role-manager/',
372 'new_tab' => true,
373 'type' => 'cta',
374 ],
375 ];
376
377 $options = Filtered_Promotions_Manager::get_filtered_promotion_data( $options, 'core/admin/notice_role_manager_promote', 'button', 'url' );
378
379 $this->print_admin_notice( $options );
380
381 return true;
382 }
383
384 private function get_installed_form_plugin_name() {
385 static $detected_form_plugin = null;
386
387 if ( null !== $detected_form_plugin ) {
388 return $detected_form_plugin;
389 }
390
391 $form_plugins_constants_to_name_mapper = [
392 'WPFORMS_VERSION' => 'WPForms',
393 'WPCF7_VERSION' => 'Contact Form 7',
394 ];
395
396 foreach ( $form_plugins_constants_to_name_mapper as $constant => $name ) {
397 if ( defined( $constant ) ) {
398 $detected_form_plugin = $name;
399 return $detected_form_plugin;
400 }
401 }
402
403 $form_plugins_classes_to_name_mapper = [
404 '\GFCommon' => 'Gravity Forms',
405 '\Ninja_Forms' => 'Ninja Forms',
406 ];
407
408 foreach ( $form_plugins_classes_to_name_mapper as $class => $name ) {
409 if ( class_exists( $class ) ) {
410 $detected_form_plugin = $name;
411 return $detected_form_plugin;
412 }
413 }
414
415 $detected_form_plugin = false;
416 return $detected_form_plugin;
417 }
418
419 private function notice_ally_pages_promotion() {
420 global $pagenow;
421 $notice_id = 'ally_pages_promotion';
422
423 if ( 'edit.php' !== $pagenow || empty( $_GET['post_type'] ) || 'page' !== $_GET['post_type'] ) {
424 return false;
425 }
426
427 if ( ! current_user_can( 'manage_options' ) ) {
428 return false;
429 }
430
431 if ( User::is_user_notice_viewed( $notice_id ) ) {
432 return false;
433 }
434
435 $plugin_slug = 'pojo-accessibility';
436 $plugin_file_path = 'pojo-accessibility/pojo-accessibility.php';
437
438 $one_subscription = Hints::is_plugin_connected_to_one_subscription();
439 $is_installed = Hints::is_plugin_installed( $plugin_slug );
440 $is_active = Hints::is_plugin_active( $plugin_slug );
441
442 if ( $is_active ) {
443 return false;
444 }
445
446 if ( $one_subscription ) {
447 $learn_more_url = 'https://go.elementor.com/acc-plg-learn-more-one';
448
449 if ( ! $is_installed ) {
450 $description = esc_html__( 'Make sure your site has an accessibility statement page. Install Web Accessibility, included in ONE, to create it in a few clicks.', 'elementor' );
451 $button_text = esc_html__( 'Install now', 'elementor' );
452 $button_url = $this->get_plugin_button_install_url( $plugin_slug );
453 $campaign_data = [
454 'name' => 'elementor_ea11y_campaign',
455 'campaign' => 'acc-statement-plg-pages-one-install',
456 'source' => 'wp-pages-one-install',
457 'medium' => 'wp-dash-one',
458 ];
459 } elseif ( ! $is_active ) {
460 $description = esc_html__( 'Your ONE subscription includes Web Accessibility. Activate it to create your accessibility statement page quickly.', 'elementor' );
461 $button_text = esc_html__( 'Activate now', 'elementor' );
462 $button_url = $this->get_plugin_button_activate_url( $plugin_file_path );
463 $campaign_data = [
464 'name' => 'elementor_ea11y_campaign',
465 'campaign' => 'acc-statement-plg-pages-one-activate',
466 'source' => 'wp-pages-one-activate',
467 'medium' => 'wp-dash-one',
468 ];
469 }
470 } else {
471 $description = esc_html__( "Create a more inclusive site experience for all your visitors. With Web Accessibility, it's easy to add your statement page in just a few clicks.", 'elementor' );
472 $learn_more_url = 'https://go.elementor.com/acc-plg-learn-more';
473
474 if ( ! $is_installed ) {
475 $button_text = esc_html__( 'Install now', 'elementor' );
476 $button_url = $this->get_plugin_button_install_url( $plugin_slug );
477 $campaign_data = [
478 'name' => 'elementor_ea11y_campaign',
479 'campaign' => 'acc-statement-plg-pages-install',
480 'source' => 'wp-pages-install',
481 'medium' => 'wp-dash',
482 ];
483 } elseif ( ! $is_active ) {
484 $button_text = esc_html__( 'Activate now', 'elementor' );
485 $button_url = $this->get_plugin_button_activate_url( $plugin_file_path );
486 $campaign_data = [
487 'name' => 'elementor_ea11y_campaign',
488 'campaign' => 'acc-statement-plg-pages-activate',
489 'source' => 'wp-pages-activate',
490 'medium' => 'wp-dash',
491 ];
492 }
493 }
494
495 $options = [
496 'title' => esc_html__( 'Make sure your site has an accessibility statement page', 'elementor' ),
497 'description' => $description,
498 'id' => $notice_id,
499 'type' => 'cta',
500 'button' => [
501 'text' => $button_text,
502 'url' => self::add_plg_campaign_data( $button_url, $campaign_data ),
503 'type' => 'cta',
504 ],
505 'button_secondary' => [
506 'text' => esc_html__( 'Learn more', 'elementor' ),
507 'url' => $learn_more_url,
508 'new_tab' => true,
509 'type' => 'cta',
510 ],
511 ];
512
513 $this->print_admin_notice( $options );
514
515 return true;
516 }
517
518 private function is_elementor_page(): bool {
519 return 0 === strpos( $this->current_screen_id, 'elementor_page' );
520 }
521
522 private function is_elementor_admin_screen(): bool {
523 return in_array( $this->current_screen_id, [ 'toplevel_page_elementor', 'edit-elementor_library' ], true );
524 }
525
526 private function is_elementor_admin_screen_with_system_info(): bool {
527 return in_array( $this->current_screen_id, [ 'toplevel_page_elementor', 'edit-elementor_library', 'elementor_page_elementor-system-info', 'dashboard' ], true );
528 }
529 private function get_plugin_button_install_url( $plugin_slug ) {
530 return wp_nonce_url( self_admin_url( 'update.php?action=install-plugin&plugin=' . $plugin_slug ), 'install-plugin_' . $plugin_slug );
531 }
532
533 private function get_plugin_button_activate_url( $plugin_file_path ) {
534 return wp_nonce_url( 'plugins.php?action=activate&amp;plugin=' . $plugin_file_path . '&amp;plugin_status=all&amp;paged=1&amp;s', 'activate-plugin_' . $plugin_file_path );
535 }
536
537 private function get_plugin_button_connect_url( $plugin_settings_page ) {
538 return self_admin_url( $plugin_settings_page );
539 }
540
541 private function get_plugin_cta_data( $plugin_slug, $plugin_file_path ) {
542 if ( Hints::is_plugin_active( $plugin_slug ) ) {
543 return false;
544 }
545
546 if ( Hints::is_plugin_installed( $plugin_slug ) ) {
547 $url = $this->get_plugin_button_activate_url( $plugin_file_path );
548 $cta_text = esc_html__( 'Activate now', 'elementor' );
549 } else {
550 $url = $this->get_plugin_button_install_url( $plugin_slug );
551 $cta_text = esc_html__( 'Install now', 'elementor' );
552 }
553
554 return [
555 'url' => $url,
556 'text' => $cta_text,
557 ];
558 }
559
560 /**
561 * For testing purposes
562 */
563 public function get_elementor_version() {
564 return ELEMENTOR_VERSION;
565 }
566
567 private function notice_plugin_image_optimization() {
568 $notice_id = 'plugin_image_optimization';
569
570 if ( 'upload' !== $this->current_screen_id ) {
571 return false;
572 }
573
574 if ( ! current_user_can( 'manage_options' ) ) {
575 return false;
576 }
577
578 if ( User::is_user_notice_viewed( $notice_id ) ) {
579 return false;
580 }
581
582 $attachments = new \WP_Query( [
583 'post_type' => 'attachment',
584 'post_status' => 'any',
585 'fields' => 'ids',
586 ] );
587
588 if ( 1 > $attachments->found_posts ) {
589 return false;
590 }
591
592 $plugin_slug = 'image-optimization';
593 $plugin_file_path = 'image-optimization/image-optimization.php';
594
595 $one_subscription = Hints::is_plugin_connected_to_one_subscription();
596 $is_installed = Hints::is_plugin_installed( $plugin_slug );
597 $is_active = Hints::is_plugin_active( $plugin_slug );
598
599 if ( $is_active ) {
600 return false;
601 }
602
603 if ( $one_subscription ) {
604 if ( ! $is_installed ) {
605 $description = esc_html__( 'Automatically optimize images to improve site speed and performance. Included with your ONE subscription.', 'elementor' );
606 $button_text = esc_html__( 'Install now', 'elementor' );
607 $button_url = $this->get_plugin_button_install_url( $plugin_slug );
608 $campaign_data = [
609 'name' => 'elementor_image_optimization_campaign',
610 'campaign' => 'io-plg-one',
611 'source' => 'io-wp-media-library-one-install',
612 'medium' => 'wp-dash-one',
613 ];
614 } elseif ( ! $is_active ) {
615 $description = esc_html__( 'Your ONE subscription includes Image Optimization. Activate it to optimize images and improve site performance.', 'elementor' );
616 $button_text = esc_html__( 'Activate now', 'elementor' );
617 $button_url = $this->get_plugin_button_activate_url( $plugin_file_path );
618 $campaign_data = [
619 'name' => 'elementor_image_optimization_campaign',
620 'campaign' => 'io-plg-one',
621 'source' => 'io-wp-media-library-one-activate',
622 'medium' => 'wp-dash-one',
623 ];
624 }
625 } else {
626 $description = esc_html__( 'Automatically compress and optimize images, resize larger files, or convert to WebP. Optimize images individually, in bulk, or on upload.', 'elementor' );
627
628 if ( ! $is_installed ) {
629 $button_text = esc_html__( 'Install now', 'elementor' );
630 $button_url = $this->get_plugin_button_install_url( $plugin_slug );
631 $campaign_data = [
632 'name' => 'elementor_image_optimization_campaign',
633 'campaign' => 'io-plg',
634 'source' => 'io-wp-media-library-install',
635 'medium' => 'wp-dash',
636 ];
637 } elseif ( ! $is_active ) {
638 $button_text = esc_html__( 'Activate now', 'elementor' );
639 $button_url = $this->get_plugin_button_activate_url( $plugin_file_path );
640 $campaign_data = [
641 'name' => 'elementor_image_optimization_campaign',
642 'campaign' => 'io-plg',
643 'source' => 'io-wp-media-library-activate',
644 'medium' => 'wp-dash',
645 ];
646 }
647 }
648
649 $options = [
650 'title' => esc_html__( 'Speed up your website with Image Optimization', 'elementor' ),
651 'description' => $description,
652 'id' => $notice_id,
653 'type' => 'cta',
654 'button' => [
655 'text' => $button_text,
656 'url' => self::add_plg_campaign_data( $button_url, $campaign_data ),
657 'type' => 'cta',
658 'data' => [
659 'campaign' => $campaign_data['campaign'],
660 'source' => $campaign_data['source'],
661 'medium' => $campaign_data['medium'],
662 ],
663 ],
664 ];
665
666 $this->print_admin_notice( $options );
667
668 return true;
669 }
670
671 public function print_admin_notice( array $options, $exclude_pages = self::DEFAULT_EXCLUDED_PAGES ) {
672 global $pagenow;
673
674 if ( in_array( $pagenow, $exclude_pages, true ) ) {
675 return;
676 }
677
678 $default_options = [
679 'id' => null,
680 'title' => '',
681 'description' => '',
682 'classes' => [ 'notice', 'e-notice' ], // We include WP's default notice class so it will be properly handled by WP's js handler
683 'type' => '',
684 'dismissible' => true,
685 'icon' => 'eicon-elementor-circle',
686 'button' => [],
687 'button_secondary' => [],
688 ];
689
690 $options = array_replace_recursive( $default_options, $options );
691
692 $notice_classes = $options['classes'];
693 $dismiss_button = '';
694 $icon = '';
695
696 if ( $options['type'] ) {
697 $notice_classes[] = 'e-notice--' . $options['type'];
698 }
699
700 $wrapper_attributes = [
701 'role' => 'region',
702 'aria-label' => esc_html__( 'Elementor notice', 'elementor' ),
703 ];
704
705 if ( $options['dismissible'] ) {
706 $label = esc_html__( 'Dismiss this notice.', 'elementor' );
707 $notice_classes[] = 'e-notice--dismissible';
708 $dismiss_button = '<i class="e-notice__dismiss" role="button" aria-label="' . $label . '" tabindex="0"></i>';
709
710 $wrapper_attributes['data-nonce'] = wp_create_nonce( 'elementor_set_admin_notice_viewed' );
711 }
712
713 if ( $options['icon'] ) {
714 $notice_classes[] = 'e-notice--extended';
715 $icon = '<div class="e-notice__icon-wrapper"><i class="' . esc_attr( $options['icon'] ) . '" aria-hidden="true"></i></div>';
716 }
717
718 $wrapper_attributes['class'] = $notice_classes;
719
720 if ( $options['id'] ) {
721 $wrapper_attributes['data-notice_id'] = $options['id'];
722 }
723
724 if ( ! empty( $options['source'] ) ) {
725 $wrapper_attributes['data-source'] = $options['source'];
726 }
727 ?>
728 <div <?php Utils::print_html_attributes( $wrapper_attributes ); ?>>
729 <?php echo $dismiss_button; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
730 <div class="e-notice__aside">
731 <?php echo $icon; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
732 </div>
733 <div class="e-notice__content">
734 <?php if ( $options['title'] ) { ?>
735 <h3><?php echo wp_kses_post( $options['title'] ); ?></h3>
736 <?php } ?>
737
738 <?php if ( $options['description'] ) { ?>
739 <p><?php echo wp_kses_post( $options['description'] ); ?></p>
740 <?php } ?>
741
742 <?php if ( ! empty( $options['button']['text'] ) || ! empty( $options['button_secondary']['text'] ) ) { ?>
743 <div class="e-notice__actions">
744 <?php
745 $one_subscription = Hints::is_plugin_connected_to_one_subscription();
746 foreach ( [ $options['button'], $options['button_secondary'] ] as $index => $button_settings ) {
747 if ( empty( $button_settings['variant'] ) && $index ) {
748 $button_settings['variant'] = 'outline';
749 }
750
751 if ( empty( $button_settings['text'] ) ) {
752 continue;
753 }
754
755 if ( $one_subscription ) {
756 if ( ! isset( $button_settings['classes'] ) ) {
757 $button_settings['classes'] = [];
758 }
759 if ( ! is_array( $button_settings['classes'] ) ) {
760 $button_settings['classes'] = [ $button_settings['classes'] ];
761 }
762 // index 0 = button, index 1 = button_secondary
763 $button_class = ( 0 === $index ) ? 'button-primary' : 'button-secondary';
764 $button_settings['classes'][] = $button_class;
765 }
766
767 $button = new Button( $button_settings );
768 $button->print_button();
769 } ?>
770 </div>
771 <?php } ?>
772 </div>
773 </div>
774 <?php }
775
776 public function admin_notices() {
777 $this->install_time = Plugin::$instance->get_install_time();
778 $this->current_screen_id = get_current_screen()->id;
779
780 foreach ( $this->plain_notices as $notice ) {
781 $method_callback = "notice_{$notice}";
782 if ( $this->$method_callback() ) {
783 return;
784 }
785 }
786
787 /** @var Base_Notice $notice_instance */
788 foreach ( $this->get_notices() as $notice_instance ) {
789 if ( ! $notice_instance->should_print() ) {
790 continue;
791 }
792
793 $this->print_admin_notice( $notice_instance->get_config() );
794
795 // It exits the method to make sure it prints only one notice.
796 return;
797 }
798 }
799
800 public function maybe_log_campaign() {
801 if ( empty( $_GET['plg_campaign'] ) || empty( $_GET['plg_campaign_name'] ) ) {
802 return;
803 }
804
805 $allowed_plgs = [
806 'elementor_image_optimization_campaign',
807 'elementor_ea11y_campaign',
808 ];
809
810 if ( ! in_array( $_GET['plg_campaign_name'], $allowed_plgs, true ) ) {
811 return;
812 }
813
814 if ( ! isset( $_GET['plg_campaign_nonce'] ) || ! wp_verify_nonce( sanitize_key( $_GET['plg_campaign_nonce'] ), sanitize_key( $_GET['plg_campaign_name'] ) ) ) {
815 return;
816 }
817
818 if ( ! current_user_can( 'manage_options' ) ) {
819 return;
820 }
821
822 if ( empty( $_GET['plg_source'] ) || empty( $_GET['plg_medium'] ) ) {
823 return;
824 }
825
826 $campaign_data = [
827 'source' => sanitize_key( $_GET['plg_source'] ),
828 'campaign' => sanitize_key( $_GET['plg_campaign'] ),
829 'medium' => sanitize_key( $_GET['plg_medium'] ),
830 ];
831
832 set_transient( sanitize_key( $_GET['plg_campaign_name'] ), $campaign_data, 30 * DAY_IN_SECONDS );
833 }
834
835 public static function add_plg_campaign_data( $url, $campaign_data ) {
836
837 foreach ( [ 'name', 'campaign' ] as $key ) {
838 if ( empty( $campaign_data[ $key ] ) ) {
839 return $url;
840 }
841 }
842
843 return add_query_arg( [
844 'plg_campaign_name' => $campaign_data['name'],
845 'plg_campaign' => $campaign_data['campaign'],
846 'plg_source' => empty( $campaign_data['source'] ) ? '' : $campaign_data['source'],
847 'plg_medium' => empty( $campaign_data['medium'] ) ? '' : $campaign_data['medium'],
848 'plg_campaign_nonce' => wp_create_nonce( $campaign_data['name'] ),
849 ], $url );
850 }
851
852 /**
853 * @since 2.9.0
854 * @access public
855 */
856 public function __construct() {
857 add_action( 'admin_notices', [ $this, 'admin_notices' ], 20 );
858 add_action( 'admin_action_install-plugin', [ $this, 'maybe_log_campaign' ] );
859 add_action( 'admin_action_activate', [ $this, 'maybe_log_campaign' ] );
860 }
861
862 /**
863 * Get module name.
864 *
865 * Retrieve the module name.
866 *
867 * @since 2.9.0
868 * @access public
869 *
870 * @return string Module name.
871 */
872 public function get_name() {
873 return 'admin-notices';
874 }
875 }
876