PluginProbe
Elementor Website Builder – more than just a page builder / 3.21.0-beta2
Elementor Website Builder – more than just a page builder v3.21.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 3.21.0-beta2, at core/admin/admin-notices.php

556 lines 16.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\Promotions\Filtered_Promotions_Manager;
8 use Elementor\Plugin;
9 use Elementor\Tracker;
10 use Elementor\User;
11 use Elementor\Utils;
12 use Elementor\Core\Admin\Notices\Base_Notice;
13 use Elementor\Core\Admin\Notices\Elementor_Dev_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 private $plain_notices = [
24 'api_notice',
25 'api_upgrade_plugin',
26 'tracker',
27 'rate_us_feedback',
28 'role_manager_promote',
29 'experiment_promotion',
30 'design_not_appearing',
31 ];
32
33 private $elementor_pages_count = null;
34
35 private $install_time = null;
36
37 private $current_screen_id = null;
38
39 private function get_notices() {
40 $notices = [
41 new Elementor_Dev_Notice(),
42 ];
43
44 /**
45 * Admin notices.
46 *
47 * Filters Elementor admin notices.
48 *
49 * This hook can be used by external developers to manage existing
50 * admin notice or to add new notices for Elementor add-ons.
51 *
52 * @param array $notices A list of notice classes.
53 */
54 $notices = apply_filters( 'elementor/core/admin/notices', $notices );
55
56 return $notices;
57 }
58
59 private function get_install_time() {
60 if ( null === $this->install_time ) {
61 $this->install_time = Plugin::$instance->get_install_time();
62 }
63
64 return $this->install_time;
65 }
66
67 private function get_elementor_pages_count() {
68 if ( null === $this->elementor_pages_count ) {
69 $elementor_pages = new \WP_Query( [
70 'no_found_rows' => true,
71 'post_type' => 'any',
72 'post_status' => 'publish',
73 'fields' => 'ids',
74 'update_post_meta_cache' => false,
75 'update_post_term_cache' => false,
76 'meta_key' => '_elementor_edit_mode',
77 'meta_value' => 'builder',
78 ] );
79
80 $this->elementor_pages_count = $elementor_pages->post_count;
81 }
82
83 return $this->elementor_pages_count;
84 }
85
86 private function notice_api_upgrade_plugin() {
87 $upgrade_notice = Api::get_upgrade_notice();
88 if ( empty( $upgrade_notice ) ) {
89 return false;
90 }
91
92 if ( ! current_user_can( 'update_plugins' ) ) {
93 return false;
94 }
95
96 if ( ! in_array( $this->current_screen_id, [ 'toplevel_page_elementor', 'edit-elementor_library', 'elementor_page_elementor-system-info', 'dashboard' ], true ) ) {
97 return false;
98 }
99
100 // Check for upgrades.
101 $update_plugins = get_site_transient( 'update_plugins' );
102
103 $has_remote_update_package = ! ( empty( $update_plugins ) || empty( $update_plugins->response[ ELEMENTOR_PLUGIN_BASE ] ) || empty( $update_plugins->response[ ELEMENTOR_PLUGIN_BASE ]->package ) );
104
105 if ( ! $has_remote_update_package && empty( $upgrade_notice['update_link'] ) ) {
106 return false;
107 }
108
109 if ( $has_remote_update_package ) {
110 $product = $update_plugins->response[ ELEMENTOR_PLUGIN_BASE ];
111
112 $details_url = self_admin_url( 'plugin-install.php?tab=plugin-information&plugin=' . $product->slug . '&section=changelog&TB_iframe=true&width=600&height=800' );
113 $upgrade_url = wp_nonce_url( self_admin_url( 'update.php?action=upgrade-plugin&plugin=' . ELEMENTOR_PLUGIN_BASE ), 'upgrade-plugin_' . ELEMENTOR_PLUGIN_BASE );
114 $new_version = $product->new_version;
115 } else {
116 $upgrade_url = $upgrade_notice['update_link'];
117 $details_url = $upgrade_url;
118
119 $new_version = $upgrade_notice['version'];
120 }
121
122 // Check if upgrade messages should be shown.
123 if ( version_compare( ELEMENTOR_VERSION, $upgrade_notice['version'], '>=' ) ) {
124 return false;
125 }
126
127 $notice_id = 'upgrade_notice_' . $upgrade_notice['version'];
128 if ( User::is_user_notice_viewed( $notice_id ) ) {
129 return false;
130 }
131
132 $message = sprintf(
133 /* translators: 1: Details URL, 2: Accessibility text, 3: Version number, 4: Update URL, 5: Accessibility text. */
134 __( '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' ),
135 esc_url( $details_url ),
136 esc_attr( sprintf(
137 /* translators: %s: Elementor version. */
138 __( 'View Elementor version %s details', 'elementor' ),
139 $new_version
140 ) ),
141 $new_version,
142 esc_url( $upgrade_url ),
143 esc_attr( esc_html__( 'Update Now', 'elementor' ) )
144 );
145
146 $options = [
147 'title' => esc_html__( 'Update Notification', 'elementor' ),
148 'description' => $message,
149 'button' => [
150 'icon_classes' => 'dashicons dashicons-update',
151 'text' => esc_html__( 'Update Now', 'elementor' ),
152 'url' => $upgrade_url,
153 ],
154 'id' => $notice_id,
155 ];
156
157 $this->print_admin_notice( $options );
158
159 return true;
160 }
161
162 private function notice_api_notice() {
163 $admin_notice = Api::get_admin_notice();
164 if ( empty( $admin_notice ) ) {
165 return false;
166 }
167
168 if ( ! current_user_can( 'manage_options' ) ) {
169 return false;
170 }
171
172 if ( ! in_array( $this->current_screen_id, [ 'toplevel_page_elementor', 'edit-elementor_library', 'elementor_page_elementor-system-info', 'dashboard' ], true ) ) {
173 return false;
174 }
175
176 $notice_id = 'admin_notice_api_' . $admin_notice['notice_id'];
177 if ( User::is_user_notice_viewed( $notice_id ) ) {
178 return false;
179 }
180
181 $options = [
182 'title' => esc_html__( 'Update Notification', 'elementor' ),
183 'description' => $admin_notice['notice_text'],
184 'id' => $notice_id,
185 ];
186
187 $this->print_admin_notice( $options );
188
189 return true;
190 }
191
192 private function notice_tracker() {
193 if ( ! current_user_can( 'manage_options' ) ) {
194 return false;
195 }
196
197 // Show tracker notice after 24 hours from installed time.
198 if ( strtotime( '+24 hours', $this->get_install_time() ) > time() ) {
199 return false;
200 }
201
202 if ( '1' === get_option( 'elementor_tracker_notice' ) ) {
203 return false;
204 }
205
206 if ( Tracker::is_allow_track() ) {
207 return false;
208 }
209
210 if ( 2 > $this->get_elementor_pages_count() ) {
211 return false;
212 }
213
214 // TODO: Skip for development env.
215 $optin_url = wp_nonce_url( add_query_arg( 'elementor_tracker', 'opt_into' ), 'opt_into' );
216 $optout_url = wp_nonce_url( add_query_arg( 'elementor_tracker', 'opt_out' ), 'opt_out' );
217
218 $tracker_description_text = esc_html__( 'Become a super contributor by opting in to share non-sensitive plugin data and to receive periodic email updates from us.', 'elementor' );
219
220 /**
221 * Tracker admin description text.
222 *
223 * Filters the admin notice text for non-sensitive data collection.
224 *
225 * @since 1.0.0
226 *
227 * @param string $tracker_description_text Description text displayed in admin notice.
228 */
229 $tracker_description_text = apply_filters( 'elementor/tracker/admin_description_text', $tracker_description_text );
230
231 $message = esc_html( $tracker_description_text ) . ' <a href="https://go.elementor.com/usage-data-tracking/" target="_blank">' . esc_html__( 'Learn more.', 'elementor' ) . '</a>';
232
233 $options = [
234 'title' => esc_html__( 'Love using Elementor?', 'elementor' ),
235 'description' => $message,
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_rate_us_feedback() {
255 $notice_id = 'rate_us_feedback';
256
257 if ( ! current_user_can( 'manage_options' ) ) {
258 return false;
259 }
260
261 if ( 'dashboard' !== $this->current_screen_id || User::is_user_notice_viewed( $notice_id ) ) {
262 return false;
263 }
264
265 if ( 10 >= $this->get_elementor_pages_count() ) {
266 return false;
267 }
268
269 $dismiss_url = add_query_arg( [
270 'action' => 'elementor_set_admin_notice_viewed',
271 'notice_id' => esc_attr( $notice_id ),
272 ], admin_url( 'admin-post.php' ) );
273
274 $options = [
275 'title' => esc_html__( 'Congrats!', 'elementor' ),
276 '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' ),
277 'id' => $notice_id,
278 'button' => [
279 'text' => esc_html__( 'Happy To Help', 'elementor' ),
280 'url' => 'https://go.elementor.com/admin-review/',
281 'new_tab' => true,
282 'type' => 'cta',
283 ],
284 'button_secondary' => [
285 'text' => esc_html__( 'Hide Notification', 'elementor' ),
286 'classes' => [ 'e-notice-dismiss' ],
287 'url' => esc_url_raw( $dismiss_url ),
288 'new_tab' => true,
289 'type' => 'cta',
290 ],
291 ];
292
293 $this->print_admin_notice( $options );
294
295 return true;
296 }
297
298 private function notice_role_manager_promote() {
299 $notice_id = 'role_manager_promote';
300
301 if ( Utils::has_pro() ) {
302 return false;
303 }
304
305 if ( ! current_user_can( 'manage_options' ) ) {
306 return false;
307 }
308
309 if ( 'elementor_page_elementor-role-manager' !== $this->current_screen_id || User::is_user_notice_viewed( $notice_id ) ) {
310 return false;
311 }
312
313 $users = new \WP_User_Query( [
314 'fields' => 'ID',
315 'number' => 10,
316 ] );
317
318 if ( 5 > $users->get_total() ) {
319 return false;
320 }
321
322 $options = [
323 'title' => esc_html__( 'Managing a multi-user site?', 'elementor' ),
324 'description' => esc_html__( 'With Elementor Pro, you can control user access and make sure no one messes up your design.', 'elementor' ),
325 'id' => $notice_id,
326
327 'button' => [
328 'text' => esc_html__( 'Learn More', 'elementor' ),
329 'url' => 'https://go.elementor.com/plugin-promotion-role-manager/',
330 'new_tab' => true,
331 'type' => 'cta',
332 ],
333 ];
334
335 $options = Filtered_Promotions_Manager::get_filtered_promotion_data( $options, 'core/admin/notice_role_manager_promote', 'button', 'url' );
336
337 $this->print_admin_notice( $options );
338
339 return true;
340 }
341
342 private function notice_experiment_promotion() {
343 $notice_id = 'experiment_promotion';
344
345 if ( ! current_user_can( 'manage_options' ) || User::is_user_notice_viewed( $notice_id ) ) {
346 return false;
347 }
348
349 $experiments = Plugin::$instance->experiments;
350 $is_all_performance_features_active = (
351 $experiments->is_feature_active( 'additional_custom_breakpoints' ) &&
352 $experiments->is_feature_active( 'e_optimized_css_loading' )
353 );
354
355 if ( $is_all_performance_features_active ) {
356 return false;
357 }
358
359 $options = [
360 'title' => esc_html__( 'Improve your site’s performance score.', 'elementor' ),
361 'description' => esc_html__( 'With our experimental speed boosting features you can go faster than ever before. Look for the Performance label on our Experiments page and activate those experiments to improve your site loading speed.', 'elementor' ),
362 'id' => $notice_id,
363 'button' => [
364 'text' => esc_html__( 'Try it out', 'elementor' ),
365 'url' => admin_url( 'admin.php?page=elementor#tab-experiments' ),
366 'type' => 'cta',
367 ],
368 'button_secondary' => [
369 'text' => esc_html__( 'Learn more', 'elementor' ),
370 'url' => 'https://go.elementor.com/wp-dash-experiment-promotion/',
371 'new_tab' => true,
372 'type' => 'cta',
373 ],
374 ];
375
376 $this->print_admin_notice( $options );
377
378 return true;
379 }
380
381 private function notice_design_not_appearing() {
382 $installs_history = get_option( 'elementor_install_history', [] );
383 $is_first_install = 1 === count( $installs_history );
384
385 if ( $is_first_install || ! current_user_can( 'update_plugins' ) ) {
386 return false;
387 }
388
389 $notice_id = 'design_not_appearing';
390 $notice = User::get_user_notices()[ $notice_id ] ?? [];
391 $notice_version = $notice['meta']['version'] ?? null;
392 $is_version_changed = $this->get_elementor_version() !== $notice_version;
393
394 if ( $is_version_changed ) {
395 User::set_user_notice( $notice_id, false, [ 'version' => $this->get_elementor_version() ] );
396 }
397
398 if ( ! in_array( $this->current_screen_id, [ 'toplevel_page_elementor', 'edit-elementor_library', 'elementor_page_elementor-system-info', 'dashboard', 'update-core', 'plugins' ], true ) ) {
399 return false;
400 }
401
402 if ( User::is_user_notice_viewed( $notice_id ) ) {
403 return false;
404 }
405
406 $options = [
407 'title' => esc_html__( 'The version was updated successfully!', 'elementor' ),
408 'description' => sprintf(
409 esc_html__( 'Encountering issues after updating the version? Don’t worry - we’ve collected all the fixes for troubleshooting common issues. %1$sFind a solution%2$s', 'elementor' ),
410 '<a href="https://go.elementor.com/wp-dash-changes-do-not-appear-online/" target="_blank">',
411 '</a>'
412 ),
413 'id' => $notice_id,
414 ];
415
416 $excluded_pages = [];
417 $this->print_admin_notice( $options, $excluded_pages );
418
419 return true;
420 }
421
422 // For testing purposes
423 public function get_elementor_version() {
424 return ELEMENTOR_VERSION;
425 }
426
427 public function print_admin_notice( array $options, $exclude_pages = self::DEFAULT_EXCLUDED_PAGES ) {
428 global $pagenow;
429
430 if ( in_array( $pagenow, $exclude_pages, true ) ) {
431 return;
432 }
433
434 $default_options = [
435 'id' => null,
436 'title' => '',
437 'description' => '',
438 'classes' => [ 'notice', 'e-notice' ], // We include WP's default notice class so it will be properly handled by WP's js handler
439 'type' => '',
440 'dismissible' => true,
441 'icon' => 'eicon-elementor',
442 'button' => [],
443 'button_secondary' => [],
444 ];
445
446 $options = array_replace_recursive( $default_options, $options );
447
448 $notice_classes = $options['classes'];
449 $dismiss_button = '';
450 $icon = '';
451
452 if ( $options['type'] ) {
453 $notice_classes[] = 'e-notice--' . $options['type'];
454 }
455
456 if ( $options['dismissible'] ) {
457 $label = esc_html__( 'Dismiss this notice.', 'elementor' );
458 $notice_classes[] = 'e-notice--dismissible';
459 $dismiss_button = '<i class="e-notice__dismiss" role="button" aria-label="' . $label . '" tabindex="0"></i>';
460 }
461
462 if ( $options['icon'] ) {
463 $notice_classes[] = 'e-notice--extended';
464 $icon = '<div class="e-notice__icon-wrapper"><i class="' . esc_attr( $options['icon'] ) . '" aria-hidden="true"></i></div>';
465 }
466
467 $wrapper_attributes = [
468 'class' => $notice_classes,
469 ];
470
471 if ( $options['id'] ) {
472 $wrapper_attributes['data-notice_id'] = $options['id'];
473 }
474 ?>
475 <div <?php Utils::print_html_attributes( $wrapper_attributes ); ?>>
476 <?php echo $dismiss_button; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
477 <div class="e-notice__aside">
478 <?php echo $icon; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
479 </div>
480 <div class="e-notice__content">
481 <?php if ( $options['title'] ) { ?>
482 <h3><?php echo wp_kses_post( $options['title'] ); ?></h3>
483 <?php } ?>
484
485 <?php if ( $options['description'] ) { ?>
486 <p><?php echo wp_kses_post( $options['description'] ); ?></p>
487 <?php } ?>
488
489 <?php if ( ! empty( $options['button']['text'] ) || ! empty( $options['button_secondary']['text'] ) ) { ?>
490 <div class="e-notice__actions">
491 <?php
492 foreach ( [ $options['button'], $options['button_secondary'] ] as $index => $button_settings ) {
493 if ( empty( $button_settings['variant'] ) && $index ) {
494 $button_settings['variant'] = 'outline';
495 }
496
497 if ( empty( $button_settings['text'] ) ) {
498 continue;
499 }
500
501 $button = new Button( $button_settings );
502 $button->print_button();
503 } ?>
504 </div>
505 <?php } ?>
506 </div>
507 </div>
508 <?php }
509
510 public function admin_notices() {
511 $this->install_time = Plugin::$instance->get_install_time();
512 $this->current_screen_id = get_current_screen()->id;
513
514 foreach ( $this->plain_notices as $notice ) {
515 $method_callback = "notice_{$notice}";
516 if ( $this->$method_callback() ) {
517 return;
518 }
519 }
520
521 /** @var Base_Notice $notice_instance */
522 foreach ( $this->get_notices() as $notice_instance ) {
523 if ( ! $notice_instance->should_print() ) {
524 continue;
525 }
526
527 $this->print_admin_notice( $notice_instance->get_config() );
528
529 // It exits the method to make sure it prints only one notice.
530 return;
531 }
532 }
533
534 /**
535 * @since 2.9.0
536 * @access public
537 */
538 public function __construct() {
539 add_action( 'admin_notices', [ $this, 'admin_notices' ], 20 );
540 }
541
542 /**
543 * Get module name.
544 *
545 * Retrieve the module name.
546 *
547 * @since 2.9.0
548 * @access public
549 *
550 * @return string Module name.
551 */
552 public function get_name() {
553 return 'admin-notices';
554 }
555 }
556