* * @see http://wcpos.com * @package WCPOS\WooCommercePOS */ namespace WCPOS\WooCommercePOS\Templates; use Exception; use WCPOS\WooCommercePOS\Services\Settings; /** * Payment class. */ class Payment { /** * The order ID. * * @var int */ private $order_id; /** * The order. * * @var \WC_Order */ private $order; /** * The coupon nonce. * * @var string */ private $coupon_nonce; /** * The troubleshooting form nonce. * * @var string */ private $troubleshooting_form_nonce; /** * Disable wp_head setting. * * @var bool */ private $disable_wp_head; /** * Disable wp_footer setting. * * @var bool */ private $disable_wp_footer; /** * Constructor. * * @param int $order_id The order ID. */ public function __construct( int $order_id ) { $this->order_id = $order_id; $this->check_troubleshooting_form_submission(); $settings_service = Settings::instance(); $this->disable_wp_head = (bool) $settings_service->get_settings( 'checkout', 'disable_wp_head' ); $this->disable_wp_footer = (bool) $settings_service->get_settings( 'checkout', 'disable_wp_footer' ); // this is a checkout page. add_filter( 'woocommerce_is_checkout', '__return_true' ); // remove the terms and conditions checkbox. add_filter( 'woocommerce_checkout_show_terms', '__return_false' ); // remove junk from head. add_filter( 'show_admin_bar', '__return_false' ); remove_action( 'wp_head', 'rsd_link' ); remove_action( 'wp_head', 'wp_generator' ); remove_action( 'wp_head', 'feed_links', 2 ); remove_action( 'wp_head', 'index_rel_link' ); remove_action( 'wp_head', 'wlwmanifest_link' ); remove_action( 'wp_head', 'feed_links_extra', 3 ); remove_action( 'wp_head', 'start_post_rel_link', 10, 0 ); remove_action( 'wp_head', 'parent_post_rel_link', 10, 0 ); remove_action( 'wp_head', 'adjacent_posts_rel_link', 10, 0 ); remove_action( 'wp_head', 'wp_shortlink_wp_head', 10, 0 ); remove_action( 'wp_head', 'adjacent_posts_rel_link_wp_head', 10, 0 ); add_action( 'wp_enqueue_scripts', array( $this, 'remove_scripts_and_styles' ), 100 ); } /** * Each theme will apply its own styles to the checkout page. * I want to keep it simple, so we remove all styles and scripts associated with the active theme. * NOTE: This is not perfect, we don't know the theme handle, so we just take a guess from the source URL. * * @return void */ /** * Remove enqueued scripts and styles. * * This function dequeues all scripts and styles that are not specified in the WCPOS settings, * unless they are specifically included by the 'woocommerce_pos_payment_template_dequeue_script_handles' * and 'woocommerce_pos_payment_template_dequeue_style_handles' filters. * * @since 1.3.0 */ public function remove_scripts_and_styles(): void { global $wp_styles, $wp_scripts; /** * List of script handles to exclude from the payment template. * * @since 1.3.0 */ $script_exclude_list = apply_filters( 'woocommerce_pos_payment_template_dequeue_script_handles', Settings::instance()->dequeue_script_handles() ); /** * List of style handles to exclude from the payment template. * * @since 1.3.0 */ $style_exclude_list = apply_filters( 'woocommerce_pos_payment_template_dequeue_style_handles', Settings::instance()->dequeue_style_handles() ); // Loop through all enqueued styles and dequeue those that are in the exclusion list. if ( \is_array( $style_exclude_list ) ) { foreach ( $wp_styles->queue as $handle ) { if ( \in_array( $handle, $style_exclude_list, true ) ) { wp_dequeue_style( $handle ); } } } // Loop through all enqueued scripts and dequeue those that are in the exclusion list. if ( \is_array( $script_exclude_list ) ) { foreach ( $wp_scripts->queue as $handle ) { if ( \in_array( $handle, $script_exclude_list, true ) ) { wp_dequeue_script( $handle ); } } } } /** * Render the payment template. * * @return void */ public function get_template(): void { if ( ! \defined( 'WOOCOMMERCE_CHECKOUT' ) ) { \define( 'WOOCOMMERCE_CHECKOUT', true ); // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedConstantFound -- WooCommerce constant. } do_action( 'woocommerce_pos_before_pay' ); try { // initialize order and nonces before the user is switched to customer. $this->initialize_order_and_nonces(); // Verify order key to prevent unauthenticated access. // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Order key is the auth mechanism here, matching WooCommerce core behavior. $provided_key = isset( $_GET['key'] ) ? sanitize_text_field( wp_unslash( $_GET['key'] ) ) : ''; if ( ! $provided_key || $provided_key !== $this->order->get_order_key() ) { wp_die( esc_html__( 'Sorry, this order cannot be paid for. The order key is missing or invalid.', 'woocommerce-pos' ), /* translators: Short WCPOS UI label; keep concise. */ esc_html__( 'Error', 'woocommerce-pos' ), array( 'response' => 403 ) ); } /* * The wp_set_current_user() function changes the global user object but it does not authenticate the user * for the current session. This means that it will not affect nonce creation or validation because WordPress * nonces are tied to the user's session. * * @TODO - is this the best way to do this? */ wp_set_current_user( $this->order->get_customer_id() ); add_filter( 'nonce_user_logged_out', array( $this, 'nonce_user_logged_out' ), 10, 2 ); // Logged in customer trying to pay for someone else's order. if ( ! current_user_can( 'pay_for_order', $this->order_id ) ) { wp_die( esc_html__( 'This order cannot be paid for. Please contact us if you need assistance.', 'woocommerce-pos' ) ); } // We need to reload the gateways here to use the current customer details. WC()->payment_gateways()->init(); $available_gateways = WC()->payment_gateways->get_available_payment_gateways(); $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. include woocommerce_pos_locate_template( 'payment.php' ); } catch ( Exception $e ) { wc_print_notice( $e->getMessage(), 'error' ); } } /** * Render the troubleshooting form HTML. * * @return string */ public function get_troubleshooting_form_html(): string { global $wp_styles, $wp_scripts; $style_handles = $wp_styles->queue; $script_handles = $wp_scripts->queue; $style_exclude_list = apply_filters( 'woocommerce_pos_payment_template_dequeue_style_handles', Settings::instance()->dequeue_style_handles() ); $script_exclude_list = apply_filters( 'woocommerce_pos_payment_template_dequeue_script_handles', Settings::instance()->dequeue_script_handles() ); $merged_style_handles = array_unique( array_merge( $style_handles, $style_exclude_list ) ); $merged_script_handles = array_unique( array_merge( $script_handles, $script_exclude_list ) ); ob_start(); ?>
order->get_meta( '_pos_user', true ); $cashier = get_user_by( 'id', $cashier ); ob_start(); ?>
: display_name ); ?>
: ID ? /* translators: Short WCPOS UI label; keep concise. */ esc_html__( 'Guest', 'woocommerce-pos' ) : esc_html( $customer->display_name ); ?>
order->get_items( 'coupon' ); if ( $coupons ) { echo '

' . esc_html__( 'Applied coupons', 'woocommerce' ) . '

'; echo ''; } ?>
order = wc_get_order( $this->order_id ); if ( ! $this->order || $this->order->get_id() !== $this->order_id ) { wp_die( esc_html__( 'Sorry, this order is invalid and cannot be paid for.', 'woocommerce-pos' ) ); } if ( $this->order->is_paid() ) { wp_die( esc_html__( 'Sorry, this order has already been paid for.', 'woocommerce-pos' ) ); } $this->coupon_nonce = wp_create_nonce( 'pos_coupon_action' ); $this->troubleshooting_form_nonce = wp_create_nonce( 'troubleshooting_form_nonce' ); } /** * Save the settings from the troubleshooting form. * * @return void */ private function check_troubleshooting_form_submission(): void { // Check if our form has been submitted. if ( isset( $_POST['troubleshooting_form_nonce'] ) ) { // Only allow users with manage_woocommerce capability to modify checkout settings. if ( ! current_user_can( 'manage_woocommerce' ) ) { wp_die( esc_html__( 'You do not have permission to modify checkout settings.', 'woocommerce-pos' ), /* translators: Short WCPOS UI label; keep concise. */ esc_html__( 'Error', 'woocommerce-pos' ), array( 'response' => 403 ) ); } // Verify the nonce. if ( ! wp_verify_nonce( $_POST['troubleshooting_form_nonce'], 'troubleshooting_form_nonce' ) ) { // Nonce doesn't verify, we should stop execution here. die( 'Nonce value cannot be verified.' ); } // This will hold your sanitized data. $sanitized_data = array(); // Sanitize all_styles array. if ( isset( $_POST['all_styles'] ) && \is_array( $_POST['all_styles'] ) ) { $sanitized_data['all_styles'] = array_map( 'sanitize_text_field', wp_unslash( $_POST['all_styles'] ) ); } // Sanitize styles array. if ( isset( $_POST['styles'] ) && \is_array( $_POST['styles'] ) ) { $sanitized_data['styles'] = array_map( 'sanitize_text_field', wp_unslash( $_POST['styles'] ) ); } else { $sanitized_data['styles'] = array(); // consider all styles unchecked if 'styles' is not submitted. } // Sanitize all_scripts array. if ( isset( $_POST['all_scripts'] ) && \is_array( $_POST['all_scripts'] ) ) { $sanitized_data['all_scripts'] = array_map( 'sanitize_text_field', wp_unslash( $_POST['all_scripts'] ) ); } // Sanitize scripts array. if ( isset( $_POST['scripts'] ) && \is_array( $_POST['scripts'] ) ) { $sanitized_data['scripts'] = array_map( 'sanitize_text_field', wp_unslash( $_POST['scripts'] ) ); } else { $sanitized_data['scripts'] = array(); // consider all scripts unchecked if 'scripts' is not submitted. } // Calculate unchecked styles and scripts. $unchecked_styles = isset( $sanitized_data['all_styles'] ) ? array_diff( $sanitized_data['all_styles'], $sanitized_data['styles'] ) : array(); $unchecked_scripts = isset( $sanitized_data['all_scripts'] ) ? array_diff( $sanitized_data['all_scripts'], $sanitized_data['scripts'] ) : array(); // Sanitize disable_wp_head and disable_wp_footer options. $disable_wp_head = isset( $_POST['disable_wp_head'] ) ? (bool) $_POST['disable_wp_head'] : false; $disable_wp_footer = isset( $_POST['disable_wp_footer'] ) ? (bool) $_POST['disable_wp_footer'] : false; // @TODO - the save settings function should allow saving by key $checkout_settings = woocommerce_pos_get_settings( 'checkout' ); $new_settings = array_merge( $checkout_settings, array( 'disable_wp_head' => $disable_wp_head, 'disable_wp_footer' => $disable_wp_footer, 'dequeue_style_handles' => $unchecked_styles, 'dequeue_script_handles' => $unchecked_scripts, ) ); $settings_service = Settings::instance(); $settings_service->save_settings( 'checkout', $new_settings ); } } }