Addresses
3 years ago
Api
1 year ago
Compatibility
2 years ago
PaymentGateway
3 months 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_Message_Handler.php
438 lines
| 1 | <?php |
| 2 | /** |
| 3 | * WooCommerce Admin Message Handler |
| 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 | * # WordPress Admin Message Handler Class |
| 27 | * |
| 28 | * This class provides a reusable WordPress admin messaging facility for setting |
| 29 | * and displaying messages and error messages across admin page requests without |
| 30 | * resorting to passing the messages as query vars. |
| 31 | * |
| 32 | * ## Usage |
| 33 | * |
| 34 | * To use simple instantiate the class then set one or more messages: |
| 35 | * |
| 36 | * ` |
| 37 | * $admin_message_handler = new WP_Admin_Message_Handler( __FILE__ ); |
| 38 | * $admin_message_handler->add_message( 'Hello World!' ); |
| 39 | * ` |
| 40 | * |
| 41 | * Then show the messages wherever you need, either with the built-in method |
| 42 | * or by writing your own: |
| 43 | * |
| 44 | * `$admin_message_handler->show_messages();` |
| 45 | */ |
| 46 | class Admin_Message_Handler { |
| 47 | |
| 48 | |
| 49 | /** transient message prefix */ |
| 50 | const MESSAGE_TRANSIENT_PREFIX = '_wp_admin_message_'; |
| 51 | |
| 52 | /** the message id GET name */ |
| 53 | const MESSAGE_ID_GET_NAME = 'wpamhid'; |
| 54 | |
| 55 | |
| 56 | /** @var string unique message identifier, defaults to __FILE__ unless otherwise set */ |
| 57 | private $message_id; |
| 58 | |
| 59 | /** @var array array of messages */ |
| 60 | private $messages = array(); |
| 61 | |
| 62 | /** @var array array of error messages */ |
| 63 | private $errors = array(); |
| 64 | |
| 65 | /** @var array array of warning messages */ |
| 66 | private $warnings = array(); |
| 67 | |
| 68 | /** @var array array of info messages */ |
| 69 | private $infos = array(); |
| 70 | |
| 71 | |
| 72 | /** |
| 73 | * Construct and initialize the admin message handler class |
| 74 | * |
| 75 | * @since 3.0.0 |
| 76 | * @param string $message_id optional message id. Best practice is to set |
| 77 | * this to a unique identifier based on the client plugin, such as __FILE__ |
| 78 | */ |
| 79 | public function __construct( $message_id = null ) { |
| 80 | |
| 81 | $this->message_id = $message_id; |
| 82 | |
| 83 | // load any available messages |
| 84 | $this->load_messages(); |
| 85 | |
| 86 | add_filter( 'wp_redirect', array( $this, 'redirect' ), 1, 2 ); |
| 87 | } |
| 88 | |
| 89 | |
| 90 | /** |
| 91 | * Persist messages |
| 92 | * |
| 93 | * @since 3.0.0 |
| 94 | * @return boolean true if any messages were set, false otherwise |
| 95 | */ |
| 96 | public function set_messages() { |
| 97 | |
| 98 | // any messages to persist? |
| 99 | if ( $this->message_count() > 0 || $this->info_count() > 0 || $this->warning_count() > 0 || $this->error_count() > 0 ) { |
| 100 | |
| 101 | set_transient( |
| 102 | self::MESSAGE_TRANSIENT_PREFIX . $this->get_message_id(), |
| 103 | array( |
| 104 | 'errors' => $this->errors, |
| 105 | 'warnings' => $this->warnings, |
| 106 | 'infos' => $this->infos, |
| 107 | 'messages' => $this->messages, |
| 108 | ), |
| 109 | 60 * 60 |
| 110 | ); |
| 111 | |
| 112 | return true; |
| 113 | } |
| 114 | |
| 115 | return false; |
| 116 | } |
| 117 | |
| 118 | |
| 119 | /** |
| 120 | * Loads messages |
| 121 | * |
| 122 | * @since 3.0.0 |
| 123 | */ |
| 124 | public function load_messages() { |
| 125 | |
| 126 | /** |
| 127 | * The nonce verification warning is ignored below because the `self::MESSAGE_ID_GET_NAME` GET arg |
| 128 | * is in fact a nonce and is verified in part by generating a fresh nonce and comparing it to the |
| 129 | * nonce in the GET arg. |
| 130 | */ |
| 131 | if ( ! isset( $_GET[ self::MESSAGE_ID_GET_NAME ] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended |
| 132 | return; |
| 133 | } |
| 134 | |
| 135 | $message_id = sanitize_text_field( wp_unslash( $_GET[ self::MESSAGE_ID_GET_NAME ] ) ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended |
| 136 | |
| 137 | if ( $this->get_message_id() === $message_id ) { |
| 138 | |
| 139 | $memo = get_transient( self::MESSAGE_TRANSIENT_PREFIX . $message_id ); |
| 140 | |
| 141 | if ( isset( $memo['errors'] ) ) { |
| 142 | $this->errors = $memo['errors']; |
| 143 | } |
| 144 | if ( isset( $memo['warnings'] ) ) { |
| 145 | $this->warnings = $memo['warnings']; |
| 146 | } |
| 147 | if ( isset( $memo['infos'] ) ) { |
| 148 | $this->infos = $memo['infos']; |
| 149 | } |
| 150 | if ( isset( $memo['messages'] ) ) { |
| 151 | $this->messages = $memo['messages']; |
| 152 | } |
| 153 | |
| 154 | $this->clear_messages( $message_id ); |
| 155 | } |
| 156 | } |
| 157 | |
| 158 | |
| 159 | /** |
| 160 | * Clear messages and errors |
| 161 | * |
| 162 | * @since 3.0.0 |
| 163 | * @param string $id the messages identifier |
| 164 | */ |
| 165 | public function clear_messages( $id ) { |
| 166 | delete_transient( self::MESSAGE_TRANSIENT_PREFIX . $id ); |
| 167 | } |
| 168 | |
| 169 | |
| 170 | /** |
| 171 | * Add an error message. |
| 172 | * |
| 173 | * @since 3.0.0 |
| 174 | * @param string $error error message |
| 175 | */ |
| 176 | public function add_error( $error ) { |
| 177 | $this->errors[] = $error; |
| 178 | } |
| 179 | |
| 180 | |
| 181 | /** |
| 182 | * Adds a warning message. |
| 183 | * |
| 184 | * @since 3.0.0 |
| 185 | * |
| 186 | * @param string $message warning message to add |
| 187 | */ |
| 188 | public function add_warning( $message ) { |
| 189 | $this->warnings[] = $message; |
| 190 | } |
| 191 | |
| 192 | /** |
| 193 | * Add a message. |
| 194 | * |
| 195 | * @since 3.0.0 |
| 196 | * @param string $message the message to add |
| 197 | */ |
| 198 | public function add_message( $message ) { |
| 199 | $this->messages[] = $message; |
| 200 | } |
| 201 | |
| 202 | |
| 203 | /** |
| 204 | * Get error count. |
| 205 | * |
| 206 | * @since 3.0.0 |
| 207 | * @return int error message count |
| 208 | */ |
| 209 | public function error_count() { |
| 210 | return count( $this->errors ); |
| 211 | } |
| 212 | |
| 213 | |
| 214 | /** |
| 215 | * Gets the warning message count. |
| 216 | * |
| 217 | * @since 3.0.0 |
| 218 | * |
| 219 | * @return int warning message count |
| 220 | */ |
| 221 | public function warning_count() { |
| 222 | return count( $this->warnings ); |
| 223 | } |
| 224 | |
| 225 | |
| 226 | /** |
| 227 | * Gets the info message count. |
| 228 | * |
| 229 | * @since 3.0.0 |
| 230 | * |
| 231 | * @return int info message count |
| 232 | */ |
| 233 | public function info_count() { |
| 234 | return count( $this->infos ); |
| 235 | } |
| 236 | |
| 237 | |
| 238 | /** |
| 239 | * Get message count. |
| 240 | * |
| 241 | * @since 3.0.0 |
| 242 | * @return int message count |
| 243 | */ |
| 244 | public function message_count() { |
| 245 | return count( $this->messages ); |
| 246 | } |
| 247 | |
| 248 | |
| 249 | /** |
| 250 | * Get error messages |
| 251 | * |
| 252 | * @since 3.0.0 |
| 253 | * @return array of error message strings |
| 254 | */ |
| 255 | public function get_errors() { |
| 256 | return $this->errors; |
| 257 | } |
| 258 | |
| 259 | |
| 260 | /** |
| 261 | * Get an error message |
| 262 | * |
| 263 | * @since 3.0.0 |
| 264 | * @param int $index the error index |
| 265 | * @return string the error message |
| 266 | */ |
| 267 | public function get_error( $index ) { |
| 268 | return isset( $this->errors[ $index ] ) ? $this->errors[ $index ] : ''; |
| 269 | } |
| 270 | |
| 271 | |
| 272 | /** |
| 273 | * Gets all warning messages. |
| 274 | * |
| 275 | * @since 3.0.0 |
| 276 | * |
| 277 | * @return array |
| 278 | */ |
| 279 | public function get_warnings() { |
| 280 | return $this->warnings; |
| 281 | } |
| 282 | |
| 283 | |
| 284 | /** |
| 285 | * Gets a specific warning message. |
| 286 | * |
| 287 | * @since 3.0.0 |
| 288 | * |
| 289 | * @param int $index warning message index |
| 290 | * @return string |
| 291 | */ |
| 292 | public function get_warning( $index ) { |
| 293 | return isset( $this->warnings[ $index ] ) ? $this->warnings[ $index ] : ''; |
| 294 | } |
| 295 | |
| 296 | |
| 297 | /** |
| 298 | * Gets all info messages. |
| 299 | * |
| 300 | * @since 3.0.0 |
| 301 | * |
| 302 | * @return array |
| 303 | */ |
| 304 | public function get_infos() { |
| 305 | return $this->infos; |
| 306 | } |
| 307 | |
| 308 | |
| 309 | /** |
| 310 | * Gets a specific info message. |
| 311 | * |
| 312 | * @since 3.0.0 |
| 313 | * |
| 314 | * @param int $index info message index |
| 315 | * @return string |
| 316 | */ |
| 317 | public function get_info( $index ) { |
| 318 | return isset( $this->infos[ $index ] ) ? $this->infos[ $index ] : ''; |
| 319 | } |
| 320 | |
| 321 | |
| 322 | /** |
| 323 | * Get messages |
| 324 | * |
| 325 | * @since 3.0.0 |
| 326 | * @return array of message strings |
| 327 | */ |
| 328 | public function get_messages() { |
| 329 | return $this->messages; |
| 330 | } |
| 331 | |
| 332 | |
| 333 | /** |
| 334 | * Get a message |
| 335 | * |
| 336 | * @since 3.0.0 |
| 337 | * @param int $index the message index |
| 338 | * @return string the message |
| 339 | */ |
| 340 | public function get_message( $index ) { |
| 341 | return isset( $this->messages[ $index ] ) ? $this->messages[ $index ] : ''; |
| 342 | } |
| 343 | |
| 344 | |
| 345 | /** |
| 346 | * Render the errors and messages. |
| 347 | * |
| 348 | * @since 3.0.0 |
| 349 | * @param array $params { |
| 350 | * Optional parameters. |
| 351 | * |
| 352 | * @type array $capabilities Any user capabilities to check if the user is allowed to view the messages, |
| 353 | * default: `manage_woocommerce` |
| 354 | * } |
| 355 | */ |
| 356 | public function show_messages( $params = array() ) { |
| 357 | |
| 358 | $params = wp_parse_args( |
| 359 | $params, |
| 360 | array( |
| 361 | 'capabilities' => array( |
| 362 | 'manage_woocommerce', |
| 363 | ), |
| 364 | ) |
| 365 | ); |
| 366 | |
| 367 | $check_user_capabilities = array(); |
| 368 | |
| 369 | // check if user has at least one capability that allows to see messages |
| 370 | foreach ( $params['capabilities'] as $capability ) { |
| 371 | $check_user_capabilities[] = current_user_can( $capability ); |
| 372 | } |
| 373 | |
| 374 | // bail out if user has no minimum capabilities to see messages |
| 375 | if ( ! in_array( true, $check_user_capabilities, true ) ) { |
| 376 | return; |
| 377 | } |
| 378 | |
| 379 | $output = ''; |
| 380 | |
| 381 | if ( $this->error_count() > 0 ) { |
| 382 | $output .= '<div id="wp-admin-message-handler-error" class="notice-error notice"><ul><li><strong>' . implode( '</strong></li><li><strong>', $this->get_errors() ) . '</strong></li></ul></div>'; |
| 383 | } |
| 384 | |
| 385 | if ( $this->warning_count() > 0 ) { |
| 386 | $output .= '<div id="wp-admin-message-handler-warning" class="notice-warning notice"><ul><li><strong>' . implode( '</strong></li><li><strong>', $this->get_warnings() ) . '</strong></li></ul></div>'; |
| 387 | } |
| 388 | |
| 389 | if ( $this->info_count() > 0 ) { |
| 390 | $output .= '<div id="wp-admin-message-handler-warning" class="notice-info notice"><ul><li><strong>' . implode( '</strong></li><li><strong>', $this->get_infos() ) . '</strong></li></ul></div>'; |
| 391 | } |
| 392 | |
| 393 | if ( $this->message_count() > 0 ) { |
| 394 | $output .= '<div id="wp-admin-message-handler-message" class="notice-success notice"><ul><li><strong>' . implode( '</strong></li><li><strong>', $this->get_messages() ) . '</strong></li></ul></div>'; |
| 395 | } |
| 396 | |
| 397 | echo wp_kses_post( $output ); |
| 398 | } |
| 399 | |
| 400 | |
| 401 | /** |
| 402 | * Redirection hook which persists messages into session data. |
| 403 | * |
| 404 | * @since 3.0.0 |
| 405 | * @param string $location the URL to redirect to |
| 406 | * @param int $status the http status |
| 407 | * @return string the URL to redirect to |
| 408 | */ |
| 409 | public function redirect( $location, $status ) { |
| 410 | |
| 411 | // add the admin message id param to the |
| 412 | if ( $this->set_messages() ) { |
| 413 | $location = add_query_arg( self::MESSAGE_ID_GET_NAME, rawurlencode( $this->get_message_id() ), $location ); |
| 414 | } |
| 415 | |
| 416 | // This return value is only used in filter callback for `wp_redirect` hook, so it's safe not to escape. |
| 417 | // nosemgrep: audit.php.wp.security.xss.query-arg |
| 418 | return $location; |
| 419 | } |
| 420 | |
| 421 | |
| 422 | /** |
| 423 | * Generate a unique id to identify the messages |
| 424 | * |
| 425 | * @since 3.0.0 |
| 426 | * @return string unique identifier |
| 427 | */ |
| 428 | protected function get_message_id() { |
| 429 | |
| 430 | if ( ! isset( $this->message_id ) ) { |
| 431 | $this->message_id = __FILE__; |
| 432 | } |
| 433 | |
| 434 | return wp_create_nonce( $this->message_id ); |
| 435 | |
| 436 | } |
| 437 | } |
| 438 |