PluginProbe ʕ •ᴥ•ʔ
WooCommerce Square / 3.8.1
WooCommerce Square v3.8.1
5.4.2 5.4.1 5.4.0 trunk 1.0.25 1.0.26 1.0.27 1.0.28 1.0.29 1.0.30 1.0.31 1.0.32 1.0.33 1.0.34 1.0.35 1.0.36 1.0.37 1.0.38 2.0.0 2.0.1 2.0.2 2.0.3 2.0.4 2.0.5 2.0.6 2.0.7 2.0.8 2.1.0 2.1.1 2.1.2 2.1.3 2.1.4 2.1.5 2.1.6 2.2.0 2.2.1 2.2.2 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.4.0 2.4.1 2.5.0 2.5.1 2.5.2 2.5.3 2.6.0 2.7.0 2.8.0 2.9.0 2.9.1 3.0.0 3.0.1 3.0.2 3.0.3 3.1.0 3.2.0 3.3.0 3.4.0 3.4.1 3.4.2 3.5.0 3.6.0 3.6.1 3.7.0 3.7.1 3.8.0 3.8.1 3.8.2 3.8.3 3.9.0 4.0.0 4.1.0 4.2.0 4.2.1 4.2.2 4.2.3 4.3.0 4.3.1 4.3.2 4.4.0 4.4.1 4.4.2 4.5.0 4.5.1 4.5.2 4.6.0 4.6.1 4.6.2 4.6.3 4.6.4 4.7.0 4.7.1 4.7.2 4.7.3 4.7.4 4.8.0 4.8.1 4.8.2 4.8.3 4.8.4 4.8.5 4.8.6 4.8.7 4.8.8 4.9.0 4.9.1 4.9.2 4.9.3 4.9.4 4.9.5 4.9.6 4.9.7 4.9.8 4.9.9 5.0.0 5.0.1 5.1.0 5.1.1 5.1.2 5.2.0 5.3.0 5.3.1 5.3.2 5.3.3
woocommerce-square / includes / Framework / Admin_Notice_Handler.php
woocommerce-square / includes / Framework Last commit date
Addresses 3 years ago Api 3 years ago Compatibility 3 years ago PaymentGateway 3 years ago Utilities 3 years ago Admin_Message_Handler.php 3 years ago Admin_Notice_Handler.php 3 years ago Lifecycle.php 3 years ago Plugin.php 3 years ago Plugin_Compatibility.php 3 years ago Plugin_Dependencies.php 3 years ago Square_Helper.php 4 years ago
Admin_Notice_Handler.php
424 lines
1 <?php
2 /**
3 * WooCommerce Plugin Framework
4 *
5 * This source file is subject to the GNU General Public License v3.0
6 * that is bundled with this package in the file license.txt.
7 * It is also available through the world-wide-web at this URL:
8 * http://www.gnu.org/licenses/gpl-3.0.html GNU General Public License v3.0 or later
9 * If you did not receive a copy of the license and are unable to
10 * obtain it through the world-wide-web, please send an email
11 * to license@skyverge.com so we can send you a copy immediately.
12 *
13 * @since 3.0.0
14 * @author WooCommerce / SkyVerge
15 * @copyright Copyright (c) 2021-2022, WooCommerce.
16 * @copyright Copyright (c) 2013-2019, SkyVerge, Inc.
17 * @license http://www.gnu.org/licenses/gpl-3.0.html GNU General Public License v3.0 or later
18 *
19 * Modified by WooCommerce on 01 December 2021.
20 */
21
22 namespace WooCommerce\Square\Framework;
23
24 defined( 'ABSPATH' ) || exit;
25
26 /**
27 * Admin Notice Handler Class
28 *
29 * The purpose of this class is to provide a facility for displaying
30 * conditional (often dismissible) admin notices during a single page
31 * request
32 *
33 * @since 3.0.0
34 */
35 class Admin_Notice_Handler {
36
37
38 /** @var Plugin the plugin */
39 private $plugin;
40
41 /** @var array associative array of id to notice text */
42 private $admin_notices = array();
43
44 /** @var boolean static member to enforce a single rendering of the admin notice placeholder element */
45 private static $admin_notice_placeholder_rendered = false;
46
47 /** @var boolean static member to enforce a single rendering of the admin notice javascript */
48 private static $admin_notice_js_rendered = false;
49
50
51 /**
52 * Initialize and setup the Admin Notice Handler
53 *
54 * @since 3.0.0
55 */
56 public function __construct( $plugin ) {
57
58 $this->plugin = $plugin;
59
60 // render any admin notices, delayed notices, and
61 add_action( 'admin_notices', array( $this, 'render_admin_notices' ), 15 );
62 add_action( 'admin_footer', array( $this, 'render_delayed_admin_notices' ), 15 );
63 add_action( 'admin_footer', array( $this, 'render_admin_notice_js' ), 20 );
64
65 // AJAX handler to dismiss any warning/error notices
66 add_action( 'wp_ajax_wc_plugin_framework_square_dismiss_notice', array( $this, 'handle_dismiss_notice' ) );
67 }
68
69
70 /**
71 * Adds the given $message as a dismissible notice identified by $message_id,
72 * unless the notice has been dismissed, or we're on the plugin settings page
73 *
74 * @since 3.0.0
75 * @param string $message the notice message to display
76 * @param string $message_id the message id
77 * @param array $params {
78 * Optional parameters.
79 *
80 * @type bool $dismissible If the notice should be dismissible
81 * @type bool $always_show_on_settings If the notice should be forced to display on the
82 * plugin settings page, regardless of `$dismissible`.
83 * @type string $notice_class Additional classes for the notice.
84 * }
85 */
86 public function add_admin_notice( $message, $message_id, $params = array() ) {
87
88 $params = wp_parse_args(
89 $params,
90 array(
91 'dismissible' => true,
92 'always_show_on_settings' => true,
93 'notice_class' => 'updated',
94 )
95 );
96
97 if ( $this->should_display_notice( $message_id, $params ) ) {
98 $this->admin_notices[ $message_id ] = array(
99 'message' => $message,
100 'rendered' => false,
101 'params' => $params,
102 );
103 }
104 }
105
106
107 /**
108 * Returns true if the identified notice hasn't been cleared, or we're on
109 * the plugin settings page (where notices are always displayed)
110 *
111 * @since 3.0.0
112 * @param string $message_id the message id
113 * @param array $params {
114 * Optional parameters.
115 *
116 * @type bool $dismissible If the notice should be dismissible
117 * @type bool $always_show_on_settings If the notice should be forced to display on the
118 * plugin settings page, regardless of `$dismissible`.
119 * }
120 * @return bool
121 */
122 public function should_display_notice( $message_id, $params = array() ) {
123
124 // bail out if user is not a shop manager
125 if ( ! current_user_can( 'manage_woocommerce' ) ) {
126 return false;
127 }
128
129 $params = wp_parse_args(
130 $params,
131 array(
132 'dismissible' => true,
133 'always_show_on_settings' => true,
134 )
135 );
136
137 // if the notice is always shown on the settings page, and we're on the settings page
138 if ( $params['always_show_on_settings'] && $this->get_plugin()->is_plugin_settings() ) {
139 return true;
140 }
141
142 // non-dismissible, always display
143 if ( ! $params['dismissible'] ) {
144 return true;
145 }
146
147 // dismissible: display if notice has not been dismissed
148 return ! $this->is_notice_dismissed( $message_id );
149 }
150
151
152 /**
153 * Render any admin notices, as well as the admin notice placeholder
154 *
155 * @since 3.0.0
156 * @param boolean $is_visible true if the notices should be immediately visible, false otherwise
157 */
158 public function render_admin_notices( $is_visible = true ) {
159
160 // default for actions
161 if ( ! is_bool( $is_visible ) ) {
162 $is_visible = true;
163 }
164
165 foreach ( $this->admin_notices as $message_id => $message_data ) {
166 if ( ! $message_data['rendered'] ) {
167 $message_data['params']['is_visible'] = $is_visible;
168 $this->render_admin_notice( $message_data['message'], $message_id, $message_data['params'] );
169 $this->admin_notices[ $message_id ]['rendered'] = true;
170 }
171 }
172
173 if ( $is_visible && ! self::$admin_notice_placeholder_rendered ) {
174 // placeholder for moving delayed notices up into place
175 echo '<div class="js-wc-' . esc_attr( $this->get_plugin()->get_id_dasherized() ) . '-admin-notice-placeholder"></div>';
176 self::$admin_notice_placeholder_rendered = true;
177 }
178
179 }
180
181
182 /**
183 * Render any delayed admin notices, which have not yet already been rendered
184 *
185 * @since 3.0.0
186 */
187 public function render_delayed_admin_notices() {
188 $this->render_admin_notices( false );
189 }
190
191
192 /**
193 * Render a single admin notice
194 *
195 * @since 3.0.0
196 * @param string $message the notice message to display
197 * @param string $message_id the message id
198 * @param array $params {
199 * Optional parameters.
200 *
201 * @type bool $dismissible If the notice should be dismissible
202 * @type bool $is_visible If the notice should be immediately visible
203 * @type bool $always_show_on_settings If the notice should be forced to display on the
204 * plugin settings page, regardless of `$dismissible`.
205 * @type string $notice_class Additional classes for the notice.
206 * }
207 */
208 public function render_admin_notice( $message, $message_id, $params = array() ) {
209
210 $params = wp_parse_args(
211 $params,
212 array(
213 'dismissible' => true,
214 'is_visible' => true,
215 'always_show_on_settings' => true,
216 'notice_class' => 'updated',
217 )
218 );
219
220 $classes = array(
221 'notice',
222 'js-wc-plugin-framework-admin-notice',
223 $params['notice_class'],
224 );
225
226 // maybe make this notice dismissible
227 // uses a WP core class which handles the markup and styling
228 if ( $params['dismissible'] && ( ! $params['always_show_on_settings'] || ! $this->get_plugin()->is_plugin_settings() ) ) {
229 $classes[] = 'is-dismissible';
230 }
231
232 $style = ! $params['is_visible'] ? 'style="display:none"' : '';
233
234 echo sprintf(
235 '<div class="%1$s" data-plugin-id="%2$s" data-message-id="%3$s" %4$s><p>%5$s</p></div>',
236 esc_attr( implode( ' ', $classes ) ),
237 esc_attr( 'square' ),
238 esc_attr( $message_id ),
239 esc_attr( $style ),
240 wp_kses_post( $message )
241 );
242 }
243
244
245 /**
246 * Render the javascript to handle the notice "dismiss" functionality
247 *
248 * @since 3.0.0
249 */
250 public function render_admin_notice_js() {
251
252 // if there were no notices, or we've already rendered the js, there's nothing to do
253 if ( empty( $this->admin_notices ) || self::$admin_notice_js_rendered ) {
254 return;
255 }
256
257 $plugin_slug = $this->get_plugin()->get_id_dasherized();
258 $ajax_url = wp_nonce_url( admin_url( 'admin-ajax.php' ), 'notice_nonce', 'notice_nonce' );
259
260 self::$admin_notice_js_rendered = true;
261
262 ob_start();
263 ?>
264
265 // Log dismissed notices
266 $( '.js-wc-plugin-framework-admin-notice' ).on( 'click.wp-dismiss-notice', '.notice-dismiss', function( e ) {
267
268 var $notice = $( this ).closest( '.js-wc-plugin-framework-admin-notice' );
269
270 log_dismissed_notice(
271 $( $notice ).data( 'plugin-id' ),
272 $( $notice ).data( 'message-id' )
273 );
274
275 } );
276
277 // Log and hide legacy notices
278 $( 'a.js-wc-plugin-framework-notice-dismiss' ).click( function( e ) {
279
280 e.preventDefault();
281
282 var $notice = $( this ).closest( '.js-wc-plugin-framework-admin-notice' );
283
284 log_dismissed_notice(
285 $( $notice ).data( 'plugin-id' ),
286 $( $notice ).data( 'message-id' )
287 );
288
289 $( $notice ).fadeOut();
290
291 } );
292
293 function log_dismissed_notice( pluginID, messageID ) {
294
295 $.get(
296 '<?php echo esc_url( $ajax_url ); ?>',
297 {
298 action: 'wc_plugin_framework_' + pluginID + '_dismiss_notice',
299 messageid: messageID
300 }
301 );
302 }
303
304 // move any delayed notices up into position .show();
305 $( '.js-wc-plugin-framework-admin-notice:hidden' ).insertAfter( '.js-wc-<?php echo esc_js( $plugin_slug ); ?>-admin-notice-placeholder' ).show();
306 <?php
307 $javascript = ob_get_clean();
308
309 wc_enqueue_js( $javascript );
310 }
311
312
313 /**
314 * Marks the identified admin notice as dismissed for the given user
315 *
316 * @since 3.0.0
317 * @param string $message_id the message identifier
318 * @param int $user_id optional user identifier, defaults to current user
319 */
320 public function dismiss_notice( $message_id, $user_id = null ) {
321
322 if ( is_null( $user_id ) ) {
323 $user_id = get_current_user_id();
324 }
325
326 $dismissed_notices = $this->get_dismissed_notices( $user_id );
327
328 $dismissed_notices[ $message_id ] = true;
329
330 update_user_meta( $user_id, '_wc_plugin_framework_square_dismissed_messages', $dismissed_notices );
331
332 /**
333 * Admin Notice Dismissed Action.
334 *
335 * Fired when a user dismisses an admin notice.
336 *
337 * @since 3.0.0
338 * @param string $message_id notice identifier
339 * @param string|int $user_id
340 */
341 do_action( 'wc_square_dismiss_notice', $message_id, $user_id );
342 }
343
344 /**
345 * Returns true if the identified admin notice has been dismissed for the
346 * given user
347 *
348 * @since 3.0.0
349 * @param string $message_id the message identifier
350 * @param int $user_id optional user identifier, defaults to current user
351 * @return boolean true if the message has been dismissed by the admin user
352 */
353 public function is_notice_dismissed( $message_id, $user_id = null ) {
354
355 $dismissed_notices = $this->get_dismissed_notices( $user_id );
356
357 return isset( $dismissed_notices[ $message_id ] ) && $dismissed_notices[ $message_id ];
358 }
359
360
361 /**
362 * Returns the full set of dismissed notices for the user identified by
363 * $user_id, for this plugin
364 *
365 * @since 3.0.0
366 * @param int $user_id optional user identifier, defaults to current user
367 * @return array of message id to dismissed status (true or false)
368 */
369 public function get_dismissed_notices( $user_id = null ) {
370
371 if ( is_null( $user_id ) ) {
372 $user_id = get_current_user_id();
373 }
374
375 $dismissed_notices = get_user_meta( $user_id, '_wc_plugin_framework_square_dismissed_messages', true );
376
377 if ( empty( $dismissed_notices ) ) {
378 return array();
379 } else {
380 return $dismissed_notices;
381 }
382 }
383
384
385 /** AJAX methods ******************************************************/
386
387
388 /**
389 * Dismiss the identified notice
390 *
391 * @since 3.0.0
392 */
393 public function handle_dismiss_notice() {
394 $message_id = isset( $_REQUEST['messageid'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['messageid'] ) ) : false;
395 $is_nonce_valid = isset( $_GET['notice_nonce'] ) ? wp_verify_nonce( sanitize_text_field( wp_unslash( $_GET['notice_nonce'] ) ), 'notice_nonce' ) : false;
396
397 if ( ! $is_nonce_valid ) {
398 wp_send_json_error( esc_html__( 'Nonce verification failed.', 'woocommerce-square' ) );
399 }
400
401 if ( ! $message_id ) {
402 wp_send_json_error( esc_html__( 'Message ID empty.', 'woocommerce-square' ) );
403 }
404
405 $this->dismiss_notice( $message_id );
406
407 wp_send_json_success();
408 }
409
410
411 /** Getter methods ******************************************************/
412
413
414 /**
415 * Get the plugin
416 *
417 * @since 3.0.0
418 * @return Plugin returns the plugin instance
419 */
420 protected function get_plugin() {
421 return $this->plugin;
422 }
423 }
424