PluginProbe ʕ •ᴥ•ʔ
WooCommerce Square / 4.5.0
WooCommerce Square v4.5.0
5.5.0 5.4.3 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 2 years ago PaymentGateway 2 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 3 years ago
Admin_Notice_Handler.php
423 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
264 // Log dismissed notices
265 $( '.js-wc-plugin-framework-admin-notice' ).on( 'click.wp-dismiss-notice', '.notice-dismiss', function( e ) {
266
267 var $notice = $( this ).closest( '.js-wc-plugin-framework-admin-notice' );
268
269 log_dismissed_notice(
270 $( $notice ).data( 'plugin-id' ),
271 $( $notice ).data( 'message-id' )
272 );
273
274 } );
275
276 // Log and hide legacy notices
277 $( 'a.js-wc-plugin-framework-notice-dismiss' ).click( function( e ) {
278
279 e.preventDefault();
280
281 var $notice = $( this ).closest( '.js-wc-plugin-framework-admin-notice' );
282
283 log_dismissed_notice(
284 $( $notice ).data( 'plugin-id' ),
285 $( $notice ).data( 'message-id' )
286 );
287
288 $( $notice ).fadeOut();
289
290 } );
291
292 function log_dismissed_notice( pluginID, messageID ) {
293
294 $.get(
295 '<?php echo esc_url( $ajax_url ); ?>',
296 {
297 action: 'wc_plugin_framework_' + pluginID + '_dismiss_notice',
298 messageid: messageID
299 }
300 );
301 }
302
303 // move any delayed notices up into position .show();
304 $( '.js-wc-plugin-framework-admin-notice:hidden' ).insertAfter( '.js-wc-<?php echo esc_js( $plugin_slug ); ?>-admin-notice-placeholder' ).show();
305 <?php
306 $javascript = ob_get_clean();
307
308 wc_enqueue_js( $javascript );
309 }
310
311
312 /**
313 * Marks the identified admin notice as dismissed for the given user
314 *
315 * @since 3.0.0
316 * @param string $message_id the message identifier
317 * @param int $user_id optional user identifier, defaults to current user
318 */
319 public function dismiss_notice( $message_id, $user_id = null ) {
320
321 if ( is_null( $user_id ) ) {
322 $user_id = get_current_user_id();
323 }
324
325 $dismissed_notices = $this->get_dismissed_notices( $user_id );
326
327 $dismissed_notices[ $message_id ] = true;
328
329 update_user_meta( $user_id, '_wc_plugin_framework_square_dismissed_messages', $dismissed_notices );
330
331 /**
332 * Admin Notice Dismissed Action.
333 *
334 * Fired when a user dismisses an admin notice.
335 *
336 * @since 3.0.0
337 * @param string $message_id notice identifier
338 * @param string|int $user_id
339 */
340 do_action( 'wc_square_dismiss_notice', $message_id, $user_id );
341 }
342
343 /**
344 * Returns true if the identified admin notice has been dismissed for the
345 * given user
346 *
347 * @since 3.0.0
348 * @param string $message_id the message identifier
349 * @param int $user_id optional user identifier, defaults to current user
350 * @return boolean true if the message has been dismissed by the admin user
351 */
352 public function is_notice_dismissed( $message_id, $user_id = null ) {
353
354 $dismissed_notices = $this->get_dismissed_notices( $user_id );
355
356 return isset( $dismissed_notices[ $message_id ] ) && $dismissed_notices[ $message_id ];
357 }
358
359
360 /**
361 * Returns the full set of dismissed notices for the user identified by
362 * $user_id, for this plugin
363 *
364 * @since 3.0.0
365 * @param int $user_id optional user identifier, defaults to current user
366 * @return array of message id to dismissed status (true or false)
367 */
368 public function get_dismissed_notices( $user_id = null ) {
369
370 if ( is_null( $user_id ) ) {
371 $user_id = get_current_user_id();
372 }
373
374 $dismissed_notices = get_user_meta( $user_id, '_wc_plugin_framework_square_dismissed_messages', true );
375
376 if ( empty( $dismissed_notices ) ) {
377 return array();
378 } else {
379 return $dismissed_notices;
380 }
381 }
382
383
384 /** AJAX methods ******************************************************/
385
386
387 /**
388 * Dismiss the identified notice
389 *
390 * @since 3.0.0
391 */
392 public function handle_dismiss_notice() {
393 $message_id = isset( $_REQUEST['messageid'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['messageid'] ) ) : false;
394 $is_nonce_valid = isset( $_GET['notice_nonce'] ) ? wp_verify_nonce( sanitize_text_field( wp_unslash( $_GET['notice_nonce'] ) ), 'notice_nonce' ) : false;
395
396 if ( ! $is_nonce_valid ) {
397 wp_send_json_error( esc_html__( 'Nonce verification failed.', 'woocommerce-square' ) );
398 }
399
400 if ( ! $message_id ) {
401 wp_send_json_error( esc_html__( 'Message ID empty.', 'woocommerce-square' ) );
402 }
403
404 $this->dismiss_notice( $message_id );
405
406 wp_send_json_success();
407 }
408
409
410 /** Getter methods ******************************************************/
411
412
413 /**
414 * Get the plugin
415 *
416 * @since 3.0.0
417 * @return Plugin returns the plugin instance
418 */
419 protected function get_plugin() {
420 return $this->plugin;
421 }
422 }
423