| 1 |
<?php |
| 2 |
/** |
| 3 |
* Payment template. |
| 4 |
* |
| 5 |
* @author Paul Kilmurray <paul@kilbot.com> |
| 6 |
* |
| 7 |
* @see http://wcpos.com |
| 8 |
* @package WCPOS\WooCommercePOS |
| 9 |
*/ |
| 10 |
|
| 11 |
namespace WCPOS\WooCommercePOS\Templates; |
| 12 |
|
| 13 |
use Exception; |
| 14 |
use WCPOS\WooCommercePOS\Services\Settings; |
| 15 |
|
| 16 |
/** |
| 17 |
* Payment class. |
| 18 |
*/ |
| 19 |
class Payment { |
| 20 |
/** |
| 21 |
* The order ID. |
| 22 |
* |
| 23 |
* @var int |
| 24 |
*/ |
| 25 |
private $order_id; |
| 26 |
|
| 27 |
/** |
| 28 |
* The order. |
| 29 |
* |
| 30 |
* @var \WC_Order |
| 31 |
*/ |
| 32 |
private $order; |
| 33 |
|
| 34 |
/** |
| 35 |
* The coupon nonce. |
| 36 |
* |
| 37 |
* @var string |
| 38 |
*/ |
| 39 |
private $coupon_nonce; |
| 40 |
|
| 41 |
/** |
| 42 |
* The troubleshooting form nonce. |
| 43 |
* |
| 44 |
* @var string |
| 45 |
*/ |
| 46 |
private $troubleshooting_form_nonce; |
| 47 |
|
| 48 |
/** |
| 49 |
* Disable wp_head setting. |
| 50 |
* |
| 51 |
* @var bool |
| 52 |
*/ |
| 53 |
private $disable_wp_head; |
| 54 |
|
| 55 |
/** |
| 56 |
* Disable wp_footer setting. |
| 57 |
* |
| 58 |
* @var bool |
| 59 |
*/ |
| 60 |
private $disable_wp_footer; |
| 61 |
|
| 62 |
/** |
| 63 |
* Constructor. |
| 64 |
* |
| 65 |
* @param int $order_id The order ID. |
| 66 |
*/ |
| 67 |
public function __construct( int $order_id ) { |
| 68 |
$this->order_id = $order_id; |
| 69 |
$this->check_troubleshooting_form_submission(); |
| 70 |
$settings_service = Settings::instance(); |
| 71 |
$this->disable_wp_head = (bool) $settings_service->get_settings( 'checkout', 'disable_wp_head' ); |
| 72 |
$this->disable_wp_footer = (bool) $settings_service->get_settings( 'checkout', 'disable_wp_footer' ); |
| 73 |
|
| 74 |
// this is a checkout page. |
| 75 |
add_filter( 'woocommerce_is_checkout', '__return_true' ); |
| 76 |
// remove the terms and conditions checkbox. |
| 77 |
add_filter( 'woocommerce_checkout_show_terms', '__return_false' ); |
| 78 |
|
| 79 |
// remove junk from head. |
| 80 |
add_filter( 'show_admin_bar', '__return_false' ); |
| 81 |
remove_action( 'wp_head', 'rsd_link' ); |
| 82 |
remove_action( 'wp_head', 'wp_generator' ); |
| 83 |
remove_action( 'wp_head', 'feed_links', 2 ); |
| 84 |
remove_action( 'wp_head', 'index_rel_link' ); |
| 85 |
remove_action( 'wp_head', 'wlwmanifest_link' ); |
| 86 |
remove_action( 'wp_head', 'feed_links_extra', 3 ); |
| 87 |
remove_action( 'wp_head', 'start_post_rel_link', 10, 0 ); |
| 88 |
remove_action( 'wp_head', 'parent_post_rel_link', 10, 0 ); |
| 89 |
remove_action( 'wp_head', 'adjacent_posts_rel_link', 10, 0 ); |
| 90 |
remove_action( 'wp_head', 'wp_shortlink_wp_head', 10, 0 ); |
| 91 |
remove_action( 'wp_head', 'adjacent_posts_rel_link_wp_head', 10, 0 ); |
| 92 |
|
| 93 |
add_action( 'wp_enqueue_scripts', array( $this, 'remove_scripts_and_styles' ), 100 ); |
| 94 |
} |
| 95 |
|
| 96 |
/** |
| 97 |
* Each theme will apply its own styles to the checkout page. |
| 98 |
* I want to keep it simple, so we remove all styles and scripts associated with the active theme. |
| 99 |
* NOTE: This is not perfect, we don't know the theme handle, so we just take a guess from the source URL. |
| 100 |
* |
| 101 |
* @return void |
| 102 |
*/ |
| 103 |
/** |
| 104 |
* Remove enqueued scripts and styles. |
| 105 |
* |
| 106 |
* This function dequeues all scripts and styles that are not specified in the WCPOS settings, |
| 107 |
* unless they are specifically included by the 'woocommerce_pos_payment_template_dequeue_script_handles' |
| 108 |
* and 'woocommerce_pos_payment_template_dequeue_style_handles' filters. |
| 109 |
* |
| 110 |
* @since 1.3.0 |
| 111 |
*/ |
| 112 |
public function remove_scripts_and_styles(): void { |
| 113 |
global $wp_styles, $wp_scripts; |
| 114 |
|
| 115 |
/** |
| 116 |
* List of script handles to exclude from the payment template. |
| 117 |
* |
| 118 |
* @since 1.3.0 |
| 119 |
*/ |
| 120 |
$script_exclude_list = apply_filters( |
| 121 |
'woocommerce_pos_payment_template_dequeue_script_handles', |
| 122 |
Settings::instance()->dequeue_script_handles() |
| 123 |
); |
| 124 |
|
| 125 |
/** |
| 126 |
* List of style handles to exclude from the payment template. |
| 127 |
* |
| 128 |
* @since 1.3.0 |
| 129 |
*/ |
| 130 |
$style_exclude_list = apply_filters( |
| 131 |
'woocommerce_pos_payment_template_dequeue_style_handles', |
| 132 |
Settings::instance()->dequeue_style_handles() |
| 133 |
); |
| 134 |
|
| 135 |
// Loop through all enqueued styles and dequeue those that are in the exclusion list. |
| 136 |
if ( \is_array( $style_exclude_list ) ) { |
| 137 |
foreach ( $wp_styles->queue as $handle ) { |
| 138 |
if ( \in_array( $handle, $style_exclude_list, true ) ) { |
| 139 |
wp_dequeue_style( $handle ); |
| 140 |
} |
| 141 |
} |
| 142 |
} |
| 143 |
|
| 144 |
// Loop through all enqueued scripts and dequeue those that are in the exclusion list. |
| 145 |
if ( \is_array( $script_exclude_list ) ) { |
| 146 |
foreach ( $wp_scripts->queue as $handle ) { |
| 147 |
if ( \in_array( $handle, $script_exclude_list, true ) ) { |
| 148 |
wp_dequeue_script( $handle ); |
| 149 |
} |
| 150 |
} |
| 151 |
} |
| 152 |
} |
| 153 |
|
| 154 |
|
| 155 |
/** |
| 156 |
* Render the payment template. |
| 157 |
* |
| 158 |
* @return void |
| 159 |
*/ |
| 160 |
public function get_template(): void { |
| 161 |
if ( ! \defined( 'WOOCOMMERCE_CHECKOUT' ) ) { |
| 162 |
\define( 'WOOCOMMERCE_CHECKOUT', true ); // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedConstantFound -- WooCommerce constant. |
| 163 |
} |
| 164 |
|
| 165 |
do_action( 'woocommerce_pos_before_pay' ); |
| 166 |
|
| 167 |
try { |
| 168 |
// initialize order and nonces before the user is switched to customer. |
| 169 |
$this->initialize_order_and_nonces(); |
| 170 |
|
| 171 |
// Verify order key to prevent unauthenticated access. |
| 172 |
// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Order key is the auth mechanism here, matching WooCommerce core behavior. |
| 173 |
$provided_key = isset( $_GET['key'] ) ? sanitize_text_field( wp_unslash( $_GET['key'] ) ) : ''; |
| 174 |
if ( ! $provided_key || $provided_key !== $this->order->get_order_key() ) { |
| 175 |
wp_die( |
| 176 |
esc_html__( 'Sorry, this order cannot be paid for. The order key is missing or invalid.', 'woocommerce-pos' ), |
| 177 |
/* translators: Short WCPOS UI label; keep concise. */ |
| 178 |
esc_html__( 'Error', 'woocommerce-pos' ), |
| 179 |
array( 'response' => 403 ) |
| 180 |
); |
| 181 |
} |
| 182 |
|
| 183 |
/* |
| 184 |
* The wp_set_current_user() function changes the global user object but it does not authenticate the user |
| 185 |
* for the current session. This means that it will not affect nonce creation or validation because WordPress |
| 186 |
* nonces are tied to the user's session. |
| 187 |
* |
| 188 |
* @TODO - is this the best way to do this? |
| 189 |
*/ |
| 190 |
wp_set_current_user( $this->order->get_customer_id() ); |
| 191 |
add_filter( 'nonce_user_logged_out', array( $this, 'nonce_user_logged_out' ), 10, 2 ); |
| 192 |
|
| 193 |
// Logged in customer trying to pay for someone else's order. |
| 194 |
if ( ! current_user_can( 'pay_for_order', $this->order_id ) ) { |
| 195 |
wp_die( esc_html__( 'This order cannot be paid for. Please contact us if you need assistance.', 'woocommerce-pos' ) ); |
| 196 |
} |
| 197 |
|
| 198 |
// We need to reload the gateways here to use the current customer details. |
| 199 |
WC()->payment_gateways()->init(); |
| 200 |
$available_gateways = WC()->payment_gateways->get_available_payment_gateways(); |
| 201 |
|
| 202 |
$order_button_text = apply_filters( 'woocommerce_pay_order_button_text', /* translators: Short WCPOS UI label; keep concise. */ __( 'Pay for order', 'woocommerce-pos' ) ); // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound -- WooCommerce core hook. |
| 203 |
|
| 204 |
include woocommerce_pos_locate_template( 'payment.php' ); |
| 205 |
} catch ( Exception $e ) { |
| 206 |
wc_print_notice( $e->getMessage(), 'error' ); |
| 207 |
} |
| 208 |
} |
| 209 |
|
| 210 |
/** |
| 211 |
* Render the troubleshooting form HTML. |
| 212 |
* |
| 213 |
* @return string |
| 214 |
*/ |
| 215 |
public function get_troubleshooting_form_html(): string { |
| 216 |
global $wp_styles, $wp_scripts; |
| 217 |
$style_handles = $wp_styles->queue; |
| 218 |
$script_handles = $wp_scripts->queue; |
| 219 |
|
| 220 |
$style_exclude_list = apply_filters( |
| 221 |
'woocommerce_pos_payment_template_dequeue_style_handles', |
| 222 |
Settings::instance()->dequeue_style_handles() |
| 223 |
); |
| 224 |
|
| 225 |
$script_exclude_list = apply_filters( |
| 226 |
'woocommerce_pos_payment_template_dequeue_script_handles', |
| 227 |
Settings::instance()->dequeue_script_handles() |
| 228 |
); |
| 229 |
|
| 230 |
$merged_style_handles = array_unique( array_merge( $style_handles, $style_exclude_list ) ); |
| 231 |
$merged_script_handles = array_unique( array_merge( $script_handles, $script_exclude_list ) ); |
| 232 |
|
| 233 |
ob_start(); |
| 234 |
?> |
| 235 |
<div class="woocommerce-pos-troubleshooting"> |
| 236 |
<div style="text-align:right"> |
| 237 |
<button type="button" class="open-troubleshooting-modal"><?php /* translators: Short WCPOS UI label; keep concise. */ esc_html_e( 'Checkout Settings', 'woocommerce-pos' ); ?></button> |
| 238 |
</div> |
| 239 |
<div id="troubleshooting-modal" class="troubleshooting-modal" style="display: none;"> |
| 240 |
<div class="troubleshooting-modal-content"> |
| 241 |
<span class="close-troubleshooting-modal">×</span> |
| 242 |
<form id="troubleshooting-form" method="POST"> |
| 243 |
<p class="woocommerce-info"><?php esc_html_e( 'Scripts and styles may interfere with the custom payment template, use this form to dequeue any problematic scripts.', 'woocommerce-pos' ); ?></p> |
| 244 |
<div style="margin-bottom: 20px;"> |
| 245 |
<h3><?php esc_html_e( 'Disable All Styles and Scripts', 'woocommerce-pos' ); ?></h3> |
| 246 |
<label for="disable_wp_head"> |
| 247 |
<input type="checkbox" id="disable_wp_head" name="disable_wp_head" value="1" <?php checked( $this->disable_wp_head ); ?>> |
| 248 |
<?php /* translators: Short WCPOS UI label; keep concise. */ esc_html_e( 'Disable wp_head', 'woocommerce-pos' ); ?> |
| 249 |
</label> |
| 250 |
<br> |
| 251 |
<label for="disable_wp_footer"> |
| 252 |
<input type="checkbox" id="disable_wp_footer" name="disable_wp_footer" value="1" <?php checked( $this->disable_wp_footer ); ?>> |
| 253 |
<?php /* translators: Short WCPOS UI label; keep concise. */ esc_html_e( 'Disable wp_footer', 'woocommerce-pos' ); ?> |
| 254 |
</label> |
| 255 |
</div> |
| 256 |
<div style="display: flex; justify-content: space-between;margin-bottom:20px;"> |
| 257 |
<div style="flex: 1;"> |
| 258 |
<h3><?php /* translators: Short WCPOS UI label; keep concise. */ esc_html_e( 'Disable Selected Styles', 'woocommerce-pos' ); ?></h3> |
| 259 |
<?php |
| 260 |
foreach ( $merged_style_handles as $handle ) { |
| 261 |
$checked = ! \in_array( $handle, $style_exclude_list, true ) ? 'checked' : ''; |
| 262 |
?> |
| 263 |
<input type="checkbox" id="<?php echo esc_attr( $handle ); ?>" name="styles[]" value="<?php echo esc_attr( $handle ); ?>" <?php echo esc_attr( $checked ); ?>> |
| 264 |
<label for="<?php echo esc_attr( $handle ); ?>"><?php echo esc_html( $handle ); ?></label> |
| 265 |
<input type="hidden" name="all_styles[]" value="<?php echo esc_attr( $handle ); ?>"><br> |
| 266 |
<?php } ?> |
| 267 |
</div> |
| 268 |
<div style="flex: 1;"> |
| 269 |
<h3><?php /* translators: Short WCPOS UI label; keep concise. */ esc_html_e( 'Disable Selected Scripts', 'woocommerce-pos' ); ?></h3> |
| 270 |
<?php |
| 271 |
foreach ( $merged_script_handles as $handle ) { |
| 272 |
$checked = ! \in_array( $handle, $script_exclude_list, true ) ? 'checked' : ''; |
| 273 |
?> |
| 274 |
<input type="checkbox" id="<?php echo esc_attr( $handle ); ?>" name="scripts[]" value="<?php echo esc_attr( $handle ); ?>" <?php echo esc_attr( $checked ); ?>> |
| 275 |
<label for="<?php echo esc_html( $handle ); ?>"><?php echo esc_html( $handle ); ?></label> |
| 276 |
<input type="hidden" name="all_scripts[]" value="<?php echo esc_attr( $handle ); ?>"><br> |
| 277 |
<?php } ?> |
| 278 |
</div> |
| 279 |
</div> |
| 280 |
<input type="hidden" name="troubleshooting_form_nonce" value="<?php echo esc_attr( $this->troubleshooting_form_nonce ); ?>" /> |
| 281 |
<button type="submit"><?php /* translators: Short WCPOS UI label; keep concise. */ esc_html_e( 'Submit', 'woocommerce-pos' ); ?></button> |
| 282 |
</form> |
| 283 |
</div> |
| 284 |
</div> |
| 285 |
</div> |
| 286 |
|
| 287 |
<script> |
| 288 |
document.querySelector('.open-troubleshooting-modal').addEventListener('click', () => { |
| 289 |
document.getElementById('troubleshooting-modal').style.display = 'block'; |
| 290 |
}); |
| 291 |
document.querySelector('.close-troubleshooting-modal').addEventListener('click', () => { |
| 292 |
document.getElementById('troubleshooting-modal').style.display = 'none'; |
| 293 |
}); |
| 294 |
window.addEventListener('click', event => { |
| 295 |
if (event.target === document.getElementById('troubleshooting-modal')) { |
| 296 |
document.getElementById('troubleshooting-modal').style.display = 'none'; |
| 297 |
} |
| 298 |
}); |
| 299 |
</script> |
| 300 |
<?php |
| 301 |
return ob_get_clean(); |
| 302 |
} |
| 303 |
|
| 304 |
/** |
| 305 |
* Render the cashier details HTML. |
| 306 |
* |
| 307 |
* @return string |
| 308 |
*/ |
| 309 |
public function get_cashier_details_html(): string { |
| 310 |
$cashier = $this->order->get_meta( '_pos_user', true ); |
| 311 |
$cashier = get_user_by( 'id', $cashier ); |
| 312 |
|
| 313 |
ob_start(); |
| 314 |
?> |
| 315 |
<div class="cashier"> |
| 316 |
<span><?php /* translators: Short WCPOS UI label; keep concise. */ esc_html_e( 'Cashier', 'woocommerce-pos' ); ?>: </span> |
| 317 |
<span class="cashier-name"><?php echo esc_html( $cashier->display_name ); ?></span> |
| 318 |
</div> |
| 319 |
<?php |
| 320 |
return ob_get_clean(); |
| 321 |
} |
| 322 |
|
| 323 |
/** |
| 324 |
* Render the address fields HTML. |
| 325 |
* |
| 326 |
* @return string |
| 327 |
*/ |
| 328 |
public function get_paying_customer_details_html(): string { |
| 329 |
$customer = wp_get_current_user(); |
| 330 |
ob_start(); |
| 331 |
?> |
| 332 |
<div class="current-user"> |
| 333 |
<span><?php /* translators: Short WCPOS UI label; keep concise. */ esc_html_e( 'Paying as customer', 'woocommerce-pos' ); ?>: </span> |
| 334 |
<span class="user-name"><?php echo 0 === $customer->ID ? /* translators: Short WCPOS UI label; keep concise. */ esc_html__( 'Guest', 'woocommerce-pos' ) : esc_html( $customer->display_name ); ?></span> |
| 335 |
</div> |
| 336 |
<div class="address-fields" style="display: none;"> |
| 337 |
<section class="woocommerce-customer-details"> |
| 338 |
|
| 339 |
<section class="woocommerce-columns woocommerce-columns--2 woocommerce-columns--addresses col2-set addresses"> |
| 340 |
<div class="woocommerce-column woocommerce-column--1 woocommerce-column--billing-address col-1"> |
| 341 |
<h2 class="woocommerce-column__title"><?php esc_html_e( 'Billing address', 'woocommerce' ); ?></h2> |
| 342 |
<address> |
| 343 |
<?php echo wp_kses_post( $this->order->get_formatted_billing_address( esc_html__( 'N/A', 'woocommerce' ) ) ); ?> |
| 344 |
<?php if ( $this->order->get_billing_phone() ) { ?> |
| 345 |
<p class="woocommerce-customer-details--phone"><?php echo esc_html( $this->order->get_billing_phone() ); ?></p> |
| 346 |
<?php } ?> |
| 347 |
<?php if ( $this->order->get_billing_email() ) { ?> |
| 348 |
<p class="woocommerce-customer-details--email"><?php echo esc_html( $this->order->get_billing_email() ); ?></p> |
| 349 |
<?php } ?> |
| 350 |
</address> |
| 351 |
</div><!-- /.col-1 --> |
| 352 |
|
| 353 |
<div class="woocommerce-column woocommerce-column--2 woocommerce-column--shipping-address col-2"> |
| 354 |
<h2 class="woocommerce-column__title"><?php esc_html_e( 'Shipping address', 'woocommerce' ); ?></h2> |
| 355 |
<address> |
| 356 |
<?php echo wp_kses_post( $this->order->get_formatted_shipping_address( esc_html__( 'N/A', 'woocommerce' ) ) ); ?> |
| 357 |
<?php if ( $this->order->get_shipping_phone() ) { ?> |
| 358 |
<p class="woocommerce-customer-details--phone"><?php echo esc_html( $this->order->get_shipping_phone() ); ?></p> |
| 359 |
<?php } ?> |
| 360 |
</address> |
| 361 |
</div><!-- /.col-2 --> |
| 362 |
|
| 363 |
</section><!-- /.col2-set --> |
| 364 |
|
| 365 |
<?php do_action( 'woocommerce_order_details_after_customer_details', $this->order ); // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound -- WooCommerce core hook. ?> |
| 366 |
|
| 367 |
</section> |
| 368 |
</div> |
| 369 |
<script> |
| 370 |
document.querySelector('.current-user .user-name').addEventListener('click', () => { |
| 371 |
const addressFields = document.querySelector('.address-fields'); |
| 372 |
addressFields.style.display = addressFields.style.display === 'none' ? 'block' : 'none'; |
| 373 |
}); |
| 374 |
</script> |
| 375 |
<?php |
| 376 |
return ob_get_clean(); |
| 377 |
} |
| 378 |
|
| 379 |
/** |
| 380 |
* Render the coupon form HTML. |
| 381 |
* |
| 382 |
* @return string |
| 383 |
*/ |
| 384 |
public function get_coupon_form_html(): string { |
| 385 |
ob_start(); |
| 386 |
?> |
| 387 |
<div class="coupons"> |
| 388 |
<form method="post" action=""> |
| 389 |
<input type="hidden" name="pos_coupon_nonce" value="<?php echo esc_attr( $this->coupon_nonce ); ?>" /> |
| 390 |
<input type="text" name="pos_coupon_code" class="input-text" placeholder="<?php esc_attr_e( 'Coupon code', 'woocommerce' ); ?>" id="pos_coupon_code" value="" /> |
| 391 |
<button type="submit" class="button" name="pos_apply_coupon" value="<?php esc_attr_e( 'Apply coupon', 'woocommerce' ); ?>"> |
| 392 |
<?php esc_html_e( 'Apply coupon', 'woocommerce' ); ?> |
| 393 |
</button> |
| 394 |
|
| 395 |
<?php |
| 396 |
$coupons = $this->order->get_items( 'coupon' ); |
| 397 |
if ( $coupons ) { |
| 398 |
echo '<h3>' . esc_html__( 'Applied coupons', 'woocommerce' ) . '</h3>'; |
| 399 |
echo '<ul>'; |
| 400 |
foreach ( $coupons as $coupon ) { |
| 401 |
echo '<li>' . esc_html( $coupon->get_code() ) . ' <button type="submit" class="button" name="pos_remove_coupon" value="' . esc_attr( $coupon->get_code() ) . '">' . esc_html__( 'Remove', 'woocommerce' ) . '</button></li>'; |
| 402 |
} |
| 403 |
echo '</ul>'; |
| 404 |
} |
| 405 |
?> |
| 406 |
</form> |
| 407 |
</div> |
| 408 |
<?php |
| 409 |
return ob_get_clean(); |
| 410 |
} |
| 411 |
|
| 412 |
/** |
| 413 |
* Fix: when checking out as Guest on the desktop application, WordPress gets a $uid from the |
| 414 |
* session, eg: 't_8b04f8283e7edc5aeee2867c89dd06'. This causes the nonce check to fail. |
| 415 |
* |
| 416 |
* @param mixed $uid The user ID. |
| 417 |
* @param mixed $action The nonce action. |
| 418 |
*/ |
| 419 |
public function nonce_user_logged_out( $uid, $action ) { |
| 420 |
if ( 'woocommerce-pay' === $action ) { |
| 421 |
return 0; |
| 422 |
} |
| 423 |
|
| 424 |
return $uid; |
| 425 |
} |
| 426 |
|
| 427 |
/** |
| 428 |
* Initialize the order and nonce properties. |
| 429 |
*/ |
| 430 |
private function initialize_order_and_nonces(): void { |
| 431 |
$this->order = wc_get_order( $this->order_id ); |
| 432 |
|
| 433 |
if ( ! $this->order || $this->order->get_id() !== $this->order_id ) { |
| 434 |
wp_die( esc_html__( 'Sorry, this order is invalid and cannot be paid for.', 'woocommerce-pos' ) ); |
| 435 |
} |
| 436 |
|
| 437 |
if ( $this->order->is_paid() ) { |
| 438 |
wp_die( esc_html__( 'Sorry, this order has already been paid for.', 'woocommerce-pos' ) ); |
| 439 |
} |
| 440 |
|
| 441 |
$this->coupon_nonce = wp_create_nonce( 'pos_coupon_action' ); |
| 442 |
$this->troubleshooting_form_nonce = wp_create_nonce( 'troubleshooting_form_nonce' ); |
| 443 |
} |
| 444 |
|
| 445 |
/** |
| 446 |
* Save the settings from the troubleshooting form. |
| 447 |
* |
| 448 |
* @return void |
| 449 |
*/ |
| 450 |
private function check_troubleshooting_form_submission(): void { |
| 451 |
// Check if our form has been submitted. |
| 452 |
if ( isset( $_POST['troubleshooting_form_nonce'] ) ) { |
| 453 |
// Only allow users with manage_woocommerce capability to modify checkout settings. |
| 454 |
if ( ! current_user_can( 'manage_woocommerce' ) ) { |
| 455 |
wp_die( |
| 456 |
esc_html__( 'You do not have permission to modify checkout settings.', 'woocommerce-pos' ), |
| 457 |
/* translators: Short WCPOS UI label; keep concise. */ |
| 458 |
esc_html__( 'Error', 'woocommerce-pos' ), |
| 459 |
array( 'response' => 403 ) |
| 460 |
); |
| 461 |
} |
| 462 |
|
| 463 |
// Verify the nonce. |
| 464 |
if ( ! wp_verify_nonce( $_POST['troubleshooting_form_nonce'], 'troubleshooting_form_nonce' ) ) { |
| 465 |
// Nonce doesn't verify, we should stop execution here. |
| 466 |
die( 'Nonce value cannot be verified.' ); |
| 467 |
} |
| 468 |
|
| 469 |
// This will hold your sanitized data. |
| 470 |
$sanitized_data = array(); |
| 471 |
|
| 472 |
// Sanitize all_styles array. |
| 473 |
if ( isset( $_POST['all_styles'] ) && \is_array( $_POST['all_styles'] ) ) { |
| 474 |
$sanitized_data['all_styles'] = array_map( 'sanitize_text_field', wp_unslash( $_POST['all_styles'] ) ); |
| 475 |
} |
| 476 |
|
| 477 |
// Sanitize styles array. |
| 478 |
if ( isset( $_POST['styles'] ) && \is_array( $_POST['styles'] ) ) { |
| 479 |
$sanitized_data['styles'] = array_map( 'sanitize_text_field', wp_unslash( $_POST['styles'] ) ); |
| 480 |
} else { |
| 481 |
$sanitized_data['styles'] = array(); // consider all styles unchecked if 'styles' is not submitted. |
| 482 |
} |
| 483 |
|
| 484 |
// Sanitize all_scripts array. |
| 485 |
if ( isset( $_POST['all_scripts'] ) && \is_array( $_POST['all_scripts'] ) ) { |
| 486 |
$sanitized_data['all_scripts'] = array_map( 'sanitize_text_field', wp_unslash( $_POST['all_scripts'] ) ); |
| 487 |
} |
| 488 |
|
| 489 |
// Sanitize scripts array. |
| 490 |
if ( isset( $_POST['scripts'] ) && \is_array( $_POST['scripts'] ) ) { |
| 491 |
$sanitized_data['scripts'] = array_map( 'sanitize_text_field', wp_unslash( $_POST['scripts'] ) ); |
| 492 |
} else { |
| 493 |
$sanitized_data['scripts'] = array(); // consider all scripts unchecked if 'scripts' is not submitted. |
| 494 |
} |
| 495 |
|
| 496 |
// Calculate unchecked styles and scripts. |
| 497 |
$unchecked_styles = isset( $sanitized_data['all_styles'] ) ? array_diff( $sanitized_data['all_styles'], $sanitized_data['styles'] ) : array(); |
| 498 |
$unchecked_scripts = isset( $sanitized_data['all_scripts'] ) ? array_diff( $sanitized_data['all_scripts'], $sanitized_data['scripts'] ) : array(); |
| 499 |
|
| 500 |
// Sanitize disable_wp_head and disable_wp_footer options. |
| 501 |
$disable_wp_head = isset( $_POST['disable_wp_head'] ) ? (bool) $_POST['disable_wp_head'] : false; |
| 502 |
$disable_wp_footer = isset( $_POST['disable_wp_footer'] ) ? (bool) $_POST['disable_wp_footer'] : false; |
| 503 |
|
| 504 |
// @TODO - the save settings function should allow saving by key |
| 505 |
$checkout_settings = woocommerce_pos_get_settings( 'checkout' ); |
| 506 |
$new_settings = array_merge( |
| 507 |
$checkout_settings, |
| 508 |
array( |
| 509 |
'disable_wp_head' => $disable_wp_head, |
| 510 |
'disable_wp_footer' => $disable_wp_footer, |
| 511 |
'dequeue_style_handles' => $unchecked_styles, |
| 512 |
'dequeue_script_handles' => $unchecked_scripts, |
| 513 |
) |
| 514 |
); |
| 515 |
|
| 516 |
$settings_service = Settings::instance(); |
| 517 |
$settings_service->save_settings( 'checkout', $new_settings ); |
| 518 |
} |
| 519 |
} |
| 520 |
} |
| 521 |
|