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

554 lines 15.9 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\Plugin;
8 use Elementor\Tracker;
9 use Elementor\User;
10 use Elementor\Utils;
11 use Elementor\Core\Admin\Notices\Base_Notice;
12 use Elementor\Core\Admin\Notices\Elementor_Dev_Notice;
13
14 if ( ! defined( 'ABSPATH' ) ) {
15 exit; // Exit if accessed directly.
16 }
17
18 class Admin_Notices extends Module {
19
20 const DEFAULT_EXCLUDED_PAGES = [ 'plugins.php', 'plugin-install.php', 'plugin-editor.php' ];
21
22 private $plain_notices = [
23 'api_notice',
24 'api_upgrade_plugin',
25 'tracker',
26 'rate_us_feedback',
27 'role_manager_promote',
28 'experiment_promotion',
29 'design_not_appearing',
30 ];
31
32 private $elementor_pages_count = null;
33
34 private $install_time = null;
35
36 private $current_screen_id = null;
37
38 private function get_notices() {
39 $notices = [
40 new Elementor_Dev_Notice(),
41 ];
42
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 addons.
50 *
51 * @param array $notices A list of notice classes.
52 */
53 $notices = apply_filters( 'elementor/core/admin/notices', $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 ( ! in_array( $this->current_screen_id, [ 'toplevel_page_elementor', 'edit-elementor_library', 'elementor_page_elementor-system-info', 'dashboard' ], true ) ) {
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 esc_attr( sprintf(
136 /* translators: %s: Elementor version. */
137 __( 'View Elementor version %s details', 'elementor' ),
138 $new_version
139 ) ),
140 $new_version,
141 esc_url( $upgrade_url ),
142 esc_attr( esc_html__( '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 ( ! in_array( $this->current_screen_id, [ 'toplevel_page_elementor', 'edit-elementor_library', 'elementor_page_elementor-system-info', 'dashboard' ], true ) ) {
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 opting in to share non-sensitive plugin data and to receive periodic email updates from us.', '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__( 'Love using Elementor?', 'elementor' ),
234 'description' => $message,
235 'button' => [
236 'text' => esc_html__( 'Sure! I\'d love to help', 'elementor' ),
237 'url' => $optin_url,
238 'type' => 'cta',
239 ],
240 'button_secondary' => [
241 'text' => esc_html__( 'No thanks', 'elementor' ),
242 'url' => $optout_url,
243 'variant' => 'outline',
244 'type' => 'cta',
245 ],
246 ];
247
248 $this->print_admin_notice( $options );
249
250 return true;
251 }
252
253 private function notice_rate_us_feedback() {
254 $notice_id = 'rate_us_feedback';
255
256 if ( ! current_user_can( 'manage_options' ) ) {
257 return false;
258 }
259
260 if ( 'dashboard' !== $this->current_screen_id || User::is_user_notice_viewed( $notice_id ) ) {
261 return false;
262 }
263
264 if ( 10 >= $this->get_elementor_pages_count() ) {
265 return false;
266 }
267
268 $dismiss_url = add_query_arg( [
269 'action' => 'elementor_set_admin_notice_viewed',
270 'notice_id' => esc_attr( $notice_id ),
271 ], admin_url( 'admin-post.php' ) );
272
273 $options = [
274 'title' => esc_html__( 'Congrats!', 'elementor' ),
275 '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' ),
276 'id' => $notice_id,
277 'button' => [
278 'text' => esc_html__( 'Happy To Help', 'elementor' ),
279 'url' => 'https://go.elementor.com/admin-review/',
280 'new_tab' => true,
281 'type' => 'cta',
282 ],
283 'button_secondary' => [
284 'text' => esc_html__( 'Hide Notification', 'elementor' ),
285 'classes' => [ 'e-notice-dismiss' ],
286 'url' => esc_url_raw( $dismiss_url ),
287 'new_tab' => true,
288 'type' => 'cta',
289 ],
290 ];
291
292 $this->print_admin_notice( $options );
293
294 return true;
295 }
296
297 private function notice_role_manager_promote() {
298 $notice_id = 'role_manager_promote';
299
300 if ( Utils::has_pro() ) {
301 return false;
302 }
303
304 if ( ! current_user_can( 'manage_options' ) ) {
305 return false;
306 }
307
308 if ( 'elementor_page_elementor-role-manager' !== $this->current_screen_id || User::is_user_notice_viewed( $notice_id ) ) {
309 return false;
310 }
311
312 $users = new \WP_User_Query( [
313 'fields' => 'ID',
314 'number' => 10,
315 ] );
316
317 if ( 5 > $users->get_total() ) {
318 return false;
319 }
320
321 $options = [
322 'title' => esc_html__( 'Managing a multi-user site?', 'elementor' ),
323 'description' => esc_html__( 'With Elementor Pro, you can control user access and make sure no one messes up your design.', 'elementor' ),
324 'id' => $notice_id,
325
326 'button' => [
327 'text' => esc_html__( 'Learn More', 'elementor' ),
328 'url' => 'https://go.elementor.com/plugin-promotion-role-manager/',
329 'new_tab' => true,
330 'type' => 'cta',
331 ],
332 ];
333
334 $this->print_admin_notice( $options );
335
336 return true;
337 }
338
339 private function notice_experiment_promotion() {
340 $notice_id = 'experiment_promotion';
341
342 if ( ! current_user_can( 'manage_options' ) || User::is_user_notice_viewed( $notice_id ) ) {
343 return false;
344 }
345
346 $experiments = Plugin::$instance->experiments;
347 $is_all_performance_features_active = (
348 $experiments->is_feature_active( 'additional_custom_breakpoints' ) &&
349 $experiments->is_feature_active( 'e_optimized_css_loading' ) &&
350 $experiments->is_feature_active( 'e_optimized_assets_loading' )
351 );
352
353 if ( $is_all_performance_features_active ) {
354 return false;
355 }
356
357 $options = [
358 'title' => esc_html__( 'Improve your site’s performance score.', 'elementor' ),
359 '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' ),
360 'id' => $notice_id,
361 'button' => [
362 'text' => esc_html__( 'Try it out', 'elementor' ),
363 'url' => admin_url( 'admin.php?page=elementor#tab-experiments' ),
364 'type' => 'cta',
365 ],
366 'button_secondary' => [
367 'text' => esc_html__( 'Learn more', 'elementor' ),
368 'url' => 'https://go.elementor.com/wp-dash-experiment-promotion/',
369 'new_tab' => true,
370 'type' => 'cta',
371 ],
372 ];
373
374 $this->print_admin_notice( $options );
375
376 return true;
377 }
378
379 private function notice_design_not_appearing() {
380 $installs_history = get_option( 'elementor_install_history', [] );
381 $is_first_install = 1 === count( $installs_history );
382
383 if ( $is_first_install || ! current_user_can( 'update_plugins' ) ) {
384 return false;
385 }
386
387 $notice_id = 'design_not_appearing';
388 $notice = User::get_user_notices()[ $notice_id ] ?? [];
389 $notice_version = $notice['meta']['version'] ?? null;
390 $is_version_changed = $this->get_elementor_version() !== $notice_version;
391
392 if ( $is_version_changed ) {
393 User::set_user_notice( $notice_id, false, [ 'version' => $this->get_elementor_version() ] );
394 }
395
396 if ( ! in_array( $this->current_screen_id, [ 'toplevel_page_elementor', 'edit-elementor_library', 'elementor_page_elementor-system-info', 'dashboard', 'update-core', 'plugins' ], true ) ) {
397 return false;
398 }
399
400 if ( User::is_user_notice_viewed( $notice_id ) ) {
401 return false;
402 }
403
404 $options = [
405 'title' => esc_html__( 'The version was updated successfully!', 'elementor' ),
406 'description' => sprintf(
407 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' ),
408 '<a href="https://go.elementor.com/wp-dash-changes-do-not-appear-online/" target="_blank">',
409 '</a>'
410 ),
411 'id' => $notice_id,
412 ];
413
414 $excluded_pages = [];
415 $this->print_admin_notice( $options, $excluded_pages );
416
417 return true;
418 }
419
420 // For testing purposes
421 public function get_elementor_version() {
422 return ELEMENTOR_VERSION;
423 }
424
425 public function print_admin_notice( array $options, $exclude_pages = self::DEFAULT_EXCLUDED_PAGES ) {
426 global $pagenow;
427
428 if ( in_array( $pagenow, $exclude_pages, true ) ) {
429 return;
430 }
431
432 $default_options = [
433 'id' => null,
434 'title' => '',
435 'description' => '',
436 'classes' => [ 'notice', 'e-notice' ], // We include WP's default notice class so it will be properly handled by WP's js handler
437 'type' => '',
438 'dismissible' => true,
439 'icon' => 'eicon-elementor',
440 'button' => [],
441 'button_secondary' => [],
442 ];
443
444 $options = array_replace_recursive( $default_options, $options );
445
446 $notice_classes = $options['classes'];
447 $dismiss_button = '';
448 $icon = '';
449
450 if ( $options['type'] ) {
451 $notice_classes[] = 'e-notice--' . $options['type'];
452 }
453
454 if ( $options['dismissible'] ) {
455 $label = esc_html__( 'Dismiss this notice.', 'elementor' );
456 $notice_classes[] = 'e-notice--dismissible';
457 $dismiss_button = '<i class="e-notice__dismiss" role="button" aria-label="' . $label . '" tabindex="0"></i>';
458 }
459
460 if ( $options['icon'] ) {
461 $notice_classes[] = 'e-notice--extended';
462 $icon = '<div class="e-notice__icon-wrapper"><i class="' . esc_attr( $options['icon'] ) . '" aria-hidden="true"></i></div>';
463 }
464
465 $wrapper_attributes = [
466 'class' => $notice_classes,
467 ];
468
469 if ( $options['id'] ) {
470 $wrapper_attributes['data-notice_id'] = $options['id'];
471 }
472 ?>
473 <div <?php Utils::print_html_attributes( $wrapper_attributes ); ?>>
474 <?php echo $dismiss_button; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
475 <div class="e-notice__aside">
476 <?php echo $icon; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
477 </div>
478 <div class="e-notice__content">
479 <?php if ( $options['title'] ) { ?>
480 <h3><?php echo wp_kses_post( $options['title'] ); ?></h3>
481 <?php } ?>
482
483 <?php if ( $options['description'] ) { ?>
484 <p><?php echo wp_kses_post( $options['description'] ); ?></p>
485 <?php } ?>
486
487 <?php if ( ! empty( $options['button']['text'] ) || ! empty( $options['button_secondary']['text'] ) ) { ?>
488 <div class="e-notice__actions">
489 <?php
490 foreach ( [ $options['button'], $options['button_secondary'] ] as $index => $button_settings ) {
491 if ( empty( $button_settings['variant'] ) && $index ) {
492 $button_settings['variant'] = 'outline';
493 }
494
495 if ( empty( $button_settings['text'] ) ) {
496 continue;
497 }
498
499 $button = new Button( $button_settings );
500 $button->print_button();
501 } ?>
502 </div>
503 <?php } ?>
504 </div>
505 </div>
506 <?php }
507
508 public function admin_notices() {
509 $this->install_time = Plugin::$instance->get_install_time();
510 $this->current_screen_id = get_current_screen()->id;
511
512 foreach ( $this->plain_notices as $notice ) {
513 $method_callback = "notice_{$notice}";
514 if ( $this->$method_callback() ) {
515 return;
516 }
517 }
518
519 /** @var Base_Notice $notice_instance */
520 foreach ( $this->get_notices() as $notice_instance ) {
521 if ( ! $notice_instance->should_print() ) {
522 continue;
523 }
524
525 $this->print_admin_notice( $notice_instance->get_config() );
526
527 // It exits the method to make sure it prints only one notice.
528 return;
529 }
530 }
531
532 /**
533 * @since 2.9.0
534 * @access public
535 */
536 public function __construct() {
537 add_action( 'admin_notices', [ $this, 'admin_notices' ], 20 );
538 }
539
540 /**
541 * Get module name.
542 *
543 * Retrieve the module name.
544 *
545 * @since 2.9.0
546 * @access public
547 *
548 * @return string Module name.
549 */
550 public function get_name() {
551 return 'admin-notices';
552 }
553 }
554