PluginProbe
Orderable – Restaurant & Food Ordering System / 1.19.0
Orderable – Restaurant & Food Ordering System v1.19.0
0.1.4 0.1.5 0.2.0 1.0.0 1.1.0 1.1.1 1.10.0 1.10.1 1.11.0 1.12.0 1.12.1 1.12.2 1.13.0 1.14.0 1.15.0 1.16.0 1.17.0 1.17.1 1.18.0 1.19.0 1.19.1 1.19.2 1.2.0 1.20.0 1.20.1 All 44 releases
orderable / inc / modules / drawer / class-drawer-ajax.php

class-drawer-ajax.php in Orderable – Restaurant & Food Ordering System 1.19.0, at inc/modules/drawer/class-drawer-ajax.php

256 lines 7.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Module: Drawer Ajax.
4 *
5 * @package Orderable/Classes
6 */
7
8 defined( 'ABSPATH' ) || exit;
9
10 /**
11 * Drawer module class.
12 */
13 class Orderable_Drawer_Ajax {
14 /**
15 * Init.
16 */
17 public static function run() {
18 Orderable_Ajax::add_ajax_methods(
19 array(
20 'cart_quantity' => true,
21 'update_cart_item_options' => true,
22 ),
23 __CLASS__
24 );
25 }
26
27 /**
28 * Modify cart item qty.
29 */
30 public static function cart_quantity() {
31 $product_id = empty( $_POST['product_id'] ) ? '' : sanitize_text_field( wp_unslash( $_POST['product_id'] ) ); // phpcs:ignore WordPress.Security.NonceVerification
32 $cart_item_key = empty( $_POST['cart_item_key'] ) ? '' : sanitize_text_field( wp_unslash( $_POST['cart_item_key'] ) ); // phpcs:ignore WordPress.Security.NonceVerification
33 $quantity = filter_input( INPUT_POST, 'quantity', FILTER_SANITIZE_NUMBER_INT );
34
35 if ( empty( $product_id ) || empty( $cart_item_key ) || ! is_numeric( $quantity ) ) {
36 wp_send_json_error();
37 }
38
39 $_product = wc_get_product( $product_id );
40
41 if ( empty( $_product ) ) {
42 wp_send_json_error();
43 }
44
45 $passed_validation = true;
46 $cart_updated = false;
47 $current_session_order_id = isset( WC()->session->order_awaiting_payment ) ? absint( WC()->session->order_awaiting_payment ) : 0;
48 $product_qty_in_cart = WC()->cart->get_cart_item_quantities();
49
50 // is_sold_individually.
51 if ( $_product->is_sold_individually() && $quantity > 1 ) {
52 /* Translators: %s Product title. */
53 wc_add_notice( sprintf( __( 'You can only have 1 %s in your cart.', 'orderable' ), $_product->get_name() ), 'error' );
54 $passed_validation = false;
55 }
56
57 // We only need to check products managing stock, with a limited stock qty.
58 if ( $_product->managing_stock() || $_product->backorders_allowed() ) {
59 // Check stock based on all items in the cart and consider any held stock within pending orders.
60 $held_stock = wc_get_held_stock_quantity( $_product, $current_session_order_id );
61
62 if ( $_product->get_stock_quantity() < ( $held_stock + $quantity ) ) {
63 /* translators: 1: product name 2: quantity in stock */
64 wc_add_notice( sprintf( __( 'Sorry, we do not have enough "%1$s" in stock to fulfill your order (%2$s available). We apologize for any inconvenience caused.', 'woocommerce' ), $_product->get_name(), wc_format_stock_quantity_for_display( $_product->get_stock_quantity() - $held_stock, $_product ) ), 'error' );
65
66 $passed_validation = false;
67 }
68 }
69
70 if ( $passed_validation ) {
71 WC()->cart->set_quantity( $cart_item_key, intval( $quantity ), false );
72 $cart_updated = true;
73 }
74
75 if ( $cart_updated ) {
76 WC()->cart->calculate_totals();
77 }
78
79 WC_AJAX::get_refreshed_fragments();
80 }
81
82 /**
83 * Update cart item attributes and addons.
84 */
85 public static function update_cart_item_options() {
86 if ( empty( $_POST['cart_item_key'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing
87 wp_send_json_error( null, 400 );
88 }
89
90 $cart_item_key = sanitize_text_field( wp_unslash( $_POST['cart_item_key'] ) ); // phpcs:ignore WordPress.Security.NonceVerification.Missing
91 $product_id = absint( filter_input( INPUT_POST, 'product_id', FILTER_SANITIZE_NUMBER_INT ) );
92 $attributes = self::get_attributes();
93 $variation_id = empty( $attributes ) ? 0 : absint( filter_input( INPUT_POST, 'variation_id', FILTER_SANITIZE_NUMBER_INT ) );
94 $orderable_fields = self::get_orderable_fields();
95
96 if (
97 empty( $cart_item_key ) ||
98 ( empty( $attributes ) && empty( $orderable_fields ) )
99 ) {
100 wp_send_json_error( null, 400 );
101 }
102
103 $cart_item = WC()->cart->get_cart_item( $cart_item_key );
104
105 if ( empty( $cart_item ) ) {
106 wp_send_json_error();
107 }
108
109 $product_data = empty( $variation_id ) ? wc_get_product( $cart_item['product_id'] ) : wc_get_product( $variation_id );
110
111 if ( ! $product_data ) {
112 wp_send_json_error();
113 }
114
115 // If the same data is sent (i.e. there is nothing to udpate), return early.
116 if (
117 WC()->cart->generate_cart_id(
118 $product_id,
119 $variation_id,
120 empty( $attributes ) ? array( false ) : $attributes,
121 empty( $orderable_fields ) ? array() : array( 'orderable_fields' => $orderable_fields )
122 )
123 ===
124 $cart_item_key
125 ) {
126 wp_send_json_success();
127 }
128
129 self::update_cart_item_attributes( $cart_item, $variation_id, $attributes, $orderable_fields );
130
131 WC()->cart->calculate_totals();
132
133 WC_AJAX::get_refreshed_fragments();
134 }
135
136 /**
137 * Get attributes values to update.
138 *
139 * @return array.
140 */
141 protected static function get_attributes() {
142 if ( empty( $_POST['attributes'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing
143 return array();
144 }
145
146 $attributes = array_filter(
147 // phpcs:ignore WordPress.Security.NonceVerification.Missing
148 (array) json_decode( sanitize_text_field( wp_unslash( $_POST['attributes'] ) ) ),
149 function( $attribute_value, $attribute_name ) {
150
151 return ! empty( $attribute_value ) && false !== strpos( $attribute_name, 'attribute_' );
152 },
153 ARRAY_FILTER_USE_BOTH
154 );
155
156 return $attributes;
157 }
158
159 /**
160 * Get Orderable Product Addons fields.
161 *
162 * @return array
163 */
164 protected static function get_orderable_fields() {
165
166 if (
167 ! class_exists( 'Orderable_Addons_Pro_Field_Groups' ) ||
168 ! class_exists( 'Orderable_Addons_Pro_Fees' )
169 ) {
170 return array();
171 }
172
173 // phpcs:ignore WordPress.Security.NonceVerification.Missing
174 $orderable_fields = empty( $_POST['orderable_fields'] ) ? array() : map_deep( wp_unslash( $_POST['orderable_fields'] ), 'sanitize_text_field' );
175
176 if ( empty( $orderable_fields ) || ! is_array( $orderable_fields ) ) {
177 return array();
178 }
179
180 $orderable_item_data = array();
181
182 foreach ( $orderable_fields as $group_id => $fields ) {
183 foreach ( $fields as $field_id => $field ) {
184 $field_setting = Orderable_Addons_Pro_Field_Groups::get_field_data( $field_id, $group_id );
185 $fees = Orderable_Addons_Pro_Fees::calculate_fees( $field, $field_id, $group_id );
186
187 $orderable_item_data[ $field_id ] = array(
188 'id' => $field_id,
189 'value' => $field,
190 'label' => $field_setting['title'],
191 'group_id' => $group_id,
192 'fees' => $fees,
193 );
194 }
195 }
196
197 return $orderable_item_data;
198 }
199
200 /**
201 * Update cart item attributes.
202 *
203 * @param array $original_cart_item The cart item to be updated.
204 * @param int $variation_id The new variation ID.
205 * @param array $attributes The new attributes.
206 * @return void
207 */
208 protected static function update_cart_item_attributes( $original_cart_item, $variation_id, $attributes, $cart_item_data ) {
209 if ( empty( $cart_item_data ) && ! empty( $original_cart_item['orderable_fields'] ) ) {
210 $cart_item_data = $original_cart_item['orderable_fields'];
211 }
212
213 if ( ! empty( $cart_item_data ) ) {
214 $cart_item_data = array( 'orderable_fields' => $cart_item_data );
215 }
216
217 /**
218 * WooCommerce stores empty attributes ('variation' on the cart item)
219 * as `array( false )`.
220 */
221 if ( empty( $attributes ) ) {
222 $attributes = array( false );
223 }
224
225 /**
226 * We update the cart item by adding the updated item to the cart.
227 * This allows 3rd plugins/themes to integrate with the default
228 * WooCommerce hooks.
229 */
230 $updated_cart_item_key = WC()->cart->add_to_cart( $original_cart_item['product_id'], $original_cart_item['quantity'], $variation_id, $attributes, $cart_item_data );
231
232 $cart_content = WC()->cart->get_cart();
233
234 /**
235 * We remove the updated item from the cart to re-insert
236 * at the same position of the original item.
237 */
238 unset( $cart_content[ $updated_cart_item_key ] );
239
240 $cart_content_updated = array();
241
242 foreach ( $cart_content as $key => $item ) {
243 // We re-insert the updated item at the same position of the original item.
244 if ( $key === $original_cart_item['key'] ) {
245 $updated_cart_item = WC()->cart->get_cart_item( $updated_cart_item_key );
246
247 $cart_content_updated[ $updated_cart_item['key'] ] = $updated_cart_item;
248 } else {
249 $cart_content_updated[ $key ] = $item;
250 }
251 }
252
253 WC()->cart->set_cart_contents( $cart_content_updated );
254 }
255 }
256