PluginProbe
WPSSO Core – Complete Schema Markup and Meta Tags / 22.7.0
WPSSO Core – Complete Schema Markup and Meta Tags v22.7.0
22.7.0 22.6.1 22.6.0 22.5.3 22.5.2 22.5.1 22.4.0 22.3.0 22.2.1 22.2.0 22.1.3 22.1.2 22.1.1 22.1.0 22.0.0 21.13.3 21.13.2 trunk 21.13.1
wpsso / lib / com / notice.php

notice.php in WPSSO Core – Complete Schema Markup and Meta Tags 22.7.0, at lib/com/notice.php

1,796 lines 51.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /*
3 * License: GPLv3
4 * License URI: https://www.gnu.org/licenses/gpl.txt
5 * Copyright 2012-2026 Jean-Sebastien Morisset (https://surniaulula.com/)
6 */
7
8 if ( ! defined( 'ABSPATH' ) ) {
9
10 die( 'These aren\'t the droids you\'re looking for.' );
11 }
12
13 if ( ! class_exists( 'SucomNotice' ) ) {
14
15 class SucomNotice {
16
17 private $p; // Plugin class object.
18 private $plugin_id = 'sucom';
19 private $plugin_ucid = 'SUCOM';
20 private $text_domain = 'sucom';
21 private $dismiss_name = 'sucom_dismissed';
22 private $notices_name = 'sucom_notices';
23 private $nonce_name = '';
24 private $default_ttl = 900; // Notice TTL is 15 mins by default.
25 private $label_transl = false;
26 private $has_shown = false;
27 private $all_types = array( 'nag', 'err', 'warn', 'inf', 'upd' ); // Sort by importance (most to least).
28 private $toolbar_types = array( 'err', 'warn', 'inf', 'upd' );
29 private $notice_info = array();
30 private $notice_cache = array();
31 private $notice_noload = array();
32
33 public $enabled = true;
34
35 public function __construct( $plugin = null, $plugin_id = null, $text_domain = null, $label_transl = false ) {
36
37 if ( ! class_exists( 'SucomUtil' ) ) { // Just in case.
38
39 require_once trailingslashit( dirname( __FILE__ ) ) . 'util.php';
40 }
41
42 if ( ! class_exists( 'SucomUtilWP' ) ) { // Just in case.
43
44 require_once trailingslashit( dirname( __FILE__ ) ) . 'util-wp.php';
45 }
46
47 $this->set_config( $plugin, $plugin_id, $text_domain, $label_transl );
48
49 $this->add_wp_callbacks();
50 }
51
52 public function set_textdomain( $text_domain = null ) {
53
54 if ( null !== $text_domain ) {
55
56 $this->text_domain = $text_domain;
57
58 } elseif ( ! empty( $this->p->cf[ 'plugin' ][ $this->plugin_id ][ 'text_domain' ] ) ) {
59
60 $this->text_domain = $this->p->cf[ 'plugin' ][ $this->plugin_id ][ 'text_domain' ];
61 }
62 }
63
64 public function set_label_transl( $label_transl = false ) {
65
66 if ( false !== $label_transl ) {
67
68 $this->label_transl = $label_transl;
69
70 } elseif ( ! empty( $this->p->cf[ 'notice' ][ 'title' ] ) ) {
71
72 $this->label_transl = sprintf( __( '%s Notice', $this->text_domain ),
73 _x( $this->p->cf[ 'notice' ][ 'title' ], 'notice title', $this->text_domain ) );
74
75 } else {
76
77 $this->label_transl = __( 'Notice', $this->text_domain );
78 }
79 }
80
81 public function is_enabled() {
82
83 return $this->enabled ? true : false;
84 }
85
86 public function enable( $state = true ) {
87
88 $prev_state = $this->is_enabled();
89
90 $this->enabled = $state;
91
92 return $prev_state; // Return the previous state to save and restore.
93 }
94
95 public function disable( $state = false ) {
96
97 return $this->enable( $state ); // Return the previous state to save and restore.
98 }
99
100 /*
101 * Note that only a single nag message is shown at a time.
102 */
103 public function nag( $msg_text, $user_id = null, $notice_key = false, $dismiss_time = false, $payload = array() ) {
104
105 $this->add_notice( 'nag', $msg_text, $user_id, $notice_key, $dismiss_time, $payload );
106 }
107
108 public function err( $msg_text, $user_id = null, $notice_key = false, $dismiss_time = false, $payload = array() ) {
109
110 $this->add_notice( 'err', $msg_text, $user_id, $notice_key, $dismiss_time, $payload );
111 }
112
113 public function warn( $msg_text, $user_id = null, $notice_key = false, $dismiss_time = false, $payload = array() ) {
114
115 $this->add_notice( 'warn', $msg_text, $user_id, $notice_key, $dismiss_time, $payload );
116 }
117
118 public function inf( $msg_text, $user_id = null, $notice_key = false, $dismiss_time = false, $payload = array() ) {
119
120 $this->add_notice( 'inf', $msg_text, $user_id, $notice_key, $dismiss_time, $payload );
121 }
122
123 public function upd( $msg_text, $user_id = null, $notice_key = false, $dismiss_time = false, $payload = array() ) {
124
125 $this->add_notice( 'upd', $msg_text, $user_id, $notice_key, $dismiss_time, $payload );
126 }
127
128 /*
129 * Clear a message type, message text, notice key from the notice cache, or clear all notices.
130 */
131 public function clear( $msg_type = '', $notice_key = false, $user_id = null ) {
132
133 $cur_uid = get_current_user_id(); // Always returns an integer.
134
135 if ( is_array( $user_id ) ) {
136
137 $clear_uids = $user_id;
138
139 } else {
140
141 $user_id = is_numeric( $user_id ) ? (int) $user_id : $cur_uid; // $user_id can be true, false, null, or numeric.
142
143 if ( empty( $user_id ) ) { // User ID is 0 (cron user, for example).
144
145 return false;
146 }
147
148 $clear_uids = array( $user_id );
149 }
150
151 unset( $user_id ); // A reminder that we are re-using this variable name below.
152
153 $clear_types = empty( $msg_type ) ? $this->all_types : array( (string) $msg_type );
154
155 foreach ( $clear_uids as $user_id ) {
156
157 $this->load_notice_cache( $user_id ); // Read and merge notices from transient cache.
158
159 foreach ( $clear_types as $msg_type ) {
160
161 if ( ! isset( $this->notice_cache[ $user_id ][ $msg_type ] ) ) { // Just in case.
162
163 continue;
164 }
165
166 foreach ( $this->notice_cache[ $user_id ][ $msg_type ] as $msg_key => $payload ) {
167
168 if ( empty( $notice_key ) || ( ! empty( $payload[ 'notice_key' ] ) && $notice_key === $payload[ 'notice_key' ] ) ) {
169
170 $this->unload_notice_cache( $user_id, $msg_type, $msg_key );
171 }
172 }
173 }
174
175 /*
176 * Save the notice cache now.
177 */
178 if ( $cur_uid !== $user_id ) {
179
180 $this->update_notice_cache( $user_id );
181 }
182 }
183 }
184
185 /*
186 * Clear a single notice key from the notice cache.
187 */
188 public function clear_key( $notice_key, $user_id = null ) {
189
190 $this->clear( $msg_type = '', $notice_key, $user_id );
191 }
192
193 /*
194 * Set reference values for admin notices.
195 */
196 public function set_ref( $url = null, $mod = false, $context_transl = null ) {
197
198 $this->notice_info[] = array(
199 'url' => $url,
200 'mod' => $mod,
201 'context_transl' => $context_transl,
202 );
203
204 return $url;
205 }
206
207 /*
208 * Restore previous reference values for admin notices.
209 */
210 public function unset_ref( $url = null ) {
211
212 if ( null === $url || $this->is_ref_url( $url ) ) {
213
214 array_pop( $this->notice_info );
215
216 return true;
217
218 }
219
220 return false;
221 }
222
223 public function get_ref( $ref_key = false, $text_prefix = '', $text_suffix = '' ) {
224
225 $refs = end( $this->notice_info ); // Get the last reference added.
226
227 if ( 'edit' === $ref_key ) {
228
229 $link = '';
230
231 if ( ! empty( $refs[ 'mod' ] ) ) {
232
233 if ( ! empty( $refs[ 'mod' ][ 'id' ] ) && is_numeric( $refs[ 'mod' ][ 'id' ] ) ) {
234
235 if ( $refs[ 'mod' ][ 'is_comment' ] ) {
236
237 $link = get_edit_comment_link( $refs[ 'mod' ][ 'id' ] );
238
239 } elseif ( $refs[ 'mod' ][ 'is_post' ] ) {
240
241 $link = get_edit_post_link( $refs[ 'mod' ][ 'id' ], $display = false );
242
243 } elseif ( $refs[ 'mod' ][ 'is_user' ] ) {
244
245 $link = get_edit_user_link( $refs[ 'mod' ][ 'id' ] );
246
247 } elseif ( $refs[ 'mod' ][ 'is_term' ] ) {
248
249 $link = get_edit_term_link( $refs[ 'mod' ][ 'id' ], $refs[ 'mod' ][ 'tax_slug' ] );
250 }
251 }
252 }
253
254 return empty( $link ) ? '' : $text_prefix . $link . $text_suffix;
255
256 } elseif ( false !== $ref_key ) {
257
258 if ( isset( $refs[ $ref_key ] ) ) {
259
260 return $text_prefix . $refs[ $ref_key ] . $text_suffix;
261 }
262
263 return null;
264
265 }
266
267 return $refs;
268 }
269
270 public function get_ref_url_html() {
271
272 $ref_html = '';
273
274 if ( $url = $this->get_ref( $ref_key = 'url' ) ) {
275
276 /*
277 * Show a shorter relative URL, if possible.
278 */
279 $pretty_url = strtolower( str_replace( home_url(), '', $url ) );
280
281 $context_transl = $this->get_ref( $ref_key = 'context_transl' );
282
283 $context_transl = empty( $context_transl ) ?
284 '<a href="' . $url . '">' . $pretty_url . '</a>' :
285 '<a href="' . $url . '">' . $context_transl . '</a>';
286
287 /*
288 * Returns an empty string or a clickable (Edit) link.
289 */
290 $edit_html = $this->get_ref(
291 $ref_key = 'edit',
292 $text_prefix = ' (<a href="',
293 $text_suffix = '">' . __( 'Edit', $this->text_domain ) . '</a>)'
294 );
295
296 $ref_html .= ' <p class="reference-message">' .
297 sprintf( __( 'Reference: %s', $this->text_domain ),
298 $context_transl . $edit_html ) . '</p>';
299 }
300
301 return $ref_html;
302 }
303
304 public function is_ref_url( $url = null ) {
305
306 if ( null === $url || $url === $this->get_ref( $ref_key = 'url' ) ) {
307
308 return true;
309
310 }
311
312 return false;
313 }
314
315 public function is_admin_pre_notices( $notice_key = false, $user_id = null ) {
316
317 if ( is_admin() ) {
318
319 if ( ! empty( $notice_key ) ) {
320
321 /*
322 * If notice is dismissed, say that we've already shown the notices.
323 */
324 if ( $this->is_dismissed( $notice_key, $user_id ) ) {
325
326 if ( ! empty( $this->p->debug->enabled ) ) {
327
328 $this->p->debug->log( 'returning false: ' . $notice_key . ' is dismissed' );
329 }
330
331 return false;
332 }
333 }
334
335 if ( $this->has_shown ) {
336
337 if ( ! empty( $this->p->debug->enabled ) ) {
338
339 $this->p->debug->log( 'returning false: notices have been shown' );
340 }
341
342 return false;
343 }
344
345 } else {
346
347 if ( ! empty( $this->p->debug->enabled ) ) {
348
349 $this->p->debug->log( 'returning false: is not admin' );
350 }
351
352 return false;
353
354 }
355
356 return true;
357 }
358
359 public function clear_dismissed( $notice_key = false, $user_id = null ) {
360
361 $this->is_dismissed( $notice_key, $user_id, $force_expire = true );
362 }
363
364 public function reset_dismissed( $user_id = null ) {
365
366 $cur_uid = get_current_user_id(); // Always returns an integer.
367 $user_id = is_numeric( $user_id ) ? (int) $user_id : $cur_uid; // $user_id can be true, false, null, or numeric.
368
369 if ( $user_id ) {
370
371 delete_user_option( $user_id, $this->dismiss_name, $global = false );
372 }
373 }
374
375 public function is_dismissed( $notice_keys = false, $user_id = null, $force_expire = false ) {
376
377 if ( empty( $notice_keys ) || ! $this->can_dismiss() ) { // Just in case.
378
379 return false;
380 }
381
382 $cur_uid = get_current_user_id(); // Always returns an integer.
383 $user_id = is_numeric( $user_id ) ? (int) $user_id : $cur_uid; // $user_id can be true, false, null, or numeric.
384
385 if ( empty( $user_id ) ) { // User ID is 0 (cron user, for example).
386
387 return false;
388 }
389
390 $user_dismissed = get_user_option( $this->dismiss_name, $user_id ); // Note that $user_id is the second argument.
391 $update_dismissed = false;
392
393 if ( ! is_array( $user_dismissed ) ) { // Nothing to do.
394
395 return false;
396 }
397
398 if ( ! is_array( $notice_keys ) ) {
399
400 $notice_keys = array( $notice_keys );
401 }
402
403 foreach ( $notice_keys as $notice_key ) {
404
405 if ( isset( $user_dismissed[ $notice_key ] ) ) { // Notice has been dismissed.
406
407 $current_time = time();
408 $dismiss_time = $user_dismissed[ $notice_key ];
409
410 if ( ! $force_expire && ( empty( $dismiss_time ) || $dismiss_time > $current_time ) ) {
411
412 return true;
413 }
414
415 unset( $user_dismissed[ $notice_key ] ); // Dismiss time has expired.
416
417 $update_dismissed = true;
418 }
419 }
420
421 if ( $update_dismissed ) {
422
423 if ( empty( $user_dismissed ) ) {
424
425 delete_user_option( $user_id, $this->dismiss_name, $global = false );
426
427 } else update_user_option( $user_id, $this->dismiss_name, $user_dismissed, $global = false );
428 }
429
430 return false;
431 }
432
433 public function can_dismiss() {
434
435 global $wp_version;
436
437 if ( version_compare( $wp_version, '4.2', '>=' ) ) {
438
439 return true;
440 }
441
442 return false;
443 }
444
445 /*
446 * Hooked to the 'in_admin_header' action.
447 *
448 * The 'in_admin_header' action executes at the beginning of the content section in an admin page.
449 */
450 public function admin_header_notices() {
451
452 if ( ! empty( $this->p->debug->enabled ) ) {
453
454 $this->p->debug->mark();
455 }
456
457 add_action( 'all_admin_notices', array( $this, 'show_admin_notices' ), -1000 );
458 }
459
460 public function show_admin_notices() {
461
462 if ( ! empty( $this->p->debug->enabled ) ) {
463
464 $this->p->debug->mark();
465 }
466
467 $user_id = get_current_user_id(); // Always returns an integer.
468
469 $notice_types = $this->all_types;
470
471 echo $this->get_notice_style(); // Always include the notice styles in all admin webpages.
472
473 /*
474 * If toolbar notices are being used, exclude these from being shown.
475 */
476 $toolbar_types = $this->get_toolbar_types(); // Returns false or array.
477
478 if ( is_array( $toolbar_types ) ) { // Admin toolbar is available.
479
480 if ( ! empty( $toolbar_types ) ) {
481
482 $notice_types = array_diff( $notice_types, $toolbar_types );
483 }
484
485 } elseif ( is_admin() ) { // Just in case.
486
487 /*
488 * SucomNotice->get_toolbar_types() will always return false for these types of requests.
489 *
490 * See is_admin_bar_showing() in wordpress/wp-includes/admin-bar.php for details.
491 */
492 if ( defined( 'XMLRPC_REQUEST' ) || defined( 'DOING_AJAX' ) || defined( 'IFRAME_REQUEST' ) || wp_is_json_request() || is_embed() ) {
493
494 return;
495 }
496
497 $msg_text = sprintf( __( 'The WordPress admin toolbar appears to be disabled (ie. the WordPress <code>%s</code> function returned false).',
498 $this->text_domain ), 'is_admin_bar_showing()' ) . ' ';
499
500 $msg_text .= __( 'As a consequence, showing discreet notices in the admin toolbar is not possible.', $this->text_domain ) . ' ';
501
502 $msg_text .= __( 'Please diagnose the issue to re-enable the admin toolbar.', $this->text_domain ) . ' ';
503
504 $notice_key = 'is_admin-is_admin_bar_showing-returned-false';
505
506 /*
507 * Clear all notices and show only this error.
508 */
509 $this->clear();
510
511 $this->err( $msg_text, $user_id, $notice_key );
512 }
513
514 if ( empty( $notice_types ) ) { // Just in case.
515
516 return;
517 }
518
519 /*
520 * An alternative to the 'admin_head' action hook to add notices.
521 */
522 $action_name = 'sucom_show_admin_notices';
523
524 if ( ! empty( $this->p->debug->enabled ) ) {
525
526 $this->p->debug->log( 'doing action \'' . $action_name . '\'' );
527 }
528
529 do_action( 'sucom_show_admin_notices', $user_id );
530
531 /*
532 * Exit early if this is a block editor page. The notices will be retrieved using an ajax call on page load
533 * and post save.
534 */
535 if ( SucomUtilWP::doing_block_editor() ) {
536
537 if ( ! empty( $this->p->debug->enabled ) ) {
538
539 $this->p->debug->log( 'exiting early: doing block editor is true' );
540 }
541
542 return;
543 }
544
545 if ( ! empty( $this->p->debug->enabled ) ) {
546
547 $this->p->debug->log( 'doing block editor is false' );
548 }
549
550 $nag_html = '';
551 $msg_html = '';
552 $user_dismissed = $user_id ? get_user_option( $this->dismiss_name, $user_id ) : false; // Note that $user_id is the second argument.
553 $update_dismissed = false;
554
555 $this->has_shown = true;
556 $this->load_notice_cache( $user_id ); // Read and merge notices from transient cache.
557 $this->load_update_notices( $user_id );
558
559 /*
560 * Loop through all the msg types and show them all.
561 */
562 foreach ( $notice_types as $msg_type ) {
563
564 if ( ! isset( $this->notice_cache[ $user_id ][ $msg_type ] ) ) { // Just in case.
565
566 continue;
567 }
568
569 foreach ( $this->notice_cache[ $user_id ][ $msg_type ] as $msg_key => $payload ) {
570
571 $this->unload_notice_cache( $user_id, $msg_type, $msg_key );
572
573 if ( empty( $payload[ 'msg_text' ] ) ) { // Nothing to show.
574
575 continue;
576 }
577
578 /*
579 * Make sure the notice has not exceeded its TTL.
580 *
581 * A 'notice_ttl' value of 0 disables the notice message expiration.
582 */
583 if ( ! empty( $payload[ 'notice_time' ] ) && ! empty( $payload[ 'notice_ttl' ] ) ) {
584
585 if ( time() > $payload[ 'notice_time' ] + $payload[ 'notice_ttl' ] ) {
586
587 continue;
588 }
589 }
590
591 if ( ! empty( $payload[ 'dismiss_time' ] ) ) { // True or seconds greater than 0.
592
593 /*
594 * Check for automatically hidden errors and/or warnings.
595 */
596 if ( ! empty( $payload[ 'notice_key' ] ) && isset( $user_dismissed[ $payload[ 'notice_key' ] ] ) ) {
597
598 $current_time = time();
599 $dismiss_time = $user_dismissed[ $payload[ 'notice_key' ] ]; // Get time for key.
600
601 if ( empty( $dismiss_time ) || $dismiss_time > $current_time ) { // 0 or time in future.
602
603 $payload[ 'hidden' ] = true;
604
605 } else { // Dismiss has expired.
606
607 unset( $user_dismissed[ $payload[ 'notice_key' ] ] );
608
609 $update_dismissed = true; // Update the user meta when done.
610 }
611 }
612 }
613
614 if ( 'nag' === $msg_type ) {
615
616 if ( empty( $nag_html ) ) { // Only show a single nag message at a time.
617
618 $nag_html .= $this->get_notice_html( $msg_type, $payload );
619 }
620
621 } else $msg_html .= $this->get_notice_html( $msg_type, $payload );
622 }
623 }
624
625 /*
626 * Don't save unless we've changed something.
627 */
628 if ( $user_id && $update_dismissed ) {
629
630 if ( empty( $user_dismissed ) ) {
631
632 delete_user_option( $user_id, $this->dismiss_name, $global = false );
633
634 } else update_user_option( $user_id, $this->dismiss_name, $user_dismissed, $global = false );
635 }
636
637 echo "\n" . '<!-- ' . $this->plugin_id . ' admin notices begin -->' . "\n";
638
639 echo '<div id="' . sanitize_html_class( $this->plugin_id . '-admin-notices-begin' ) . '"></div>' . "\n";
640
641 echo $nag_html . "\n";
642
643 echo $msg_html . "\n";
644
645 echo '<!-- ' . $this->plugin_id . ' admin notices end -->' . "\n";
646
647 if ( ! empty( $this->p->debug->enabled ) ) {
648
649 $this->p->debug->log( $this->plugin_id . ' admin notices end' );
650 }
651 }
652
653 public function ajax_get_notices_json() {
654
655 $doing_ajax = SucomUtilWP::doing_ajax();
656
657 if ( ! $doing_ajax ) { // Just in case.
658
659 return;
660
661 } elseif ( SucomUtil::get_const( 'DOING_AUTOSAVE' ) ) {
662
663 die( -1 );
664 }
665
666 /*
667 * Check nonce value before using $_REQUEST.
668 */
669 check_ajax_referer( $this->nonce_name, '_ajax_nonce', $die = true );
670
671 $notice_types = $this->all_types;
672
673 if ( ! empty( $_REQUEST[ '_notice_types' ] ) ) {
674
675 if ( is_array( $_REQUEST[ '_notice_types' ] ) ) {
676
677 $notice_types = $_REQUEST[ '_notice_types' ];
678
679 } else $notice_types = explode( ',', $_REQUEST[ '_notice_types' ] );
680 }
681
682 if ( ! empty( $_REQUEST[ '_exclude_types' ] ) ) {
683
684 if ( is_array( $_REQUEST[ '_exclude_types' ] ) ) {
685
686 $exclude_types = $_REQUEST[ '_exclude_types' ];
687
688 } else $exclude_types = explode( ',', $_REQUEST[ '_exclude_types' ] );
689
690 $notice_types = array_diff( $notice_types, $exclude_types );
691 }
692
693 if ( empty( $notice_types ) ) { // Just in case.
694
695 die( -1 );
696 }
697
698 $user_id = get_current_user_id(); // Always returns an integer.
699 $user_dismissed = $user_id ? get_user_option( $this->dismiss_name, $user_id ) : false; // Note that $user_id is the second argument.
700 $update_dismissed = false;
701 $json_notices = array();
702 $ajax_context = empty( $_REQUEST[ 'context' ] ) ? '' : $_REQUEST[ 'context' ]; // 'block_editor' or 'toolbar_notices'
703
704 $this->has_shown = true;
705 $this->load_notice_cache( $user_id ); // Read and merge notices from transient cache.
706 $this->load_update_notices( $user_id );
707
708 /*
709 * Loop through all the msg types and show them all.
710 */
711 foreach ( $notice_types as $msg_type ) {
712
713 if ( ! isset( $this->notice_cache[ $user_id ][ $msg_type ] ) ) { // Just in case.
714
715 continue;
716 }
717
718 foreach ( $this->notice_cache[ $user_id ][ $msg_type ] as $msg_key => $payload ) {
719
720 $this->unload_notice_cache( $user_id, $msg_type, $msg_key );
721
722 if ( empty( $payload[ 'msg_text' ] ) ) { // Nothing to show.
723
724 continue;
725 }
726
727 /*
728 * Make sure the notice has not exceeded its TTL.
729 *
730 * A 'notice_ttl' value of 0 disables the notice message expiration.
731 */
732 if ( ! empty( $payload[ 'notice_time' ] ) && ! empty( $payload[ 'notice_ttl' ] ) ) {
733
734 if ( time() > $payload[ 'notice_time' ] + $payload[ 'notice_ttl' ] ) {
735
736 continue;
737 }
738 }
739
740 if ( ! empty( $payload[ 'dismiss_time' ] ) ) { // True or seconds greater than 0.
741
742 /*
743 * Check for automatically hidden errors and/or warnings.
744 */
745 if ( ! empty( $payload[ 'notice_key' ] ) && isset( $user_dismissed[ $payload[ 'notice_key' ] ] ) ) {
746
747 $current_time = time();
748
749 $dismiss_time = $user_dismissed[ $payload[ 'notice_key' ] ]; // Get time for key.
750
751 if ( empty( $dismiss_time ) || $dismiss_time > $current_time ) { // 0 or time in future.
752
753 $payload[ 'hidden' ] = true;
754
755 } else { // Dismiss has expired.
756
757 unset( $user_dismissed[ $payload[ 'notice_key' ] ] );
758
759 $update_dismissed = true; // Update the user meta when done.
760 }
761 }
762 }
763
764 $payload[ 'msg_html' ] = $this->get_notice_html( $msg_type, $payload, $notice_alt = true );
765
766 $json_notices[ $msg_type ][ $msg_key ] = $payload;
767 }
768 }
769
770 /*
771 * Don't save unless we've changed something.
772 */
773 if ( $user_id && $update_dismissed ) {
774
775 if ( empty( $user_dismissed ) ) {
776
777 delete_user_option( $user_id, $this->dismiss_name, $global = false );
778
779 } else update_user_option( $user_id, $this->dismiss_name, $user_dismissed, $global = false );
780 }
781
782 $json_encoded = wp_json_encode( $json_notices );
783
784 die( $json_encoded );
785 }
786
787 public function ajax_dismiss_notice() {
788
789 $doing_ajax = SucomUtilWP::doing_ajax();
790
791 if ( ! $doing_ajax ) { // Just in case.
792
793 return;
794 }
795
796 $user_id = get_current_user_id(); // Always returns an integer.
797 $dismiss_info = array();
798
799 if ( empty( $user_id ) || ! current_user_can( 'edit_user', $user_id ) ) {
800
801 die( -1 );
802 }
803
804 check_ajax_referer( __FILE__, 'dismiss_nonce', $die = true );
805
806 /*
807 * Quick sanitation of input values.
808 */
809 foreach ( array( 'notice_key', 'dismiss_time' ) as $key ) {
810
811 $dismiss_info[ $key ] = sanitize_text_field( filter_input( INPUT_POST, $key ) );
812 }
813
814 if ( empty( $dismiss_info[ 'notice_key' ] ) ) { // Just in case.
815
816 die( -1 );
817 }
818
819 $user_dismissed = get_user_option( $this->dismiss_name, $user_id ); // Note that $user_id is the second argument.
820
821 if ( ! is_array( $user_dismissed ) ) {
822
823 $user_dismissed = array();
824 }
825
826 if ( empty( $dismiss_info[ 'dismiss_time' ] ) || ! is_numeric( $dismiss_info[ 'dismiss_time' ] ) ) {
827
828 $user_dismissed[ $dismiss_info[ 'notice_key' ] ] = 0;
829
830 } else {
831
832 $user_dismissed[ $dismiss_info[ 'notice_key' ] ] = time() + $dismiss_info[ 'dismiss_time' ];
833 }
834
835 update_user_option( $user_id, $this->dismiss_name, $user_dismissed, $global = false );
836
837 die( '1' );
838 }
839
840 /*
841 * Returns false or an array of notice types to include in the toolbar menu.
842 *
843 * Called by WpssoScript->get_admin_page_script_data() to define the types shown for ajax calls.
844 */
845 public function get_toolbar_types() {
846
847 /*
848 * is_admin_bar_showing() should always return true in the back-end for a standard request (ie. not xmlrpc, ajax, iframe).
849 */
850 $toolbar_types = is_admin_bar_showing() ? $this->toolbar_types : false;
851
852 $toolbar_types = apply_filters( 'sucom_toolbar_notice_types', $toolbar_types );
853
854 return $toolbar_types;
855 }
856
857 public function admin_footer_script() {
858
859 if ( ! empty( $this->p->debug->enabled ) ) {
860
861 $this->p->debug->mark();
862 }
863
864 echo $this->get_notice_script();
865 }
866
867 /*
868 * Called by the WordPress 'shutdown' action. Save notices for all user IDs in the notice cache.
869 */
870 public function shutdown_notice_cache() {
871
872 if ( ! empty( $this->p->debug->enabled ) ) {
873
874 $this->p->debug->mark();
875 }
876
877 foreach ( $this->notice_cache as $user_id => $msg_types ) {
878
879 $this->update_notice_cache( $user_id );
880 }
881 }
882
883 /*
884 * Set property values for text domain, notice label, etc.
885 */
886 private function set_config( $plugin = null, $plugin_id = null, $text_domain = null, $label_transl = false ) {
887
888 if ( null !== $plugin ) {
889
890 $this->p =& $plugin;
891
892 if ( ! empty( $this->p->debug->enabled ) ) {
893
894 $this->p->debug->mark();
895 }
896 }
897
898 /*
899 * Set the lower and upper case acronyms.
900 */
901 if ( null !== $plugin_id ) {
902
903 $this->plugin_id = $plugin_id;
904
905 } elseif ( ! empty( $this->p->id ) ) {
906
907 $this->plugin_id = $this->p->id;
908 }
909
910 $this->plugin_ucid = strtoupper( $this->plugin_id );
911
912 /*
913 * Set the text domain.
914 */
915 $this->set_textdomain( $text_domain );
916
917 /*
918 * Set the dismiss key name.
919 */
920 if ( defined( $this->plugin_ucid . '_DISMISS_NAME' ) ) {
921
922 $this->dismiss_name = constant( $this->plugin_ucid . '_DISMISS_NAME' );
923
924 } else {
925
926 $this->dismiss_name = $this->plugin_id . '_dismissed';
927 }
928
929 /*
930 * Set the notices key name.
931 */
932 if ( defined( $this->plugin_ucid . '_NOTICES_NAME' ) ) {
933
934 $this->notices_name = constant( $this->plugin_ucid . '_NOTICES_NAME' );
935
936 } else {
937
938 $this->notices_name = $this->plugin_id . '_notices';
939 }
940
941 /*
942 * Set the nonce key name.
943 */
944 if ( defined( $this->plugin_ucid . '_NONCE_NAME' ) ) {
945
946 $this->nonce_name = constant( $this->plugin_ucid . '_NONCE_NAME' );
947
948 } elseif ( defined( 'NONCE_KEY' ) ) {
949
950 $this->nonce_name = NONCE_KEY;
951 }
952
953 /*
954 * Set the translated notice label.
955 */
956 $this->set_label_transl( $label_transl );
957 }
958
959 /*
960 * Add WordPress action and filter callbacks.
961 */
962 private function add_wp_callbacks() {
963
964 static $do_once = null;
965
966 if ( $do_once ) return; // Stop here.
967
968 $do_once = true;
969
970 $doing_cron = defined( 'DOING_CRON' ) ? DOING_CRON : false;
971
972 if ( is_admin() ) {
973
974 add_action( 'wp_ajax_' . $this->plugin_id . '_dismiss_notice', array( $this, 'ajax_dismiss_notice' ) );
975
976 add_action( 'wp_ajax_' . $this->plugin_id . '_get_notices_json', array( $this, 'ajax_get_notices_json' ) );
977
978 /*
979 * The 'in_admin_header' action executes at the beginning of the content section in an admin page.
980 */
981 add_action( 'in_admin_header', array( $this, 'admin_header_notices' ), PHP_INT_MAX );
982
983 add_action( 'admin_footer', array( $this, 'admin_footer_script' ) );
984 }
985
986 if ( is_admin() || $doing_cron ) {
987
988 add_action( 'shutdown', array( $this, 'shutdown_notice_cache' ), -2000, 0 );
989 }
990 }
991
992 /*
993 * $msg_text can be a single text string, or an array of text strings.
994 */
995 private function add_notice( $msg_type, $msg_text, $user_id = null, $notice_key = false, $dismiss_time = false, $payload = array() ) {
996
997 if ( ! $this->enabled ) { // Just in case.
998
999 return false;
1000 }
1001
1002 /*
1003 * If $msg_text is an array of text strings, implode the array into a single text string.
1004 */
1005 $msg_text = is_array( $msg_text ) ? implode( $glue = ' ', $msg_text ) : (string) $msg_text;
1006 $msg_text = trim( $msg_text );
1007
1008 if ( empty( $msg_type ) || empty( $msg_text ) ) {
1009
1010 return false;
1011 }
1012
1013 $cur_uid = get_current_user_id(); // Always returns an integer.
1014 $user_id = is_numeric( $user_id ) ? (int) $user_id : $cur_uid; // $user_id can be true, false, null, or numeric.
1015
1016 if ( empty( $user_id ) ) { // User ID is 0 (cron user, for example).
1017
1018 return false;
1019 }
1020
1021 $payload[ 'user_id' ] = $user_id;
1022 $payload[ 'notice_label' ] = isset( $payload[ 'notice_label' ] ) ? $payload[ 'notice_label' ] : $this->label_transl;
1023 $payload[ 'notice_key' ] = empty( $notice_key ) ? false : sanitize_key( $notice_key );
1024 $payload[ 'notice_time' ] = time();
1025
1026 /*
1027 * 0 disables notice expiration.
1028 */
1029 $payload[ 'notice_ttl' ] = isset( $payload[ 'notice_ttl' ] ) ? (int) $payload[ 'notice_ttl' ] : $this->default_ttl;
1030 $payload[ 'dismiss_time' ] = false;
1031 $payload[ 'dismiss_diff' ] = isset( $payload[ 'dismiss_diff' ] ) ? $payload[ 'dismiss_diff' ] : null;
1032
1033 /*
1034 * Add dismiss text for dismiss button and notice message.
1035 */
1036 if ( $this->can_dismiss() ) {
1037
1038 $payload[ 'dismiss_time' ] = $dismiss_time; // Maybe true, false, 0, or seconds greater than 0.
1039
1040 if ( null === $payload[ 'dismiss_diff' ] ) { // Has not been provided, so set a default value.
1041
1042 $dismiss_suffix_msg = false;
1043
1044 if ( true === $payload[ 'dismiss_time' ] ) { // True.
1045
1046 $payload[ 'dismiss_diff' ] = __( 'Forever', $this->text_domain );
1047
1048 $dismiss_suffix_msg = __( 'This notice can be dismissed permanently.', $this->text_domain );
1049
1050 } elseif ( empty( $payload[ 'dismiss_time' ] ) ) { // False or 0 seconds.
1051
1052 $payload[ 'dismiss_time' ] = false;
1053
1054 $payload[ 'dismiss_diff' ] = false;
1055
1056 } elseif ( is_numeric( $payload[ 'dismiss_time' ] ) ) { // Seconds greater than 0.
1057
1058 $payload[ 'dismiss_diff' ] = human_time_diff( 0, $payload[ 'dismiss_time' ] );
1059
1060 $dismiss_suffix_msg = __( 'This notice can be dismissed for %s.', $this->text_domain );
1061 }
1062
1063 if ( ! empty( $payload[ 'dismiss_diff' ] ) && $dismiss_suffix_msg ) {
1064
1065 $msg_close_div = '';
1066
1067 if ( '</div>' === substr( $msg_text, -6 ) ) {
1068
1069 $msg_text = substr( $msg_text, 0, -6 );
1070
1071 $msg_close_div = '</div>';
1072 }
1073
1074 $msg_add_p = '</p>' === substr( $msg_text, -4 ) ? true : false;
1075
1076 $msg_text .= $msg_add_p || $msg_close_div ? '<p>' : ' ';
1077 $msg_text .= sprintf( $dismiss_suffix_msg, $payload[ 'dismiss_diff' ] );
1078 $msg_text .= $msg_add_p || $msg_close_div ? '</p>' : '';
1079 $msg_text .= $msg_close_div;
1080 }
1081 }
1082 }
1083
1084 /*
1085 * Maybe add a reference URL at the end.
1086 */
1087 $msg_text .= $this->get_ref_url_html();
1088
1089 $payload[ 'msg_text' ] = preg_replace( '/<!--spoken-->(.*?)<!--\/spoken-->/Us', ' ', $msg_text );
1090 $payload[ 'msg_spoken' ] = preg_replace( '/<!--not-spoken-->(.*?)<!--\/not-spoken-->/Us', ' ', $msg_text );
1091 $payload[ 'msg_spoken' ] = SucomUtil::decode_html( SucomUtil::strip_html( $payload[ 'msg_spoken' ] ) );
1092
1093 $msg_key = empty( $payload[ 'notice_key' ] ) ? sanitize_key( $payload[ 'msg_spoken' ] ) : $payload[ 'notice_key' ];
1094
1095 $this->notice_cache[ $user_id ][ $msg_type ][ $msg_key ] = $payload;
1096
1097 /*
1098 * Save the notice cache now.
1099 */
1100 if ( $cur_uid !== $user_id ) {
1101
1102 $this->update_notice_cache( $user_id );
1103 }
1104 }
1105
1106 private function unload_notice_cache( $user_id, $msg_type, $msg_key ) {
1107
1108 unset( $this->notice_cache[ $user_id ][ $msg_type ][ $msg_key ] );
1109
1110 if ( empty( $this->notice_cache[ $user_id ][ $msg_type ] ) ) {
1111
1112 unset( $this->notice_cache[ $user_id ][ $msg_type ] );
1113 }
1114
1115 $this->notice_noload[ $user_id ][ $msg_type ][ $msg_key ] = true;
1116 }
1117
1118 /*
1119 * Merge notice cache with saved notices (without overwriting).
1120 */
1121 private function load_notice_cache( $user_id = null ) {
1122
1123 $cur_uid = get_current_user_id(); // Always returns an integer.
1124 $user_id = is_numeric( $user_id ) ? (int) $user_id : $cur_uid; // $user_id can be true, false, null, or numeric.
1125 $result = $this->get_notice_cache( $user_id ); // Always returns an array.
1126
1127 if ( ! empty( $result ) ) {
1128
1129 foreach ( $this->all_types as $msg_type ) {
1130
1131 if ( ! empty( $result[ $msg_type ] ) ) {
1132
1133 foreach ( $result[ $msg_type ] as $msg_key => $payload ) {
1134
1135 if ( ! isset( $this->notice_cache[ $user_id ][ $msg_type ][ $msg_key ] ) &&
1136 ! isset( $this->notice_noload[ $user_id ][ $msg_type ][ $msg_key ] ) ) {
1137
1138 $this->notice_cache[ $user_id ][ $msg_type ][ $msg_key ] = $payload;
1139
1140 $this->notice_noload[ $user_id ][ $msg_type ][ $msg_key ] = true;
1141 }
1142 }
1143 }
1144 }
1145 }
1146 }
1147
1148 private function load_update_notices( $user_id ) {
1149
1150 if ( ! class_exists( 'SucomUpdate' ) ) {
1151
1152 return;
1153
1154 } elseif ( empty( $this->p->cf[ 'plugin' ] ) ) { // Just in case.
1155
1156 return;
1157 }
1158
1159 foreach ( $this->p->cf[ 'plugin' ] as $ext => $info ) {
1160
1161 if ( SucomUpdate::is_configured( $ext ) ) {
1162
1163 foreach ( array( 'inf', 'err' ) as $type ) {
1164
1165 if ( $msg = SucomUpdate::get_umsg( $ext, $type ) ) {
1166
1167 $msg_text = preg_replace( '/<!--spoken-->(.*?)<!--\/spoken-->/Us', ' ', $msg );
1168 $msg_spoken = preg_replace( '/<!--not-spoken-->(.*?)<!--\/not-spoken-->/Us', ' ', $msg );
1169 $msg_spoken = SucomUtil::decode_html( SucomUtil::strip_html( $msg_spoken ) );
1170 $msg_key = sanitize_key( $msg_spoken );
1171
1172 $this->notice_cache[ $user_id ][ $type ][ $msg_key ] = array(
1173 'notice_label' => $this->label_transl,
1174 'notice_key' => $msg_key,
1175 'msg_text' => $msg_text,
1176 'msg_spoken' => $msg_spoken,
1177 );
1178 }
1179 }
1180 }
1181 }
1182 }
1183
1184 private function update_notice_cache( $user_id = null ) {
1185
1186 $cur_uid = get_current_user_id(); // Always returns an integer.
1187 $user_id = is_numeric( $user_id ) ? (int) $user_id : $cur_uid; // $user_id can be true, false, null, or numeric.
1188 $update = true;
1189 $result = false;
1190
1191 if ( ! empty( $user_id ) ) { // Just in case.
1192
1193 if ( $cur_uid !== $user_id ) {
1194
1195 $this->load_notice_cache( $user_id ); // Read and merge notices from transient cache.
1196 }
1197
1198 $result = update_user_option( $user_id, $this->notices_name, $this->notice_cache[ $user_id ], $global = false );
1199 }
1200
1201 $this->notice_cache[ $user_id ] = array();
1202
1203 return $result;
1204 }
1205
1206 private function get_notice_cache( $user_id = null ) {
1207
1208 $cur_uid = get_current_user_id(); // Always returns an integer.
1209 $user_id = is_numeric( $user_id ) ? (int) $user_id : $cur_uid; // $user_id can be true, false, null, or numeric.
1210 $result = array();
1211
1212 if ( ! empty( $user_id ) ) { // Nothing to do.
1213
1214 $result = get_user_option( $this->notices_name, $user_id );
1215
1216 if ( ! is_array( $result ) ) { // Always return an array.
1217
1218 $result = array();
1219 }
1220 }
1221
1222 return $result;
1223 }
1224
1225 /*
1226 * Use a reference for the $payload variable so we can modify the 'msg_text' element and remove text that should be
1227 * shown only once.
1228 */
1229 private function get_notice_html( $msg_type, array &$payload, $notice_alt = false ) {
1230
1231 /*
1232 * Add an 'inline' class in toolbar notices to prevent WordPress from moving the notice.
1233 *
1234 * See wordpress/wp-admin/js/common.js:1083
1235 */
1236 $notice_type = $notice_alt ? 'notice notice-alt inline' : 'notice';
1237 $notice_display = 'block';
1238
1239 switch ( $msg_type ) {
1240
1241 case 'nag':
1242
1243 $payload[ 'notice_label' ] = ''; // No label for nag notices.
1244
1245 $msg_type = 'nag';
1246 $css_class = 'update-nag';
1247
1248 break;
1249
1250 case 'err':
1251 case 'error':
1252
1253 $msg_type = 'err';
1254 $css_class = $notice_type . ' notice-error error';
1255
1256 break;
1257
1258 case 'warn':
1259 case 'warning':
1260
1261 $msg_type = 'warn';
1262 $css_class = $notice_type . ' notice-warning';
1263
1264 break;
1265
1266 case 'inf':
1267 case 'info':
1268
1269 $msg_type = 'inf';
1270 $css_class = $notice_type . ' notice-info';
1271
1272 break;
1273
1274 case 'upd':
1275 case 'updated':
1276
1277 $msg_type = 'upd';
1278 $css_class = $notice_type . ' notice-success updated';
1279
1280 break;
1281
1282 default: // Unknown $msg_type.
1283
1284 $msg_type = 'unknown';
1285 $css_class = $notice_type;
1286
1287 break;
1288 }
1289
1290 $css_id_attr = empty( $payload[ 'notice_key' ] ) ? '' : ' id="' . $msg_type . '-' . $payload[ 'notice_key' ] . '"';
1291 $is_dismissible = empty( $payload[ 'dismiss_time' ] ) ? false : true;
1292 $data_attr = '';
1293
1294 if ( $is_dismissible ) {
1295
1296 $data_attr .= ' data-notice-key="' . ( isset( $payload[ 'notice_key' ] ) ?
1297 esc_attr( $payload[ 'notice_key' ] ) : '' ). '"';
1298
1299 $data_attr .= ' data-dismiss-time="' . ( isset( $payload[ 'dismiss_time' ] ) &&
1300 is_numeric( $payload[ 'dismiss_time' ] ) ?
1301 esc_attr( $payload[ 'dismiss_time' ] ) : 0 ) . '"';
1302
1303 $data_attr .= ' data-dismiss-nonce="' . wp_create_nonce( __FILE__ ) . '"';
1304 }
1305
1306 $style_attr = ' style="' .
1307 ( empty( $payload[ 'style' ] ) ? '' : $payload[ 'style' ] ) .
1308 ( empty( $payload[ 'hidden' ] ) ? 'display:' . $notice_display . ' !important;' : 'display:none !important;' ) . '"';
1309
1310 $msg_html = '<div class="' . $this->plugin_id . '-notice ' .
1311 ( $is_dismissible ? $this->plugin_id . '-dismissible ' : '' ) .
1312 $css_class . '"' . $css_id_attr . $style_attr . $data_attr . '>'; // Display block or none.
1313
1314 /*
1315 * Float the dismiss button on the right, so the button must be added first.
1316 */
1317 if ( ! empty( $payload[ 'dismiss_diff' ] ) && $is_dismissible ) {
1318
1319 $msg_html .= '<button class="notice-dismiss" type="button">' .
1320 '<span class="notice-dismiss-text">' . $payload[ 'dismiss_diff' ] . '</span>' .
1321 '</button><!-- .notice-dismiss -->';
1322 }
1323
1324 /*
1325 * The notice label can be false, an empty string, or translated string.
1326 */
1327 if ( ! empty( $payload[ 'notice_label' ] ) ) {
1328
1329 $msg_html .= '<div class="notice-label">' . $payload[ 'notice_label' ] . '</div><!-- .notice-label -->';
1330 }
1331
1332 /*
1333 * Check to see if there's a section that should be shown only once.
1334 */
1335 if ( preg_match( '/<!-- *show-once *-->.*<!-- *\/show-once *-->/Us', $payload[ 'msg_text' ], $matches ) ) {
1336
1337 static $show_once = array();
1338
1339 $match_md5 = md5( $matches[ 0 ] );
1340
1341 /*
1342 * Remove the "show once" text if it has already been shown, or remove it from dismisible and
1343 * dismissed notices, so it can be shown in a later notice.
1344 */
1345 if ( isset( $show_once[ $match_md5 ] ) || ( $is_dismissible && $this->is_dismissed( $payload[ 'notice_key' ] ) ) ) {
1346
1347 /*
1348 * The $payload is a reference variable so we can modify the 'msg_text' element and remove
1349 * text that should be shown only once.
1350 */
1351 $payload[ 'msg_text' ] = str_replace( $matches[ 0 ], '', $payload[ 'msg_text' ] );
1352
1353 } else {
1354
1355 $show_once[ $match_md5 ] = true;
1356 }
1357 }
1358
1359 $msg_html .= '<div class="notice-message">' . $payload[ 'msg_text' ] . '</div><!-- .notice-message -->';
1360 $msg_html .= '</div><!-- .' . $this->plugin_id . '-notice -->' . "\n";
1361
1362 return $msg_html;
1363 }
1364
1365 /*
1366 * Refresh the minimized notice stylesheet.
1367 *
1368 * See WpssoUtilCache->refresh().
1369 */
1370 public function refresh_notice_style() {
1371
1372 $this->get_notice_style( $read_cache = false );
1373 }
1374
1375 /*
1376 * See SucomNotice->show_admin_notices().
1377 */
1378 private function get_notice_style( $read_cache = true ) {
1379
1380 global $wp_version;
1381
1382 $cache_md5_pre = $this->plugin_id . '_';
1383 $cache_exp_secs = WEEK_IN_SECONDS;
1384 $cache_salt = __METHOD__ . '(wp_version:' . $wp_version . ')';
1385 $cache_id = $cache_md5_pre . md5( $cache_salt );
1386
1387 if ( $read_cache ) {
1388
1389 if ( ! SucomUtilWP::doing_dev() ) {
1390
1391 if ( $custom_style_css = get_transient( $cache_id ) ) {
1392
1393 return '<style type="text/css">' . $custom_style_css . '</style>';
1394 }
1395 }
1396 }
1397
1398 $custom_style_css = '
1399 body.wp-admin.has-toolbar-notices #wpadminbar,
1400 body.wp-admin.is-fullscreen-mode.has-toolbar-notices #wpadminbar,
1401 body.wp-admin.is-wp-toolbar-disabled.has-toolbar-notices #wpadminbar,
1402 body.wp-admin.woocommerce-embed-page.has-toolbar-notices #wpadminbar {
1403 display:block !important;
1404 }
1405 body.wp-admin.is-fullscreen-mode.has-toolbar-notices .block-editor__container {
1406 min-height:calc(100vh - 32px);
1407 }
1408 body.wp-admin.is-fullscreen-mode.has-toolbar-notices .interface-interface-skeleton {
1409 top:32px;
1410 }
1411 body.wp-admin.is-fullscreen-mode.has-toolbar-notices .block-editor__container .block-editor-editor-skeleton,
1412 body.wp-admin.is-fullscreen-mode.has-toolbar-notices .block-editor__container .block-editor-editor-skeleton .editor-post-publish-panel {
1413 top:32px;
1414 }
1415 @keyframes blinker {
1416 25% { opacity: 0; }
1417 75% { opacity: 1; }
1418 }
1419 .components-notice-list .' . $this->plugin_id . '-notice {
1420 margin:0;
1421 min-height:0;
1422 -webkit-box-shadow:none;
1423 -moz-box-shadow:none;
1424 box-shadow:none;
1425 }
1426 .components-notice-list .is-dismissible .' . $this->plugin_id . '-notice {
1427 padding-right:30px;
1428 }
1429 .components-notice-list .' . $this->plugin_id . '-notice *,
1430 #wpadminbar .' . $this->plugin_id . '-notice *,
1431 .' . $this->plugin_id . '-notice * {
1432 line-height:1.4em;
1433 }
1434 .components-notice-list .' . $this->plugin_id . '-notice .notice-label,
1435 .components-notice-list .' . $this->plugin_id . '-notice .notice-message,
1436 .components-notice-list .' . $this->plugin_id . '-notice .notice-dismiss {
1437 padding:8px;
1438 margin:0;
1439 border:0;
1440 background:inherit;
1441 }
1442 #wpadminbar #wp-toolbar li.has-toolbar-notices.show-timeout div.ab-sub-wrapper {
1443 display:block;
1444 }
1445 #wpadminbar #wp-toolbar li.has-toolbar-notices div.ab-item {
1446 color:inherit !important;
1447 background:inherit !important;
1448 }
1449 #wpadminbar #wp-toolbar li.has-toolbar-notices #' . $this->plugin_id . '-toolbar-notices-icon.ab-icon::before {
1450 color:#fff; /* White on background color. */
1451 background-color:inherit;
1452 }
1453 #wpadminbar #wp-toolbar li.has-toolbar-notices #' . $this->plugin_id . '-toolbar-notices-count {
1454 color:#fff; /* White on background color. */
1455 background-color:inherit;
1456 }
1457 #wpadminbar #wp-toolbar li.has-toolbar-notices.toolbar-notices-error {
1458 background-color:#dc3232; /* Red. */
1459 }
1460 #wpadminbar #wp-toolbar li.has-toolbar-notices.toolbar-notices-warning {
1461 background-color:#ffb900; /* Yellow. */
1462 }
1463 #wpadminbar #wp-toolbar li.has-toolbar-notices.toolbar-notices-info {
1464 background-color:#00a0d2; /* Blue. */
1465 }
1466 #wpadminbar #wp-toolbar li.has-toolbar-notices.toolbar-notices-success {
1467 background-color:#46b450; /* Green. */
1468 }
1469 #wpadminbar #wp-toolbar #wp-admin-bar-' . $this->plugin_id . '-toolbar-notices .ab-sub-wrapper {
1470 color:#c3c4c7;
1471 background-color:rgb(30, 30, 30);
1472 }
1473 #wpadminbar #wp-toolbar li.has-toolbar-notices #wp-admin-bar-' . $this->plugin_id . '-toolbar-notices-default {
1474 padding:0;
1475 }
1476 #wpadminbar #wp-toolbar li.has-toolbar-notices #wp-admin-bar-' . $this->plugin_id . '-toolbar-notices-container {
1477 min-width:60vw; /* Minimum width. */
1478 max-height:90vh; /* Minimum height. */
1479 overflow-y:scroll;
1480 }
1481 #wpadminbar #wp-toolbar li.has-toolbar-notices.show-timeout #wp-admin-bar-' . $this->plugin_id . '-toolbar-notices-container {
1482 max-height:20vh; /* Minimum height with timeout. */
1483 }
1484 #wpadminbar .' . $this->plugin_id . '-notice,
1485 #wpadminbar .' . $this->plugin_id . '-notice.error,
1486 #wpadminbar .' . $this->plugin_id . '-notice.updated,
1487 .' . $this->plugin_id . '-notice,
1488 .' . $this->plugin_id . '-notice.error,
1489 .' . $this->plugin_id . '-notice.updated {
1490 clear:both;
1491 padding:0;
1492 -webkit-box-shadow:none;
1493 -moz-box-shadow:none;
1494 box-shadow:none;
1495 }
1496 #wpadminbar .' . $this->plugin_id . '-notice,
1497 #wpadminbar .' . $this->plugin_id . '-notice.error,
1498 #wpadminbar .' . $this->plugin_id . '-notice.updated {
1499 background:inherit;
1500 border-bottom:none;
1501 border-right:none;
1502 }
1503 #wpadminbar .' . $this->plugin_id . '-notice > div,
1504 #wpadminbar .' . $this->plugin_id . '-notice.error > div,
1505 #wpadminbar .' . $this->plugin_id . '-notice.updated > div {
1506 min-height:50px;
1507 }
1508 #wpadminbar .' . $this->plugin_id . '-notice.notice.notice-alt {
1509 display:block !important; /* Fix Squirrly SEO display:none !important. */
1510 position:static !important; /* Fix Squirrly SEO position:absolute !important. */
1511 top:inherit !important; /* Fix Squirrly SEO top:-1000px !important. */
1512 height:auto !important; /* Fix Squirrly SEO height:0 !important. */
1513 }
1514 #wpadminbar div.' . $this->plugin_id . '-notice.notice-copy {
1515 font-size:0.9em;
1516 line-height:1;
1517 text-align:center;
1518 min-height:auto;
1519 }
1520 #wpadminbar div.' . $this->plugin_id . '-notice.notice-copy > div {
1521 min-height:auto;
1522 }
1523 #wpadminbar div.' . $this->plugin_id . '-notice.notice-copy div.notice-message {
1524 display:inline-block;
1525 padding:5px 20px;
1526 }
1527 #wpadminbar div.' . $this->plugin_id . '-notice.notice-copy div.notice-message a {
1528 font-size:0.9em;
1529 font-weight:200;
1530 letter-spacing:0.2px;
1531 }
1532 #wpadminbar div.' . $this->plugin_id . '-notice a,
1533 .' . $this->plugin_id . '-notice a {
1534 display:inline;
1535 text-decoration:underline;
1536 padding:0;
1537 }
1538 #wpadminbar div.' . $this->plugin_id . '-notice .notice-label,
1539 #wpadminbar div.' . $this->plugin_id . '-notice .notice-message,
1540 #wpadminbar div.' . $this->plugin_id . '-notice .notice-dismiss {
1541 position:relative;
1542 display:table-cell;
1543 padding:20px;
1544 margin:0;
1545 border:none;
1546 vertical-align:top;
1547 background:inherit;
1548 }
1549 @media screen and ( max-width:1200px ) {
1550 #wpadminbar div.' . $this->plugin_id . '-notice .notice-label {
1551 display:none;
1552 }
1553 }
1554 .' . $this->plugin_id . '-notice div.notice-actions {
1555 text-align:center;
1556 margin:20px 0 15px 0;
1557 }
1558 .' . $this->plugin_id . '-notice div.notice-single-button {
1559 display:inline-block;
1560 vertical-align:top;
1561 margin:5px;
1562 }
1563 .' . $this->plugin_id . '-notice .notice-label,
1564 .' . $this->plugin_id . '-notice .notice-message,
1565 .' . $this->plugin_id . '-notice .notice-dismiss {
1566 position:relative;
1567 display:table-cell;
1568 padding:15px 20px;
1569 margin:0;
1570 border:none;
1571 vertical-align:top;
1572 }
1573 .' . $this->plugin_id . '-notice .notice-dismiss-text {
1574 color:#c3c4c7;
1575 }
1576 .' . $this->plugin_id . '-notice .notice-dismiss::before {
1577 color:#c3c4c7;
1578 font-size:18px;
1579 display:inline-block;
1580 padding:2px;
1581 }
1582 .' . $this->plugin_id . '-notice .notice-dismiss:hover::before {
1583 color:#d63638;
1584 }
1585 .components-notice-list .' . $this->plugin_id . '-notice .notice-dismiss,
1586 #wpadminbar .' . $this->plugin_id . '-notice .notice-dismiss,
1587 .' . $this->plugin_id . '-notice .notice-dismiss {
1588 clear:both; /* Clear the "Screen Options" tab in nags. */
1589 display:block;
1590 float:right;
1591 top:0;
1592 right:0;
1593 padding-left:0;
1594 padding-bottom:15px;
1595 }
1596 #wpadminbar .' . $this->plugin_id . '-notice .notice-label,
1597 .' . $this->plugin_id . '-notice .notice-label {
1598 font-weight:600;
1599 color:#444; /* Default text color. */
1600 background-color:#fcfcfc; /* Default background color. */
1601 white-space:nowrap;
1602 }
1603 #wpadminbar .' . $this->plugin_id . '-notice.notice-error .notice-label,
1604 .' . $this->plugin_id . '-notice.notice-error .notice-label {
1605 background-color:#fbeaea;
1606 }
1607 #wpadminbar .' . $this->plugin_id . '-notice.notice-warning .notice-label,
1608 .' . $this->plugin_id . '-notice.notice-warning .notice-label {
1609 background-color:#fff8e5;
1610 }
1611 #wpadminbar .' . $this->plugin_id . '-notice.notice-info .notice-label,
1612 .' . $this->plugin_id . '-notice.notice-info .notice-label {
1613 background-color:#e5f5fa;
1614 }
1615 #wpadminbar .' . $this->plugin_id . '-notice.notice-success .notice-label,
1616 .' . $this->plugin_id . '-notice.notice-success .notice-label {
1617 background-color:#ecf7ed;
1618 }
1619 .' . $this->plugin_id . '-notice.notice-success .notice-label::before,
1620 .' . $this->plugin_id . '-notice.notice-info .notice-label::before,
1621 .' . $this->plugin_id . '-notice.notice-warning .notice-label::before,
1622 .' . $this->plugin_id . '-notice.notice-error .notice-label::before {
1623 font-family:"Dashicons";
1624 font-size:1.2em;
1625 vertical-align:bottom;
1626 margin-right:6px;
1627 }
1628 .' . $this->plugin_id . '-notice.notice-error .notice-label::before {
1629 content:"\f488"; /* megaphone */
1630 }
1631 .' . $this->plugin_id . '-notice.notice-warning .notice-label::before {
1632 content:"\f227"; /* flag */
1633 }
1634 .' . $this->plugin_id . '-notice.notice-info .notice-label::before {
1635 content:"\f537"; /* sticky */
1636 }
1637 .' . $this->plugin_id . '-notice.notice-success .notice-label::before {
1638 content:"\f147"; /* yes */
1639 }
1640 #wpadminbar .' . $this->plugin_id . '-notice .notice-message h2,
1641 .' . $this->plugin_id . '-notice .notice-message h2 {
1642 font-size:1.2em;
1643 }
1644 #wpadminbar .' . $this->plugin_id . '-notice .notice-message h3,
1645 .' . $this->plugin_id . '-notice .notice-message h3 {
1646 font-size:1.1em;
1647 margin-top:1.2em;
1648 margin-bottom:0.8em;
1649 }
1650 #wpadminbar .' . $this->plugin_id . '-notice .notice-message code,
1651 .' . $this->plugin_id . '-notice .notice-message code {
1652 font-family:"Courier", monospace;
1653 font-size:1em;
1654 vertical-align:middle;
1655 padding:0 2px;
1656 margin:0;
1657 }
1658 #wpadminbar .' . $this->plugin_id . '-notice .notice-message a,
1659 .' . $this->plugin_id . '-notice .notice-message a {
1660 display:inline;
1661 text-decoration:underline;
1662 }
1663 #wpadminbar .' . $this->plugin_id . '-notice .notice-message a code,
1664 .' . $this->plugin_id . '-notice .notice-message a code {
1665 padding:0;
1666 vertical-align:middle;
1667 }
1668 #wpadminbar .' . $this->plugin_id . '-notice .notice-message p,
1669 #wpadminbar .' . $this->plugin_id . '-notice .notice-message pre,
1670 .' . $this->plugin_id . '-notice .notice-message p,
1671 .' . $this->plugin_id . '-notice .notice-message pre {
1672 color:inherit;
1673 margin:0.8em 0 0 0;
1674 }
1675 #wpadminbar .' . $this->plugin_id . '-notice .notice-message .top,
1676 .' . $this->plugin_id . '-notice .notice-message .top {
1677 margin-top:0;
1678 }
1679 #wpadminbar .' . $this->plugin_id . '-notice .notice-message p.reference-message,
1680 .' . $this->plugin_id . '-notice .notice-message p.reference-message {
1681 color:#c3c4c7;
1682 font-size:0.9em;
1683 margin:10px 0 0 0;
1684 }
1685 #wpadminbar .' . $this->plugin_id . '-notice .notice-message p.reference-message a {
1686 font-size:0.9em;
1687 }
1688 #wpadminbar .' . $this->plugin_id . '-notice .notice-message p.smaller-message,
1689 #wpadminbar .' . $this->plugin_id . '-notice .notice-message p.smaller-message a,
1690 .' . $this->plugin_id . '-notice .notice-message p.smaller-message,
1691 .' . $this->plugin_id . '-notice .notice-message p.smaller-message a {
1692 font-size:0.9em;
1693 }
1694 #wpadminbar .' . $this->plugin_id . '-notice .notice-message ul,
1695 .' . $this->plugin_id . '-notice .notice-message ul {
1696 margin:1em 0 1em 3em;
1697 list-style:disc outside none;
1698 }
1699 #wpadminbar .' . $this->plugin_id . '-notice .notice-message ol,
1700 .' . $this->plugin_id . '-notice .notice-message ol {
1701 margin:1em 0 1em 3em;
1702 list-style:decimal outside none;
1703 }
1704 #wpadminbar .' . $this->plugin_id . '-notice .notice-message li,
1705 .' . $this->plugin_id . '-notice .notice-message li {
1706 text-align:left;
1707 margin:5px 0 5px 0;
1708 padding-left:0.8em;
1709 list-style:inherit;
1710 }
1711 #wpadminbar .' . $this->plugin_id . '-notice .notice-message b,
1712 #wpadminbar .' . $this->plugin_id . '-notice .notice-message b a,
1713 #wpadminbar .' . $this->plugin_id . '-notice .notice-message strong,
1714 #wpadminbar .' . $this->plugin_id . '-notice .notice-message strong a,
1715 .' . $this->plugin_id . '-notice .notice-message b,
1716 .' . $this->plugin_id . '-notice .notice-message b a,
1717 .' . $this->plugin_id . '-notice .notice-message strong,
1718 .' . $this->plugin_id . '-notice .notice-message strong a {
1719 font-weight:600;
1720 }
1721 #wpadminbar .' . $this->plugin_id . '-notice .notice-dismiss .notice-dismiss-text,
1722 .' . $this->plugin_id . '-notice .notice-dismiss .notice-dismiss-text {
1723 display:inline-block;
1724 font-size:12px;
1725 padding:2px;
1726 vertical-align:top;
1727 white-space:nowrap;
1728 }
1729 .' . $this->plugin_id . '-notice .notice-message .button-highlight {
1730 border-color:#0074a2;
1731 background-color:#daeefc;
1732 }
1733 .' . $this->plugin_id . '-notice .notice-message .button-highlight:hover {
1734 background-color:#c8e6fb;
1735 }
1736 ';
1737
1738 if ( ! SucomUtilWP::doing_dev() ) {
1739
1740 $custom_style_css = SucomUtil::minify_css( $custom_style_css, $this->plugin_id );
1741
1742 set_transient( $cache_id, $custom_style_css, $cache_exp_secs );
1743 }
1744
1745 return '<style type="text/css">' . $custom_style_css . '</style>';
1746 }
1747
1748 private function get_notice_script() {
1749
1750 if ( ! empty( $this->p->debug->enabled ) ) {
1751
1752 $this->p->debug->mark();
1753 }
1754
1755 return '
1756 <script>
1757
1758 jQuery( document ).on( "click", "div.' . $this->plugin_id . '-dismissible > button.notice-dismiss, div.' .
1759 $this->plugin_id . '-dismissible .dismiss-on-click", function() {
1760
1761 var notice = jQuery( this ).closest( ".' . $this->plugin_id . '-dismissible" );
1762
1763 var dismiss_msg = jQuery( this ).data( "dismiss-msg" );
1764
1765 var ajaxDismissData = {
1766 action: "' . $this->plugin_id . '_dismiss_notice",
1767 notice_key: notice.data( "notice-key" ),
1768 dismiss_time: notice.data( "dismiss-time" ),
1769 dismiss_nonce: notice.data( "dismiss-nonce" ),
1770 }
1771
1772 if ( notice.data( "notice-key" ) ) {
1773
1774 jQuery.post( ajaxurl, ajaxDismissData );
1775 }
1776
1777 /*
1778 * We use remove() instead of hide() for containers with "display:block !important;".
1779 */
1780 if ( dismiss_msg ) {
1781
1782 notice.children( "button.notice-dismiss" ).remove();
1783
1784 jQuery( this ).closest( "div.notice-message" ).html( dismiss_msg );
1785
1786 } else {
1787
1788 notice.remove();
1789 }
1790 } );
1791
1792 </script>' . "\n";
1793 }
1794 }
1795 }
1796