PluginProbe
StreamCast – bring live radio to your site with a sleek player / 2.2.3
StreamCast – bring live radio to your site with a sleek player v2.2.3
2.4.5 2.4.4 trunk 1.0 1.1 2.0.0 2.1.10 2.1.2 2.1.4 2.1.5 2.1.8 2.2.1 2.2.3 2.2.4 2.2.5 2.3.0 2.3.1 2.3.2 2.3.3 2.3.4 2.3.5 2.3.6 2.3.7 2.3.8 2.3.9 All 29 releases
streamcast / freemius / includes / managers / class-fs-admin-notice-manager.php

class-fs-admin-notice-manager.php in StreamCast – bring live radio to your site with a sleek player 2.2.3, at freemius/includes/managers/class-fs-admin-notice-manager.php

533 lines 18.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * @package Freemius
4 * @copyright Copyright (c) 2015, Freemius, Inc.
5 * @license https://www.gnu.org/licenses/gpl-3.0.html GNU General Public License Version 3
6 * @since 1.0.7
7 */
8
9 if ( ! defined( 'ABSPATH' ) ) {
10 exit;
11 }
12
13 class FS_Admin_Notice_Manager {
14 /**
15 * @since 1.2.2
16 *
17 * @var string
18 */
19 protected $_module_unique_affix;
20 /**
21 * @var string
22 */
23 protected $_id;
24 /**
25 * @var string
26 */
27 protected $_title;
28 /**
29 * @var array[string]array
30 */
31 private $_notices = array();
32 /**
33 * @var FS_Key_Value_Storage
34 */
35 private $_sticky_storage;
36 /**
37 * @var FS_Logger
38 */
39 protected $_logger;
40 /**
41 * @since 2.0.0
42 * @var int The ID of the blog that is associated with the current site level admin notices.
43 */
44 private $_blog_id = 0;
45 /**
46 * @since 2.0.0
47 * @var bool
48 */
49 private $_is_network_notices;
50
51 /**
52 * @var FS_Admin_Notice_Manager[]
53 */
54 private static $_instances = array();
55
56 /**
57 * @param string $id
58 * @param string $title
59 * @param string $module_unique_affix
60 * @param bool $is_network_and_blog_admins Whether or not the message should be shown both on
61 * network and blog admin pages.
62 * @param bool $network_level_or_blog_id Since 2.0.0
63 *
64 * @return \FS_Admin_Notice_Manager
65 */
66 static function instance(
67 $id,
68 $title = '',
69 $module_unique_affix = '',
70 $is_network_and_blog_admins = false,
71 $network_level_or_blog_id = false
72 ) {
73 if ( $is_network_and_blog_admins ) {
74 $network_level_or_blog_id = true;
75 }
76
77 $key = strtolower( $id );
78
79 if ( is_multisite() ) {
80 if ( true === $network_level_or_blog_id ) {
81 $key .= ':ms';
82 } else if ( is_numeric( $network_level_or_blog_id ) && $network_level_or_blog_id > 0 ) {
83 $key .= ":{$network_level_or_blog_id}";
84 } else {
85 $network_level_or_blog_id = get_current_blog_id();
86
87 $key .= ":{$network_level_or_blog_id}";
88 }
89 }
90
91 if ( ! isset( self::$_instances[ $key ] ) ) {
92 self::$_instances[ $key ] = new FS_Admin_Notice_Manager(
93 $id,
94 $title,
95 $module_unique_affix,
96 $is_network_and_blog_admins,
97 $network_level_or_blog_id
98 );
99 }
100
101 return self::$_instances[ $key ];
102 }
103
104 /**
105 * @param string $id
106 * @param string $title
107 * @param string $module_unique_affix
108 * @param bool $is_network_and_blog_admins Whether or not the message should be shown both on network and
109 * blog admin pages.
110 * @param bool|int $network_level_or_blog_id
111 */
112 protected function __construct(
113 $id,
114 $title = '',
115 $module_unique_affix = '',
116 $is_network_and_blog_admins = false,
117 $network_level_or_blog_id = false
118 ) {
119 $this->_id = $id;
120 $this->_logger = FS_Logger::get_logger( WP_FS__SLUG . '_' . $this->_id . '_data', WP_FS__DEBUG_SDK, WP_FS__ECHO_DEBUG_SDK );
121 $this->_title = ! empty( $title ) ? $title : '';
122 $this->_module_unique_affix = $module_unique_affix;
123 $this->_sticky_storage = FS_Key_Value_Storage::instance( 'admin_notices', $this->_id, $network_level_or_blog_id );
124
125 if ( is_multisite() ) {
126 $this->_is_network_notices = ( true === $network_level_or_blog_id );
127
128 if ( is_numeric( $network_level_or_blog_id ) ) {
129 $this->_blog_id = $network_level_or_blog_id;
130 }
131 } else {
132 $this->_is_network_notices = false;
133 }
134
135 $is_network_admin = fs_is_network_admin();
136 $is_blog_admin = fs_is_blog_admin();
137
138 if ( ( $this->_is_network_notices && $is_network_admin ) ||
139 ( ! $this->_is_network_notices && $is_blog_admin ) ||
140 ( $is_network_and_blog_admins && ( $is_network_admin || $is_blog_admin ) )
141 ) {
142 if ( 0 < count( $this->_sticky_storage ) ) {
143 $ajax_action_suffix = str_replace( ':', '-', $this->_id );
144
145 // If there are sticky notices for the current slug, add a callback
146 // to the AJAX action that handles message dismiss.
147 add_action( "wp_ajax_fs_dismiss_notice_action_{$ajax_action_suffix}", array(
148 &$this,
149 'dismiss_notice_ajax_callback'
150 ) );
151
152 foreach ( $this->_sticky_storage as $msg ) {
153 // Add admin notice.
154 $this->add(
155 $msg['message'],
156 $msg['title'],
157 $msg['type'],
158 true,
159 $msg['id'],
160 false,
161 isset( $msg['wp_user_id'] ) ? $msg['wp_user_id'] : null,
162 ! empty( $msg['plugin'] ) ? $msg['plugin'] : null,
163 $is_network_and_blog_admins,
164 isset( $msg['dismissible'] ) ?
165 $msg['dismissible'] :
166 null
167 );
168 }
169 }
170 }
171 }
172
173 /**
174 * Remove sticky message by ID.
175 *
176 * @author Vova Feldman (@svovaf)
177 * @since 1.0.7
178 *
179 */
180 function dismiss_notice_ajax_callback() {
181 check_admin_referer( 'fs_dismiss_notice_action' );
182
183 if ( ! is_numeric( $_POST['message_id'] ) ) {
184 $this->_sticky_storage->remove( $_POST['message_id'] );
185 }
186
187 wp_die();
188 }
189
190 /**
191 * Rendered sticky message dismiss JavaScript.
192 *
193 * @author Vova Feldman (@svovaf)
194 * @since 1.0.7
195 */
196 static function _add_sticky_dismiss_javascript() {
197 $params = array();
198 fs_require_once_template( 'sticky-admin-notice-js.php', $params );
199 }
200
201 private static $_added_sticky_javascript = false;
202
203 /**
204 * Hook to the admin_footer to add sticky message dismiss JavaScript handler.
205 *
206 * @author Vova Feldman (@svovaf)
207 * @since 1.0.7
208 */
209 private static function has_sticky_messages() {
210 if ( ! self::$_added_sticky_javascript ) {
211 add_action( 'admin_footer', array( 'FS_Admin_Notice_Manager', '_add_sticky_dismiss_javascript' ) );
212 }
213 }
214
215 /**
216 * Handle admin_notices by printing the admin messages stacked in the queue.
217 *
218 * @author Vova Feldman (@svovaf)
219 * @since 1.0.4
220 *
221 */
222 function _admin_notices_hook() {
223 if ( function_exists( 'current_user_can' ) &&
224 ! current_user_can( 'manage_options' )
225 ) {
226 // Only show messages to admins.
227 return;
228 }
229
230 foreach ( $this->_notices as $id => $msg ) {
231 if ( isset( $msg['wp_user_id'] ) && is_numeric( $msg['wp_user_id'] ) ) {
232 if ( get_current_user_id() != $msg['wp_user_id'] ) {
233 continue;
234 }
235 }
236
237 /**
238 * Added a filter to control the visibility of admin notices.
239 *
240 * Usage example:
241 *
242 * /**
243 * * @param bool $show
244 * * @param array $msg {
245 * * @var string $message The actual message.
246 * * @var string $title An optional message title.
247 * * @var string $type The type of the message ('success', 'update', 'warning', 'promotion').
248 * * @var string $id The unique identifier of the message.
249 * * @var string $manager_id The unique identifier of the notices manager. For plugins it would be the plugin's slug, for themes - `<slug>-theme`.
250 * * @var string $plugin The product's title.
251 * * @var string $wp_user_id An optional WP user ID that this admin notice is for.
252 * * }
253 * *
254 * * @return bool
255 * *\/
256 * function my_custom_show_admin_notice( $show, $msg ) {
257 * if ('trial_promotion' != $msg['id']) {
258 * return false;
259 * }
260 *
261 * return $show;
262 * }
263 *
264 * my_fs()->add_filter( 'show_admin_notice', 'my_custom_show_admin_notice', 10, 2 );
265 *
266 * @author Vova Feldman
267 * @since 2.2.0
268 */
269 $show_notice = call_user_func_array( 'fs_apply_filter', array(
270 $this->_module_unique_affix,
271 'show_admin_notice',
272 $this->show_admin_notices(),
273 $msg
274 ) );
275
276 if ( true !== $show_notice ) {
277 continue;
278 }
279
280 fs_require_template( 'admin-notice.php', $msg );
281
282 if ( $msg['sticky'] ) {
283 self::has_sticky_messages();
284 }
285 }
286 }
287
288 /**
289 * Enqueue common stylesheet to style admin notice.
290 *
291 * @author Vova Feldman (@svovaf)
292 * @since 1.0.7
293 */
294 function _enqueue_styles() {
295 fs_enqueue_local_style( 'fs_common', '/admin/common.css' );
296 }
297
298 /**
299 * Check if the current page is the Gutenberg block editor.
300 *
301 * @author Vova Feldman (@svovaf)
302 * @since 2.2.3
303 *
304 * @return bool
305 */
306 function is_gutenberg_page() {
307 if ( function_exists( 'is_gutenberg_page' ) &&
308 is_gutenberg_page()
309 ) {
310 // The Gutenberg plugin is on.
311 return true;
312 }
313
314 $current_screen = get_current_screen();
315
316 if ( method_exists( $current_screen, 'is_block_editor' ) &&
317 $current_screen->is_block_editor()
318 ) {
319 // Gutenberg page on 5+.
320 return true;
321 }
322
323 return false;
324 }
325
326 /**
327 * Check if admin notices should be shown on page. E.g., we don't want to show notices in the Visual Editor.
328 *
329 * @author Xiaheng Chen (@xhchen)
330 * @since 2.4.2
331 *
332 * @return bool
333 */
334 function show_admin_notices() {
335 global $pagenow;
336
337 if ( 'about.php' === $pagenow ) {
338 // Don't show admin notices on the About page.
339 return false;
340 }
341
342 if ( $this->is_gutenberg_page() ) {
343 // Don't show admin notices in Gutenberg (visual editor).
344 return false;
345 }
346
347 return true;
348 }
349
350 /**
351 * Add admin message to admin messages queue, and hook to admin_notices / all_admin_notices if not yet hooked.
352 *
353 * @author Vova Feldman (@svovaf)
354 * @since 1.0.4
355 *
356 * @param string $message
357 * @param string $title
358 * @param string $type
359 * @param bool $is_sticky
360 * @param string $id Message ID
361 * @param bool $store_if_sticky
362 * @param number|null $wp_user_id
363 * @param string|null $plugin_title
364 * @param bool $is_network_and_blog_admins Whether or not the message should be shown both on network
365 * and blog admin pages.
366 * @param bool|null $is_dismissible
367 * @param array $data
368 *
369 * @uses add_action()
370 */
371 function add(
372 $message,
373 $title = '',
374 $type = 'success',
375 $is_sticky = false,
376 $id = '',
377 $store_if_sticky = true,
378 $wp_user_id = null,
379 $plugin_title = null,
380 $is_network_and_blog_admins = false,
381 $is_dismissible = null,
382 $data = array()
383 ) {
384 $notices_type = $this->get_notices_type();
385
386 if ( empty( $this->_notices ) ) {
387 if ( ! $is_network_and_blog_admins ) {
388 add_action( $notices_type, array( &$this, "_admin_notices_hook" ) );
389 } else {
390 add_action( 'network_admin_notices', array( &$this, "_admin_notices_hook" ) );
391 add_action( 'admin_notices', array( &$this, "_admin_notices_hook" ) );
392 }
393
394 add_action( 'admin_enqueue_scripts', array( &$this, '_enqueue_styles' ) );
395 }
396
397 if ( '' === $id ) {
398 $id = md5( $title . ' ' . $message . ' ' . $type );
399 }
400
401 $message_object = array(
402 'message' => $message,
403 'title' => $title,
404 'type' => $type,
405 'sticky' => $is_sticky,
406 'id' => $id,
407 'manager_id' => $this->_id,
408 'plugin' => ( ! is_null( $plugin_title ) ? $plugin_title : $this->_title ),
409 'wp_user_id' => $wp_user_id,
410 'dismissible' => $is_dismissible,
411 'data' => $data
412 );
413
414 if ( $is_sticky && $store_if_sticky ) {
415 $this->_sticky_storage->{$id} = $message_object;
416 }
417
418 $this->_notices[ $id ] = $message_object;
419 }
420
421 /**
422 * @author Vova Feldman (@svovaf)
423 * @since 1.0.7
424 *
425 * @param string|string[] $ids
426 * @param bool $store
427 */
428 function remove_sticky( $ids, $store = true ) {
429 if ( ! is_array( $ids ) ) {
430 $ids = array( $ids );
431 }
432
433 foreach ( $ids as $id ) {
434 // Remove from sticky storage.
435 $this->_sticky_storage->remove( $id, $store );
436
437 if ( isset( $this->_notices[ $id ] ) ) {
438 unset( $this->_notices[ $id ] );
439 }
440 }
441 }
442
443 /**
444 * Check if sticky message exists by id.
445 *
446 * @author Vova Feldman (@svovaf)
447 * @since 1.0.9
448 *
449 * @param $id
450 *
451 * @return bool
452 */
453 function has_sticky( $id ) {
454 return isset( $this->_sticky_storage[ $id ] );
455 }
456
457 /**
458 * Adds sticky admin notification.
459 *
460 * @author Vova Feldman (@svovaf)
461 * @since 1.0.7
462 *
463 * @param string $message
464 * @param string $id Message ID
465 * @param string $title
466 * @param string $type
467 * @param number|null $wp_user_id
468 * @param string|null $plugin_title
469 * @param bool $is_network_and_blog_admins Whether or not the message should be shown both on network
470 * and blog admin pages.
471 * @param bool $is_dimissible
472 * @param array $data
473 */
474 function add_sticky( $message, $id, $title = '', $type = 'success', $wp_user_id = null, $plugin_title = null, $is_network_and_blog_admins = false, $is_dimissible = true, $data = array() ) {
475 if ( ! empty( $this->_module_unique_affix ) ) {
476 $message = fs_apply_filter( $this->_module_unique_affix, "sticky_message_{$id}", $message );
477 $title = fs_apply_filter( $this->_module_unique_affix, "sticky_title_{$id}", $title );
478 }
479
480 $this->add( $message, $title, $type, true, $id, true, $wp_user_id, $plugin_title, $is_network_and_blog_admins, $is_dimissible, $data );
481 }
482
483 /**
484 * Retrieves the data of an sticky notice.
485 *
486 * @author Leo Fajardo (@leorw)
487 * @since 2.4.3
488 *
489 * @param string $id Message ID.
490 *
491 * @return array|null
492 */
493 function get_sticky( $id ) {
494 return isset( $this->_sticky_storage->{$id} ) ?
495 $this->_sticky_storage->{$id} :
496 null;
497 }
498
499 /**
500 * Clear all sticky messages.
501 *
502 * @author Vova Feldman (@svovaf)
503 * @since 1.0.8
504 *
505 * @param bool $is_temporary @since 2.5.1
506 */
507 function clear_all_sticky( $is_temporary = false ) {
508 if ( $is_temporary ) {
509 $this->_notices = array();
510 } else {
511 $this->_sticky_storage->clear_all();
512 }
513 }
514
515 #--------------------------------------------------------------------------------
516 #region Helper Method
517 #--------------------------------------------------------------------------------
518
519 /**
520 * @author Vova Feldman (@svovaf)
521 * @since 2.0.0
522 *
523 * @return string
524 */
525 private function get_notices_type() {
526 return $this->_is_network_notices ?
527 'network_admin_notices' :
528 'admin_notices';
529 }
530
531 #endregion
532 }
533