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

555 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( 'e_dom_optimization' ) &&
349 $experiments->is_feature_active( 'additional_custom_breakpoints' ) &&
350 $experiments->is_feature_active( 'e_optimized_css_loading' ) &&
351 $experiments->is_feature_active( 'e_optimized_assets_loading' )
352 );
353
354 if ( $is_all_performance_features_active ) {
355 return false;
356 }
357
358 $options = [
359 'title' => esc_html__( 'Improve your site’s performance score.', 'elementor' ),
360 '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' ),
361 'id' => $notice_id,
362 'button' => [
363 'text' => esc_html__( 'Try it out', 'elementor' ),
364 'url' => admin_url( 'admin.php?page=elementor#tab-experiments' ),
365 'type' => 'cta',
366 ],
367 'button_secondary' => [
368 'text' => esc_html__( 'Learn more', 'elementor' ),
369 'url' => 'https://go.elementor.com/wp-dash-experiment-promotion/',
370 'new_tab' => true,
371 'type' => 'cta',
372 ],
373 ];
374
375 $this->print_admin_notice( $options );
376
377 return true;
378 }
379
380 private function notice_design_not_appearing() {
381 $installs_history = get_option( 'elementor_install_history', [] );
382 $is_first_install = 1 === count( $installs_history );
383
384 if ( $is_first_install || ! current_user_can( 'update_plugins' ) ) {
385 return false;
386 }
387
388 $notice_id = 'design_not_appearing';
389 $notice = User::get_user_notices()[ $notice_id ] ?? [];
390 $notice_version = $notice['meta']['version'] ?? null;
391 $is_version_changed = $this->get_elementor_version() !== $notice_version;
392
393 if ( $is_version_changed ) {
394 User::set_user_notice( $notice_id, false, [ 'version' => $this->get_elementor_version() ] );
395 }
396
397 if ( ! in_array( $this->current_screen_id, [ 'toplevel_page_elementor', 'edit-elementor_library', 'elementor_page_elementor-system-info', 'dashboard', 'update-core', 'plugins' ], true ) ) {
398 return false;
399 }
400
401 if ( User::is_user_notice_viewed( $notice_id ) ) {
402 return false;
403 }
404
405 $options = [
406 'title' => esc_html__( 'The version was updated successfully!', 'elementor' ),
407 'description' => sprintf(
408 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' ),
409 '<a href="https://go.elementor.com/wp-dash-changes-do-not-appear-online/" target="_blank">',
410 '</a>'
411 ),
412 'id' => $notice_id,
413 ];
414
415 $excluded_pages = [];
416 $this->print_admin_notice( $options, $excluded_pages );
417
418 return true;
419 }
420
421 // For testing purposes
422 public function get_elementor_version() {
423 return ELEMENTOR_VERSION;
424 }
425
426 public function print_admin_notice( array $options, $exclude_pages = self::DEFAULT_EXCLUDED_PAGES ) {
427 global $pagenow;
428
429 if ( in_array( $pagenow, $exclude_pages, true ) ) {
430 return;
431 }
432
433 $default_options = [
434 'id' => null,
435 'title' => '',
436 'description' => '',
437 'classes' => [ 'notice', 'e-notice' ], // We include WP's default notice class so it will be properly handled by WP's js handler
438 'type' => '',
439 'dismissible' => true,
440 'icon' => 'eicon-elementor',
441 'button' => [],
442 'button_secondary' => [],
443 ];
444
445 $options = array_replace_recursive( $default_options, $options );
446
447 $notice_classes = $options['classes'];
448 $dismiss_button = '';
449 $icon = '';
450
451 if ( $options['type'] ) {
452 $notice_classes[] = 'e-notice--' . $options['type'];
453 }
454
455 if ( $options['dismissible'] ) {
456 $label = esc_html__( 'Dismiss this notice.', 'elementor' );
457 $notice_classes[] = 'e-notice--dismissible';
458 $dismiss_button = '<i class="e-notice__dismiss" role="button" aria-label="' . $label . '" tabindex="0"></i>';
459 }
460
461 if ( $options['icon'] ) {
462 $notice_classes[] = 'e-notice--extended';
463 $icon = '<div class="e-notice__icon-wrapper"><i class="' . esc_attr( $options['icon'] ) . '" aria-hidden="true"></i></div>';
464 }
465
466 $wrapper_attributes = [
467 'class' => $notice_classes,
468 ];
469
470 if ( $options['id'] ) {
471 $wrapper_attributes['data-notice_id'] = $options['id'];
472 }
473 ?>
474 <div <?php Utils::print_html_attributes( $wrapper_attributes ); ?>>
475 <?php echo $dismiss_button; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
476 <div class="e-notice__aside">
477 <?php echo $icon; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
478 </div>
479 <div class="e-notice__content">
480 <?php if ( $options['title'] ) { ?>
481 <h3><?php echo wp_kses_post( $options['title'] ); ?></h3>
482 <?php } ?>
483
484 <?php if ( $options['description'] ) { ?>
485 <p><?php echo wp_kses_post( $options['description'] ); ?></p>
486 <?php } ?>
487
488 <?php if ( ! empty( $options['button']['text'] ) || ! empty( $options['button_secondary']['text'] ) ) { ?>
489 <div class="e-notice__actions">
490 <?php
491 foreach ( [ $options['button'], $options['button_secondary'] ] as $index => $button_settings ) {
492 if ( empty( $button_settings['variant'] ) && $index ) {
493 $button_settings['variant'] = 'outline';
494 }
495
496 if ( empty( $button_settings['text'] ) ) {
497 continue;
498 }
499
500 $button = new Button( $button_settings );
501 $button->print_button();
502 } ?>
503 </div>
504 <?php } ?>
505 </div>
506 </div>
507 <?php }
508
509 public function admin_notices() {
510 $this->install_time = Plugin::$instance->get_install_time();
511 $this->current_screen_id = get_current_screen()->id;
512
513 foreach ( $this->plain_notices as $notice ) {
514 $method_callback = "notice_{$notice}";
515 if ( $this->$method_callback() ) {
516 return;
517 }
518 }
519
520 /** @var Base_Notice $notice_instance */
521 foreach ( $this->get_notices() as $notice_instance ) {
522 if ( ! $notice_instance->should_print() ) {
523 continue;
524 }
525
526 $this->print_admin_notice( $notice_instance->get_config() );
527
528 // It exits the method to make sure it prints only one notice.
529 return;
530 }
531 }
532
533 /**
534 * @since 2.9.0
535 * @access public
536 */
537 public function __construct() {
538 add_action( 'admin_notices', [ $this, 'admin_notices' ], 20 );
539 }
540
541 /**
542 * Get module name.
543 *
544 * Retrieve the module name.
545 *
546 * @since 2.9.0
547 * @access public
548 *
549 * @return string Module name.
550 */
551 public function get_name() {
552 return 'admin-notices';
553 }
554 }
555