1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
if ( ! defined( 'ABSPATH' ) ) { |
4
|
|
|
exit; // Exit if accessed directly |
5
|
|
|
} |
6
|
|
|
|
7
|
|
|
/** |
8
|
|
|
* WooCommerce WC_AJAX. |
9
|
|
|
* |
10
|
|
|
* AJAX Event Handler. |
11
|
|
|
* |
12
|
|
|
* @class WC_AJAX |
13
|
|
|
* @version 2.4.0 |
14
|
|
|
* @package WooCommerce/Classes |
15
|
|
|
* @category Class |
16
|
|
|
* @author WooThemes |
17
|
|
|
*/ |
18
|
|
|
class WC_AJAX { |
19
|
|
|
|
20
|
|
|
/** |
21
|
|
|
* Hook in ajax handlers. |
22
|
|
|
*/ |
23
|
|
|
public static function init() { |
24
|
|
|
add_action( 'init', array( __CLASS__, 'define_ajax' ), 0 ); |
25
|
|
|
add_action( 'template_redirect', array( __CLASS__, 'do_wc_ajax' ), 0 ); |
26
|
|
|
self::add_ajax_events(); |
27
|
|
|
} |
28
|
|
|
|
29
|
|
|
/** |
30
|
|
|
* Get WC Ajax Endpoint. |
31
|
|
|
* @param string $request Optional |
32
|
|
|
* @return string |
33
|
|
|
*/ |
34
|
|
|
public static function get_endpoint( $request = '' ) { |
35
|
|
|
return esc_url_raw( add_query_arg( 'wc-ajax', $request, remove_query_arg( array( 'remove_item', 'add-to-cart', 'added-to-cart' ) ) ) ); |
36
|
|
|
} |
37
|
|
|
|
38
|
|
|
/** |
39
|
|
|
* Set WC AJAX constant and headers. |
40
|
|
|
*/ |
41
|
|
|
public static function define_ajax() { |
42
|
|
|
if ( ! empty( $_GET['wc-ajax'] ) ) { |
43
|
|
|
if ( ! defined( 'DOING_AJAX' ) ) { |
44
|
|
|
define( 'DOING_AJAX', true ); |
45
|
|
|
} |
46
|
|
|
if ( ! defined( 'WC_DOING_AJAX' ) ) { |
47
|
|
|
define( 'WC_DOING_AJAX', true ); |
48
|
|
|
} |
49
|
|
|
// Turn off display_errors during AJAX events to prevent malformed JSON |
50
|
|
|
if ( ! WP_DEBUG || ( WP_DEBUG && ! WP_DEBUG_DISPLAY ) ) { |
51
|
|
|
@ini_set( 'display_errors', 0 ); |
52
|
|
|
} |
53
|
|
|
$GLOBALS['wpdb']->hide_errors(); |
54
|
|
|
} |
55
|
|
|
} |
56
|
|
|
|
57
|
|
|
/** |
58
|
|
|
* Send headers for WC Ajax Requests |
59
|
|
|
* @since 2.5.0 |
60
|
|
|
*/ |
61
|
|
|
private static function wc_ajax_headers() { |
62
|
|
|
send_origin_headers(); |
63
|
|
|
@header( 'Content-Type: text/html; charset=' . get_option( 'blog_charset' ) ); |
64
|
|
|
@header( 'X-Robots-Tag: noindex' ); |
65
|
|
|
send_nosniff_header(); |
66
|
|
|
nocache_headers(); |
67
|
|
|
status_header( 200 ); |
68
|
|
|
} |
69
|
|
|
|
70
|
|
|
/** |
71
|
|
|
* Check for WC Ajax request and fire action. |
72
|
|
|
*/ |
73
|
|
|
public static function do_wc_ajax() { |
74
|
|
|
global $wp_query; |
75
|
|
|
|
76
|
|
|
if ( ! empty( $_GET['wc-ajax'] ) ) { |
77
|
|
|
$wp_query->set( 'wc-ajax', sanitize_text_field( $_GET['wc-ajax'] ) ); |
78
|
|
|
} |
79
|
|
|
|
80
|
|
|
if ( $action = $wp_query->get( 'wc-ajax' ) ) { |
81
|
|
|
self::wc_ajax_headers(); |
82
|
|
|
do_action( 'wc_ajax_' . sanitize_text_field( $action ) ); |
83
|
|
|
die(); |
84
|
|
|
} |
85
|
|
|
} |
86
|
|
|
|
87
|
|
|
/** |
88
|
|
|
* Hook in methods - uses WordPress ajax handlers (admin-ajax). |
89
|
|
|
*/ |
90
|
|
|
public static function add_ajax_events() { |
91
|
|
|
// woocommerce_EVENT => nopriv |
92
|
|
|
$ajax_events = array( |
93
|
|
|
'get_refreshed_fragments' => true, |
94
|
|
|
'apply_coupon' => true, |
95
|
|
|
'remove_coupon' => true, |
96
|
|
|
'update_shipping_method' => true, |
97
|
|
|
'get_cart_totals' => true, |
98
|
|
|
'update_order_review' => true, |
99
|
|
|
'add_to_cart' => true, |
100
|
|
|
'checkout' => true, |
101
|
|
|
'get_variation' => true, |
102
|
|
|
'feature_product' => false, |
103
|
|
|
'mark_order_status' => false, |
104
|
|
|
'add_attribute' => false, |
105
|
|
|
'add_new_attribute' => false, |
106
|
|
|
'remove_variation' => false, |
107
|
|
|
'remove_variations' => false, |
108
|
|
|
'save_attributes' => false, |
109
|
|
|
'add_variation' => false, |
110
|
|
|
'link_all_variations' => false, |
111
|
|
|
'revoke_access_to_download' => false, |
112
|
|
|
'grant_access_to_download' => false, |
113
|
|
|
'get_customer_details' => false, |
114
|
|
|
'add_order_item' => false, |
115
|
|
|
'add_order_fee' => false, |
116
|
|
|
'add_order_shipping' => false, |
117
|
|
|
'add_order_tax' => false, |
118
|
|
|
'remove_order_item' => false, |
119
|
|
|
'remove_order_tax' => false, |
120
|
|
|
'reduce_order_item_stock' => false, |
121
|
|
|
'increase_order_item_stock' => false, |
122
|
|
|
'add_order_item_meta' => false, |
123
|
|
|
'remove_order_item_meta' => false, |
124
|
|
|
'calc_line_taxes' => false, |
125
|
|
|
'save_order_items' => false, |
126
|
|
|
'load_order_items' => false, |
127
|
|
|
'add_order_note' => false, |
128
|
|
|
'delete_order_note' => false, |
129
|
|
|
'json_search_products' => false, |
130
|
|
|
'json_search_products_and_variations' => false, |
131
|
|
|
'json_search_grouped_products' => false, |
132
|
|
|
'json_search_downloadable_products_and_variations' => false, |
133
|
|
|
'json_search_customers' => false, |
134
|
|
|
'term_ordering' => false, |
135
|
|
|
'product_ordering' => false, |
136
|
|
|
'refund_line_items' => false, |
137
|
|
|
'delete_refund' => false, |
138
|
|
|
'rated' => false, |
139
|
|
|
'update_api_key' => false, |
140
|
|
|
'get_customer_location' => true, |
141
|
|
|
'load_variations' => false, |
142
|
|
|
'save_variations' => false, |
143
|
|
|
'bulk_edit_variations' => false, |
144
|
|
|
'tax_rates_save_changes' => false, |
145
|
|
|
'shipping_zones_save_changes' => false, |
146
|
|
|
'shipping_zone_add_method' => false, |
147
|
|
|
'shipping_zone_methods_save_changes' => false, |
148
|
|
|
'shipping_zone_methods_save_settings' => false, |
149
|
|
|
'shipping_classes_save_changes' => false, |
150
|
|
|
); |
151
|
|
|
|
152
|
|
|
foreach ( $ajax_events as $ajax_event => $nopriv ) { |
153
|
|
|
add_action( 'wp_ajax_woocommerce_' . $ajax_event, array( __CLASS__, $ajax_event ) ); |
154
|
|
|
|
155
|
|
|
if ( $nopriv ) { |
156
|
|
|
add_action( 'wp_ajax_nopriv_woocommerce_' . $ajax_event, array( __CLASS__, $ajax_event ) ); |
157
|
|
|
|
158
|
|
|
// WC AJAX can be used for frontend ajax requests |
159
|
|
|
add_action( 'wc_ajax_' . $ajax_event, array( __CLASS__, $ajax_event ) ); |
160
|
|
|
} |
161
|
|
|
} |
162
|
|
|
} |
163
|
|
|
|
164
|
|
|
/** |
165
|
|
|
* Get a refreshed cart fragment. |
166
|
|
|
*/ |
167
|
|
|
public static function get_refreshed_fragments() { |
168
|
|
|
|
169
|
|
|
// Get mini cart |
170
|
|
|
ob_start(); |
171
|
|
|
|
172
|
|
|
woocommerce_mini_cart(); |
173
|
|
|
|
174
|
|
|
$mini_cart = ob_get_clean(); |
175
|
|
|
|
176
|
|
|
// Fragments and mini cart are returned |
177
|
|
|
$data = array( |
178
|
|
|
'fragments' => apply_filters( 'woocommerce_add_to_cart_fragments', array( |
179
|
|
|
'div.widget_shopping_cart_content' => '<div class="widget_shopping_cart_content">' . $mini_cart . '</div>' |
180
|
|
|
) |
181
|
|
|
), |
182
|
|
|
'cart_hash' => apply_filters( 'woocommerce_add_to_cart_hash', WC()->cart->get_cart_for_session() ? md5( json_encode( WC()->cart->get_cart_for_session() ) ) : '', WC()->cart->get_cart_for_session() ) |
183
|
|
|
); |
184
|
|
|
|
185
|
|
|
wp_send_json( $data ); |
186
|
|
|
|
187
|
|
|
} |
188
|
|
|
|
189
|
|
|
/** |
190
|
|
|
* AJAX apply coupon on checkout page. |
191
|
|
|
*/ |
192
|
|
|
public static function apply_coupon() { |
193
|
|
|
|
194
|
|
|
check_ajax_referer( 'apply-coupon', 'security' ); |
195
|
|
|
|
196
|
|
|
if ( ! empty( $_POST['coupon_code'] ) ) { |
197
|
|
|
WC()->cart->add_discount( sanitize_text_field( $_POST['coupon_code'] ) ); |
198
|
|
|
} else { |
199
|
|
|
wc_add_notice( WC_Coupon::get_generic_coupon_error( WC_Coupon::E_WC_COUPON_PLEASE_ENTER ), 'error' ); |
200
|
|
|
} |
201
|
|
|
|
202
|
|
|
wc_print_notices(); |
203
|
|
|
|
204
|
|
|
die(); |
205
|
|
|
} |
206
|
|
|
|
207
|
|
|
/** |
208
|
|
|
* AJAX remove coupon on cart and checkout page. |
209
|
|
|
*/ |
210
|
|
|
public static function remove_coupon() { |
211
|
|
|
|
212
|
|
|
check_ajax_referer( 'remove-coupon', 'security' ); |
213
|
|
|
|
214
|
|
|
$coupon = wc_clean( $_POST['coupon'] ); |
215
|
|
|
|
216
|
|
|
if ( ! isset( $coupon ) || empty( $coupon ) ) { |
217
|
|
|
wc_add_notice( __( 'Sorry there was a problem removing this coupon.', 'woocommerce' ), 'error' ); |
218
|
|
|
|
219
|
|
|
} else { |
220
|
|
|
|
221
|
|
|
WC()->cart->remove_coupon( $coupon ); |
222
|
|
|
|
223
|
|
|
wc_add_notice( __( 'Coupon has been removed.', 'woocommerce' ) ); |
224
|
|
|
} |
225
|
|
|
|
226
|
|
|
wc_print_notices(); |
227
|
|
|
|
228
|
|
|
die(); |
229
|
|
|
} |
230
|
|
|
|
231
|
|
|
/** |
232
|
|
|
* AJAX update shipping method on cart page. |
233
|
|
|
*/ |
234
|
|
|
public static function update_shipping_method() { |
235
|
|
|
|
236
|
|
|
check_ajax_referer( 'update-shipping-method', 'security' ); |
237
|
|
|
|
238
|
|
|
if ( ! defined('WOOCOMMERCE_CART') ) { |
239
|
|
|
define( 'WOOCOMMERCE_CART', true ); |
240
|
|
|
} |
241
|
|
|
|
242
|
|
|
$chosen_shipping_methods = WC()->session->get( 'chosen_shipping_methods' ); |
243
|
|
|
|
244
|
|
View Code Duplication |
if ( isset( $_POST['shipping_method'] ) && is_array( $_POST['shipping_method'] ) ) { |
|
|
|
|
245
|
|
|
foreach ( $_POST['shipping_method'] as $i => $value ) { |
246
|
|
|
$chosen_shipping_methods[ $i ] = wc_clean( $value ); |
247
|
|
|
} |
248
|
|
|
} |
249
|
|
|
|
250
|
|
|
WC()->session->set( 'chosen_shipping_methods', $chosen_shipping_methods ); |
251
|
|
|
|
252
|
|
|
WC()->cart->calculate_totals(); |
253
|
|
|
|
254
|
|
|
woocommerce_cart_totals(); |
255
|
|
|
|
256
|
|
|
die(); |
257
|
|
|
} |
258
|
|
|
|
259
|
|
|
/** |
260
|
|
|
* AJAX receive updated cart_totals div. |
261
|
|
|
*/ |
262
|
|
|
public static function get_cart_totals() { |
263
|
|
|
|
264
|
|
|
if ( ! defined( 'WOOCOMMERCE_CART' ) ) { |
265
|
|
|
define( 'WOOCOMMERCE_CART', true ); |
266
|
|
|
} |
267
|
|
|
|
268
|
|
|
WC()->cart->calculate_totals(); |
269
|
|
|
|
270
|
|
|
woocommerce_cart_totals(); |
271
|
|
|
|
272
|
|
|
die(); |
273
|
|
|
} |
274
|
|
|
|
275
|
|
|
/** |
276
|
|
|
* AJAX update order review on checkout. |
277
|
|
|
*/ |
278
|
|
|
public static function update_order_review() { |
279
|
|
|
ob_start(); |
280
|
|
|
|
281
|
|
|
check_ajax_referer( 'update-order-review', 'security' ); |
282
|
|
|
|
283
|
|
|
if ( ! defined( 'WOOCOMMERCE_CHECKOUT' ) ) { |
284
|
|
|
define( 'WOOCOMMERCE_CHECKOUT', true ); |
285
|
|
|
} |
286
|
|
|
|
287
|
|
|
if ( WC()->cart->is_empty() ) { |
288
|
|
|
$data = array( |
289
|
|
|
'fragments' => apply_filters( 'woocommerce_update_order_review_fragments', array( |
290
|
|
|
'form.woocommerce-checkout' => '<div class="woocommerce-error">' . __( 'Sorry, your session has expired.', 'woocommerce' ) . ' <a href="' . esc_url( wc_get_page_permalink( 'shop' ) ) . '" class="wc-backward">' . __( 'Return to shop', 'woocommerce' ) . '</a></div>' |
291
|
|
|
) ) |
292
|
|
|
); |
293
|
|
|
|
294
|
|
|
wp_send_json( $data ); |
295
|
|
|
|
296
|
|
|
die(); |
297
|
|
|
} |
298
|
|
|
|
299
|
|
|
do_action( 'woocommerce_checkout_update_order_review', $_POST['post_data'] ); |
300
|
|
|
|
301
|
|
|
$chosen_shipping_methods = WC()->session->get( 'chosen_shipping_methods' ); |
302
|
|
|
|
303
|
|
View Code Duplication |
if ( isset( $_POST['shipping_method'] ) && is_array( $_POST['shipping_method'] ) ) { |
|
|
|
|
304
|
|
|
foreach ( $_POST['shipping_method'] as $i => $value ) { |
305
|
|
|
$chosen_shipping_methods[ $i ] = wc_clean( $value ); |
306
|
|
|
} |
307
|
|
|
} |
308
|
|
|
|
309
|
|
|
WC()->session->set( 'chosen_shipping_methods', $chosen_shipping_methods ); |
310
|
|
|
WC()->session->set( 'chosen_payment_method', empty( $_POST['payment_method'] ) ? '' : $_POST['payment_method'] ); |
311
|
|
|
|
312
|
|
|
if ( isset( $_POST['country'] ) ) { |
313
|
|
|
WC()->customer->set_country( $_POST['country'] ); |
314
|
|
|
} |
315
|
|
|
|
316
|
|
|
if ( isset( $_POST['state'] ) ) { |
317
|
|
|
WC()->customer->set_state( $_POST['state'] ); |
318
|
|
|
} |
319
|
|
|
|
320
|
|
|
if ( isset( $_POST['postcode'] ) ) { |
321
|
|
|
WC()->customer->set_postcode( $_POST['postcode'] ); |
322
|
|
|
} |
323
|
|
|
|
324
|
|
|
if ( isset( $_POST['city'] ) ) { |
325
|
|
|
WC()->customer->set_city( $_POST['city'] ); |
326
|
|
|
} |
327
|
|
|
|
328
|
|
|
if ( isset( $_POST['address'] ) ) { |
329
|
|
|
WC()->customer->set_address( $_POST['address'] ); |
330
|
|
|
} |
331
|
|
|
|
332
|
|
|
if ( isset( $_POST['address_2'] ) ) { |
333
|
|
|
WC()->customer->set_address_2( $_POST['address_2'] ); |
334
|
|
|
} |
335
|
|
|
|
336
|
|
|
if ( wc_ship_to_billing_address_only() ) { |
337
|
|
|
|
338
|
|
View Code Duplication |
if ( ! empty( $_POST['country'] ) ) { |
|
|
|
|
339
|
|
|
WC()->customer->set_shipping_country( $_POST['country'] ); |
340
|
|
|
WC()->customer->calculated_shipping( true ); |
341
|
|
|
} |
342
|
|
|
|
343
|
|
|
if ( isset( $_POST['state'] ) ) { |
344
|
|
|
WC()->customer->set_shipping_state( $_POST['state'] ); |
345
|
|
|
} |
346
|
|
|
|
347
|
|
|
if ( isset( $_POST['postcode'] ) ) { |
348
|
|
|
WC()->customer->set_shipping_postcode( $_POST['postcode'] ); |
349
|
|
|
} |
350
|
|
|
|
351
|
|
|
if ( isset( $_POST['city'] ) ) { |
352
|
|
|
WC()->customer->set_shipping_city( $_POST['city'] ); |
353
|
|
|
} |
354
|
|
|
|
355
|
|
|
if ( isset( $_POST['address'] ) ) { |
356
|
|
|
WC()->customer->set_shipping_address( $_POST['address'] ); |
357
|
|
|
} |
358
|
|
|
|
359
|
|
|
if ( isset( $_POST['address_2'] ) ) { |
360
|
|
|
WC()->customer->set_shipping_address_2( $_POST['address_2'] ); |
361
|
|
|
} |
362
|
|
|
} else { |
363
|
|
|
|
364
|
|
View Code Duplication |
if ( ! empty( $_POST['s_country'] ) ) { |
|
|
|
|
365
|
|
|
WC()->customer->set_shipping_country( $_POST['s_country'] ); |
366
|
|
|
WC()->customer->calculated_shipping( true ); |
367
|
|
|
} |
368
|
|
|
|
369
|
|
|
if ( isset( $_POST['s_state'] ) ) { |
370
|
|
|
WC()->customer->set_shipping_state( $_POST['s_state'] ); |
371
|
|
|
} |
372
|
|
|
|
373
|
|
|
if ( isset( $_POST['s_postcode'] ) ) { |
374
|
|
|
WC()->customer->set_shipping_postcode( $_POST['s_postcode'] ); |
375
|
|
|
} |
376
|
|
|
|
377
|
|
|
if ( isset( $_POST['s_city'] ) ) { |
378
|
|
|
WC()->customer->set_shipping_city( $_POST['s_city'] ); |
379
|
|
|
} |
380
|
|
|
|
381
|
|
|
if ( isset( $_POST['s_address'] ) ) { |
382
|
|
|
WC()->customer->set_shipping_address( $_POST['s_address'] ); |
383
|
|
|
} |
384
|
|
|
|
385
|
|
|
if ( isset( $_POST['s_address_2'] ) ) { |
386
|
|
|
WC()->customer->set_shipping_address_2( $_POST['s_address_2'] ); |
387
|
|
|
} |
388
|
|
|
} |
389
|
|
|
|
390
|
|
|
WC()->cart->calculate_totals(); |
391
|
|
|
|
392
|
|
|
// Get order review fragment |
393
|
|
|
ob_start(); |
394
|
|
|
woocommerce_order_review(); |
395
|
|
|
$woocommerce_order_review = ob_get_clean(); |
396
|
|
|
|
397
|
|
|
// Get checkout payment fragment |
398
|
|
|
ob_start(); |
399
|
|
|
woocommerce_checkout_payment(); |
400
|
|
|
$woocommerce_checkout_payment = ob_get_clean(); |
401
|
|
|
|
402
|
|
|
// Get messages if reload checkout is not true |
403
|
|
|
$messages = ''; |
404
|
|
|
if ( ! isset( WC()->session->reload_checkout ) ) { |
405
|
|
|
ob_start(); |
406
|
|
|
wc_print_notices(); |
407
|
|
|
$messages = ob_get_clean(); |
408
|
|
|
} |
409
|
|
|
|
410
|
|
|
$data = array( |
411
|
|
|
'result' => empty( $messages ) ? 'success' : 'failure', |
412
|
|
|
'messages' => $messages, |
413
|
|
|
'reload' => isset( WC()->session->reload_checkout ) ? 'true' : 'false', |
414
|
|
|
'fragments' => apply_filters( 'woocommerce_update_order_review_fragments', array( |
415
|
|
|
'.woocommerce-checkout-review-order-table' => $woocommerce_order_review, |
416
|
|
|
'.woocommerce-checkout-payment' => $woocommerce_checkout_payment |
417
|
|
|
) ) |
418
|
|
|
); |
419
|
|
|
|
420
|
|
|
unset( WC()->session->refresh_totals, WC()->session->reload_checkout ); |
421
|
|
|
|
422
|
|
|
wp_send_json( $data ); |
423
|
|
|
|
424
|
|
|
die(); |
425
|
|
|
} |
426
|
|
|
|
427
|
|
|
/** |
428
|
|
|
* AJAX add to cart. |
429
|
|
|
*/ |
430
|
|
|
public static function add_to_cart() { |
431
|
|
|
ob_start(); |
432
|
|
|
|
433
|
|
|
$product_id = apply_filters( 'woocommerce_add_to_cart_product_id', absint( $_POST['product_id'] ) ); |
434
|
|
|
$quantity = empty( $_POST['quantity'] ) ? 1 : wc_stock_amount( $_POST['quantity'] ); |
435
|
|
|
$passed_validation = apply_filters( 'woocommerce_add_to_cart_validation', true, $product_id, $quantity ); |
436
|
|
|
$product_status = get_post_status( $product_id ); |
437
|
|
|
|
438
|
|
|
if ( $passed_validation && false !== WC()->cart->add_to_cart( $product_id, $quantity ) && 'publish' === $product_status ) { |
439
|
|
|
|
440
|
|
|
do_action( 'woocommerce_ajax_added_to_cart', $product_id ); |
441
|
|
|
|
442
|
|
|
if ( get_option( 'woocommerce_cart_redirect_after_add' ) == 'yes' ) { |
443
|
|
|
wc_add_to_cart_message( array( $product_id => $quantity ), true ); |
444
|
|
|
} |
445
|
|
|
|
446
|
|
|
// Return fragments |
447
|
|
|
self::get_refreshed_fragments(); |
448
|
|
|
|
449
|
|
|
} else { |
450
|
|
|
|
451
|
|
|
// If there was an error adding to the cart, redirect to the product page to show any errors |
452
|
|
|
$data = array( |
453
|
|
|
'error' => true, |
454
|
|
|
'product_url' => apply_filters( 'woocommerce_cart_redirect_after_error', get_permalink( $product_id ), $product_id ) |
455
|
|
|
); |
456
|
|
|
|
457
|
|
|
wp_send_json( $data ); |
458
|
|
|
|
459
|
|
|
} |
460
|
|
|
|
461
|
|
|
die(); |
462
|
|
|
} |
463
|
|
|
|
464
|
|
|
/** |
465
|
|
|
* Process ajax checkout form. |
466
|
|
|
*/ |
467
|
|
|
public static function checkout() { |
468
|
|
|
if ( ! defined( 'WOOCOMMERCE_CHECKOUT' ) ) { |
469
|
|
|
define( 'WOOCOMMERCE_CHECKOUT', true ); |
470
|
|
|
} |
471
|
|
|
|
472
|
|
|
WC()->checkout()->process_checkout(); |
473
|
|
|
|
474
|
|
|
die(0); |
475
|
|
|
} |
476
|
|
|
|
477
|
|
|
/** |
478
|
|
|
* Get a matching variation based on posted attributes. |
479
|
|
|
*/ |
480
|
|
|
public static function get_variation() { |
481
|
|
|
ob_start(); |
482
|
|
|
|
483
|
|
|
if ( empty( $_POST['product_id'] ) || ! ( $variable_product = wc_get_product( absint( $_POST['product_id'] ), array( 'product_type' => 'variable' ) ) ) ) { |
484
|
|
|
die(); |
485
|
|
|
} |
486
|
|
|
|
487
|
|
|
$variation_id = $variable_product->get_matching_variation( wp_unslash( $_POST ) ); |
488
|
|
|
|
489
|
|
|
if ( $variation_id ) { |
490
|
|
|
$variation = $variable_product->get_available_variation( $variation_id ); |
491
|
|
|
} else { |
492
|
|
|
$variation = false; |
493
|
|
|
} |
494
|
|
|
|
495
|
|
|
wp_send_json( $variation ); |
496
|
|
|
|
497
|
|
|
die(); |
498
|
|
|
} |
499
|
|
|
|
500
|
|
|
/** |
501
|
|
|
* Feature a product from admin. |
502
|
|
|
*/ |
503
|
|
|
public static function feature_product() { |
504
|
|
|
if ( current_user_can( 'edit_products' ) && check_admin_referer( 'woocommerce-feature-product' ) ) { |
505
|
|
|
$product_id = absint( $_GET['product_id'] ); |
506
|
|
|
|
507
|
|
|
if ( 'product' === get_post_type( $product_id ) ) { |
508
|
|
|
update_post_meta( $product_id, '_featured', get_post_meta( $product_id, '_featured', true ) === 'yes' ? 'no' : 'yes' ); |
509
|
|
|
|
510
|
|
|
delete_transient( 'wc_featured_products' ); |
511
|
|
|
} |
512
|
|
|
} |
513
|
|
|
|
514
|
|
|
wp_safe_redirect( wp_get_referer() ? remove_query_arg( array( 'trashed', 'untrashed', 'deleted', 'ids' ), wp_get_referer() ) : admin_url( 'edit.php?post_type=product' ) ); |
515
|
|
|
die(); |
516
|
|
|
} |
517
|
|
|
|
518
|
|
|
/** |
519
|
|
|
* Mark an order with a status. |
520
|
|
|
*/ |
521
|
|
|
public static function mark_order_status() { |
522
|
|
|
if ( current_user_can( 'edit_shop_orders' ) && check_admin_referer( 'woocommerce-mark-order-status' ) ) { |
523
|
|
|
$status = sanitize_text_field( $_GET['status'] ); |
524
|
|
|
$order_id = absint( $_GET['order_id'] ); |
525
|
|
|
|
526
|
|
|
if ( wc_is_order_status( 'wc-' . $status ) && $order_id ) { |
527
|
|
|
$order = wc_get_order( $order_id ); |
528
|
|
|
$order->update_status( $status, '', true ); |
529
|
|
|
do_action( 'woocommerce_order_edit_status', $order_id, $status ); |
530
|
|
|
} |
531
|
|
|
} |
532
|
|
|
|
533
|
|
|
wp_safe_redirect( wp_get_referer() ? wp_get_referer() : admin_url( 'edit.php?post_type=shop_order' ) ); |
534
|
|
|
die(); |
535
|
|
|
} |
536
|
|
|
|
537
|
|
|
/** |
538
|
|
|
* Add an attribute row. |
539
|
|
|
*/ |
540
|
|
|
public static function add_attribute() { |
541
|
|
|
ob_start(); |
542
|
|
|
|
543
|
|
|
check_ajax_referer( 'add-attribute', 'security' ); |
544
|
|
|
|
545
|
|
|
if ( ! current_user_can( 'edit_products' ) ) { |
546
|
|
|
die(-1); |
547
|
|
|
} |
548
|
|
|
|
549
|
|
|
global $wc_product_attributes; |
550
|
|
|
|
551
|
|
|
$thepostid = 0; |
552
|
|
|
$taxonomy = sanitize_text_field( $_POST['taxonomy'] ); |
553
|
|
|
$i = absint( $_POST['i'] ); |
554
|
|
|
$position = 0; |
555
|
|
|
$metabox_class = array(); |
556
|
|
|
$attribute = array( |
557
|
|
|
'name' => $taxonomy, |
558
|
|
|
'value' => '', |
559
|
|
|
'is_visible' => apply_filters( 'woocommerce_attribute_default_visibility', 1 ), |
560
|
|
|
'is_variation' => apply_filters( 'woocommerce_attribute_default_is_variation', 0 ), |
561
|
|
|
'is_taxonomy' => $taxonomy ? 1 : 0 |
562
|
|
|
); |
563
|
|
|
|
564
|
|
|
if ( $taxonomy ) { |
565
|
|
|
$attribute_taxonomy = $wc_product_attributes[ $taxonomy ]; |
566
|
|
|
$metabox_class[] = 'taxonomy'; |
567
|
|
|
$metabox_class[] = $taxonomy; |
568
|
|
|
$attribute_label = wc_attribute_label( $taxonomy ); |
569
|
|
|
} else { |
570
|
|
|
$attribute_label = ''; |
571
|
|
|
} |
572
|
|
|
|
573
|
|
|
include( 'admin/meta-boxes/views/html-product-attribute.php' ); |
574
|
|
|
die(); |
575
|
|
|
} |
576
|
|
|
|
577
|
|
|
/** |
578
|
|
|
* Add a new attribute via ajax function. |
579
|
|
|
*/ |
580
|
|
|
public static function add_new_attribute() { |
581
|
|
|
ob_start(); |
582
|
|
|
|
583
|
|
|
check_ajax_referer( 'add-attribute', 'security' ); |
584
|
|
|
|
585
|
|
|
if ( ! current_user_can( 'manage_product_terms' ) ) { |
586
|
|
|
die(-1); |
587
|
|
|
} |
588
|
|
|
|
589
|
|
|
$taxonomy = esc_attr( $_POST['taxonomy'] ); |
590
|
|
|
$term = wc_clean( $_POST['term'] ); |
591
|
|
|
|
592
|
|
|
if ( taxonomy_exists( $taxonomy ) ) { |
593
|
|
|
|
594
|
|
|
$result = wp_insert_term( $term, $taxonomy ); |
595
|
|
|
|
596
|
|
|
if ( is_wp_error( $result ) ) { |
597
|
|
|
wp_send_json( array( |
598
|
|
|
'error' => $result->get_error_message() |
599
|
|
|
) ); |
600
|
|
|
} else { |
601
|
|
|
$term = get_term_by( 'id', $result['term_id'], $taxonomy ); |
602
|
|
|
wp_send_json( array( |
603
|
|
|
'term_id' => $term->term_id, |
604
|
|
|
'name' => $term->name, |
605
|
|
|
'slug' => $term->slug |
606
|
|
|
) ); |
607
|
|
|
} |
608
|
|
|
} |
609
|
|
|
|
610
|
|
|
die(); |
611
|
|
|
} |
612
|
|
|
|
613
|
|
|
/** |
614
|
|
|
* Delete variations via ajax function. |
615
|
|
|
*/ |
616
|
|
|
public static function remove_variations() { |
617
|
|
|
check_ajax_referer( 'delete-variations', 'security' ); |
618
|
|
|
|
619
|
|
|
if ( ! current_user_can( 'edit_products' ) ) { |
620
|
|
|
die(-1); |
621
|
|
|
} |
622
|
|
|
|
623
|
|
|
$variation_ids = (array) $_POST['variation_ids']; |
624
|
|
|
|
625
|
|
|
foreach ( $variation_ids as $variation_id ) { |
626
|
|
|
$variation = get_post( $variation_id ); |
627
|
|
|
|
628
|
|
|
if ( $variation && 'product_variation' == $variation->post_type ) { |
629
|
|
|
wp_delete_post( $variation_id ); |
630
|
|
|
} |
631
|
|
|
} |
632
|
|
|
|
633
|
|
|
die(); |
634
|
|
|
} |
635
|
|
|
|
636
|
|
|
/** |
637
|
|
|
* Save attributes via ajax. |
638
|
|
|
*/ |
639
|
|
|
public static function save_attributes() { |
640
|
|
|
|
641
|
|
|
check_ajax_referer( 'save-attributes', 'security' ); |
642
|
|
|
|
643
|
|
|
if ( ! current_user_can( 'edit_products' ) ) { |
644
|
|
|
die(-1); |
645
|
|
|
} |
646
|
|
|
|
647
|
|
|
// Get post data |
648
|
|
|
parse_str( $_POST['data'], $data ); |
649
|
|
|
$post_id = absint( $_POST['post_id'] ); |
650
|
|
|
|
651
|
|
|
// Save Attributes |
652
|
|
|
$attributes = array(); |
653
|
|
|
|
654
|
|
|
if ( isset( $data['attribute_names'] ) ) { |
655
|
|
|
|
656
|
|
|
$attribute_names = array_map( 'stripslashes', $data['attribute_names'] ); |
657
|
|
|
$attribute_values = isset( $data['attribute_values'] ) ? $data['attribute_values'] : array(); |
658
|
|
|
|
659
|
|
|
if ( isset( $data['attribute_visibility'] ) ) { |
660
|
|
|
$attribute_visibility = $data['attribute_visibility']; |
661
|
|
|
} |
662
|
|
|
|
663
|
|
|
if ( isset( $data['attribute_variation'] ) ) { |
664
|
|
|
$attribute_variation = $data['attribute_variation']; |
665
|
|
|
} |
666
|
|
|
|
667
|
|
|
$attribute_is_taxonomy = $data['attribute_is_taxonomy']; |
668
|
|
|
$attribute_position = $data['attribute_position']; |
669
|
|
|
$attribute_names_max_key = max( array_keys( $attribute_names ) ); |
670
|
|
|
|
671
|
|
|
for ( $i = 0; $i <= $attribute_names_max_key; $i++ ) { |
672
|
|
|
if ( empty( $attribute_names[ $i ] ) ) { |
673
|
|
|
continue; |
674
|
|
|
} |
675
|
|
|
|
676
|
|
|
$is_visible = isset( $attribute_visibility[ $i ] ) ? 1 : 0; |
677
|
|
|
$is_variation = isset( $attribute_variation[ $i ] ) ? 1 : 0; |
678
|
|
|
$is_taxonomy = $attribute_is_taxonomy[ $i ] ? 1 : 0; |
679
|
|
|
|
680
|
|
|
if ( $is_taxonomy ) { |
681
|
|
|
|
682
|
|
|
if ( isset( $attribute_values[ $i ] ) ) { |
683
|
|
|
|
684
|
|
|
// Select based attributes - Format values (posted values are slugs) |
685
|
|
|
if ( is_array( $attribute_values[ $i ] ) ) { |
686
|
|
|
$values = array_map( 'sanitize_title', $attribute_values[ $i ] ); |
687
|
|
|
|
688
|
|
|
// Text based attributes - Posted values are term names, wp_set_object_terms wants ids or slugs. |
689
|
|
|
} else { |
690
|
|
|
$values = array(); |
691
|
|
|
$raw_values = array_map( 'wc_sanitize_term_text_based', explode( WC_DELIMITER, $attribute_values[ $i ] ) ); |
692
|
|
|
|
693
|
|
|
foreach ( $raw_values as $value ) { |
694
|
|
|
$term = get_term_by( 'name', $value, $attribute_names[ $i ] ); |
695
|
|
|
if ( ! $term ) { |
696
|
|
|
$term = wp_insert_term( $value, $attribute_names[ $i ] ); |
697
|
|
|
|
698
|
|
|
if ( $term && ! is_wp_error( $term ) ) { |
699
|
|
|
$values[] = $term['term_id']; |
700
|
|
|
} |
701
|
|
|
} else { |
702
|
|
|
$values[] = $term->term_id; |
703
|
|
|
} |
704
|
|
|
} |
705
|
|
|
} |
706
|
|
|
|
707
|
|
|
// Remove empty items in the array |
708
|
|
|
$values = array_filter( $values, 'strlen' ); |
709
|
|
|
|
710
|
|
|
} else { |
711
|
|
|
$values = array(); |
712
|
|
|
} |
713
|
|
|
|
714
|
|
|
// Update post terms |
715
|
|
|
if ( taxonomy_exists( $attribute_names[ $i ] ) ) { |
716
|
|
|
wp_set_object_terms( $post_id, $values, $attribute_names[ $i ] ); |
717
|
|
|
} |
718
|
|
|
|
719
|
|
View Code Duplication |
if ( $values ) { |
|
|
|
|
720
|
|
|
// Add attribute to array, but don't set values |
721
|
|
|
$attributes[ sanitize_title( $attribute_names[ $i ] ) ] = array( |
722
|
|
|
'name' => wc_clean( $attribute_names[ $i ] ), |
723
|
|
|
'value' => '', |
724
|
|
|
'position' => $attribute_position[ $i ], |
725
|
|
|
'is_visible' => $is_visible, |
726
|
|
|
'is_variation' => $is_variation, |
727
|
|
|
'is_taxonomy' => $is_taxonomy |
728
|
|
|
); |
729
|
|
|
} |
730
|
|
|
|
731
|
|
View Code Duplication |
} elseif ( isset( $attribute_values[ $i ] ) ) { |
|
|
|
|
732
|
|
|
|
733
|
|
|
// Text based, possibly separated by pipes (WC_DELIMITER). Preserve line breaks in non-variation attributes. |
734
|
|
|
$values = $is_variation ? wc_clean( $attribute_values[ $i ] ) : implode( "\n", array_map( 'wc_clean', explode( "\n", $attribute_values[ $i ] ) ) ); |
735
|
|
|
$values = implode( ' ' . WC_DELIMITER . ' ', wc_get_text_attributes( $values ) ); |
736
|
|
|
|
737
|
|
|
// Custom attribute - Add attribute to array and set the values |
738
|
|
|
$attributes[ sanitize_title( $attribute_names[ $i ] ) ] = array( |
739
|
|
|
'name' => wc_clean( $attribute_names[ $i ] ), |
740
|
|
|
'value' => $values, |
741
|
|
|
'position' => $attribute_position[ $i ], |
742
|
|
|
'is_visible' => $is_visible, |
743
|
|
|
'is_variation' => $is_variation, |
744
|
|
|
'is_taxonomy' => $is_taxonomy |
745
|
|
|
); |
746
|
|
|
} |
747
|
|
|
|
748
|
|
|
} |
749
|
|
|
} |
750
|
|
|
|
751
|
|
|
uasort( $attributes, 'wc_product_attribute_uasort_comparison' ); |
752
|
|
|
|
753
|
|
|
update_post_meta( $post_id, '_product_attributes', $attributes ); |
754
|
|
|
|
755
|
|
|
die(); |
756
|
|
|
} |
757
|
|
|
|
758
|
|
|
/** |
759
|
|
|
* Add variation via ajax function. |
760
|
|
|
*/ |
761
|
|
|
public static function add_variation() { |
762
|
|
|
|
763
|
|
|
check_ajax_referer( 'add-variation', 'security' ); |
764
|
|
|
|
765
|
|
|
if ( ! current_user_can( 'edit_products' ) ) { |
766
|
|
|
die(-1); |
767
|
|
|
} |
768
|
|
|
|
769
|
|
|
global $post; |
770
|
|
|
|
771
|
|
|
$post_id = intval( $_POST['post_id'] ); |
772
|
|
|
$post = get_post( $post_id ); // Set $post global so its available like within the admin screens |
773
|
|
|
$loop = intval( $_POST['loop'] ); |
774
|
|
|
|
775
|
|
|
$variation = array( |
776
|
|
|
'post_title' => 'Product #' . $post_id . ' Variation', |
777
|
|
|
'post_content' => '', |
778
|
|
|
'post_status' => 'publish', |
779
|
|
|
'post_author' => get_current_user_id(), |
780
|
|
|
'post_parent' => $post_id, |
781
|
|
|
'post_type' => 'product_variation', |
782
|
|
|
'menu_order' => -1 |
783
|
|
|
); |
784
|
|
|
|
785
|
|
|
$variation_id = wp_insert_post( $variation ); |
786
|
|
|
|
787
|
|
|
do_action( 'woocommerce_create_product_variation', $variation_id ); |
788
|
|
|
|
789
|
|
|
if ( $variation_id ) { |
790
|
|
|
$variation = get_post( $variation_id ); |
791
|
|
|
$variation_meta = get_post_meta( $variation_id ); |
792
|
|
|
$variation_data = array(); |
793
|
|
|
$shipping_classes = get_the_terms( $variation_id, 'product_shipping_class' ); |
794
|
|
|
$variation_fields = array( |
795
|
|
|
'_sku' => '', |
796
|
|
|
'_stock' => '', |
797
|
|
|
'_regular_price' => '', |
798
|
|
|
'_sale_price' => '', |
799
|
|
|
'_weight' => '', |
800
|
|
|
'_length' => '', |
801
|
|
|
'_width' => '', |
802
|
|
|
'_height' => '', |
803
|
|
|
'_download_limit' => '', |
804
|
|
|
'_download_expiry' => '', |
805
|
|
|
'_downloadable_files' => '', |
806
|
|
|
'_downloadable' => '', |
807
|
|
|
'_virtual' => '', |
808
|
|
|
'_thumbnail_id' => '', |
809
|
|
|
'_sale_price_dates_from' => '', |
810
|
|
|
'_sale_price_dates_to' => '', |
811
|
|
|
'_manage_stock' => '', |
812
|
|
|
'_stock_status' => '', |
813
|
|
|
'_backorders' => null, |
814
|
|
|
'_tax_class' => null, |
815
|
|
|
'_variation_description' => '' |
816
|
|
|
); |
817
|
|
|
|
818
|
|
View Code Duplication |
foreach ( $variation_fields as $field => $value ) { |
|
|
|
|
819
|
|
|
$variation_data[ $field ] = isset( $variation_meta[ $field ][0] ) ? maybe_unserialize( $variation_meta[ $field ][0] ) : $value; |
820
|
|
|
} |
821
|
|
|
|
822
|
|
|
// Add the variation attributes |
823
|
|
|
$variation_data = array_merge( $variation_data, wc_get_product_variation_attributes( $variation_id ) ); |
824
|
|
|
|
825
|
|
|
// Formatting |
826
|
|
|
$variation_data['_regular_price'] = wc_format_localized_price( $variation_data['_regular_price'] ); |
827
|
|
|
$variation_data['_sale_price'] = wc_format_localized_price( $variation_data['_sale_price'] ); |
828
|
|
|
$variation_data['_weight'] = wc_format_localized_decimal( $variation_data['_weight'] ); |
829
|
|
|
$variation_data['_length'] = wc_format_localized_decimal( $variation_data['_length'] ); |
830
|
|
|
$variation_data['_width'] = wc_format_localized_decimal( $variation_data['_width'] ); |
831
|
|
|
$variation_data['_height'] = wc_format_localized_decimal( $variation_data['_height'] ); |
832
|
|
|
$variation_data['_thumbnail_id'] = absint( $variation_data['_thumbnail_id'] ); |
833
|
|
|
$variation_data['image'] = $variation_data['_thumbnail_id'] ? wp_get_attachment_thumb_url( $variation_data['_thumbnail_id'] ) : ''; |
834
|
|
|
$variation_data['shipping_class'] = $shipping_classes && ! is_wp_error( $shipping_classes ) ? current( $shipping_classes )->term_id : ''; |
835
|
|
|
$variation_data['menu_order'] = $variation->menu_order; |
836
|
|
|
$variation_data['_stock'] = wc_stock_amount( $variation_data['_stock'] ); |
837
|
|
|
|
838
|
|
|
// Get tax classes |
839
|
|
|
$tax_classes = WC_Tax::get_tax_classes(); |
840
|
|
|
$tax_class_options = array(); |
841
|
|
|
$tax_class_options[''] = __( 'Standard', 'woocommerce' ); |
842
|
|
|
|
843
|
|
View Code Duplication |
if ( ! empty( $tax_classes ) ) { |
|
|
|
|
844
|
|
|
foreach ( $tax_classes as $class ) { |
845
|
|
|
$tax_class_options[ sanitize_title( $class ) ] = esc_attr( $class ); |
846
|
|
|
} |
847
|
|
|
} |
848
|
|
|
|
849
|
|
|
// Set backorder options |
850
|
|
|
$backorder_options = array( |
851
|
|
|
'no' => __( 'Do not allow', 'woocommerce' ), |
852
|
|
|
'notify' => __( 'Allow, but notify customer', 'woocommerce' ), |
853
|
|
|
'yes' => __( 'Allow', 'woocommerce' ) |
854
|
|
|
); |
855
|
|
|
|
856
|
|
|
// set stock status options |
857
|
|
|
$stock_status_options = array( |
858
|
|
|
'instock' => __( 'In stock', 'woocommerce' ), |
859
|
|
|
'outofstock' => __( 'Out of stock', 'woocommerce' ) |
860
|
|
|
); |
861
|
|
|
|
862
|
|
|
// Get attributes |
863
|
|
|
$attributes = (array) maybe_unserialize( get_post_meta( $post_id, '_product_attributes', true ) ); |
864
|
|
|
|
865
|
|
|
$parent_data = array( |
866
|
|
|
'id' => $post_id, |
867
|
|
|
'attributes' => $attributes, |
868
|
|
|
'tax_class_options' => $tax_class_options, |
869
|
|
|
'sku' => get_post_meta( $post_id, '_sku', true ), |
870
|
|
|
'weight' => wc_format_localized_decimal( get_post_meta( $post_id, '_weight', true ) ), |
871
|
|
|
'length' => wc_format_localized_decimal( get_post_meta( $post_id, '_length', true ) ), |
872
|
|
|
'width' => wc_format_localized_decimal( get_post_meta( $post_id, '_width', true ) ), |
873
|
|
|
'height' => wc_format_localized_decimal( get_post_meta( $post_id, '_height', true ) ), |
874
|
|
|
'tax_class' => get_post_meta( $post_id, '_tax_class', true ), |
875
|
|
|
'backorder_options' => $backorder_options, |
876
|
|
|
'stock_status_options' => $stock_status_options |
877
|
|
|
); |
878
|
|
|
|
879
|
|
|
if ( ! $parent_data['weight'] ) { |
880
|
|
|
$parent_data['weight'] = wc_format_localized_decimal( 0 ); |
881
|
|
|
} |
882
|
|
|
|
883
|
|
|
if ( ! $parent_data['length'] ) { |
884
|
|
|
$parent_data['length'] = wc_format_localized_decimal( 0 ); |
885
|
|
|
} |
886
|
|
|
|
887
|
|
|
if ( ! $parent_data['width'] ) { |
888
|
|
|
$parent_data['width'] = wc_format_localized_decimal( 0 ); |
889
|
|
|
} |
890
|
|
|
|
891
|
|
|
if ( ! $parent_data['height'] ) { |
892
|
|
|
$parent_data['height'] = wc_format_localized_decimal( 0 ); |
893
|
|
|
} |
894
|
|
|
|
895
|
|
|
include( 'admin/meta-boxes/views/html-variation-admin.php' ); |
896
|
|
|
} |
897
|
|
|
|
898
|
|
|
die(); |
899
|
|
|
} |
900
|
|
|
|
901
|
|
|
/** |
902
|
|
|
* Link all variations via ajax function. |
903
|
|
|
*/ |
904
|
|
|
public static function link_all_variations() { |
905
|
|
|
|
906
|
|
|
if ( ! defined( 'WC_MAX_LINKED_VARIATIONS' ) ) { |
907
|
|
|
define( 'WC_MAX_LINKED_VARIATIONS', 49 ); |
908
|
|
|
} |
909
|
|
|
|
910
|
|
|
check_ajax_referer( 'link-variations', 'security' ); |
911
|
|
|
|
912
|
|
|
if ( ! current_user_can( 'edit_products' ) ) { |
913
|
|
|
die(-1); |
914
|
|
|
} |
915
|
|
|
|
916
|
|
|
wc_set_time_limit( 0 ); |
917
|
|
|
|
918
|
|
|
$post_id = intval( $_POST['post_id'] ); |
919
|
|
|
|
920
|
|
|
if ( ! $post_id ) { |
921
|
|
|
die(); |
922
|
|
|
} |
923
|
|
|
|
924
|
|
|
$variations = array(); |
925
|
|
|
$_product = wc_get_product( $post_id, array( 'product_type' => 'variable' ) ); |
926
|
|
|
|
927
|
|
|
// Put variation attributes into an array |
928
|
|
|
foreach ( $_product->get_attributes() as $attribute ) { |
929
|
|
|
|
930
|
|
|
if ( ! $attribute['is_variation'] ) { |
931
|
|
|
continue; |
932
|
|
|
} |
933
|
|
|
|
934
|
|
|
$attribute_field_name = 'attribute_' . sanitize_title( $attribute['name'] ); |
935
|
|
|
|
936
|
|
|
if ( $attribute['is_taxonomy'] ) { |
937
|
|
|
$options = wc_get_product_terms( $post_id, $attribute['name'], array( 'fields' => 'slugs' ) ); |
938
|
|
|
} else { |
939
|
|
|
$options = explode( WC_DELIMITER, $attribute['value'] ); |
940
|
|
|
} |
941
|
|
|
|
942
|
|
|
$options = array_map( 'trim', $options ); |
943
|
|
|
|
944
|
|
|
$variations[ $attribute_field_name ] = $options; |
945
|
|
|
} |
946
|
|
|
|
947
|
|
|
// Quit out if none were found |
948
|
|
|
if ( sizeof( $variations ) == 0 ) { |
949
|
|
|
die(); |
950
|
|
|
} |
951
|
|
|
|
952
|
|
|
// Get existing variations so we don't create duplicates |
953
|
|
|
$available_variations = array(); |
954
|
|
|
|
955
|
|
|
foreach( $_product->get_children() as $child_id ) { |
956
|
|
|
$child = $_product->get_child( $child_id ); |
957
|
|
|
|
958
|
|
|
if ( ! empty( $child->variation_id ) ) { |
959
|
|
|
$available_variations[] = $child->get_variation_attributes(); |
960
|
|
|
} |
961
|
|
|
} |
962
|
|
|
|
963
|
|
|
// Created posts will all have the following data |
964
|
|
|
$variation_post_data = array( |
965
|
|
|
'post_title' => 'Product #' . $post_id . ' Variation', |
966
|
|
|
'post_content' => '', |
967
|
|
|
'post_status' => 'publish', |
968
|
|
|
'post_author' => get_current_user_id(), |
969
|
|
|
'post_parent' => $post_id, |
970
|
|
|
'post_type' => 'product_variation' |
971
|
|
|
); |
972
|
|
|
|
973
|
|
|
$variation_ids = array(); |
974
|
|
|
$added = 0; |
975
|
|
|
$possible_variations = wc_array_cartesian( $variations ); |
976
|
|
|
|
977
|
|
|
foreach ( $possible_variations as $variation ) { |
978
|
|
|
|
979
|
|
|
// Check if variation already exists |
980
|
|
|
if ( in_array( $variation, $available_variations ) ) { |
981
|
|
|
continue; |
982
|
|
|
} |
983
|
|
|
|
984
|
|
|
$variation_id = wp_insert_post( $variation_post_data ); |
985
|
|
|
|
986
|
|
|
$variation_ids[] = $variation_id; |
987
|
|
|
|
988
|
|
|
foreach ( $variation as $key => $value ) { |
989
|
|
|
update_post_meta( $variation_id, $key, $value ); |
990
|
|
|
} |
991
|
|
|
|
992
|
|
|
// Save stock status |
993
|
|
|
update_post_meta( $variation_id, '_stock_status', 'instock' ); |
994
|
|
|
|
995
|
|
|
$added++; |
996
|
|
|
|
997
|
|
|
do_action( 'product_variation_linked', $variation_id ); |
998
|
|
|
|
999
|
|
|
if ( $added > WC_MAX_LINKED_VARIATIONS ) { |
1000
|
|
|
break; |
1001
|
|
|
} |
1002
|
|
|
} |
1003
|
|
|
|
1004
|
|
|
delete_transient( 'wc_product_children_' . $post_id ); |
1005
|
|
|
|
1006
|
|
|
echo $added; |
1007
|
|
|
|
1008
|
|
|
die(); |
1009
|
|
|
} |
1010
|
|
|
|
1011
|
|
|
/** |
1012
|
|
|
* Delete download permissions via ajax function. |
1013
|
|
|
*/ |
1014
|
|
|
public static function revoke_access_to_download() { |
1015
|
|
|
|
1016
|
|
|
check_ajax_referer( 'revoke-access', 'security' ); |
1017
|
|
|
|
1018
|
|
|
if ( ! current_user_can( 'edit_shop_orders' ) ) { |
1019
|
|
|
die(-1); |
1020
|
|
|
} |
1021
|
|
|
|
1022
|
|
|
global $wpdb; |
1023
|
|
|
|
1024
|
|
|
$download_id = $_POST['download_id']; |
1025
|
|
|
$product_id = intval( $_POST['product_id'] ); |
1026
|
|
|
$order_id = intval( $_POST['order_id'] ); |
1027
|
|
|
|
1028
|
|
|
$wpdb->query( $wpdb->prepare( "DELETE FROM {$wpdb->prefix}woocommerce_downloadable_product_permissions WHERE order_id = %d AND product_id = %d AND download_id = %s;", $order_id, $product_id, $download_id ) ); |
1029
|
|
|
|
1030
|
|
|
do_action( 'woocommerce_ajax_revoke_access_to_product_download', $download_id, $product_id, $order_id ); |
1031
|
|
|
|
1032
|
|
|
die(); |
1033
|
|
|
} |
1034
|
|
|
|
1035
|
|
|
/** |
1036
|
|
|
* Grant download permissions via ajax function. |
1037
|
|
|
*/ |
1038
|
|
|
public static function grant_access_to_download() { |
1039
|
|
|
|
1040
|
|
|
check_ajax_referer( 'grant-access', 'security' ); |
1041
|
|
|
|
1042
|
|
|
if ( ! current_user_can( 'edit_shop_orders' ) ) { |
1043
|
|
|
die(-1); |
1044
|
|
|
} |
1045
|
|
|
|
1046
|
|
|
global $wpdb; |
1047
|
|
|
|
1048
|
|
|
$wpdb->hide_errors(); |
1049
|
|
|
|
1050
|
|
|
$order_id = intval( $_POST['order_id'] ); |
1051
|
|
|
$product_ids = $_POST['product_ids']; |
1052
|
|
|
$loop = intval( $_POST['loop'] ); |
1053
|
|
|
$file_counter = 0; |
1054
|
|
|
$order = wc_get_order( $order_id ); |
1055
|
|
|
|
1056
|
|
|
if ( ! is_array( $product_ids ) ) { |
1057
|
|
|
$product_ids = array( $product_ids ); |
1058
|
|
|
} |
1059
|
|
|
|
1060
|
|
|
foreach ( $product_ids as $product_id ) { |
1061
|
|
|
$product = wc_get_product( $product_id ); |
1062
|
|
|
$files = $product->get_files(); |
1063
|
|
|
|
1064
|
|
|
if ( ! $order->billing_email ) { |
1065
|
|
|
die(); |
1066
|
|
|
} |
1067
|
|
|
|
1068
|
|
|
if ( $files ) { |
|
|
|
|
1069
|
|
|
foreach ( $files as $download_id => $file ) { |
1070
|
|
|
if ( $inserted_id = wc_downloadable_file_permission( $download_id, $product_id, $order ) ) { |
|
|
|
|
1071
|
|
|
|
1072
|
|
|
// insert complete - get inserted data |
1073
|
|
|
$download = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM {$wpdb->prefix}woocommerce_downloadable_product_permissions WHERE permission_id = %d", $inserted_id ) ); |
1074
|
|
|
|
1075
|
|
|
$loop ++; |
1076
|
|
|
$file_counter ++; |
1077
|
|
|
|
1078
|
|
View Code Duplication |
if ( isset( $file['name'] ) ) { |
|
|
|
|
1079
|
|
|
$file_count = $file['name']; |
1080
|
|
|
} else { |
1081
|
|
|
$file_count = sprintf( __( 'File %d', 'woocommerce' ), $file_counter ); |
1082
|
|
|
} |
1083
|
|
|
include( 'admin/meta-boxes/views/html-order-download-permission.php' ); |
1084
|
|
|
} |
1085
|
|
|
} |
1086
|
|
|
} |
1087
|
|
|
} |
1088
|
|
|
|
1089
|
|
|
die(); |
1090
|
|
|
} |
1091
|
|
|
|
1092
|
|
|
/** |
1093
|
|
|
* Get customer details via ajax. |
1094
|
|
|
*/ |
1095
|
|
|
public static function get_customer_details() { |
1096
|
|
|
ob_start(); |
1097
|
|
|
|
1098
|
|
|
check_ajax_referer( 'get-customer-details', 'security' ); |
1099
|
|
|
|
1100
|
|
|
if ( ! current_user_can( 'edit_shop_orders' ) ) { |
1101
|
|
|
die(-1); |
1102
|
|
|
} |
1103
|
|
|
|
1104
|
|
|
$user_id = (int) trim(stripslashes($_POST['user_id'])); |
1105
|
|
|
$type_to_load = esc_attr(trim(stripslashes($_POST['type_to_load']))); |
1106
|
|
|
|
1107
|
|
|
$customer_data = array( |
1108
|
|
|
$type_to_load . '_first_name' => get_user_meta( $user_id, $type_to_load . '_first_name', true ), |
1109
|
|
|
$type_to_load . '_last_name' => get_user_meta( $user_id, $type_to_load . '_last_name', true ), |
1110
|
|
|
$type_to_load . '_company' => get_user_meta( $user_id, $type_to_load . '_company', true ), |
1111
|
|
|
$type_to_load . '_address_1' => get_user_meta( $user_id, $type_to_load . '_address_1', true ), |
1112
|
|
|
$type_to_load . '_address_2' => get_user_meta( $user_id, $type_to_load . '_address_2', true ), |
1113
|
|
|
$type_to_load . '_city' => get_user_meta( $user_id, $type_to_load . '_city', true ), |
1114
|
|
|
$type_to_load . '_postcode' => get_user_meta( $user_id, $type_to_load . '_postcode', true ), |
1115
|
|
|
$type_to_load . '_country' => get_user_meta( $user_id, $type_to_load . '_country', true ), |
1116
|
|
|
$type_to_load . '_state' => get_user_meta( $user_id, $type_to_load . '_state', true ), |
1117
|
|
|
$type_to_load . '_email' => get_user_meta( $user_id, $type_to_load . '_email', true ), |
1118
|
|
|
$type_to_load . '_phone' => get_user_meta( $user_id, $type_to_load . '_phone', true ), |
1119
|
|
|
); |
1120
|
|
|
|
1121
|
|
|
$customer_data = apply_filters( 'woocommerce_found_customer_details', $customer_data, $user_id, $type_to_load ); |
1122
|
|
|
|
1123
|
|
|
wp_send_json( $customer_data ); |
1124
|
|
|
} |
1125
|
|
|
|
1126
|
|
|
/** |
1127
|
|
|
* Add order item via ajax. |
1128
|
|
|
*/ |
1129
|
|
|
public static function add_order_item() { |
1130
|
|
|
check_ajax_referer( 'order-item', 'security' ); |
1131
|
|
|
|
1132
|
|
|
if ( ! current_user_can( 'edit_shop_orders' ) ) { |
1133
|
|
|
die(-1); |
1134
|
|
|
} |
1135
|
|
|
|
1136
|
|
|
$item_to_add = sanitize_text_field( $_POST['item_to_add'] ); |
1137
|
|
|
$order_id = absint( $_POST['order_id'] ); |
1138
|
|
|
|
1139
|
|
|
// Find the item |
1140
|
|
|
if ( ! is_numeric( $item_to_add ) ) { |
1141
|
|
|
die(); |
1142
|
|
|
} |
1143
|
|
|
|
1144
|
|
|
$post = get_post( $item_to_add ); |
1145
|
|
|
|
1146
|
|
|
if ( ! $post || ( 'product' !== $post->post_type && 'product_variation' !== $post->post_type ) ) { |
1147
|
|
|
die(); |
1148
|
|
|
} |
1149
|
|
|
|
1150
|
|
|
$_product = wc_get_product( $post->ID ); |
1151
|
|
|
$order = wc_get_order( $order_id ); |
1152
|
|
|
$order_taxes = $order->get_taxes(); |
1153
|
|
|
$class = 'new_row'; |
1154
|
|
|
|
1155
|
|
|
// Set values |
1156
|
|
|
$item = array(); |
1157
|
|
|
|
1158
|
|
|
$item['product_id'] = $_product->id; |
1159
|
|
|
$item['variation_id'] = isset( $_product->variation_id ) ? $_product->variation_id : ''; |
1160
|
|
|
$item['variation_data'] = $item['variation_id'] ? $_product->get_variation_attributes() : ''; |
1161
|
|
|
$item['name'] = $_product->get_title(); |
1162
|
|
|
$item['tax_class'] = $_product->get_tax_class(); |
1163
|
|
|
$item['qty'] = 1; |
1164
|
|
|
$item['line_subtotal'] = wc_format_decimal( $_product->get_price_excluding_tax() ); |
1165
|
|
|
$item['line_subtotal_tax'] = ''; |
1166
|
|
|
$item['line_total'] = wc_format_decimal( $_product->get_price_excluding_tax() ); |
1167
|
|
|
$item['line_tax'] = ''; |
1168
|
|
|
$item['type'] = 'line_item'; |
1169
|
|
|
|
1170
|
|
|
// Add line item |
1171
|
|
|
$item_id = wc_add_order_item( $order_id, array( |
1172
|
|
|
'order_item_name' => $item['name'], |
1173
|
|
|
'order_item_type' => 'line_item' |
1174
|
|
|
) ); |
1175
|
|
|
|
1176
|
|
|
// Add line item meta |
1177
|
|
|
if ( $item_id ) { |
1178
|
|
|
wc_add_order_item_meta( $item_id, '_qty', $item['qty'] ); |
1179
|
|
|
wc_add_order_item_meta( $item_id, '_tax_class', $item['tax_class'] ); |
1180
|
|
|
wc_add_order_item_meta( $item_id, '_product_id', $item['product_id'] ); |
1181
|
|
|
wc_add_order_item_meta( $item_id, '_variation_id', $item['variation_id'] ); |
1182
|
|
|
wc_add_order_item_meta( $item_id, '_line_subtotal', $item['line_subtotal'] ); |
1183
|
|
|
wc_add_order_item_meta( $item_id, '_line_subtotal_tax', $item['line_subtotal_tax'] ); |
1184
|
|
|
wc_add_order_item_meta( $item_id, '_line_total', $item['line_total'] ); |
1185
|
|
|
wc_add_order_item_meta( $item_id, '_line_tax', $item['line_tax'] ); |
1186
|
|
|
|
1187
|
|
|
// Since 2.2 |
1188
|
|
|
wc_add_order_item_meta( $item_id, '_line_tax_data', array( 'total' => array(), 'subtotal' => array() ) ); |
1189
|
|
|
|
1190
|
|
|
// Store variation data in meta |
1191
|
|
View Code Duplication |
if ( $item['variation_data'] && is_array( $item['variation_data'] ) ) { |
|
|
|
|
1192
|
|
|
foreach ( $item['variation_data'] as $key => $value ) { |
1193
|
|
|
wc_add_order_item_meta( $item_id, str_replace( 'attribute_', '', $key ), $value ); |
1194
|
|
|
} |
1195
|
|
|
} |
1196
|
|
|
|
1197
|
|
|
do_action( 'woocommerce_ajax_add_order_item_meta', $item_id, $item ); |
1198
|
|
|
} |
1199
|
|
|
|
1200
|
|
|
$item['item_meta'] = $order->get_item_meta( $item_id ); |
1201
|
|
|
$item['item_meta_array'] = $order->get_item_meta_array( $item_id ); |
1202
|
|
|
$item = $order->expand_item_meta( $item ); |
1203
|
|
|
$item = apply_filters( 'woocommerce_ajax_order_item', $item, $item_id ); |
1204
|
|
|
|
1205
|
|
|
include( 'admin/meta-boxes/views/html-order-item.php' ); |
1206
|
|
|
|
1207
|
|
|
// Quit out |
1208
|
|
|
die(); |
1209
|
|
|
} |
1210
|
|
|
|
1211
|
|
|
/** |
1212
|
|
|
* Add order fee via ajax. |
1213
|
|
|
*/ |
1214
|
|
|
public static function add_order_fee() { |
1215
|
|
|
|
1216
|
|
|
check_ajax_referer( 'order-item', 'security' ); |
1217
|
|
|
|
1218
|
|
|
if ( ! current_user_can( 'edit_shop_orders' ) ) { |
1219
|
|
|
die(-1); |
1220
|
|
|
} |
1221
|
|
|
|
1222
|
|
|
$order_id = absint( $_POST['order_id'] ); |
1223
|
|
|
$order = wc_get_order( $order_id ); |
1224
|
|
|
$order_taxes = $order->get_taxes(); |
1225
|
|
|
$item = array(); |
1226
|
|
|
|
1227
|
|
|
// Add new fee |
1228
|
|
|
$fee = new stdClass(); |
1229
|
|
|
$fee->name = ''; |
1230
|
|
|
$fee->tax_class = ''; |
1231
|
|
|
$fee->taxable = $fee->tax_class !== '0'; |
1232
|
|
|
$fee->amount = ''; |
1233
|
|
|
$fee->tax = ''; |
1234
|
|
|
$fee->tax_data = array(); |
1235
|
|
|
$item_id = $order->add_fee( $fee ); |
1236
|
|
|
|
1237
|
|
|
include( 'admin/meta-boxes/views/html-order-fee.php' ); |
1238
|
|
|
|
1239
|
|
|
// Quit out |
1240
|
|
|
die(); |
1241
|
|
|
} |
1242
|
|
|
|
1243
|
|
|
/** |
1244
|
|
|
* Add order shipping cost via ajax. |
1245
|
|
|
*/ |
1246
|
|
|
public static function add_order_shipping() { |
1247
|
|
|
|
1248
|
|
|
check_ajax_referer( 'order-item', 'security' ); |
1249
|
|
|
|
1250
|
|
|
if ( ! current_user_can( 'edit_shop_orders' ) ) { |
1251
|
|
|
die(-1); |
1252
|
|
|
} |
1253
|
|
|
|
1254
|
|
|
$order_id = absint( $_POST['order_id'] ); |
1255
|
|
|
$order = wc_get_order( $order_id ); |
1256
|
|
|
$order_taxes = $order->get_taxes(); |
1257
|
|
|
$shipping_methods = WC()->shipping() ? WC()->shipping->load_shipping_methods() : array(); |
1258
|
|
|
$item = array(); |
1259
|
|
|
|
1260
|
|
|
// Add new shipping |
1261
|
|
|
$shipping = new WC_Shipping_Rate(); |
1262
|
|
|
$item_id = $order->add_shipping( $shipping ); |
1263
|
|
|
|
1264
|
|
|
include( 'admin/meta-boxes/views/html-order-shipping.php' ); |
1265
|
|
|
|
1266
|
|
|
// Quit out |
1267
|
|
|
die(); |
1268
|
|
|
} |
1269
|
|
|
|
1270
|
|
|
/** |
1271
|
|
|
* Add order tax column via ajax. |
1272
|
|
|
*/ |
1273
|
|
|
public static function add_order_tax() { |
1274
|
|
|
global $wpdb; |
1275
|
|
|
|
1276
|
|
|
check_ajax_referer( 'order-item', 'security' ); |
1277
|
|
|
|
1278
|
|
|
if ( ! current_user_can( 'edit_shop_orders' ) ) { |
1279
|
|
|
die(-1); |
1280
|
|
|
} |
1281
|
|
|
|
1282
|
|
|
$order_id = absint( $_POST['order_id'] ); |
1283
|
|
|
$rate_id = absint( $_POST['rate_id'] ); |
1284
|
|
|
$order = wc_get_order( $order_id ); |
1285
|
|
|
$data = get_post_meta( $order_id ); |
1286
|
|
|
|
1287
|
|
|
// Add new tax |
1288
|
|
|
$order->add_tax( $rate_id, 0, 0 ); |
1289
|
|
|
|
1290
|
|
|
// Return HTML items |
1291
|
|
|
include( 'admin/meta-boxes/views/html-order-items.php' ); |
1292
|
|
|
|
1293
|
|
|
die(); |
1294
|
|
|
} |
1295
|
|
|
|
1296
|
|
|
/** |
1297
|
|
|
* Remove an order item. |
1298
|
|
|
*/ |
1299
|
|
|
public static function remove_order_item() { |
1300
|
|
|
check_ajax_referer( 'order-item', 'security' ); |
1301
|
|
|
|
1302
|
|
|
if ( ! current_user_can( 'edit_shop_orders' ) ) { |
1303
|
|
|
die(-1); |
1304
|
|
|
} |
1305
|
|
|
|
1306
|
|
|
$order_item_ids = $_POST['order_item_ids']; |
1307
|
|
|
|
1308
|
|
|
if ( ! is_array( $order_item_ids ) && is_numeric( $order_item_ids ) ) { |
1309
|
|
|
$order_item_ids = array( $order_item_ids ); |
1310
|
|
|
} |
1311
|
|
|
|
1312
|
|
|
if ( sizeof( $order_item_ids ) > 0 ) { |
1313
|
|
|
foreach( $order_item_ids as $id ) { |
1314
|
|
|
wc_delete_order_item( absint( $id ) ); |
1315
|
|
|
} |
1316
|
|
|
} |
1317
|
|
|
|
1318
|
|
|
die(); |
1319
|
|
|
} |
1320
|
|
|
|
1321
|
|
|
/** |
1322
|
|
|
* Remove an order tax. |
1323
|
|
|
*/ |
1324
|
|
|
public static function remove_order_tax() { |
1325
|
|
|
|
1326
|
|
|
check_ajax_referer( 'order-item', 'security' ); |
1327
|
|
|
|
1328
|
|
|
if ( ! current_user_can( 'edit_shop_orders' ) ) { |
1329
|
|
|
die(-1); |
1330
|
|
|
} |
1331
|
|
|
|
1332
|
|
|
$order_id = absint( $_POST['order_id'] ); |
1333
|
|
|
$rate_id = absint( $_POST['rate_id'] ); |
1334
|
|
|
|
1335
|
|
|
wc_delete_order_item( $rate_id ); |
1336
|
|
|
|
1337
|
|
|
// Return HTML items |
1338
|
|
|
$order = wc_get_order( $order_id ); |
1339
|
|
|
$data = get_post_meta( $order_id ); |
1340
|
|
|
include( 'admin/meta-boxes/views/html-order-items.php' ); |
1341
|
|
|
|
1342
|
|
|
die(); |
1343
|
|
|
} |
1344
|
|
|
|
1345
|
|
|
/** |
1346
|
|
|
* Reduce order item stock. |
1347
|
|
|
*/ |
1348
|
|
|
public static function reduce_order_item_stock() { |
1349
|
|
|
check_ajax_referer( 'order-item', 'security' ); |
1350
|
|
|
if ( ! current_user_can( 'edit_shop_orders' ) ) { |
1351
|
|
|
die(-1); |
1352
|
|
|
} |
1353
|
|
|
$order_id = absint( $_POST['order_id'] ); |
1354
|
|
|
$order_item_ids = isset( $_POST['order_item_ids'] ) ? $_POST['order_item_ids'] : array(); |
1355
|
|
|
$order_item_qty = isset( $_POST['order_item_qty'] ) ? $_POST['order_item_qty'] : array(); |
1356
|
|
|
$order = wc_get_order( $order_id ); |
1357
|
|
|
$order_items = $order->get_items(); |
1358
|
|
|
$return = array(); |
1359
|
|
|
if ( $order && ! empty( $order_items ) && sizeof( $order_item_ids ) > 0 ) { |
1360
|
|
|
foreach ( $order_items as $item_id => $order_item ) { |
1361
|
|
|
// Only reduce checked items |
1362
|
|
|
if ( ! in_array( $item_id, $order_item_ids ) ) { |
1363
|
|
|
continue; |
1364
|
|
|
} |
1365
|
|
|
$_product = $order->get_product_from_item( $order_item ); |
1366
|
|
|
if ( $_product->exists() && $_product->managing_stock() && isset( $order_item_qty[ $item_id ] ) && $order_item_qty[ $item_id ] > 0 ) { |
1367
|
|
|
$stock_change = apply_filters( 'woocommerce_reduce_order_stock_quantity', $order_item_qty[ $item_id ], $item_id ); |
1368
|
|
|
$new_stock = $_product->reduce_stock( $stock_change ); |
1369
|
|
|
$item_name = $_product->get_sku() ? $_product->get_sku() : $order_item['product_id']; |
1370
|
|
|
$note = sprintf( __( 'Item %s stock reduced from %s to %s.', 'woocommerce' ), $item_name, $new_stock + $stock_change, $new_stock ); |
1371
|
|
|
$return[] = $note; |
1372
|
|
|
$order->add_order_note( $note ); |
1373
|
|
|
$order->send_stock_notifications( $_product, $new_stock, $order_item_qty[ $item_id ] ); |
1374
|
|
|
} |
1375
|
|
|
} |
1376
|
|
|
do_action( 'woocommerce_reduce_order_stock', $order ); |
1377
|
|
|
if ( empty( $return ) ) { |
1378
|
|
|
$return[] = __( 'No products had their stock reduced - they may not have stock management enabled.', 'woocommerce' ); |
1379
|
|
|
} |
1380
|
|
|
echo implode( ', ', $return ); |
1381
|
|
|
} |
1382
|
|
|
die(); |
1383
|
|
|
} |
1384
|
|
|
|
1385
|
|
|
/** |
1386
|
|
|
* Increase order item stock. |
1387
|
|
|
*/ |
1388
|
|
|
public static function increase_order_item_stock() { |
1389
|
|
|
check_ajax_referer( 'order-item', 'security' ); |
1390
|
|
|
if ( ! current_user_can( 'edit_shop_orders' ) ) { |
1391
|
|
|
die(-1); |
1392
|
|
|
} |
1393
|
|
|
$order_id = absint( $_POST['order_id'] ); |
1394
|
|
|
$order_item_ids = isset( $_POST['order_item_ids'] ) ? $_POST['order_item_ids'] : array(); |
1395
|
|
|
$order_item_qty = isset( $_POST['order_item_qty'] ) ? $_POST['order_item_qty'] : array(); |
1396
|
|
|
$order = wc_get_order( $order_id ); |
1397
|
|
|
$order_items = $order->get_items(); |
1398
|
|
|
$return = array(); |
1399
|
|
|
if ( $order && ! empty( $order_items ) && sizeof( $order_item_ids ) > 0 ) { |
1400
|
|
|
foreach ( $order_items as $item_id => $order_item ) { |
1401
|
|
|
// Only reduce checked items |
1402
|
|
|
if ( ! in_array( $item_id, $order_item_ids ) ) { |
1403
|
|
|
continue; |
1404
|
|
|
} |
1405
|
|
|
$_product = $order->get_product_from_item( $order_item ); |
1406
|
|
|
if ( $_product->exists() && $_product->managing_stock() && isset( $order_item_qty[ $item_id ] ) && $order_item_qty[ $item_id ] > 0 ) { |
1407
|
|
|
$old_stock = $_product->get_stock_quantity(); |
1408
|
|
|
$stock_change = apply_filters( 'woocommerce_restore_order_stock_quantity', $order_item_qty[ $item_id ], $item_id ); |
1409
|
|
|
$new_quantity = $_product->increase_stock( $stock_change ); |
1410
|
|
|
$item_name = $_product->get_sku() ? $_product->get_sku(): $order_item['product_id']; |
1411
|
|
|
$note = sprintf( __( 'Item %s stock increased from %s to %s.', 'woocommerce' ), $item_name, $old_stock, $new_quantity ); |
1412
|
|
|
$return[] = $note; |
1413
|
|
|
$order->add_order_note( $note ); |
1414
|
|
|
} |
1415
|
|
|
} |
1416
|
|
|
do_action( 'woocommerce_restore_order_stock', $order ); |
1417
|
|
|
if ( empty( $return ) ) { |
1418
|
|
|
$return[] = __( 'No products had their stock increased - they may not have stock management enabled.', 'woocommerce' ); |
1419
|
|
|
} |
1420
|
|
|
echo implode( ', ', $return ); |
1421
|
|
|
} |
1422
|
|
|
die(); |
1423
|
|
|
} |
1424
|
|
|
|
1425
|
|
|
/** |
1426
|
|
|
* Add some meta to a line item. |
1427
|
|
|
*/ |
1428
|
|
|
public static function add_order_item_meta() { |
1429
|
|
|
check_ajax_referer( 'order-item', 'security' ); |
1430
|
|
|
|
1431
|
|
|
if ( ! current_user_can( 'edit_shop_orders' ) ) { |
1432
|
|
|
die(-1); |
1433
|
|
|
} |
1434
|
|
|
|
1435
|
|
|
$meta_id = wc_add_order_item_meta( absint( $_POST['order_item_id'] ), __( 'Name', 'woocommerce' ), __( 'Value', 'woocommerce' ) ); |
1436
|
|
|
|
1437
|
|
|
if ( $meta_id ) { |
1438
|
|
|
echo '<tr data-meta_id="' . esc_attr( $meta_id ) . '"><td><input type="text" name="meta_key[' . $meta_id . ']" /><textarea name="meta_value[' . $meta_id . ']"></textarea></td><td width="1%"><button class="remove_order_item_meta button">×</button></td></tr>'; |
1439
|
|
|
} |
1440
|
|
|
|
1441
|
|
|
die(); |
1442
|
|
|
} |
1443
|
|
|
|
1444
|
|
|
/** |
1445
|
|
|
* Remove meta from a line item. |
1446
|
|
|
*/ |
1447
|
|
|
public static function remove_order_item_meta() { |
1448
|
|
|
check_ajax_referer( 'order-item', 'security' ); |
1449
|
|
|
|
1450
|
|
|
if ( ! current_user_can( 'edit_shop_orders' ) ) { |
1451
|
|
|
die(-1); |
1452
|
|
|
} |
1453
|
|
|
|
1454
|
|
|
global $wpdb; |
1455
|
|
|
|
1456
|
|
|
$wpdb->delete( "{$wpdb->prefix}woocommerce_order_itemmeta", array( |
1457
|
|
|
'meta_id' => absint( $_POST['meta_id'] ), |
1458
|
|
|
) ); |
1459
|
|
|
|
1460
|
|
|
die(); |
1461
|
|
|
} |
1462
|
|
|
|
1463
|
|
|
/** |
1464
|
|
|
* Calc line tax. |
1465
|
|
|
*/ |
1466
|
|
|
public static function calc_line_taxes() { |
1467
|
|
|
global $wpdb; |
1468
|
|
|
|
1469
|
|
|
check_ajax_referer( 'calc-totals', 'security' ); |
1470
|
|
|
|
1471
|
|
|
if ( ! current_user_can( 'edit_shop_orders' ) ) { |
1472
|
|
|
die(-1); |
1473
|
|
|
} |
1474
|
|
|
|
1475
|
|
|
$tax = new WC_Tax(); |
1476
|
|
|
$tax_based_on = get_option( 'woocommerce_tax_based_on' ); |
1477
|
|
|
$order_id = absint( $_POST['order_id'] ); |
1478
|
|
|
$items = array(); |
1479
|
|
|
$country = strtoupper( esc_attr( $_POST['country'] ) ); |
1480
|
|
|
$state = strtoupper( esc_attr( $_POST['state'] ) ); |
1481
|
|
|
$postcode = strtoupper( esc_attr( $_POST['postcode'] ) ); |
1482
|
|
|
$city = wc_clean( esc_attr( $_POST['city'] ) ); |
1483
|
|
|
$order = wc_get_order( $order_id ); |
1484
|
|
|
$taxes = array(); |
1485
|
|
|
$shipping_taxes = array(); |
1486
|
|
|
$order_item_tax_classes = array(); |
1487
|
|
|
|
1488
|
|
|
// Default to base |
1489
|
|
View Code Duplication |
if ( 'base' === $tax_based_on || empty( $country ) ) { |
|
|
|
|
1490
|
|
|
$default = wc_get_base_location(); |
1491
|
|
|
$country = $default['country']; |
1492
|
|
|
$state = $default['state']; |
1493
|
|
|
$postcode = ''; |
1494
|
|
|
$city = ''; |
1495
|
|
|
} |
1496
|
|
|
|
1497
|
|
|
// Parse the jQuery serialized items |
1498
|
|
|
parse_str( $_POST['items'], $items ); |
1499
|
|
|
|
1500
|
|
|
// Prevent undefined warnings |
1501
|
|
|
if ( ! isset( $items['line_tax'] ) ) { |
1502
|
|
|
$items['line_tax'] = array(); |
1503
|
|
|
} |
1504
|
|
|
if ( ! isset( $items['line_subtotal_tax'] ) ) { |
1505
|
|
|
$items['line_subtotal_tax'] = array(); |
1506
|
|
|
} |
1507
|
|
|
$items['order_taxes'] = array(); |
1508
|
|
|
|
1509
|
|
|
// Action |
1510
|
|
|
$items = apply_filters( 'woocommerce_ajax_calc_line_taxes', $items, $order_id, $country, $_POST ); |
1511
|
|
|
|
1512
|
|
|
$is_vat_exempt = get_post_meta( $order_id, '_is_vat_exempt', true ); |
1513
|
|
|
|
1514
|
|
|
// Tax is calculated only if tax is enabled and order is not vat exempted |
1515
|
|
|
if ( wc_tax_enabled() && $is_vat_exempt !== 'yes' ) { |
1516
|
|
|
|
1517
|
|
|
// Get items and fees taxes |
1518
|
|
|
if ( isset( $items['order_item_id'] ) ) { |
1519
|
|
|
$line_total = $line_subtotal = array(); |
1520
|
|
|
|
1521
|
|
|
foreach ( $items['order_item_id'] as $item_id ) { |
1522
|
|
|
$item_id = absint( $item_id ); |
1523
|
|
|
$line_total[ $item_id ] = isset( $items['line_total'][ $item_id ] ) ? wc_format_decimal( $items['line_total'][ $item_id ] ) : 0; |
1524
|
|
|
$line_subtotal[ $item_id ] = isset( $items['line_subtotal'][ $item_id ] ) ? wc_format_decimal( $items['line_subtotal'][ $item_id ] ) : $line_total[ $item_id ]; |
1525
|
|
|
$order_item_tax_classes[ $item_id ] = isset( $items['order_item_tax_class'][ $item_id ] ) ? sanitize_text_field( $items['order_item_tax_class'][ $item_id ] ) : ''; |
1526
|
|
|
$product_id = $order->get_item_meta( $item_id, '_product_id', true ); |
1527
|
|
|
|
1528
|
|
|
// Get product details |
1529
|
|
|
if ( get_post_type( $product_id ) == 'product' ) { |
1530
|
|
|
$_product = wc_get_product( $product_id ); |
1531
|
|
|
$item_tax_status = $_product->get_tax_status(); |
1532
|
|
|
} else { |
1533
|
|
|
$item_tax_status = 'taxable'; |
1534
|
|
|
} |
1535
|
|
|
|
1536
|
|
|
if ( '0' !== $order_item_tax_classes[ $item_id ] && 'taxable' === $item_tax_status ) { |
1537
|
|
|
$tax_rates = WC_Tax::find_rates( array( |
1538
|
|
|
'country' => $country, |
1539
|
|
|
'state' => $state, |
1540
|
|
|
'postcode' => $postcode, |
1541
|
|
|
'city' => $city, |
1542
|
|
|
'tax_class' => $order_item_tax_classes[ $item_id ] |
1543
|
|
|
) ); |
1544
|
|
|
|
1545
|
|
|
$line_taxes = WC_Tax::calc_tax( $line_total[ $item_id ], $tax_rates, false ); |
1546
|
|
|
$line_subtotal_taxes = WC_Tax::calc_tax( $line_subtotal[ $item_id ], $tax_rates, false ); |
1547
|
|
|
|
1548
|
|
|
// Set the new line_tax |
1549
|
|
|
foreach ( $line_taxes as $_tax_id => $_tax_value ) { |
1550
|
|
|
$items['line_tax'][ $item_id ][ $_tax_id ] = $_tax_value; |
1551
|
|
|
} |
1552
|
|
|
|
1553
|
|
|
// Set the new line_subtotal_tax |
1554
|
|
|
foreach ( $line_subtotal_taxes as $_tax_id => $_tax_value ) { |
1555
|
|
|
$items['line_subtotal_tax'][ $item_id ][ $_tax_id ] = $_tax_value; |
1556
|
|
|
} |
1557
|
|
|
|
1558
|
|
|
// Sum the item taxes |
1559
|
|
View Code Duplication |
foreach ( array_keys( $taxes + $line_taxes ) as $key ) { |
|
|
|
|
1560
|
|
|
$taxes[ $key ] = ( isset( $line_taxes[ $key ] ) ? $line_taxes[ $key ] : 0 ) + ( isset( $taxes[ $key ] ) ? $taxes[ $key ] : 0 ); |
1561
|
|
|
} |
1562
|
|
|
} |
1563
|
|
|
} |
1564
|
|
|
} |
1565
|
|
|
|
1566
|
|
|
// Get shipping taxes |
1567
|
|
|
if ( isset( $items['shipping_method_id'] ) ) { |
1568
|
|
|
$matched_tax_rates = array(); |
1569
|
|
|
$order_item_tax_classes = array_unique( array_values( $order_item_tax_classes ) ); |
1570
|
|
|
|
1571
|
|
|
// If multiple classes are found, use the first one. Don't bother with standard rate, we can get that later. |
1572
|
|
View Code Duplication |
if ( sizeof( $order_item_tax_classes ) > 1 && ! in_array( '', $order_item_tax_classes ) ) { |
|
|
|
|
1573
|
|
|
$tax_classes = WC_Tax::get_tax_classes(); |
1574
|
|
|
|
1575
|
|
|
foreach ( $tax_classes as $tax_class ) { |
1576
|
|
|
$tax_class = sanitize_title( $tax_class ); |
1577
|
|
|
if ( in_array( $tax_class, $order_item_tax_classes ) ) { |
1578
|
|
|
$matched_tax_rates = WC_Tax::find_shipping_rates( array( |
1579
|
|
|
'country' => $country, |
1580
|
|
|
'state' => $state, |
1581
|
|
|
'postcode' => $postcode, |
1582
|
|
|
'city' => $city, |
1583
|
|
|
'tax_class' => $tax_class, |
1584
|
|
|
) ); |
1585
|
|
|
break; |
1586
|
|
|
} |
1587
|
|
|
} |
1588
|
|
|
// If a single tax class is found, use it |
1589
|
|
|
} elseif ( sizeof( $order_item_tax_classes ) === 1 ) { |
1590
|
|
|
$matched_tax_rates = WC_Tax::find_shipping_rates( array( |
1591
|
|
|
'country' => $country, |
1592
|
|
|
'state' => $state, |
1593
|
|
|
'postcode' => $postcode, |
1594
|
|
|
'city' => $city, |
1595
|
|
|
'tax_class' => $order_item_tax_classes[0] |
1596
|
|
|
) ); |
1597
|
|
|
} |
1598
|
|
|
|
1599
|
|
|
// Get standard rate if no taxes were found |
1600
|
|
|
if ( ! sizeof( $matched_tax_rates ) ) { |
1601
|
|
|
$matched_tax_rates = WC_Tax::find_shipping_rates( array( |
1602
|
|
|
'country' => $country, |
1603
|
|
|
'state' => $state, |
1604
|
|
|
'postcode' => $postcode, |
1605
|
|
|
'city' => $city |
1606
|
|
|
) ); |
1607
|
|
|
} |
1608
|
|
|
|
1609
|
|
|
$shipping_cost = $shipping_taxes = array(); |
1610
|
|
|
|
1611
|
|
|
foreach ( $items['shipping_method_id'] as $item_id ) { |
1612
|
|
|
$item_id = absint( $item_id ); |
1613
|
|
|
$shipping_cost[ $item_id ] = isset( $items['shipping_cost'][ $item_id ] ) ? wc_format_decimal( $items['shipping_cost'][ $item_id ] ) : 0; |
1614
|
|
|
$_shipping_taxes = WC_Tax::calc_shipping_tax( $shipping_cost[ $item_id ], $matched_tax_rates ); |
1615
|
|
|
|
1616
|
|
|
// Set the new shipping_taxes |
1617
|
|
|
foreach ( $_shipping_taxes as $_tax_id => $_tax_value ) { |
1618
|
|
|
$items['shipping_taxes'][ $item_id ][ $_tax_id ] = $_tax_value; |
1619
|
|
|
|
1620
|
|
|
$shipping_taxes[ $_tax_id ] = isset( $shipping_taxes[ $_tax_id ] ) ? $shipping_taxes[ $_tax_id ] + $_tax_value : $_tax_value; |
1621
|
|
|
} |
1622
|
|
|
} |
1623
|
|
|
} |
1624
|
|
|
} |
1625
|
|
|
|
1626
|
|
|
// Remove old tax rows |
1627
|
|
|
$order->remove_order_items( 'tax' ); |
1628
|
|
|
|
1629
|
|
|
// Add tax rows |
1630
|
|
|
foreach ( array_keys( $taxes + $shipping_taxes ) as $tax_rate_id ) { |
1631
|
|
|
$order->add_tax( $tax_rate_id, isset( $taxes[ $tax_rate_id ] ) ? $taxes[ $tax_rate_id ] : 0, isset( $shipping_taxes[ $tax_rate_id ] ) ? $shipping_taxes[ $tax_rate_id ] : 0 ); |
1632
|
|
|
} |
1633
|
|
|
|
1634
|
|
|
// Create the new order_taxes |
1635
|
|
|
foreach ( $order->get_taxes() as $tax_id => $tax_item ) { |
1636
|
|
|
$items['order_taxes'][ $tax_id ] = absint( $tax_item['rate_id'] ); |
1637
|
|
|
} |
1638
|
|
|
|
1639
|
|
|
$items = apply_filters( 'woocommerce_ajax_after_calc_line_taxes', $items, $order_id, $country, $_POST ); |
1640
|
|
|
|
1641
|
|
|
// Save order items |
1642
|
|
|
wc_save_order_items( $order_id, $items ); |
1643
|
|
|
|
1644
|
|
|
// Return HTML items |
1645
|
|
|
$order = wc_get_order( $order_id ); |
1646
|
|
|
$data = get_post_meta( $order_id ); |
1647
|
|
|
include( 'admin/meta-boxes/views/html-order-items.php' ); |
1648
|
|
|
|
1649
|
|
|
die(); |
1650
|
|
|
} |
1651
|
|
|
|
1652
|
|
|
/** |
1653
|
|
|
* Save order items via ajax. |
1654
|
|
|
*/ |
1655
|
|
|
public static function save_order_items() { |
1656
|
|
|
check_ajax_referer( 'order-item', 'security' ); |
1657
|
|
|
|
1658
|
|
|
if ( ! current_user_can( 'edit_shop_orders' ) ) { |
1659
|
|
|
die(-1); |
1660
|
|
|
} |
1661
|
|
|
|
1662
|
|
|
if ( isset( $_POST['order_id'] ) && isset( $_POST['items'] ) ) { |
1663
|
|
|
$order_id = absint( $_POST['order_id'] ); |
1664
|
|
|
|
1665
|
|
|
// Parse the jQuery serialized items |
1666
|
|
|
$items = array(); |
1667
|
|
|
parse_str( $_POST['items'], $items ); |
1668
|
|
|
|
1669
|
|
|
// Save order items |
1670
|
|
|
wc_save_order_items( $order_id, $items ); |
|
|
|
|
1671
|
|
|
|
1672
|
|
|
// Return HTML items |
1673
|
|
|
$order = wc_get_order( $order_id ); |
1674
|
|
|
$data = get_post_meta( $order_id ); |
1675
|
|
|
include( 'admin/meta-boxes/views/html-order-items.php' ); |
1676
|
|
|
} |
1677
|
|
|
|
1678
|
|
|
die(); |
1679
|
|
|
} |
1680
|
|
|
|
1681
|
|
|
/** |
1682
|
|
|
* Load order items via ajax. |
1683
|
|
|
*/ |
1684
|
|
|
public static function load_order_items() { |
1685
|
|
|
check_ajax_referer( 'order-item', 'security' ); |
1686
|
|
|
|
1687
|
|
|
if ( ! current_user_can( 'edit_shop_orders' ) ) { |
1688
|
|
|
die(-1); |
1689
|
|
|
} |
1690
|
|
|
|
1691
|
|
|
// Return HTML items |
1692
|
|
|
$order_id = absint( $_POST['order_id'] ); |
1693
|
|
|
$order = wc_get_order( $order_id ); |
1694
|
|
|
$data = get_post_meta( $order_id ); |
1695
|
|
|
include( 'admin/meta-boxes/views/html-order-items.php' ); |
1696
|
|
|
|
1697
|
|
|
die(); |
1698
|
|
|
} |
1699
|
|
|
|
1700
|
|
|
/** |
1701
|
|
|
* Add order note via ajax. |
1702
|
|
|
*/ |
1703
|
|
|
public static function add_order_note() { |
1704
|
|
|
|
1705
|
|
|
check_ajax_referer( 'add-order-note', 'security' ); |
1706
|
|
|
|
1707
|
|
|
if ( ! current_user_can( 'edit_shop_orders' ) ) { |
1708
|
|
|
die(-1); |
1709
|
|
|
} |
1710
|
|
|
|
1711
|
|
|
$post_id = absint( $_POST['post_id'] ); |
1712
|
|
|
$note = wp_kses_post( trim( stripslashes( $_POST['note'] ) ) ); |
1713
|
|
|
$note_type = $_POST['note_type']; |
1714
|
|
|
|
1715
|
|
|
$is_customer_note = $note_type == 'customer' ? 1 : 0; |
1716
|
|
|
|
1717
|
|
|
if ( $post_id > 0 ) { |
1718
|
|
|
$order = wc_get_order( $post_id ); |
1719
|
|
|
$comment_id = $order->add_order_note( $note, $is_customer_note, true ); |
1720
|
|
|
|
1721
|
|
|
echo '<li rel="' . esc_attr( $comment_id ) . '" class="note '; |
1722
|
|
|
if ( $is_customer_note ) { |
1723
|
|
|
echo 'customer-note'; |
1724
|
|
|
} |
1725
|
|
|
echo '"><div class="note_content">'; |
1726
|
|
|
echo wpautop( wptexturize( $note ) ); |
1727
|
|
|
echo '</div><p class="meta"><a href="#" class="delete_note">'.__( 'Delete note', 'woocommerce' ).'</a></p>'; |
1728
|
|
|
echo '</li>'; |
1729
|
|
|
} |
1730
|
|
|
|
1731
|
|
|
// Quit out |
1732
|
|
|
die(); |
1733
|
|
|
} |
1734
|
|
|
|
1735
|
|
|
/** |
1736
|
|
|
* Delete order note via ajax. |
1737
|
|
|
*/ |
1738
|
|
|
public static function delete_order_note() { |
1739
|
|
|
|
1740
|
|
|
check_ajax_referer( 'delete-order-note', 'security' ); |
1741
|
|
|
|
1742
|
|
|
if ( ! current_user_can( 'edit_shop_orders' ) ) { |
1743
|
|
|
die(-1); |
1744
|
|
|
} |
1745
|
|
|
|
1746
|
|
|
$note_id = (int) $_POST['note_id']; |
1747
|
|
|
|
1748
|
|
|
if ( $note_id > 0 ) { |
1749
|
|
|
wp_delete_comment( $note_id ); |
1750
|
|
|
} |
1751
|
|
|
|
1752
|
|
|
// Quit out |
1753
|
|
|
die(); |
1754
|
|
|
} |
1755
|
|
|
|
1756
|
|
|
/** |
1757
|
|
|
* Search for products and echo json. |
1758
|
|
|
* |
1759
|
|
|
* @param string $x (default: '') |
1760
|
|
|
* @param string $post_types (default: array('product')) |
1761
|
|
|
*/ |
1762
|
|
|
public static function json_search_products( $x = '', $post_types = array( 'product' ) ) { |
|
|
|
|
1763
|
|
|
global $wpdb; |
1764
|
|
|
|
1765
|
|
|
ob_start(); |
1766
|
|
|
|
1767
|
|
|
check_ajax_referer( 'search-products', 'security' ); |
1768
|
|
|
|
1769
|
|
|
$term = (string) wc_clean( stripslashes( $_GET['term'] ) ); |
1770
|
|
|
|
1771
|
|
|
if ( empty( $term ) ) { |
1772
|
|
|
die(); |
1773
|
|
|
} |
1774
|
|
|
|
1775
|
|
|
$like_term = '%' . $wpdb->esc_like( $term ) . '%'; |
1776
|
|
|
|
1777
|
|
|
if ( is_numeric( $term ) ) { |
1778
|
|
|
$query = $wpdb->prepare( " |
1779
|
|
|
SELECT ID FROM {$wpdb->posts} posts LEFT JOIN {$wpdb->postmeta} postmeta ON posts.ID = postmeta.post_id |
1780
|
|
|
WHERE posts.post_status = 'publish' |
1781
|
|
|
AND ( |
1782
|
|
|
posts.post_parent = %s |
1783
|
|
|
OR posts.ID = %s |
1784
|
|
|
OR posts.post_title LIKE %s |
1785
|
|
|
OR ( |
1786
|
|
|
postmeta.meta_key = '_sku' AND postmeta.meta_value LIKE %s |
1787
|
|
|
) |
1788
|
|
|
) |
1789
|
|
|
", $term, $term, $term, $like_term ); |
1790
|
|
|
} else { |
1791
|
|
|
$query = $wpdb->prepare( " |
1792
|
|
|
SELECT ID FROM {$wpdb->posts} posts LEFT JOIN {$wpdb->postmeta} postmeta ON posts.ID = postmeta.post_id |
1793
|
|
|
WHERE posts.post_status = 'publish' |
1794
|
|
|
AND ( |
1795
|
|
|
posts.post_title LIKE %s |
1796
|
|
|
or posts.post_content LIKE %s |
1797
|
|
|
OR ( |
1798
|
|
|
postmeta.meta_key = '_sku' AND postmeta.meta_value LIKE %s |
1799
|
|
|
) |
1800
|
|
|
) |
1801
|
|
|
", $like_term, $like_term, $like_term ); |
1802
|
|
|
} |
1803
|
|
|
|
1804
|
|
|
$query .= " AND posts.post_type IN ('" . implode( "','", array_map( 'esc_sql', $post_types ) ) . "')"; |
1805
|
|
|
|
1806
|
|
|
if ( ! empty( $_GET['exclude'] ) ) { |
1807
|
|
|
$query .= " AND posts.ID NOT IN (" . implode( ',', array_map( 'intval', explode( ',', $_GET['exclude'] ) ) ) . ")"; |
1808
|
|
|
} |
1809
|
|
|
|
1810
|
|
|
if ( ! empty( $_GET['include'] ) ) { |
1811
|
|
|
$query .= " AND posts.ID IN (" . implode( ',', array_map( 'intval', explode( ',', $_GET['include'] ) ) ) . ")"; |
1812
|
|
|
} |
1813
|
|
|
|
1814
|
|
|
if ( ! empty( $_GET['limit'] ) ) { |
1815
|
|
|
$query .= " LIMIT " . intval( $_GET['limit'] ); |
1816
|
|
|
} |
1817
|
|
|
|
1818
|
|
|
$posts = array_unique( $wpdb->get_col( $query ) ); |
1819
|
|
|
$found_products = array(); |
1820
|
|
|
|
1821
|
|
|
if ( ! empty( $posts ) ) { |
1822
|
|
|
foreach ( $posts as $post ) { |
1823
|
|
|
$product = wc_get_product( $post ); |
1824
|
|
|
|
1825
|
|
|
if ( ! current_user_can( 'read_product', $post ) ) { |
1826
|
|
|
continue; |
1827
|
|
|
} |
1828
|
|
|
|
1829
|
|
|
if ( ! $product || ( $product->is_type( 'variation' ) && empty( $product->parent ) ) ) { |
1830
|
|
|
continue; |
1831
|
|
|
} |
1832
|
|
|
|
1833
|
|
|
$found_products[ $post ] = rawurldecode( $product->get_formatted_name() ); |
1834
|
|
|
} |
1835
|
|
|
} |
1836
|
|
|
|
1837
|
|
|
$found_products = apply_filters( 'woocommerce_json_search_found_products', $found_products ); |
1838
|
|
|
|
1839
|
|
|
wp_send_json( $found_products ); |
1840
|
|
|
} |
1841
|
|
|
|
1842
|
|
|
/** |
1843
|
|
|
* Search for product variations and return json. |
1844
|
|
|
* |
1845
|
|
|
* @see WC_AJAX::json_search_products() |
1846
|
|
|
*/ |
1847
|
|
|
public static function json_search_products_and_variations() { |
1848
|
|
|
self::json_search_products( '', array( 'product', 'product_variation' ) ); |
1849
|
|
|
} |
1850
|
|
|
|
1851
|
|
|
/** |
1852
|
|
|
* Search for grouped products and return json. |
1853
|
|
|
*/ |
1854
|
|
|
public static function json_search_grouped_products() { |
1855
|
|
|
ob_start(); |
1856
|
|
|
|
1857
|
|
|
check_ajax_referer( 'search-products', 'security' ); |
1858
|
|
|
|
1859
|
|
|
$term = (string) wc_clean( stripslashes( $_GET['term'] ) ); |
1860
|
|
|
$exclude = array(); |
1861
|
|
|
|
1862
|
|
|
if ( empty( $term ) ) { |
1863
|
|
|
die(); |
1864
|
|
|
} |
1865
|
|
|
|
1866
|
|
View Code Duplication |
if ( ! empty( $_GET['exclude'] ) ) { |
|
|
|
|
1867
|
|
|
$exclude = array_map( 'intval', explode( ',', $_GET['exclude'] ) ); |
1868
|
|
|
} |
1869
|
|
|
|
1870
|
|
|
$found_products = array(); |
1871
|
|
|
|
1872
|
|
|
if ( $grouped_term = get_term_by( 'slug', 'grouped', 'product_type' ) ) { |
1873
|
|
|
|
1874
|
|
|
$posts_in = array_unique( (array) get_objects_in_term( $grouped_term->term_id, 'product_type' ) ); |
1875
|
|
|
|
1876
|
|
|
if ( sizeof( $posts_in ) > 0 ) { |
1877
|
|
|
|
1878
|
|
|
$args = array( |
1879
|
|
|
'post_type' => 'product', |
1880
|
|
|
'post_status' => 'any', |
1881
|
|
|
'numberposts' => -1, |
1882
|
|
|
'orderby' => 'title', |
1883
|
|
|
'order' => 'asc', |
1884
|
|
|
'post_parent' => 0, |
1885
|
|
|
'suppress_filters' => 0, |
1886
|
|
|
'include' => $posts_in, |
1887
|
|
|
's' => $term, |
1888
|
|
|
'fields' => 'ids', |
1889
|
|
|
'exclude' => $exclude |
1890
|
|
|
); |
1891
|
|
|
|
1892
|
|
|
$posts = get_posts( $args ); |
1893
|
|
|
|
1894
|
|
|
if ( ! empty( $posts ) ) { |
1895
|
|
|
foreach ( $posts as $post ) { |
1896
|
|
|
$product = wc_get_product( $post ); |
1897
|
|
|
|
1898
|
|
|
if ( ! current_user_can( 'read_product', $post ) ) { |
1899
|
|
|
continue; |
1900
|
|
|
} |
1901
|
|
|
|
1902
|
|
|
$found_products[ $post ] = rawurldecode( $product->get_formatted_name() ); |
1903
|
|
|
} |
1904
|
|
|
} |
1905
|
|
|
} |
1906
|
|
|
} |
1907
|
|
|
|
1908
|
|
|
$found_products = apply_filters( 'woocommerce_json_search_found_grouped_products', $found_products ); |
1909
|
|
|
|
1910
|
|
|
wp_send_json( $found_products ); |
1911
|
|
|
} |
1912
|
|
|
|
1913
|
|
|
/** |
1914
|
|
|
* Search for downloadable product variations and return json. |
1915
|
|
|
* |
1916
|
|
|
* @see WC_AJAX::json_search_products() |
1917
|
|
|
*/ |
1918
|
|
|
public static function json_search_downloadable_products_and_variations() { |
1919
|
|
|
ob_start(); |
1920
|
|
|
|
1921
|
|
|
check_ajax_referer( 'search-products', 'security' ); |
1922
|
|
|
|
1923
|
|
|
$term = (string) wc_clean( stripslashes( $_GET['term'] ) ); |
1924
|
|
|
$exclude = array(); |
1925
|
|
|
|
1926
|
|
View Code Duplication |
if ( ! empty( $_GET['exclude'] ) ) { |
|
|
|
|
1927
|
|
|
$exclude = array_map( 'intval', explode( ',', $_GET['exclude'] ) ); |
1928
|
|
|
} |
1929
|
|
|
|
1930
|
|
|
$args = array( |
1931
|
|
|
'post_type' => array( 'product', 'product_variation' ), |
1932
|
|
|
'posts_per_page' => -1, |
1933
|
|
|
'post_status' => 'publish', |
1934
|
|
|
'order' => 'ASC', |
1935
|
|
|
'orderby' => 'parent title', |
1936
|
|
|
'meta_query' => array( |
1937
|
|
|
array( |
1938
|
|
|
'key' => '_downloadable', |
1939
|
|
|
'value' => 'yes' |
1940
|
|
|
) |
1941
|
|
|
), |
1942
|
|
|
's' => $term, |
1943
|
|
|
'exclude' => $exclude |
1944
|
|
|
); |
1945
|
|
|
|
1946
|
|
|
$posts = get_posts( $args ); |
1947
|
|
|
$found_products = array(); |
1948
|
|
|
|
1949
|
|
|
if ( ! empty( $posts ) ) { |
1950
|
|
|
foreach ( $posts as $post ) { |
1951
|
|
|
$product = wc_get_product( $post->ID ); |
1952
|
|
|
|
1953
|
|
|
if ( ! current_user_can( 'read_product', $post->ID ) ) { |
1954
|
|
|
continue; |
1955
|
|
|
} |
1956
|
|
|
|
1957
|
|
|
$found_products[ $post->ID ] = $product->get_formatted_name(); |
1958
|
|
|
} |
1959
|
|
|
} |
1960
|
|
|
|
1961
|
|
|
wp_send_json( $found_products ); |
1962
|
|
|
} |
1963
|
|
|
|
1964
|
|
|
/** |
1965
|
|
|
* Search for customers and return json. |
1966
|
|
|
*/ |
1967
|
|
|
public static function json_search_customers() { |
1968
|
|
|
ob_start(); |
1969
|
|
|
|
1970
|
|
|
check_ajax_referer( 'search-customers', 'security' ); |
1971
|
|
|
|
1972
|
|
|
if ( ! current_user_can( 'edit_shop_orders' ) ) { |
1973
|
|
|
die(-1); |
1974
|
|
|
} |
1975
|
|
|
|
1976
|
|
|
$term = wc_clean( stripslashes( $_GET['term'] ) ); |
1977
|
|
|
$exclude = array(); |
1978
|
|
|
|
1979
|
|
|
if ( empty( $term ) ) { |
1980
|
|
|
die(); |
1981
|
|
|
} |
1982
|
|
|
|
1983
|
|
|
if ( ! empty( $_GET['exclude'] ) ) { |
1984
|
|
|
$exclude = array_map( 'intval', explode( ',', $_GET['exclude'] ) ); |
1985
|
|
|
} |
1986
|
|
|
|
1987
|
|
|
$found_customers = array(); |
1988
|
|
|
|
1989
|
|
|
add_action( 'pre_user_query', array( __CLASS__, 'json_search_customer_name' ) ); |
1990
|
|
|
|
1991
|
|
|
$customers_query = new WP_User_Query( apply_filters( 'woocommerce_json_search_customers_query', array( |
1992
|
|
|
'fields' => 'all', |
1993
|
|
|
'orderby' => 'display_name', |
1994
|
|
|
'search' => '*' . $term . '*', |
1995
|
|
|
'search_columns' => array( 'ID', 'user_login', 'user_email', 'user_nicename' ) |
1996
|
|
|
) ) ); |
1997
|
|
|
|
1998
|
|
|
remove_action( 'pre_user_query', array( __CLASS__, 'json_search_customer_name' ) ); |
1999
|
|
|
|
2000
|
|
|
$customers = $customers_query->get_results(); |
2001
|
|
|
|
2002
|
|
|
if ( ! empty( $customers ) ) { |
2003
|
|
|
foreach ( $customers as $customer ) { |
2004
|
|
|
if ( ! in_array( $customer->ID, $exclude ) ) { |
2005
|
|
|
$found_customers[ $customer->ID ] = $customer->display_name . ' (#' . $customer->ID . ' – ' . sanitize_email( $customer->user_email ) . ')'; |
2006
|
|
|
} |
2007
|
|
|
} |
2008
|
|
|
} |
2009
|
|
|
|
2010
|
|
|
$found_customers = apply_filters( 'woocommerce_json_search_found_customers', $found_customers ); |
2011
|
|
|
|
2012
|
|
|
wp_send_json( $found_customers ); |
2013
|
|
|
} |
2014
|
|
|
|
2015
|
|
|
/** |
2016
|
|
|
* When searching using the WP_User_Query, search names (user meta) too. |
2017
|
|
|
* @param object $query |
2018
|
|
|
* @return object |
2019
|
|
|
*/ |
2020
|
|
|
public static function json_search_customer_name( $query ) { |
2021
|
|
|
global $wpdb; |
2022
|
|
|
|
2023
|
|
|
$term = wc_clean( stripslashes( $_GET['term'] ) ); |
2024
|
|
|
if ( method_exists( $wpdb, 'esc_like' ) ) { |
2025
|
|
|
$term = $wpdb->esc_like( $term ); |
2026
|
|
|
} else { |
2027
|
|
|
$term = like_escape( $term ); |
2028
|
|
|
} |
2029
|
|
|
|
2030
|
|
|
$query->query_from .= " INNER JOIN {$wpdb->usermeta} AS user_name ON {$wpdb->users}.ID = user_name.user_id AND ( user_name.meta_key = 'first_name' OR user_name.meta_key = 'last_name' ) "; |
2031
|
|
|
$query->query_where .= $wpdb->prepare( " OR user_name.meta_value LIKE %s ", '%' . $term . '%' ); |
2032
|
|
|
} |
2033
|
|
|
|
2034
|
|
|
/** |
2035
|
|
|
* Ajax request handling for categories ordering. |
2036
|
|
|
*/ |
2037
|
|
|
public static function term_ordering() { |
2038
|
|
|
|
2039
|
|
|
// check permissions again and make sure we have what we need |
2040
|
|
|
if ( ! current_user_can( 'edit_products' ) || empty( $_POST['id'] ) ) { |
2041
|
|
|
die(-1); |
2042
|
|
|
} |
2043
|
|
|
|
2044
|
|
|
$id = (int) $_POST['id']; |
2045
|
|
|
$next_id = isset( $_POST['nextid'] ) && (int) $_POST['nextid'] ? (int) $_POST['nextid'] : null; |
2046
|
|
|
$taxonomy = isset( $_POST['thetaxonomy'] ) ? esc_attr( $_POST['thetaxonomy'] ) : null; |
2047
|
|
|
$term = get_term_by( 'id', $id, $taxonomy ); |
2048
|
|
|
|
2049
|
|
|
if ( ! $id || ! $term || ! $taxonomy ) { |
2050
|
|
|
die(0); |
2051
|
|
|
} |
2052
|
|
|
|
2053
|
|
|
wc_reorder_terms( $term, $next_id, $taxonomy ); |
2054
|
|
|
|
2055
|
|
|
$children = get_terms( $taxonomy, "child_of=$id&menu_order=ASC&hide_empty=0" ); |
2056
|
|
|
|
2057
|
|
|
if ( $term && sizeof( $children ) ) { |
2058
|
|
|
echo 'children'; |
2059
|
|
|
die(); |
2060
|
|
|
} |
2061
|
|
|
} |
2062
|
|
|
|
2063
|
|
|
/** |
2064
|
|
|
* Ajax request handling for product ordering. |
2065
|
|
|
* |
2066
|
|
|
* Based on Simple Page Ordering by 10up (https://wordpress.org/extend/plugins/simple-page-ordering/). |
2067
|
|
|
*/ |
2068
|
|
|
public static function product_ordering() { |
2069
|
|
|
global $wpdb; |
2070
|
|
|
|
2071
|
|
|
ob_start(); |
2072
|
|
|
|
2073
|
|
|
// check permissions again and make sure we have what we need |
2074
|
|
|
if ( ! current_user_can('edit_products') || empty( $_POST['id'] ) || ( ! isset( $_POST['previd'] ) && ! isset( $_POST['nextid'] ) ) ) { |
2075
|
|
|
die(-1); |
2076
|
|
|
} |
2077
|
|
|
|
2078
|
|
|
// real post? |
2079
|
|
|
if ( ! $post = get_post( $_POST['id'] ) ) { |
2080
|
|
|
die(-1); |
2081
|
|
|
} |
2082
|
|
|
|
2083
|
|
|
$previd = isset( $_POST['previd'] ) ? $_POST['previd'] : false; |
2084
|
|
|
$nextid = isset( $_POST['nextid'] ) ? $_POST['nextid'] : false; |
2085
|
|
|
$new_pos = array(); // store new positions for ajax |
2086
|
|
|
|
2087
|
|
|
$siblings = $wpdb->get_results( $wpdb->prepare( " |
2088
|
|
|
SELECT ID, menu_order FROM {$wpdb->posts} AS posts |
2089
|
|
|
WHERE posts.post_type = 'product' |
2090
|
|
|
AND posts.post_status IN ( 'publish', 'pending', 'draft', 'future', 'private' ) |
2091
|
|
|
AND posts.ID NOT IN (%d) |
2092
|
|
|
ORDER BY posts.menu_order ASC, posts.ID DESC |
2093
|
|
|
", $post->ID ) ); |
2094
|
|
|
|
2095
|
|
|
$menu_order = 0; |
2096
|
|
|
|
2097
|
|
|
foreach ( $siblings as $sibling ) { |
2098
|
|
|
|
2099
|
|
|
// if this is the post that comes after our repositioned post, set our repositioned post position and increment menu order |
2100
|
|
View Code Duplication |
if ( $nextid == $sibling->ID ) { |
|
|
|
|
2101
|
|
|
$wpdb->update( |
2102
|
|
|
$wpdb->posts, |
2103
|
|
|
array( |
2104
|
|
|
'menu_order' => $menu_order |
2105
|
|
|
), |
2106
|
|
|
array( 'ID' => $post->ID ), |
2107
|
|
|
array( '%d' ), |
2108
|
|
|
array( '%d' ) |
2109
|
|
|
); |
2110
|
|
|
$new_pos[ $post->ID ] = $menu_order; |
2111
|
|
|
$menu_order++; |
2112
|
|
|
} |
2113
|
|
|
|
2114
|
|
|
// if repositioned post has been set, and new items are already in the right order, we can stop |
2115
|
|
|
if ( isset( $new_pos[ $post->ID ] ) && $sibling->menu_order >= $menu_order ) { |
2116
|
|
|
break; |
2117
|
|
|
} |
2118
|
|
|
|
2119
|
|
|
// set the menu order of the current sibling and increment the menu order |
2120
|
|
|
$wpdb->update( |
2121
|
|
|
$wpdb->posts, |
2122
|
|
|
array( |
2123
|
|
|
'menu_order' => $menu_order |
2124
|
|
|
), |
2125
|
|
|
array( 'ID' => $sibling->ID ), |
2126
|
|
|
array( '%d' ), |
2127
|
|
|
array( '%d' ) |
2128
|
|
|
); |
2129
|
|
|
$new_pos[ $sibling->ID ] = $menu_order; |
2130
|
|
|
$menu_order++; |
2131
|
|
|
|
2132
|
|
View Code Duplication |
if ( ! $nextid && $previd == $sibling->ID ) { |
|
|
|
|
2133
|
|
|
$wpdb->update( |
2134
|
|
|
$wpdb->posts, |
2135
|
|
|
array( |
2136
|
|
|
'menu_order' => $menu_order |
2137
|
|
|
), |
2138
|
|
|
array( 'ID' => $post->ID ), |
2139
|
|
|
array( '%d' ), |
2140
|
|
|
array( '%d' ) |
2141
|
|
|
); |
2142
|
|
|
$new_pos[$post->ID] = $menu_order; |
2143
|
|
|
$menu_order++; |
2144
|
|
|
} |
2145
|
|
|
|
2146
|
|
|
} |
2147
|
|
|
|
2148
|
|
|
do_action( 'woocommerce_after_product_ordering' ); |
2149
|
|
|
|
2150
|
|
|
wp_send_json( $new_pos ); |
2151
|
|
|
} |
2152
|
|
|
|
2153
|
|
|
/** |
2154
|
|
|
* Handle a refund via the edit order screen. |
2155
|
|
|
*/ |
2156
|
|
|
public static function refund_line_items() { |
2157
|
|
|
ob_start(); |
2158
|
|
|
|
2159
|
|
|
check_ajax_referer( 'order-item', 'security' ); |
2160
|
|
|
|
2161
|
|
|
if ( ! current_user_can( 'edit_shop_orders' ) ) { |
2162
|
|
|
die(-1); |
2163
|
|
|
} |
2164
|
|
|
|
2165
|
|
|
$order_id = absint( $_POST['order_id'] ); |
2166
|
|
|
$refund_amount = wc_format_decimal( sanitize_text_field( $_POST['refund_amount'] ), wc_get_price_decimals() ); |
2167
|
|
|
$refund_reason = sanitize_text_field( $_POST['refund_reason'] ); |
2168
|
|
|
$line_item_qtys = json_decode( sanitize_text_field( stripslashes( $_POST['line_item_qtys'] ) ), true ); |
2169
|
|
|
$line_item_totals = json_decode( sanitize_text_field( stripslashes( $_POST['line_item_totals'] ) ), true ); |
2170
|
|
|
$line_item_tax_totals = json_decode( sanitize_text_field( stripslashes( $_POST['line_item_tax_totals'] ) ), true ); |
2171
|
|
|
$api_refund = $_POST['api_refund'] === 'true' ? true : false; |
2172
|
|
|
$restock_refunded_items = $_POST['restock_refunded_items'] === 'true' ? true : false; |
2173
|
|
|
$refund = false; |
2174
|
|
|
$response_data = array(); |
2175
|
|
|
|
2176
|
|
|
try { |
2177
|
|
|
// Validate that the refund can occur |
2178
|
|
|
$order = wc_get_order( $order_id ); |
2179
|
|
|
$order_items = $order->get_items(); |
2180
|
|
|
$max_refund = wc_format_decimal( $order->get_total() - $order->get_total_refunded(), wc_get_price_decimals() ); |
2181
|
|
|
|
2182
|
|
|
if ( ! $refund_amount || $max_refund < $refund_amount || 0 > $refund_amount ) { |
2183
|
|
|
throw new exception( __( 'Invalid refund amount', 'woocommerce' ) ); |
2184
|
|
|
} |
2185
|
|
|
|
2186
|
|
|
// Prepare line items which we are refunding |
2187
|
|
|
$line_items = array(); |
2188
|
|
|
$item_ids = array_unique( array_merge( array_keys( $line_item_qtys, $line_item_totals ) ) ); |
2189
|
|
|
|
2190
|
|
|
foreach ( $item_ids as $item_id ) { |
2191
|
|
|
$line_items[ $item_id ] = array( 'qty' => 0, 'refund_total' => 0, 'refund_tax' => array() ); |
2192
|
|
|
} |
2193
|
|
|
foreach ( $line_item_qtys as $item_id => $qty ) { |
2194
|
|
|
$line_items[ $item_id ]['qty'] = max( $qty, 0 ); |
2195
|
|
|
} |
2196
|
|
|
foreach ( $line_item_totals as $item_id => $total ) { |
2197
|
|
|
$line_items[ $item_id ]['refund_total'] = wc_format_decimal( $total ); |
2198
|
|
|
} |
2199
|
|
|
foreach ( $line_item_tax_totals as $item_id => $tax_totals ) { |
2200
|
|
|
$line_items[ $item_id ]['refund_tax'] = array_map( 'wc_format_decimal', $tax_totals ); |
2201
|
|
|
} |
2202
|
|
|
|
2203
|
|
|
// Create the refund object |
2204
|
|
|
$refund = wc_create_refund( array( |
2205
|
|
|
'amount' => $refund_amount, |
2206
|
|
|
'reason' => $refund_reason, |
2207
|
|
|
'order_id' => $order_id, |
2208
|
|
|
'line_items' => $line_items, |
2209
|
|
|
) ); |
2210
|
|
|
|
2211
|
|
|
if ( is_wp_error( $refund ) ) { |
2212
|
|
|
throw new Exception( $refund->get_error_message() ); |
2213
|
|
|
} |
2214
|
|
|
|
2215
|
|
|
// Refund via API |
2216
|
|
|
if ( $api_refund ) { |
2217
|
|
|
if ( WC()->payment_gateways() ) { |
2218
|
|
|
$payment_gateways = WC()->payment_gateways->payment_gateways(); |
2219
|
|
|
} |
2220
|
|
|
if ( isset( $payment_gateways[ $order->payment_method ] ) && $payment_gateways[ $order->payment_method ]->supports( 'refunds' ) ) { |
2221
|
|
|
$result = $payment_gateways[ $order->payment_method ]->process_refund( $order_id, $refund_amount, $refund_reason ); |
2222
|
|
|
|
2223
|
|
|
do_action( 'woocommerce_refund_processed', $refund, $result ); |
2224
|
|
|
|
2225
|
|
|
if ( is_wp_error( $result ) ) { |
2226
|
|
|
throw new Exception( $result->get_error_message() ); |
2227
|
|
|
} elseif ( ! $result ) { |
2228
|
|
|
throw new Exception( __( 'Refund failed', 'woocommerce' ) ); |
2229
|
|
|
} |
2230
|
|
|
} |
2231
|
|
|
} |
2232
|
|
|
|
2233
|
|
|
// restock items |
2234
|
|
|
foreach ( $line_item_qtys as $item_id => $qty ) { |
2235
|
|
|
if ( $restock_refunded_items && $qty && isset( $order_items[ $item_id ] ) ) { |
2236
|
|
|
$order_item = $order_items[ $item_id ]; |
2237
|
|
|
$_product = $order->get_product_from_item( $order_item ); |
2238
|
|
|
|
2239
|
|
|
if ( $_product && $_product->exists() && $_product->managing_stock() ) { |
2240
|
|
|
$old_stock = wc_stock_amount( $_product->stock ); |
2241
|
|
|
$new_quantity = $_product->increase_stock( $qty ); |
2242
|
|
|
|
2243
|
|
|
$order->add_order_note( sprintf( __( 'Item #%s stock increased from %s to %s.', 'woocommerce' ), $order_item['product_id'], $old_stock, $new_quantity ) ); |
2244
|
|
|
|
2245
|
|
|
do_action( 'woocommerce_restock_refunded_item', $_product->id, $old_stock, $new_quantity, $order ); |
2246
|
|
|
} |
2247
|
|
|
} |
2248
|
|
|
} |
2249
|
|
|
|
2250
|
|
|
// Trigger notifications and status changes |
2251
|
|
|
if ( $order->get_remaining_refund_amount() > 0 || ( $order->has_free_item() && $order->get_remaining_refund_items() > 0 ) ) { |
2252
|
|
|
/** |
2253
|
|
|
* woocommerce_order_partially_refunded. |
2254
|
|
|
* |
2255
|
|
|
* @since 2.4.0 |
2256
|
|
|
* Note: 3rd arg was added in err. Kept for bw compat. 2.4.3. |
2257
|
|
|
*/ |
2258
|
|
|
do_action( 'woocommerce_order_partially_refunded', $order_id, $refund->id, $refund->id ); |
2259
|
|
|
} else { |
2260
|
|
|
do_action( 'woocommerce_order_fully_refunded', $order_id, $refund->id ); |
2261
|
|
|
|
2262
|
|
|
$order->update_status( apply_filters( 'woocommerce_order_fully_refunded_status', 'refunded', $order_id, $refund->id ) ); |
2263
|
|
|
$response_data['status'] = 'fully_refunded'; |
2264
|
|
|
} |
2265
|
|
|
|
2266
|
|
|
do_action( 'woocommerce_order_refunded', $order_id, $refund->id ); |
2267
|
|
|
|
2268
|
|
|
// Clear transients |
2269
|
|
|
wc_delete_shop_order_transients( $order_id ); |
2270
|
|
|
wp_send_json_success( $response_data ); |
2271
|
|
|
|
2272
|
|
|
} catch ( Exception $e ) { |
2273
|
|
|
if ( $refund && is_a( $refund, 'WC_Order_Refund' ) ) { |
2274
|
|
|
wp_delete_post( $refund->id, true ); |
2275
|
|
|
} |
2276
|
|
|
|
2277
|
|
|
wp_send_json_error( array( 'error' => $e->getMessage() ) ); |
2278
|
|
|
} |
2279
|
|
|
} |
2280
|
|
|
|
2281
|
|
|
/** |
2282
|
|
|
* Delete a refund. |
2283
|
|
|
*/ |
2284
|
|
|
public static function delete_refund() { |
2285
|
|
|
check_ajax_referer( 'order-item', 'security' ); |
2286
|
|
|
|
2287
|
|
|
if ( ! current_user_can( 'edit_shop_orders' ) ) { |
2288
|
|
|
die(-1); |
2289
|
|
|
} |
2290
|
|
|
|
2291
|
|
|
$refund_ids = array_map( 'absint', is_array( $_POST['refund_id'] ) ? $_POST['refund_id'] : array( $_POST['refund_id'] ) ); |
2292
|
|
|
foreach ( $refund_ids as $refund_id ) { |
2293
|
|
|
if ( $refund_id && 'shop_order_refund' === get_post_type( $refund_id ) ) { |
2294
|
|
|
$order_id = wp_get_post_parent_id( $refund_id ); |
2295
|
|
|
wc_delete_shop_order_transients( $order_id ); |
2296
|
|
|
wp_delete_post( $refund_id ); |
2297
|
|
|
do_action( 'woocommerce_refund_deleted', $refund_id, $order_id ); |
2298
|
|
|
} |
2299
|
|
|
} |
2300
|
|
|
die(); |
2301
|
|
|
} |
2302
|
|
|
|
2303
|
|
|
/** |
2304
|
|
|
* Triggered when clicking the rating footer. |
2305
|
|
|
*/ |
2306
|
|
|
public static function rated() { |
2307
|
|
|
if ( ! current_user_can( 'manage_woocommerce' ) ) { |
2308
|
|
|
die(-1); |
2309
|
|
|
} |
2310
|
|
|
|
2311
|
|
|
update_option( 'woocommerce_admin_footer_text_rated', 1 ); |
2312
|
|
|
die(); |
2313
|
|
|
} |
2314
|
|
|
|
2315
|
|
|
/** |
2316
|
|
|
* Create/Update API key. |
2317
|
|
|
*/ |
2318
|
|
|
public static function update_api_key() { |
2319
|
|
|
ob_start(); |
2320
|
|
|
|
2321
|
|
|
global $wpdb; |
2322
|
|
|
|
2323
|
|
|
check_ajax_referer( 'update-api-key', 'security' ); |
2324
|
|
|
|
2325
|
|
|
if ( ! current_user_can( 'manage_woocommerce' ) ) { |
2326
|
|
|
die(-1); |
2327
|
|
|
} |
2328
|
|
|
|
2329
|
|
|
try { |
2330
|
|
|
if ( empty( $_POST['description'] ) ) { |
2331
|
|
|
throw new Exception( __( 'Description is missing.', 'woocommerce' ) ); |
2332
|
|
|
} |
2333
|
|
|
if ( empty( $_POST['user'] ) ) { |
2334
|
|
|
throw new Exception( __( 'User is missing.', 'woocommerce' ) ); |
2335
|
|
|
} |
2336
|
|
|
if ( empty( $_POST['permissions'] ) ) { |
2337
|
|
|
throw new Exception( __( 'Permissions is missing.', 'woocommerce' ) ); |
2338
|
|
|
} |
2339
|
|
|
|
2340
|
|
|
$key_id = absint( $_POST['key_id'] ); |
2341
|
|
|
$description = sanitize_text_field( wp_unslash( $_POST['description'] ) ); |
2342
|
|
|
$permissions = ( in_array( $_POST['permissions'], array( 'read', 'write', 'read_write' ) ) ) ? sanitize_text_field( $_POST['permissions'] ) : 'read'; |
2343
|
|
|
$user_id = absint( $_POST['user'] ); |
2344
|
|
|
|
2345
|
|
|
if ( 0 < $key_id ) { |
2346
|
|
|
$data = array( |
2347
|
|
|
'user_id' => $user_id, |
2348
|
|
|
'description' => $description, |
2349
|
|
|
'permissions' => $permissions |
2350
|
|
|
); |
2351
|
|
|
|
2352
|
|
|
$wpdb->update( |
2353
|
|
|
$wpdb->prefix . 'woocommerce_api_keys', |
2354
|
|
|
$data, |
2355
|
|
|
array( 'key_id' => $key_id ), |
2356
|
|
|
array( |
2357
|
|
|
'%d', |
2358
|
|
|
'%s', |
2359
|
|
|
'%s' |
2360
|
|
|
), |
2361
|
|
|
array( '%d' ) |
2362
|
|
|
); |
2363
|
|
|
|
2364
|
|
|
$data['consumer_key'] = ''; |
2365
|
|
|
$data['consumer_secret'] = ''; |
2366
|
|
|
$data['message'] = __( 'API Key updated successfully.', 'woocommerce' ); |
2367
|
|
|
} else { |
2368
|
|
|
$consumer_key = 'ck_' . wc_rand_hash(); |
2369
|
|
|
$consumer_secret = 'cs_' . wc_rand_hash(); |
2370
|
|
|
|
2371
|
|
|
$data = array( |
2372
|
|
|
'user_id' => $user_id, |
2373
|
|
|
'description' => $description, |
2374
|
|
|
'permissions' => $permissions, |
2375
|
|
|
'consumer_key' => wc_api_hash( $consumer_key ), |
2376
|
|
|
'consumer_secret' => $consumer_secret, |
2377
|
|
|
'truncated_key' => substr( $consumer_key, -7 ) |
2378
|
|
|
); |
2379
|
|
|
|
2380
|
|
|
$wpdb->insert( |
2381
|
|
|
$wpdb->prefix . 'woocommerce_api_keys', |
2382
|
|
|
$data, |
2383
|
|
|
array( |
2384
|
|
|
'%d', |
2385
|
|
|
'%s', |
2386
|
|
|
'%s', |
2387
|
|
|
'%s', |
2388
|
|
|
'%s', |
2389
|
|
|
'%s' |
2390
|
|
|
) |
2391
|
|
|
); |
2392
|
|
|
|
2393
|
|
|
$key_id = $wpdb->insert_id; |
2394
|
|
|
$data['consumer_key'] = $consumer_key; |
2395
|
|
|
$data['consumer_secret'] = $consumer_secret; |
2396
|
|
|
$data['message'] = __( 'API Key generated successfully. Make sure to copy your new API keys now. You won\'t be able to see it again!', 'woocommerce' ); |
2397
|
|
|
$data['revoke_url'] = '<a style="color: #a00; text-decoration: none;" href="' . esc_url( wp_nonce_url( add_query_arg( array( 'revoke-key' => $key_id ), admin_url( 'admin.php?page=wc-settings&tab=api§ion=keys' ) ), 'revoke' ) ). '">' . __( 'Revoke Key', 'woocommerce' ) . '</a>'; |
2398
|
|
|
} |
2399
|
|
|
|
2400
|
|
|
wp_send_json_success( $data ); |
2401
|
|
|
} catch ( Exception $e ) { |
2402
|
|
|
wp_send_json_error( array( 'message' => $e->getMessage() ) ); |
2403
|
|
|
} |
2404
|
|
|
} |
2405
|
|
|
|
2406
|
|
|
/** |
2407
|
|
|
* Locate user via AJAX. |
2408
|
|
|
*/ |
2409
|
|
|
public static function get_customer_location() { |
2410
|
|
|
$location_hash = WC_Cache_Helper::geolocation_ajax_get_location_hash(); |
2411
|
|
|
wp_send_json_success( array( 'hash' => $location_hash ) ); |
2412
|
|
|
} |
2413
|
|
|
|
2414
|
|
|
/** |
2415
|
|
|
* Load variations via AJAX. |
2416
|
|
|
*/ |
2417
|
|
|
public static function load_variations() { |
2418
|
|
|
ob_start(); |
2419
|
|
|
|
2420
|
|
|
check_ajax_referer( 'load-variations', 'security' ); |
2421
|
|
|
|
2422
|
|
|
// Check permissions again and make sure we have what we need |
2423
|
|
View Code Duplication |
if ( ! current_user_can( 'edit_products' ) || empty( $_POST['product_id'] ) || empty( $_POST['attributes'] ) ) { |
|
|
|
|
2424
|
|
|
die( -1 ); |
2425
|
|
|
} |
2426
|
|
|
|
2427
|
|
|
global $post; |
2428
|
|
|
|
2429
|
|
|
$product_id = absint( $_POST['product_id'] ); |
2430
|
|
|
$post = get_post( $product_id ); // Set $post global so its available like within the admin screens |
2431
|
|
|
$per_page = ! empty( $_POST['per_page'] ) ? absint( $_POST['per_page'] ) : 10; |
2432
|
|
|
$page = ! empty( $_POST['page'] ) ? absint( $_POST['page'] ) : 1; |
2433
|
|
|
|
2434
|
|
|
// Get attributes |
2435
|
|
|
$attributes = array(); |
2436
|
|
|
$posted_attributes = wp_unslash( $_POST['attributes'] ); |
2437
|
|
|
|
2438
|
|
|
foreach ( $posted_attributes as $key => $value ) { |
2439
|
|
|
$attributes[ $key ] = array_map( 'wc_clean', $value ); |
2440
|
|
|
} |
2441
|
|
|
|
2442
|
|
|
// Get tax classes |
2443
|
|
|
$tax_classes = WC_Tax::get_tax_classes(); |
2444
|
|
|
$tax_class_options = array(); |
2445
|
|
|
$tax_class_options[''] = __( 'Standard', 'woocommerce' ); |
2446
|
|
|
|
2447
|
|
View Code Duplication |
if ( ! empty( $tax_classes ) ) { |
|
|
|
|
2448
|
|
|
foreach ( $tax_classes as $class ) { |
2449
|
|
|
$tax_class_options[ sanitize_title( $class ) ] = esc_attr( $class ); |
2450
|
|
|
} |
2451
|
|
|
} |
2452
|
|
|
|
2453
|
|
|
// Set backorder options |
2454
|
|
|
$backorder_options = array( |
2455
|
|
|
'no' => __( 'Do not allow', 'woocommerce' ), |
2456
|
|
|
'notify' => __( 'Allow, but notify customer', 'woocommerce' ), |
2457
|
|
|
'yes' => __( 'Allow', 'woocommerce' ) |
2458
|
|
|
); |
2459
|
|
|
|
2460
|
|
|
// set stock status options |
2461
|
|
|
$stock_status_options = array( |
2462
|
|
|
'instock' => __( 'In stock', 'woocommerce' ), |
2463
|
|
|
'outofstock' => __( 'Out of stock', 'woocommerce' ) |
2464
|
|
|
); |
2465
|
|
|
|
2466
|
|
|
$parent_data = array( |
2467
|
|
|
'id' => $product_id, |
2468
|
|
|
'attributes' => $attributes, |
2469
|
|
|
'tax_class_options' => $tax_class_options, |
2470
|
|
|
'sku' => get_post_meta( $product_id, '_sku', true ), |
2471
|
|
|
'weight' => wc_format_localized_decimal( get_post_meta( $product_id, '_weight', true ) ), |
2472
|
|
|
'length' => wc_format_localized_decimal( get_post_meta( $product_id, '_length', true ) ), |
2473
|
|
|
'width' => wc_format_localized_decimal( get_post_meta( $product_id, '_width', true ) ), |
2474
|
|
|
'height' => wc_format_localized_decimal( get_post_meta( $product_id, '_height', true ) ), |
2475
|
|
|
'tax_class' => get_post_meta( $product_id, '_tax_class', true ), |
2476
|
|
|
'backorder_options' => $backorder_options, |
2477
|
|
|
'stock_status_options' => $stock_status_options |
2478
|
|
|
); |
2479
|
|
|
|
2480
|
|
|
if ( ! $parent_data['weight'] ) { |
2481
|
|
|
$parent_data['weight'] = wc_format_localized_decimal( 0 ); |
2482
|
|
|
} |
2483
|
|
|
|
2484
|
|
|
if ( ! $parent_data['length'] ) { |
2485
|
|
|
$parent_data['length'] = wc_format_localized_decimal( 0 ); |
2486
|
|
|
} |
2487
|
|
|
|
2488
|
|
|
if ( ! $parent_data['width'] ) { |
2489
|
|
|
$parent_data['width'] = wc_format_localized_decimal( 0 ); |
2490
|
|
|
} |
2491
|
|
|
|
2492
|
|
|
if ( ! $parent_data['height'] ) { |
2493
|
|
|
$parent_data['height'] = wc_format_localized_decimal( 0 ); |
2494
|
|
|
} |
2495
|
|
|
|
2496
|
|
|
// Get variations |
2497
|
|
|
$args = apply_filters( 'woocommerce_ajax_admin_get_variations_args', array( |
2498
|
|
|
'post_type' => 'product_variation', |
2499
|
|
|
'post_status' => array( 'private', 'publish' ), |
2500
|
|
|
'posts_per_page' => $per_page, |
2501
|
|
|
'paged' => $page, |
2502
|
|
|
'orderby' => array( 'menu_order' => 'ASC', 'ID' => 'DESC' ), |
2503
|
|
|
'post_parent' => $product_id |
2504
|
|
|
), $product_id ); |
2505
|
|
|
|
2506
|
|
|
$variations = get_posts( $args ); |
2507
|
|
|
$loop = 0; |
2508
|
|
|
|
2509
|
|
|
if ( $variations ) { |
2510
|
|
|
|
2511
|
|
|
foreach ( $variations as $variation ) { |
2512
|
|
|
$variation_id = absint( $variation->ID ); |
2513
|
|
|
$variation_meta = get_post_meta( $variation_id ); |
2514
|
|
|
$variation_data = array(); |
2515
|
|
|
$shipping_classes = get_the_terms( $variation_id, 'product_shipping_class' ); |
2516
|
|
|
$variation_fields = array( |
2517
|
|
|
'_sku' => '', |
2518
|
|
|
'_stock' => '', |
2519
|
|
|
'_regular_price' => '', |
2520
|
|
|
'_sale_price' => '', |
2521
|
|
|
'_weight' => '', |
2522
|
|
|
'_length' => '', |
2523
|
|
|
'_width' => '', |
2524
|
|
|
'_height' => '', |
2525
|
|
|
'_download_limit' => '', |
2526
|
|
|
'_download_expiry' => '', |
2527
|
|
|
'_downloadable_files' => '', |
2528
|
|
|
'_downloadable' => '', |
2529
|
|
|
'_virtual' => '', |
2530
|
|
|
'_thumbnail_id' => '', |
2531
|
|
|
'_sale_price_dates_from' => '', |
2532
|
|
|
'_sale_price_dates_to' => '', |
2533
|
|
|
'_manage_stock' => '', |
2534
|
|
|
'_stock_status' => '', |
2535
|
|
|
'_backorders' => null, |
2536
|
|
|
'_tax_class' => null, |
2537
|
|
|
'_variation_description' => '' |
2538
|
|
|
); |
2539
|
|
|
|
2540
|
|
View Code Duplication |
foreach ( $variation_fields as $field => $value ) { |
|
|
|
|
2541
|
|
|
$variation_data[ $field ] = isset( $variation_meta[ $field ][0] ) ? maybe_unserialize( $variation_meta[ $field ][0] ) : $value; |
2542
|
|
|
} |
2543
|
|
|
|
2544
|
|
|
// Add the variation attributes |
2545
|
|
|
$variation_data = array_merge( $variation_data, wc_get_product_variation_attributes( $variation_id ) ); |
2546
|
|
|
|
2547
|
|
|
// Formatting |
2548
|
|
|
$variation_data['_regular_price'] = wc_format_localized_price( $variation_data['_regular_price'] ); |
2549
|
|
|
$variation_data['_sale_price'] = wc_format_localized_price( $variation_data['_sale_price'] ); |
2550
|
|
|
$variation_data['_weight'] = wc_format_localized_decimal( $variation_data['_weight'] ); |
2551
|
|
|
$variation_data['_length'] = wc_format_localized_decimal( $variation_data['_length'] ); |
2552
|
|
|
$variation_data['_width'] = wc_format_localized_decimal( $variation_data['_width'] ); |
2553
|
|
|
$variation_data['_height'] = wc_format_localized_decimal( $variation_data['_height'] ); |
2554
|
|
|
$variation_data['_thumbnail_id'] = absint( $variation_data['_thumbnail_id'] ); |
2555
|
|
|
$variation_data['image'] = $variation_data['_thumbnail_id'] ? wp_get_attachment_thumb_url( $variation_data['_thumbnail_id'] ) : ''; |
2556
|
|
|
$variation_data['shipping_class'] = $shipping_classes && ! is_wp_error( $shipping_classes ) ? current( $shipping_classes )->term_id : ''; |
2557
|
|
|
$variation_data['menu_order'] = $variation->menu_order; |
2558
|
|
|
$variation_data['_stock'] = '' === $variation_data['_stock'] ? '' : wc_stock_amount( $variation_data['_stock'] ); |
2559
|
|
|
|
2560
|
|
|
include( 'admin/meta-boxes/views/html-variation-admin.php' ); |
2561
|
|
|
|
2562
|
|
|
$loop++; |
2563
|
|
|
} |
2564
|
|
|
} |
2565
|
|
|
|
2566
|
|
|
die(); |
2567
|
|
|
} |
2568
|
|
|
|
2569
|
|
|
/** |
2570
|
|
|
* Save variations via AJAX. |
2571
|
|
|
*/ |
2572
|
|
|
public static function save_variations() { |
2573
|
|
|
ob_start(); |
2574
|
|
|
|
2575
|
|
|
check_ajax_referer( 'save-variations', 'security' ); |
2576
|
|
|
|
2577
|
|
|
// Check permissions again and make sure we have what we need |
2578
|
|
View Code Duplication |
if ( ! current_user_can( 'edit_products' ) || empty( $_POST ) || empty( $_POST['product_id'] ) ) { |
|
|
|
|
2579
|
|
|
die( -1 ); |
2580
|
|
|
} |
2581
|
|
|
|
2582
|
|
|
// Remove previous meta box errors |
2583
|
|
|
WC_Admin_Meta_Boxes::$meta_box_errors = array(); |
2584
|
|
|
|
2585
|
|
|
$product_id = absint( $_POST['product_id'] ); |
2586
|
|
|
$product_type = empty( $_POST['product-type'] ) ? 'simple' : sanitize_title( stripslashes( $_POST['product-type'] ) ); |
2587
|
|
|
|
2588
|
|
|
$product_type_terms = wp_get_object_terms( $product_id, 'product_type' ); |
2589
|
|
|
|
2590
|
|
|
// If the product type hasn't been set or it has changed, update it before saving variations |
2591
|
|
|
if ( empty( $product_type_terms ) || $product_type !== sanitize_title( current( $product_type_terms )->name ) ) { |
2592
|
|
|
wp_set_object_terms( $product_id, $product_type, 'product_type' ); |
2593
|
|
|
} |
2594
|
|
|
|
2595
|
|
|
WC_Meta_Box_Product_Data::save_variations( $product_id, get_post( $product_id ) ); |
2596
|
|
|
|
2597
|
|
|
do_action( 'woocommerce_ajax_save_product_variations', $product_id ); |
2598
|
|
|
|
2599
|
|
|
// Clear cache/transients |
2600
|
|
|
wc_delete_product_transients( $product_id ); |
2601
|
|
|
|
2602
|
|
|
if ( $errors = WC_Admin_Meta_Boxes::$meta_box_errors ) { |
2603
|
|
|
echo '<div class="error notice is-dismissible">'; |
2604
|
|
|
|
2605
|
|
|
foreach ( $errors as $error ) { |
2606
|
|
|
echo '<p>' . wp_kses_post( $error ) . '</p>'; |
2607
|
|
|
} |
2608
|
|
|
|
2609
|
|
|
echo '<button type="button" class="notice-dismiss"><span class="screen-reader-text">' . __( 'Dismiss this notice.', 'woocommerce' ) . '</span></button>'; |
2610
|
|
|
echo '</div>'; |
2611
|
|
|
|
2612
|
|
|
delete_option( 'woocommerce_meta_box_errors' ); |
2613
|
|
|
} |
2614
|
|
|
|
2615
|
|
|
die(); |
2616
|
|
|
} |
2617
|
|
|
|
2618
|
|
|
/** |
2619
|
|
|
* Bulk action - Toggle Enabled. |
2620
|
|
|
* @access private |
2621
|
|
|
* @param array $variations |
2622
|
|
|
* @param array $data |
2623
|
|
|
*/ |
2624
|
|
|
private static function variation_bulk_action_toggle_enabled( $variations, $data ) { |
|
|
|
|
2625
|
|
|
global $wpdb; |
2626
|
|
|
|
2627
|
|
|
foreach ( $variations as $variation_id ) { |
2628
|
|
|
$post_status = get_post_status( $variation_id ); |
2629
|
|
|
$new_status = 'private' === $post_status ? 'publish' : 'private'; |
2630
|
|
|
$wpdb->update( $wpdb->posts, array( 'post_status' => $new_status ), array( 'ID' => $variation_id ) ); |
2631
|
|
|
} |
2632
|
|
|
} |
2633
|
|
|
|
2634
|
|
|
/** |
2635
|
|
|
* Bulk action - Toggle Downloadable Checkbox. |
2636
|
|
|
* @access private |
2637
|
|
|
* @param array $variations |
2638
|
|
|
* @param array $data |
2639
|
|
|
*/ |
2640
|
|
View Code Duplication |
private static function variation_bulk_action_toggle_downloadable( $variations, $data ) { |
|
|
|
|
2641
|
|
|
foreach ( $variations as $variation_id ) { |
2642
|
|
|
$_downloadable = get_post_meta( $variation_id, '_downloadable', true ); |
2643
|
|
|
$is_downloadable = 'no' === $_downloadable ? 'yes' : 'no'; |
2644
|
|
|
update_post_meta( $variation_id, '_downloadable', wc_clean( $is_downloadable ) ); |
2645
|
|
|
} |
2646
|
|
|
} |
2647
|
|
|
|
2648
|
|
|
/** |
2649
|
|
|
* Bulk action - Toggle Virtual Checkbox. |
2650
|
|
|
* @access private |
2651
|
|
|
* @param array $variations |
2652
|
|
|
* @param array $data |
2653
|
|
|
*/ |
2654
|
|
View Code Duplication |
private static function variation_bulk_action_toggle_virtual( $variations, $data ) { |
|
|
|
|
2655
|
|
|
foreach ( $variations as $variation_id ) { |
2656
|
|
|
$_virtual = get_post_meta( $variation_id, '_virtual', true ); |
2657
|
|
|
$is_virtual = 'no' === $_virtual ? 'yes' : 'no'; |
2658
|
|
|
update_post_meta( $variation_id, '_virtual', wc_clean( $is_virtual ) ); |
2659
|
|
|
} |
2660
|
|
|
} |
2661
|
|
|
|
2662
|
|
|
/** |
2663
|
|
|
* Bulk action - Toggle Manage Stock Checkbox. |
2664
|
|
|
* @access private |
2665
|
|
|
* @param array $variations |
2666
|
|
|
* @param array $data |
2667
|
|
|
*/ |
2668
|
|
|
private static function variation_bulk_action_toggle_manage_stock( $variations, $data ) { |
|
|
|
|
2669
|
|
|
foreach ( $variations as $variation_id ) { |
2670
|
|
|
$_manage_stock = get_post_meta( $variation_id, '_manage_stock', true ); |
2671
|
|
|
$is_manage_stock = 'no' === $_manage_stock || '' === $_manage_stock ? 'yes' : 'no'; |
2672
|
|
|
update_post_meta( $variation_id, '_manage_stock', $is_manage_stock ); |
2673
|
|
|
} |
2674
|
|
|
} |
2675
|
|
|
|
2676
|
|
|
/** |
2677
|
|
|
* Bulk action - Set Regular Prices. |
2678
|
|
|
* @access private |
2679
|
|
|
* @param array $variations |
2680
|
|
|
* @param array $data |
2681
|
|
|
*/ |
2682
|
|
View Code Duplication |
private static function variation_bulk_action_variable_regular_price( $variations, $data ) { |
|
|
|
|
2683
|
|
|
if ( ! isset( $data['value'] ) ) { |
2684
|
|
|
return; |
2685
|
|
|
} |
2686
|
|
|
|
2687
|
|
|
foreach ( $variations as $variation_id ) { |
2688
|
|
|
// Price fields |
2689
|
|
|
$regular_price = wc_clean( $data['value'] ); |
2690
|
|
|
$sale_price = get_post_meta( $variation_id, '_sale_price', true ); |
2691
|
|
|
|
2692
|
|
|
// Date fields |
2693
|
|
|
$date_from = get_post_meta( $variation_id, '_sale_price_dates_from', true ); |
2694
|
|
|
$date_to = get_post_meta( $variation_id, '_sale_price_dates_to', true ); |
2695
|
|
|
$date_from = ! empty( $date_from ) ? date( 'Y-m-d', $date_from ) : ''; |
2696
|
|
|
$date_to = ! empty( $date_to ) ? date( 'Y-m-d', $date_to ) : ''; |
2697
|
|
|
|
2698
|
|
|
_wc_save_product_price( $variation_id, $regular_price, $sale_price, $date_from, $date_to ); |
|
|
|
|
2699
|
|
|
} |
2700
|
|
|
} |
2701
|
|
|
|
2702
|
|
|
/** |
2703
|
|
|
* Bulk action - Set Sale Prices. |
2704
|
|
|
* @access private |
2705
|
|
|
* @param array $variations |
2706
|
|
|
* @param array $data |
2707
|
|
|
*/ |
2708
|
|
View Code Duplication |
private static function variation_bulk_action_variable_sale_price( $variations, $data ) { |
|
|
|
|
2709
|
|
|
if ( ! isset( $data['value'] ) ) { |
2710
|
|
|
return; |
2711
|
|
|
} |
2712
|
|
|
|
2713
|
|
|
foreach ( $variations as $variation_id ) { |
2714
|
|
|
// Price fields |
2715
|
|
|
$regular_price = get_post_meta( $variation_id, '_regular_price', true ); |
2716
|
|
|
$sale_price = wc_clean( $data['value'] ); |
2717
|
|
|
|
2718
|
|
|
// Date fields |
2719
|
|
|
$date_from = get_post_meta( $variation_id, '_sale_price_dates_from', true ); |
2720
|
|
|
$date_to = get_post_meta( $variation_id, '_sale_price_dates_to', true ); |
2721
|
|
|
$date_from = ! empty( $date_from ) ? date( 'Y-m-d', $date_from ) : ''; |
2722
|
|
|
$date_to = ! empty( $date_to ) ? date( 'Y-m-d', $date_to ) : ''; |
2723
|
|
|
|
2724
|
|
|
_wc_save_product_price( $variation_id, $regular_price, $sale_price, $date_from, $date_to ); |
|
|
|
|
2725
|
|
|
} |
2726
|
|
|
} |
2727
|
|
|
|
2728
|
|
|
/** |
2729
|
|
|
* Bulk action - Set Stock. |
2730
|
|
|
* @access private |
2731
|
|
|
* @param array $variations |
2732
|
|
|
* @param array $data |
2733
|
|
|
*/ |
2734
|
|
|
private static function variation_bulk_action_variable_stock( $variations, $data ) { |
|
|
|
|
2735
|
|
|
if ( ! isset( $data['value'] ) ) { |
2736
|
|
|
return; |
2737
|
|
|
} |
2738
|
|
|
|
2739
|
|
|
$value = wc_clean( $data['value'] ); |
2740
|
|
|
|
2741
|
|
|
foreach ( $variations as $variation_id ) { |
2742
|
|
|
if ( 'yes' === get_post_meta( $variation_id, '_manage_stock', true ) ) { |
2743
|
|
|
wc_update_product_stock( $variation_id, wc_stock_amount( $value ) ); |
|
|
|
|
2744
|
|
|
} else { |
2745
|
|
|
delete_post_meta( $variation_id, '_stock' ); |
2746
|
|
|
} |
2747
|
|
|
} |
2748
|
|
|
} |
2749
|
|
|
|
2750
|
|
|
/** |
2751
|
|
|
* Bulk action - Set Weight. |
2752
|
|
|
* @access private |
2753
|
|
|
* @param array $variations |
2754
|
|
|
* @param array $data |
2755
|
|
|
*/ |
2756
|
|
|
private static function variation_bulk_action_variable_weight( $variations, $data ) { |
|
|
|
|
2757
|
|
|
self::variation_bulk_set_meta( $variations, '_weight', wc_clean( $data['value'] ) ); |
2758
|
|
|
} |
2759
|
|
|
|
2760
|
|
|
/** |
2761
|
|
|
* Bulk action - Set Length. |
2762
|
|
|
* @access private |
2763
|
|
|
* @param array $variations |
2764
|
|
|
* @param array $data |
2765
|
|
|
*/ |
2766
|
|
|
private static function variation_bulk_action_variable_length( $variations, $data ) { |
|
|
|
|
2767
|
|
|
self::variation_bulk_set_meta( $variations, '_length', wc_clean( $data['value'] ) ); |
2768
|
|
|
} |
2769
|
|
|
|
2770
|
|
|
/** |
2771
|
|
|
* Bulk action - Set Width. |
2772
|
|
|
* @access private |
2773
|
|
|
* @param array $variations |
2774
|
|
|
* @param array $data |
2775
|
|
|
*/ |
2776
|
|
|
private static function variation_bulk_action_variable_width( $variations, $data ) { |
|
|
|
|
2777
|
|
|
self::variation_bulk_set_meta( $variations, '_width', wc_clean( $data['value'] ) ); |
2778
|
|
|
} |
2779
|
|
|
|
2780
|
|
|
/** |
2781
|
|
|
* Bulk action - Set Height. |
2782
|
|
|
* @access private |
2783
|
|
|
* @param array $variations |
2784
|
|
|
* @param array $data |
2785
|
|
|
*/ |
2786
|
|
|
private static function variation_bulk_action_variable_height( $variations, $data ) { |
|
|
|
|
2787
|
|
|
self::variation_bulk_set_meta( $variations, '_height', wc_clean( $data['value'] ) ); |
2788
|
|
|
} |
2789
|
|
|
|
2790
|
|
|
/** |
2791
|
|
|
* Bulk action - Set Download Limit. |
2792
|
|
|
* @access private |
2793
|
|
|
* @param array $variations |
2794
|
|
|
* @param array $data |
2795
|
|
|
*/ |
2796
|
|
|
private static function variation_bulk_action_variable_download_limit( $variations, $data ) { |
|
|
|
|
2797
|
|
|
self::variation_bulk_set_meta( $variations, '_download_limit', wc_clean( $data['value'] ) ); |
2798
|
|
|
} |
2799
|
|
|
|
2800
|
|
|
/** |
2801
|
|
|
* Bulk action - Set Download Expiry. |
2802
|
|
|
* @access private |
2803
|
|
|
* @param array $variations |
2804
|
|
|
* @param array $data |
2805
|
|
|
*/ |
2806
|
|
|
private static function variation_bulk_action_variable_download_expiry( $variations, $data ) { |
|
|
|
|
2807
|
|
|
self::variation_bulk_set_meta( $variations, '_download_expiry', wc_clean( $data['value'] ) ); |
2808
|
|
|
} |
2809
|
|
|
|
2810
|
|
|
/** |
2811
|
|
|
* Bulk action - Delete all. |
2812
|
|
|
* @access private |
2813
|
|
|
* @param array $variations |
2814
|
|
|
* @param array $data |
2815
|
|
|
*/ |
2816
|
|
|
private static function variation_bulk_action_delete_all( $variations, $data ) { |
|
|
|
|
2817
|
|
|
if ( isset( $data['allowed'] ) && 'true' === $data['allowed'] ) { |
2818
|
|
|
foreach ( $variations as $variation_id ) { |
2819
|
|
|
wp_delete_post( $variation_id ); |
2820
|
|
|
} |
2821
|
|
|
} |
2822
|
|
|
} |
2823
|
|
|
|
2824
|
|
|
/** |
2825
|
|
|
* Bulk action - Sale Schedule. |
2826
|
|
|
* @access private |
2827
|
|
|
* @param array $variations |
2828
|
|
|
* @param array $data |
2829
|
|
|
*/ |
2830
|
|
|
private static function variation_bulk_action_variable_sale_schedule( $variations, $data ) { |
|
|
|
|
2831
|
|
|
if ( ! isset( $data['date_from'] ) && ! isset( $data['date_to'] ) ) { |
2832
|
|
|
return; |
2833
|
|
|
} |
2834
|
|
|
|
2835
|
|
|
foreach ( $variations as $variation_id ) { |
2836
|
|
|
// Price fields |
2837
|
|
|
$regular_price = get_post_meta( $variation_id, '_regular_price', true ); |
2838
|
|
|
$sale_price = get_post_meta( $variation_id, '_sale_price', true ); |
2839
|
|
|
|
2840
|
|
|
// Date fields |
2841
|
|
|
$date_from = get_post_meta( $variation_id, '_sale_price_dates_from', true ); |
2842
|
|
|
$date_to = get_post_meta( $variation_id, '_sale_price_dates_to', true ); |
2843
|
|
|
|
2844
|
|
View Code Duplication |
if ( 'false' === $data['date_from'] ) { |
|
|
|
|
2845
|
|
|
$date_from = ! empty( $date_from ) ? date( 'Y-m-d', $date_from ) : ''; |
2846
|
|
|
} else { |
2847
|
|
|
$date_from = $data['date_from']; |
2848
|
|
|
} |
2849
|
|
|
|
2850
|
|
View Code Duplication |
if ( 'false' === $data['date_to'] ) { |
|
|
|
|
2851
|
|
|
$date_to = ! empty( $date_to ) ? date( 'Y-m-d', $date_to ) : ''; |
2852
|
|
|
} else { |
2853
|
|
|
$date_to = $data['date_to']; |
2854
|
|
|
} |
2855
|
|
|
|
2856
|
|
|
_wc_save_product_price( $variation_id, $regular_price, $sale_price, $date_from, $date_to ); |
2857
|
|
|
} |
2858
|
|
|
} |
2859
|
|
|
|
2860
|
|
|
/** |
2861
|
|
|
* Bulk action - Increase Regular Prices. |
2862
|
|
|
* @access private |
2863
|
|
|
* @param array $variations |
2864
|
|
|
* @param array $data |
2865
|
|
|
*/ |
2866
|
|
|
private static function variation_bulk_action_variable_regular_price_increase( $variations, $data ) { |
|
|
|
|
2867
|
|
|
self::variation_bulk_adjust_price( $variations, '_regular_price', '+', wc_clean( $data['value'] ) ); |
2868
|
|
|
} |
2869
|
|
|
|
2870
|
|
|
/** |
2871
|
|
|
* Bulk action - Decrease Regular Prices. |
2872
|
|
|
* @access private |
2873
|
|
|
* @param array $variations |
2874
|
|
|
* @param array $data |
2875
|
|
|
*/ |
2876
|
|
|
private static function variation_bulk_action_variable_regular_price_decrease( $variations, $data ) { |
|
|
|
|
2877
|
|
|
self::variation_bulk_adjust_price( $variations, '_regular_price', '-', wc_clean( $data['value'] ) ); |
2878
|
|
|
} |
2879
|
|
|
|
2880
|
|
|
/** |
2881
|
|
|
* Bulk action - Increase Sale Prices. |
2882
|
|
|
* @access private |
2883
|
|
|
* @param array $variations |
2884
|
|
|
* @param array $data |
2885
|
|
|
*/ |
2886
|
|
|
private static function variation_bulk_action_variable_sale_price_increase( $variations, $data ) { |
|
|
|
|
2887
|
|
|
self::variation_bulk_adjust_price( $variations, '_sale_price', '+', wc_clean( $data['value'] ) ); |
2888
|
|
|
} |
2889
|
|
|
|
2890
|
|
|
/** |
2891
|
|
|
* Bulk action - Decrease Sale Prices. |
2892
|
|
|
* @access private |
2893
|
|
|
* @param array $variations |
2894
|
|
|
* @param array $data |
2895
|
|
|
*/ |
2896
|
|
|
private static function variation_bulk_action_variable_sale_price_decrease( $variations, $data ) { |
|
|
|
|
2897
|
|
|
self::variation_bulk_adjust_price( $variations, '_sale_price', '-', wc_clean( $data['value'] ) ); |
2898
|
|
|
} |
2899
|
|
|
|
2900
|
|
|
/** |
2901
|
|
|
* Bulk action - Set Price. |
2902
|
|
|
* @access private |
2903
|
|
|
* @param array $variations |
2904
|
|
|
* @param string $operator + or - |
2905
|
|
|
* @param string $field price being adjusted |
2906
|
|
|
* @param string $value Price or Percent |
2907
|
|
|
*/ |
2908
|
|
|
private static function variation_bulk_adjust_price( $variations, $field, $operator, $value ) { |
2909
|
|
|
foreach ( $variations as $variation_id ) { |
2910
|
|
|
// Get existing data |
2911
|
|
|
$_regular_price = get_post_meta( $variation_id, '_regular_price', true ); |
2912
|
|
|
$_sale_price = get_post_meta( $variation_id, '_sale_price', true ); |
2913
|
|
|
$date_from = get_post_meta( $variation_id, '_sale_price_dates_from', true ); |
2914
|
|
|
$date_to = get_post_meta( $variation_id, '_sale_price_dates_to', true ); |
2915
|
|
|
$date_from = ! empty( $date_from ) ? date( 'Y-m-d', $date_from ) : ''; |
2916
|
|
|
$date_to = ! empty( $date_to ) ? date( 'Y-m-d', $date_to ) : ''; |
2917
|
|
|
|
2918
|
|
|
if ( '%' === substr( $value, -1 ) ) { |
2919
|
|
|
$percent = wc_format_decimal( substr( $value, 0, -1 ) ); |
2920
|
|
|
$$field += ( ( $$field / 100 ) * $percent ) * "{$operator}1"; |
2921
|
|
|
} else { |
2922
|
|
|
$$field += $value * "{$operator}1"; |
2923
|
|
|
} |
2924
|
|
|
_wc_save_product_price( $variation_id, $_regular_price, $_sale_price, $date_from, $date_to ); |
2925
|
|
|
} |
2926
|
|
|
} |
2927
|
|
|
|
2928
|
|
|
/** |
2929
|
|
|
* Bulk action - Set Meta. |
2930
|
|
|
* @access private |
2931
|
|
|
* @param array $variations |
2932
|
|
|
* @param string $field |
2933
|
|
|
* @param string $value |
2934
|
|
|
*/ |
2935
|
|
|
private static function variation_bulk_set_meta( $variations, $field, $value ) { |
2936
|
|
|
foreach ( $variations as $variation_id ) { |
2937
|
|
|
update_post_meta( $variation_id, $field, $value ); |
2938
|
|
|
} |
2939
|
|
|
} |
2940
|
|
|
|
2941
|
|
|
|
2942
|
|
|
/** |
2943
|
|
|
* Bulk edit variations via AJAX. |
2944
|
|
|
*/ |
2945
|
|
|
public static function bulk_edit_variations() { |
2946
|
|
|
ob_start(); |
2947
|
|
|
|
2948
|
|
|
check_ajax_referer( 'bulk-edit-variations', 'security' ); |
2949
|
|
|
|
2950
|
|
|
// Check permissions again and make sure we have what we need |
2951
|
|
View Code Duplication |
if ( ! current_user_can( 'edit_products' ) || empty( $_POST['product_id'] ) || empty( $_POST['bulk_action'] ) ) { |
|
|
|
|
2952
|
|
|
die( -1 ); |
2953
|
|
|
} |
2954
|
|
|
|
2955
|
|
|
$product_id = absint( $_POST['product_id'] ); |
2956
|
|
|
$bulk_action = wc_clean( $_POST['bulk_action'] ); |
2957
|
|
|
$data = ! empty( $_POST['data'] ) ? array_map( 'wc_clean', $_POST['data'] ) : array(); |
2958
|
|
|
$variations = array(); |
2959
|
|
|
|
2960
|
|
|
if ( apply_filters( 'woocommerce_bulk_edit_variations_need_children', true ) ) { |
2961
|
|
|
$variations = get_posts( array( |
2962
|
|
|
'post_parent' => $product_id, |
2963
|
|
|
'posts_per_page' => -1, |
2964
|
|
|
'post_type' => 'product_variation', |
2965
|
|
|
'fields' => 'ids', |
2966
|
|
|
'post_status' => array( 'publish', 'private' ) |
2967
|
|
|
) ); |
2968
|
|
|
} |
2969
|
|
|
|
2970
|
|
|
if ( method_exists( __CLASS__, "variation_bulk_action_$bulk_action" ) ) { |
2971
|
|
|
call_user_func( array( __CLASS__, "variation_bulk_action_$bulk_action" ), $variations, $data ); |
2972
|
|
|
} else { |
2973
|
|
|
do_action( 'woocommerce_bulk_edit_variations_default', $bulk_action, $data, $product_id, $variations ); |
2974
|
|
|
} |
2975
|
|
|
|
2976
|
|
|
do_action( 'woocommerce_bulk_edit_variations', $bulk_action, $data, $product_id, $variations ); |
2977
|
|
|
|
2978
|
|
|
// Sync and update transients |
2979
|
|
|
WC_Product_Variable::sync( $product_id ); |
2980
|
|
|
wc_delete_product_transients( $product_id ); |
2981
|
|
|
die(); |
2982
|
|
|
} |
2983
|
|
|
|
2984
|
|
|
/** |
2985
|
|
|
* Handle submissions from assets/js/settings-views-html-settings-tax.js Backbone model. |
2986
|
|
|
*/ |
2987
|
|
|
public static function tax_rates_save_changes() { |
2988
|
|
|
if ( ! isset( $_POST['wc_tax_nonce'], $_POST['changes'] ) ) { |
2989
|
|
|
wp_send_json_error( 'missing_fields' ); |
2990
|
|
|
exit; |
2991
|
|
|
} |
2992
|
|
|
|
2993
|
|
|
$current_class = ! empty( $_POST['current_class'] ) ? $_POST['current_class'] : ''; // This is sanitized seven lines later. |
2994
|
|
|
|
2995
|
|
|
if ( ! wp_verify_nonce( $_POST['wc_tax_nonce'], 'wc_tax_nonce-class:' . $current_class ) ) { |
2996
|
|
|
wp_send_json_error( 'bad_nonce' ); |
2997
|
|
|
exit; |
2998
|
|
|
} |
2999
|
|
|
|
3000
|
|
|
$current_class = WC_Tax::format_tax_rate_class( $current_class ); |
3001
|
|
|
|
3002
|
|
|
// Check User Caps |
3003
|
|
|
if ( ! current_user_can( 'manage_woocommerce' ) ) { |
3004
|
|
|
wp_send_json_error( 'missing_capabilities' ); |
3005
|
|
|
exit; |
3006
|
|
|
} |
3007
|
|
|
|
3008
|
|
|
$changes = $_POST['changes']; |
3009
|
|
|
foreach ( $changes as $tax_rate_id => $data ) { |
3010
|
|
|
if ( isset( $data['deleted'] ) ) { |
3011
|
|
|
if ( isset( $data['newRow'] ) ) { |
3012
|
|
|
// So the user added and deleted a new row. |
3013
|
|
|
// That's fine, it's not in the database anyways. NEXT! |
3014
|
|
|
continue; |
3015
|
|
|
} |
3016
|
|
|
WC_Tax::_delete_tax_rate( $tax_rate_id ); |
3017
|
|
|
} |
3018
|
|
|
|
3019
|
|
|
$tax_rate = array_intersect_key( $data, array( |
3020
|
|
|
'tax_rate_country' => 1, |
3021
|
|
|
'tax_rate_state' => 1, |
3022
|
|
|
'tax_rate' => 1, |
3023
|
|
|
'tax_rate_name' => 1, |
3024
|
|
|
'tax_rate_priority' => 1, |
3025
|
|
|
'tax_rate_compound' => 1, |
3026
|
|
|
'tax_rate_shipping' => 1, |
3027
|
|
|
'tax_rate_order' => 1, |
3028
|
|
|
) ); |
3029
|
|
|
|
3030
|
|
|
if ( isset( $data['newRow'] ) ) { |
3031
|
|
|
// Hurrah, shiny and new! |
3032
|
|
|
$tax_rate['tax_rate_class'] = $current_class; |
3033
|
|
|
$tax_rate_id = WC_Tax::_insert_tax_rate( $tax_rate ); |
3034
|
|
|
} else { |
3035
|
|
|
// Updating an existing rate ... |
3036
|
|
|
if ( ! empty( $tax_rate ) ) { |
3037
|
|
|
WC_Tax::_update_tax_rate( $tax_rate_id, $tax_rate ); |
3038
|
|
|
} |
3039
|
|
|
} |
3040
|
|
|
|
3041
|
|
|
if ( isset( $data['postcode'] ) ) { |
3042
|
|
|
WC_Tax::_update_tax_rate_postcodes( $tax_rate_id, array_map( 'wc_clean', $data['postcode'] ) ); |
|
|
|
|
3043
|
|
|
} |
3044
|
|
|
if ( isset( $data['city'] ) ) { |
3045
|
|
|
WC_Tax::_update_tax_rate_cities( $tax_rate_id, array_map( 'wc_clean', $data['city'] ) ); |
|
|
|
|
3046
|
|
|
} |
3047
|
|
|
} |
3048
|
|
|
|
3049
|
|
|
wp_send_json_success( array( |
3050
|
|
|
'rates' => WC_Tax::get_rates_for_tax_class( $current_class ), |
3051
|
|
|
) ); |
3052
|
|
|
} |
3053
|
|
|
|
3054
|
|
|
/** |
3055
|
|
|
* Handle submissions from assets/js/wc-shipping-zones.js Backbone model. |
3056
|
|
|
*/ |
3057
|
|
|
public static function shipping_zones_save_changes() { |
3058
|
|
|
if ( ! isset( $_POST['wc_shipping_zones_nonce'], $_POST['changes'] ) ) { |
3059
|
|
|
wp_send_json_error( 'missing_fields' ); |
3060
|
|
|
exit; |
3061
|
|
|
} |
3062
|
|
|
|
3063
|
|
|
if ( ! wp_verify_nonce( $_POST['wc_shipping_zones_nonce'], 'wc_shipping_zones_nonce' ) ) { |
3064
|
|
|
wp_send_json_error( 'bad_nonce' ); |
3065
|
|
|
exit; |
3066
|
|
|
} |
3067
|
|
|
|
3068
|
|
|
// Check User Caps |
3069
|
|
|
if ( ! current_user_can( 'manage_woocommerce' ) ) { |
3070
|
|
|
wp_send_json_error( 'missing_capabilities' ); |
3071
|
|
|
exit; |
3072
|
|
|
} |
3073
|
|
|
|
3074
|
|
|
$changes = $_POST['changes']; |
3075
|
|
|
foreach ( $changes as $zone_id => $data ) { |
3076
|
|
|
if ( isset( $data['deleted'] ) ) { |
3077
|
|
|
if ( isset( $data['newRow'] ) ) { |
3078
|
|
|
// So the user added and deleted a new row. |
3079
|
|
|
// That's fine, it's not in the database anyways. NEXT! |
3080
|
|
|
continue; |
3081
|
|
|
} |
3082
|
|
|
WC_Shipping_Zones::delete_zone( $zone_id ); |
3083
|
|
|
continue; |
3084
|
|
|
} |
3085
|
|
|
|
3086
|
|
|
$zone_data = array_intersect_key( $data, array( |
3087
|
|
|
'zone_id' => 1, |
3088
|
|
|
'zone_name' => 1, |
3089
|
|
|
'zone_order' => 1, |
3090
|
|
|
'zone_locations' => 1, |
3091
|
|
|
'zone_postcodes' => 1 |
3092
|
|
|
) ); |
3093
|
|
|
|
3094
|
|
|
if ( isset( $zone_data['zone_id'] ) ) { |
3095
|
|
|
$zone = new WC_Shipping_Zone( $zone_data['zone_id'] ); |
3096
|
|
|
|
3097
|
|
|
if ( isset( $zone_data['zone_name'] ) ) { |
3098
|
|
|
$zone->set_zone_name( $zone_data['zone_name'] ); |
3099
|
|
|
} |
3100
|
|
|
|
3101
|
|
|
if ( isset( $zone_data['zone_order'] ) ) { |
3102
|
|
|
$zone->set_zone_order( $zone_data['zone_order'] ); |
3103
|
|
|
} |
3104
|
|
|
|
3105
|
|
|
if ( isset( $zone_data['zone_locations'] ) ) { |
3106
|
|
|
$zone->clear_locations( array( 'state', 'country', 'continent' ) ); |
3107
|
|
|
$locations = array_filter( array_map( 'wc_clean', (array) $zone_data['zone_locations'] ) ); |
3108
|
|
|
foreach ( $locations as $location ) { |
3109
|
|
|
// Each posted location will be in the format type:code |
3110
|
|
|
$location_parts = explode( ':', $location ); |
3111
|
|
|
switch ( $location_parts[0] ) { |
3112
|
|
|
case 'state' : |
3113
|
|
|
$zone->add_location( $location_parts[1] . ':' . $location_parts[2], 'state' ); |
3114
|
|
|
break; |
3115
|
|
|
case 'country' : |
3116
|
|
|
$zone->add_location( $location_parts[1], 'country' ); |
3117
|
|
|
break; |
3118
|
|
|
case 'continent' : |
3119
|
|
|
$zone->add_location( $location_parts[1], 'continent' ); |
3120
|
|
|
break; |
3121
|
|
|
} |
3122
|
|
|
} |
3123
|
|
|
} |
3124
|
|
|
|
3125
|
|
|
if ( isset( $zone_data['zone_postcodes'] ) ) { |
3126
|
|
|
$zone->clear_locations( 'postcode' ); |
3127
|
|
|
$postcodes = array_filter( array_map( 'strtoupper', array_map( 'wc_clean', explode( "\n", $zone_data['zone_postcodes'] ) ) ) ); |
3128
|
|
|
foreach ( $postcodes as $postcode ) { |
3129
|
|
|
$zone->add_location( $postcode, 'postcode' ); |
3130
|
|
|
} |
3131
|
|
|
} |
3132
|
|
|
|
3133
|
|
|
$zone->save(); |
3134
|
|
|
} |
3135
|
|
|
} |
3136
|
|
|
|
3137
|
|
|
wp_send_json_success( array( |
3138
|
|
|
'zones' => WC_Shipping_Zones::get_zones() |
3139
|
|
|
) ); |
3140
|
|
|
} |
3141
|
|
|
|
3142
|
|
|
/** |
3143
|
|
|
* Handle submissions from assets/js/wc-shipping-zone-methods.js Backbone model. |
3144
|
|
|
*/ |
3145
|
|
View Code Duplication |
public static function shipping_zone_add_method() { |
|
|
|
|
3146
|
|
|
if ( ! isset( $_POST['wc_shipping_zones_nonce'], $_POST['zone_id'], $_POST['method_id'] ) ) { |
3147
|
|
|
wp_send_json_error( 'missing_fields' ); |
3148
|
|
|
exit; |
3149
|
|
|
} |
3150
|
|
|
|
3151
|
|
|
if ( ! wp_verify_nonce( $_POST['wc_shipping_zones_nonce'], 'wc_shipping_zones_nonce' ) ) { |
3152
|
|
|
wp_send_json_error( 'bad_nonce' ); |
3153
|
|
|
exit; |
3154
|
|
|
} |
3155
|
|
|
|
3156
|
|
|
// Check User Caps |
3157
|
|
|
if ( ! current_user_can( 'manage_woocommerce' ) ) { |
3158
|
|
|
wp_send_json_error( 'missing_capabilities' ); |
3159
|
|
|
exit; |
3160
|
|
|
} |
3161
|
|
|
|
3162
|
|
|
$zone_id = absint( $_POST['zone_id'] ); |
3163
|
|
|
$zone = WC_Shipping_Zones::get_zone( $zone_id ); |
3164
|
|
|
$instance_id = $zone->add_shipping_method( wc_clean( $_POST['method_id'] ) ); |
3165
|
|
|
|
3166
|
|
|
wp_send_json_success( array( |
3167
|
|
|
'instance_id' => $instance_id, |
3168
|
|
|
'zone_id' => $zone_id, |
3169
|
|
|
'methods' => $zone->get_shipping_methods() |
3170
|
|
|
) ); |
3171
|
|
|
} |
3172
|
|
|
|
3173
|
|
|
/** |
3174
|
|
|
* Handle submissions from assets/js/wc-shipping-zone-methods.js Backbone model. |
3175
|
|
|
*/ |
3176
|
|
|
public static function shipping_zone_methods_save_changes() { |
3177
|
|
|
if ( ! isset( $_POST['wc_shipping_zones_nonce'], $_POST['zone_id'], $_POST['changes'] ) ) { |
3178
|
|
|
wp_send_json_error( 'missing_fields' ); |
3179
|
|
|
exit; |
3180
|
|
|
} |
3181
|
|
|
|
3182
|
|
|
if ( ! wp_verify_nonce( $_POST['wc_shipping_zones_nonce'], 'wc_shipping_zones_nonce' ) ) { |
3183
|
|
|
wp_send_json_error( 'bad_nonce' ); |
3184
|
|
|
exit; |
3185
|
|
|
} |
3186
|
|
|
|
3187
|
|
|
if ( ! current_user_can( 'manage_woocommerce' ) ) { |
3188
|
|
|
wp_send_json_error( 'missing_capabilities' ); |
3189
|
|
|
exit; |
3190
|
|
|
} |
3191
|
|
|
|
3192
|
|
|
global $wpdb; |
3193
|
|
|
|
3194
|
|
|
$zone_id = absint( $_POST['zone_id'] ); |
3195
|
|
|
$zone = new WC_Shipping_Zone( $zone_id ); |
3196
|
|
|
$changes = $_POST['changes']; |
3197
|
|
|
|
3198
|
|
|
foreach ( $changes as $instance_id => $data ) { |
3199
|
|
|
$method_id = $wpdb->get_var( $wpdb->prepare( "SELECT method_id FROM {$wpdb->prefix}woocommerce_shipping_zone_methods WHERE instance_id = %d", $instance_id ) ); |
3200
|
|
|
|
3201
|
|
|
if ( isset( $data['deleted'] ) ) { |
3202
|
|
|
if ( $wpdb->delete( "{$wpdb->prefix}woocommerce_shipping_zone_methods", array( 'instance_id' => $instance_id ) ) ) { |
3203
|
|
|
do_action( 'woocommerce_shipping_zone_method_deleted', $instance_id, $method_id, $zone_id ); |
3204
|
|
|
} |
3205
|
|
|
continue; |
3206
|
|
|
} |
3207
|
|
|
|
3208
|
|
|
$method_data = array_intersect_key( $data, array( |
3209
|
|
|
'method_order' => 1, |
3210
|
|
|
'enabled' => 1 |
3211
|
|
|
) ); |
3212
|
|
|
|
3213
|
|
|
if ( isset( $method_data['method_order'] ) ) { |
3214
|
|
|
$wpdb->update( "{$wpdb->prefix}woocommerce_shipping_zone_methods", array( 'method_order' => absint( $method_data['method_order'] ) ), array( 'instance_id' => absint( $instance_id ) ) ); |
3215
|
|
|
} |
3216
|
|
|
|
3217
|
|
|
if ( isset( $method_data['enabled'] ) ) { |
3218
|
|
|
$is_enabled = absint( 'yes' === $method_data['enabled'] ); |
3219
|
|
|
if ( $wpdb->update( "{$wpdb->prefix}woocommerce_shipping_zone_methods", array( 'is_enabled' => $is_enabled ), array( 'instance_id' => absint( $instance_id ) ) ) ) { |
3220
|
|
|
do_action( 'woocommerce_shipping_zone_method_status_toggled', $instance_id, $method_id, $zone_id, $is_enabled ); |
3221
|
|
|
} |
3222
|
|
|
} |
3223
|
|
|
} |
3224
|
|
|
|
3225
|
|
|
wp_send_json_success( array( |
3226
|
|
|
'methods' => $zone->get_shipping_methods() |
3227
|
|
|
) ); |
3228
|
|
|
} |
3229
|
|
|
|
3230
|
|
|
/** |
3231
|
|
|
* Save method settings |
3232
|
|
|
*/ |
3233
|
|
View Code Duplication |
public static function shipping_zone_methods_save_settings() { |
|
|
|
|
3234
|
|
|
if ( ! isset( $_POST['wc_shipping_zones_nonce'], $_POST['instance_id'], $_POST['data'] ) ) { |
3235
|
|
|
wp_send_json_error( 'missing_fields' ); |
3236
|
|
|
exit; |
3237
|
|
|
} |
3238
|
|
|
|
3239
|
|
|
if ( ! wp_verify_nonce( $_POST['wc_shipping_zones_nonce'], 'wc_shipping_zones_nonce' ) ) { |
3240
|
|
|
wp_send_json_error( 'bad_nonce' ); |
3241
|
|
|
exit; |
3242
|
|
|
} |
3243
|
|
|
|
3244
|
|
|
if ( ! current_user_can( 'manage_woocommerce' ) ) { |
3245
|
|
|
wp_send_json_error( 'missing_capabilities' ); |
3246
|
|
|
exit; |
3247
|
|
|
} |
3248
|
|
|
|
3249
|
|
|
$instance_id = absint( $_POST['instance_id'] ); |
3250
|
|
|
$zone = WC_Shipping_Zones::get_zone_by( 'instance_id', $instance_id ); |
3251
|
|
|
$shipping_method = WC_Shipping_Zones::get_shipping_method( $instance_id ); |
3252
|
|
|
$shipping_method->set_post_data( $_POST['data'] ); |
3253
|
|
|
$shipping_method->process_admin_options(); |
3254
|
|
|
|
3255
|
|
|
wp_send_json_success( array( |
3256
|
|
|
'methods' => $zone->get_shipping_methods(), |
3257
|
|
|
'errors' => $shipping_method->get_errors(), |
3258
|
|
|
) ); |
3259
|
|
|
} |
3260
|
|
|
|
3261
|
|
|
/** |
3262
|
|
|
* Handle submissions from assets/js/wc-shipping-classes.js Backbone model. |
3263
|
|
|
*/ |
3264
|
|
|
public static function shipping_classes_save_changes() { |
3265
|
|
|
if ( ! isset( $_POST['wc_shipping_classes_nonce'], $_POST['changes'] ) ) { |
3266
|
|
|
wp_send_json_error( 'missing_fields' ); |
3267
|
|
|
exit; |
3268
|
|
|
} |
3269
|
|
|
|
3270
|
|
|
if ( ! wp_verify_nonce( $_POST['wc_shipping_classes_nonce'], 'wc_shipping_classes_nonce' ) ) { |
3271
|
|
|
wp_send_json_error( 'bad_nonce' ); |
3272
|
|
|
exit; |
3273
|
|
|
} |
3274
|
|
|
|
3275
|
|
|
if ( ! current_user_can( 'manage_woocommerce' ) ) { |
3276
|
|
|
wp_send_json_error( 'missing_capabilities' ); |
3277
|
|
|
exit; |
3278
|
|
|
} |
3279
|
|
|
|
3280
|
|
|
$changes = $_POST['changes']; |
3281
|
|
|
|
3282
|
|
|
foreach ( $changes as $term_id => $data ) { |
3283
|
|
|
$term_id = absint( $term_id ); |
3284
|
|
|
|
3285
|
|
|
if ( isset( $data['deleted'] ) ) { |
3286
|
|
|
if ( isset( $data['newRow'] ) ) { |
3287
|
|
|
// So the user added and deleted a new row. |
3288
|
|
|
// That's fine, it's not in the database anyways. NEXT! |
3289
|
|
|
continue; |
3290
|
|
|
} |
3291
|
|
|
wp_delete_term( $term_id, 'product_shipping_class' ); |
3292
|
|
|
continue; |
3293
|
|
|
} |
3294
|
|
|
|
3295
|
|
|
$update_args = array(); |
3296
|
|
|
|
3297
|
|
|
if ( isset( $data['name'] ) ) { |
3298
|
|
|
$update_args['name'] = wc_clean( $data['name'] ); |
3299
|
|
|
} |
3300
|
|
|
|
3301
|
|
|
if ( isset( $data['slug'] ) ) { |
3302
|
|
|
$update_args['slug'] = wc_clean( $data['slug'] ); |
3303
|
|
|
} |
3304
|
|
|
|
3305
|
|
|
if ( isset( $data['description'] ) ) { |
3306
|
|
|
$update_args['description'] = wc_clean( $data['description'] ); |
3307
|
|
|
} |
3308
|
|
|
|
3309
|
|
|
if ( isset( $data['newRow'] ) ) { |
3310
|
|
|
$update_args = array_filter( $update_args ); |
3311
|
|
|
if ( empty( $update_args['name'] ) ) { |
3312
|
|
|
continue; |
3313
|
|
|
} |
3314
|
|
|
$term_id = wp_insert_term( $update_args['name'], 'product_shipping_class', $update_args ); |
3315
|
|
|
} else { |
3316
|
|
|
wp_update_term( $term_id, 'product_shipping_class', $update_args ); |
3317
|
|
|
} |
3318
|
|
|
|
3319
|
|
|
do_action( 'woocommerce_shipping_classes_save_class', $term_id, $data ); |
3320
|
|
|
} |
3321
|
|
|
|
3322
|
|
|
$wc_shipping = WC_Shipping::instance(); |
3323
|
|
|
|
3324
|
|
|
wp_send_json_success( array( |
3325
|
|
|
'shipping_classes' => $wc_shipping->get_shipping_classes() |
3326
|
|
|
) ); |
3327
|
|
|
} |
3328
|
|
|
} |
3329
|
|
|
|
3330
|
|
|
WC_AJAX::init(); |
3331
|
|
|
|
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.