PluginProbe
WCPOS – Point of Sale (POS) plugin for WooCommerce / 1.10.19
WCPOS – Point of Sale (POS) plugin for WooCommerce v1.10.19
1.10.19 1.10.18 1.10.17 1.10.16 1.10.15 1.10.13 1.10.14 1.10.12 1.10.11 1.10.10 1.10.9 1.10.8 untagged-3d9b7ccddc54df87c672 1.10.7 1.10.6 1.10.5 1.10.3 1.10.4 1.10.2 1.10.1 1.10.0 1.9.17 1.9.15 1.9.16 1.9.14 All 163 releases
woocommerce-pos / includes / Admin / Orders / Single_Order.php

Single_Order.php in WCPOS – Point of Sale (POS) plugin for WooCommerce 1.10.19, at includes/Admin/Orders/Single_Order.php

164 lines 6.0 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Single Order
4 *
5 * @package WCPOS\WooCommercePOS
6 */
7
8 namespace WCPOS\WooCommercePOS\Admin\Orders;
9
10 use WC_Abstract_Order;
11 use WC_Order;
12 use WCPOS\WooCommercePOS\Services\Order_Notes;
13
14 /**
15 * Single_Order class.
16 */
17 class Single_Order {
18
19 /**
20 * Constructor.
21 */
22 public function __construct() {
23 add_filter( 'wc_order_is_editable', array( $this, 'wc_order_is_editable' ), 10, 2 );
24 add_action( 'woocommerce_admin_order_data_after_order_details', array( $this, 'add_cashier_select' ) );
25 add_action( 'woocommerce_process_shop_order_meta', array( $this, 'save_cashier_select' ) );
26 add_action( 'woocommerce_process_shop_order_meta', array( $this, 'add_customer_change_note' ), 10 );
27
28 $this->add_available_gateways();
29 }
30
31 /**
32 * We need to add the POS gateways to the available gateways for the edit order dropdown.
33 * It's possible another plugin could just re-init after us, but this will work for most cases.
34 */
35 public function add_available_gateways() {
36 // @phpstan-ignore-next-line
37 if ( WC()->payment_gateways() ) {
38 $payment_gateways = WC()->payment_gateways->payment_gateways;
39 $settings = woocommerce_pos_get_settings( 'payment_gateways' );
40
41 // Add POS gateways to the available gateways for the edit order dropdown.
42 foreach ( $payment_gateways as $gateway ) {
43 if ( isset( $settings['gateways'][ $gateway->id ] ) && $settings['gateways'][ $gateway->id ]['enabled'] ) {
44 $gateway->enabled = 'yes';
45 }
46 }
47
48 // Directly set the modified gateways back to the WooCommerce Payment Gateways instance.
49 WC()->payment_gateways->payment_gateways = $payment_gateways;
50 }
51 }
52
53 /**
54 * Makes POS orders editable by default.
55 *
56 * @param bool $is_editable Whether the order is editable.
57 * @param WC_Abstract_Order $order The order object.
58 *
59 * @return bool
60 */
61 public function wc_order_is_editable( $is_editable, WC_Abstract_Order $order ) {
62 if ( 'pos-open' == $order->get_status() ) {
63 return true;
64 }
65
66 return $is_editable;
67 }
68
69 /**
70 * Add cashier select to order page.
71 *
72 * @param WC_Abstract_Order $order Order object.
73 */
74 public function add_cashier_select( $order ): void {
75 // only show if order created by POS.
76 if ( ! woocommerce_pos_is_pos_order( $order ) ) {
77 return;
78 }
79
80 $cashier_id = $order->get_meta( '_pos_user' );
81
82 // Create nonce for security.
83 wp_nonce_field( 'pos_cashier_select_action', 'pos_cashier_select_nonce' );
84
85 echo '<p class="form-field form-field-wide">';
86 echo '<label for="_pos_user">' . /* translators: Order list label shown in WooCommerce admin for POS orders. */ esc_html__( 'POS Cashier', 'woocommerce-pos' ) . ':</label>';
87 echo '<select class="wc-customer-search" id="_pos_user" name="_pos_user" data-placeholder="' . /* translators: Order list label shown in WooCommerce admin for POS orders. */ esc_attr__( 'Search for a cashier&hellip;', 'woocommerce-pos' ) . '" data-allow_clear="true" style="width: 100%;">';
88 if ( $cashier_id ) {
89 $user = get_user_by( 'id', $cashier_id );
90 if ( $user ) {
91 echo '<option value="' . esc_attr( (string) $user->ID ) . '"' . selected( true, true, false ) . '>' . esc_html( $user->display_name . ' (#' . $user->ID . ' &ndash; ' . $user->user_email ) . ')</option>';
92 }
93 }
94 echo '</select>';
95 echo '</p>';
96 }
97
98 /**
99 * Save store select in order admin.
100 *
101 * @param int $post_id The post ID.
102 */
103 public function save_cashier_select( $post_id ): void {
104 // Security checks.
105 if ( ! isset( $_POST['pos_cashier_select_nonce'] ) || ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['pos_cashier_select_nonce'] ) ), 'pos_cashier_select_action' ) ) {
106 return;
107 }
108
109 /**
110 * NOTE: HPOS adds a second arg for WC_Abstract_Order, but we will make it backwards compatible.
111 */
112 $order = wc_get_order( $post_id );
113
114 // Check if $order is instance of WC_Abstract_Order and $_POST['_pos_user'] is set.
115 if ( $order instanceof WC_Abstract_Order && isset( $_POST['_pos_user'] ) ) {
116 $new_pos_cashier = (int) sanitize_text_field( wp_unslash( $_POST['_pos_user'] ) );
117 $current_pos_cashier = (int) $order->get_meta( '_pos_user' );
118
119 // Update meta only if _pos_user has changed.
120 if ( $current_pos_cashier !== $new_pos_cashier ) {
121 $order->update_meta_data( '_pos_user', (string) $new_pos_cashier );
122 $order->save();
123
124 // Add an order note indicating the change.
125 $current_cashier = get_userdata( $current_pos_cashier );
126 $new_cashier = get_userdata( $new_pos_cashier );
127 $note = sprintf(
128 // translators: 1: old POS cashier, 2: new POS cashier.
129 __( 'POS cashier changed from %1$s to %2$s.', 'woocommerce-pos' ),
130 $current_cashier ? $current_cashier->display_name : /* translators: Fallback cashier name shown when the POS cashier user cannot be found. */ __( 'Unknown', 'woocommerce-pos' ),
131 $new_cashier ? $new_cashier->display_name : /* translators: Fallback cashier name shown when the POS cashier user cannot be found. */ __( 'Unknown', 'woocommerce-pos' )
132 );
133 $order->add_order_note( $note );
134 }
135 }
136 }
137
138 /**
139 * Add an audit note before WooCommerce applies its posted customer change.
140 *
141 * WooCommerce 10.4.3 registers WC_Meta_Box_Order_Data::save at priority 40;
142 * this priority-10 callback therefore reads the old customer from the order.
143 * Core verifies its order-data nonce before firing this hook.
144 *
145 * @param int $post_id The order ID.
146 */
147 public function add_customer_change_note( $post_id ): void {
148 // phpcs:disable WordPress.Security.NonceVerification.Missing -- WooCommerce verifies its order-data nonce before firing this hook.
149 if ( ! array_key_exists( 'customer_user', $_POST ) ) {
150 return;
151 }
152 $order = wc_get_order( $post_id );
153 if ( ! $order instanceof WC_Order || ! woocommerce_pos_is_pos_order( $order ) ) {
154 return;
155 }
156 $old_customer_id = $order->get_customer_id();
157 $new_customer_id = absint( wp_unslash( $_POST['customer_user'] ?? 0 ) );
158 // phpcs:enable WordPress.Security.NonceVerification.Missing
159 if ( $old_customer_id !== $new_customer_id ) {
160 Order_Notes::add_admin_customer_change_note( $order, $old_customer_id, $new_customer_id );
161 }
162 }
163 }
164