PluginProbe ʕ •ᴥ•ʔ
WooCommerce Square / 5.4.2
WooCommerce Square v5.4.2
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 1 year ago Compatibility 2 years ago PaymentGateway 1 day ago Utilities 1 year ago Admin_Message_Handler.php 3 years ago Admin_Notice_Handler.php 3 months ago Lifecycle.php 2 years ago Plugin.php 11 months ago Plugin_Compatibility.php 2 years ago Plugin_Dependencies.php 1 year ago Square_Helper.php 8 months ago
Admin_Notice_Handler.php
425 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) 2013-2019, SkyVerge, Inc.
16 * @license http://www.gnu.org/licenses/gpl-3.0.html GNU General Public License v3.0 or later
17 *
18 * Modified by WooCommerce on 01 December 2021.
19 */
20
21 namespace WooCommerce\Square\Framework;
22
23 defined( 'ABSPATH' ) || exit;
24
25 /**
26 * Admin Notice Handler Class
27 *
28 * The purpose of this class is to provide a facility for displaying
29 * conditional (often dismissible) admin notices during a single page
30 * request
31 *
32 * @since 3.0.0
33 */
34 class Admin_Notice_Handler {
35
36
37 /** @var Plugin the plugin */
38 private $plugin;
39
40 /** @var array associative array of id to notice text */
41 private $admin_notices = array();
42
43 /** @var boolean static member to enforce a single rendering of the admin notice placeholder element */
44 private static $admin_notice_placeholder_rendered = false;
45
46 /** @var boolean static member to enforce a single rendering of the admin notice javascript */
47 private static $admin_notice_js_rendered = false;
48
49
50 /**
51 * Initialize and setup the Admin Notice Handler
52 *
53 * @since 3.0.0
54 */
55 public function __construct( $plugin ) {
56
57 $this->plugin = $plugin;
58
59 // render any admin notices, delayed notices, and
60 add_action( 'admin_notices', array( $this, 'render_admin_notices' ), 15 );
61 add_action( 'admin_footer', array( $this, 'render_delayed_admin_notices' ), 15 );
62 add_action( 'admin_footer', array( $this, 'render_admin_notice_js' ), 20 );
63
64 // AJAX handler to dismiss any warning/error notices
65 add_action( 'wp_ajax_wc_plugin_framework_square_dismiss_notice', array( $this, 'handle_dismiss_notice' ) );
66 }
67
68
69 /**
70 * Adds the given $message as a dismissible notice identified by $message_id,
71 * unless the notice has been dismissed, or we're on the plugin settings page
72 *
73 * @since 3.0.0
74 * @param string $message the notice message to display
75 * @param string $message_id the message id
76 * @param array $params {
77 * Optional parameters.
78 *
79 * @type bool $dismissible If the notice should be dismissible
80 * @type bool $always_show_on_settings If the notice should be forced to display on the
81 * plugin settings page, regardless of `$dismissible`.
82 * @type string $notice_class Additional classes for the notice.
83 * }
84 */
85 public function add_admin_notice( $message, $message_id, $params = array() ) {
86
87 $params = wp_parse_args(
88 $params,
89 array(
90 'dismissible' => true,
91 'always_show_on_settings' => true,
92 'notice_class' => 'updated',
93 )
94 );
95
96 if ( $this->should_display_notice( $message_id, $params ) ) {
97 $this->admin_notices[ $message_id ] = array(
98 'message' => $message,
99 'rendered' => false,
100 'params' => $params,
101 );
102 }
103 }
104
105
106 /**
107 * Returns true if the identified notice hasn't been cleared, or we're on
108 * the plugin settings page (where notices are always displayed)
109 *
110 * @since 3.0.0
111 * @param string $message_id the message id
112 * @param array $params {
113 * Optional parameters.
114 *
115 * @type bool $dismissible If the notice should be dismissible
116 * @type bool $always_show_on_settings If the notice should be forced to display on the
117 * plugin settings page, regardless of `$dismissible`.
118 * }
119 * @return bool
120 */
121 public function should_display_notice( $message_id, $params = array() ) {
122
123 // bail out if user is not a shop manager
124 if ( ! current_user_can( 'manage_woocommerce' ) ) {
125 return false;
126 }
127
128 $params = wp_parse_args(
129 $params,
130 array(
131 'dismissible' => true,
132 'always_show_on_settings' => true,
133 )
134 );
135
136 // if the notice is always shown on the settings page, and we're on the settings page
137 if ( $params['always_show_on_settings'] && $this->get_plugin()->is_plugin_settings() ) {
138 return true;
139 }
140
141 // non-dismissible, always display
142 if ( ! $params['dismissible'] ) {
143 return true;
144 }
145
146 // dismissible: display if notice has not been dismissed
147 return ! $this->is_notice_dismissed( $message_id );
148 }
149
150
151 /**
152 * Render any admin notices, as well as the admin notice placeholder
153 *
154 * @since 3.0.0
155 * @param boolean $is_visible true if the notices should be immediately visible, false otherwise
156 */
157 public function render_admin_notices( $is_visible = true ) {
158
159 // default for actions
160 if ( ! is_bool( $is_visible ) ) {
161 $is_visible = true;
162 }
163
164 foreach ( $this->admin_notices as $message_id => $message_data ) {
165 if ( ! $message_data['rendered'] ) {
166 $message_data['params']['is_visible'] = $is_visible;
167 $this->render_admin_notice( $message_data['message'], $message_id, $message_data['params'] );
168 $this->admin_notices[ $message_id ]['rendered'] = true;
169 }
170 }
171
172 if ( $is_visible && ! self::$admin_notice_placeholder_rendered ) {
173 // placeholder for moving delayed notices up into place
174 echo '<div class="js-wc-' . esc_attr( $this->get_plugin()->get_id_dasherized() ) . '-admin-notice-placeholder"></div>';
175 self::$admin_notice_placeholder_rendered = true;
176 }
177
178 }
179
180
181 /**
182 * Render any delayed admin notices, which have not yet already been rendered
183 *
184 * @since 3.0.0
185 */
186 public function render_delayed_admin_notices() {
187 $this->render_admin_notices( false );
188 }
189
190
191 /**
192 * Render a single admin notice
193 *
194 * @since 3.0.0
195 * @param string $message the notice message to display
196 * @param string $message_id the message id
197 * @param array $params {
198 * Optional parameters.
199 *
200 * @type bool $dismissible If the notice should be dismissible
201 * @type bool $is_visible If the notice should be immediately visible
202 * @type bool $always_show_on_settings If the notice should be forced to display on the
203 * plugin settings page, regardless of `$dismissible`.
204 * @type string $notice_class Additional classes for the notice.
205 * }
206 */
207 public function render_admin_notice( $message, $message_id, $params = array() ) {
208
209 $params = wp_parse_args(
210 $params,
211 array(
212 'dismissible' => true,
213 'is_visible' => true,
214 'always_show_on_settings' => true,
215 'notice_class' => 'updated',
216 )
217 );
218
219 $classes = array(
220 'notice',
221 'js-wc-plugin-framework-admin-notice',
222 $params['notice_class'],
223 );
224
225 // maybe make this notice dismissible
226 // uses a WP core class which handles the markup and styling
227 if ( $params['dismissible'] && ( ! $params['always_show_on_settings'] || ! $this->get_plugin()->is_plugin_settings() ) ) {
228 $classes[] = 'is-dismissible';
229 }
230
231 $style = ! $params['is_visible'] ? 'style="display:none"' : '';
232
233 echo sprintf(
234 '<div class="%1$s" data-plugin-id="%2$s" data-message-id="%3$s" %4$s><p>%5$s</p></div>',
235 esc_attr( implode( ' ', $classes ) ),
236 esc_attr( 'square' ),
237 esc_attr( $message_id ),
238 esc_attr( $style ),
239 wp_kses_post( $message )
240 );
241 }
242
243
244 /**
245 * Render the javascript to handle the notice "dismiss" functionality
246 *
247 * @since 3.0.0
248 */
249 public function render_admin_notice_js() {
250
251 // if there were no notices, or we've already rendered the js, there's nothing to do
252 if ( empty( $this->admin_notices ) || self::$admin_notice_js_rendered ) {
253 return;
254 }
255
256 $plugin_slug = $this->get_plugin()->get_id_dasherized();
257 $ajax_url = wp_nonce_url( admin_url( 'admin-ajax.php' ), 'notice_nonce', 'notice_nonce' );
258
259 self::$admin_notice_js_rendered = true;
260
261 ob_start();
262 ?>
263 ( function( $ ) {
264 $( function() {
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 } );
307 } )( jQuery );
308 <?php
309 $javascript = ob_get_clean();
310 \WooCommerce\Square\Utilities\Helper::enqueue_inline_script( 'wc-square-admin-notice-inline', $javascript );
311 }
312
313
314 /**
315 * Marks the identified admin notice as dismissed for the given user
316 *
317 * @since 3.0.0
318 * @param string $message_id the message identifier
319 * @param int $user_id optional user identifier, defaults to current user
320 */
321 public function dismiss_notice( $message_id, $user_id = null ) {
322
323 if ( is_null( $user_id ) ) {
324 $user_id = get_current_user_id();
325 }
326
327 $dismissed_notices = $this->get_dismissed_notices( $user_id );
328
329 $dismissed_notices[ $message_id ] = true;
330
331 update_user_meta( $user_id, '_wc_plugin_framework_square_dismissed_messages', $dismissed_notices );
332
333 /**
334 * Admin Notice Dismissed Action.
335 *
336 * Fired when a user dismisses an admin notice.
337 *
338 * @since 3.0.0
339 * @param string $message_id notice identifier
340 * @param string|int $user_id
341 */
342 do_action( 'wc_square_dismiss_notice', $message_id, $user_id );
343 }
344
345 /**
346 * Returns true if the identified admin notice has been dismissed for the
347 * given user
348 *
349 * @since 3.0.0
350 * @param string $message_id the message identifier
351 * @param int $user_id optional user identifier, defaults to current user
352 * @return boolean true if the message has been dismissed by the admin user
353 */
354 public function is_notice_dismissed( $message_id, $user_id = null ) {
355
356 $dismissed_notices = $this->get_dismissed_notices( $user_id );
357
358 return isset( $dismissed_notices[ $message_id ] ) && $dismissed_notices[ $message_id ];
359 }
360
361
362 /**
363 * Returns the full set of dismissed notices for the user identified by
364 * $user_id, for this plugin
365 *
366 * @since 3.0.0
367 * @param int $user_id optional user identifier, defaults to current user
368 * @return array of message id to dismissed status (true or false)
369 */
370 public function get_dismissed_notices( $user_id = null ) {
371
372 if ( is_null( $user_id ) ) {
373 $user_id = get_current_user_id();
374 }
375
376 $dismissed_notices = get_user_meta( $user_id, '_wc_plugin_framework_square_dismissed_messages', true );
377
378 if ( empty( $dismissed_notices ) ) {
379 return array();
380 } else {
381 return $dismissed_notices;
382 }
383 }
384
385
386 /** AJAX methods ******************************************************/
387
388
389 /**
390 * Dismiss the identified notice
391 *
392 * @since 3.0.0
393 */
394 public function handle_dismiss_notice() {
395 $message_id = isset( $_REQUEST['messageid'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['messageid'] ) ) : false;
396 $is_nonce_valid = isset( $_GET['notice_nonce'] ) ? wp_verify_nonce( sanitize_text_field( wp_unslash( $_GET['notice_nonce'] ) ), 'notice_nonce' ) : false;
397
398 if ( ! $is_nonce_valid ) {
399 wp_send_json_error( esc_html__( 'Nonce verification failed.', 'woocommerce-square' ) );
400 }
401
402 if ( ! $message_id ) {
403 wp_send_json_error( esc_html__( 'Message ID empty.', 'woocommerce-square' ) );
404 }
405
406 $this->dismiss_notice( $message_id );
407
408 wp_send_json_success();
409 }
410
411
412 /** Getter methods ******************************************************/
413
414
415 /**
416 * Get the plugin
417 *
418 * @since 3.0.0
419 * @return Plugin returns the plugin instance
420 */
421 protected function get_plugin() {
422 return $this->plugin;
423 }
424 }
425