1
|
|
|
<?php |
2
|
|
|
/** |
3
|
|
|
* REST API Orders controller |
4
|
|
|
* |
5
|
|
|
* Handles requests to the /orders endpoint. |
6
|
|
|
* |
7
|
|
|
* @author WooThemes |
8
|
|
|
* @category API |
9
|
|
|
* @package WooCommerce/API |
10
|
|
|
* @since 2.6.0 |
11
|
|
|
*/ |
12
|
|
|
|
13
|
|
|
if ( ! defined( 'ABSPATH' ) ) { |
14
|
|
|
exit; |
15
|
|
|
} |
16
|
|
|
|
17
|
|
|
/** |
18
|
|
|
* REST API Orders controller class. |
19
|
|
|
* |
20
|
|
|
* @package WooCommerce/API |
21
|
|
|
* @extends WC_REST_Posts_Controller |
22
|
|
|
*/ |
23
|
|
|
class WC_REST_Orders_Controller extends WC_REST_Posts_Controller { |
24
|
|
|
|
25
|
|
|
/** |
26
|
|
|
* Endpoint namespace. |
27
|
|
|
* |
28
|
|
|
* @var string |
29
|
|
|
*/ |
30
|
|
|
protected $namespace = 'wc/v1'; |
31
|
|
|
|
32
|
|
|
/** |
33
|
|
|
* Route base. |
34
|
|
|
* |
35
|
|
|
* @var string |
36
|
|
|
*/ |
37
|
|
|
protected $rest_base = 'orders'; |
38
|
|
|
|
39
|
|
|
/** |
40
|
|
|
* Post type. |
41
|
|
|
* |
42
|
|
|
* @var string |
43
|
|
|
*/ |
44
|
|
|
protected $post_type = 'shop_order'; |
45
|
|
|
|
46
|
|
|
/** |
47
|
|
|
* Initialize orders actions. |
48
|
|
|
*/ |
49
|
|
|
public function __construct() { |
50
|
|
|
add_filter( "woocommerce_rest_{$this->post_type}_query", array( $this, 'query_args' ), 10, 2 ); |
51
|
|
|
} |
52
|
|
|
|
53
|
|
|
/** |
54
|
|
|
* Register the routes for orders. |
55
|
|
|
*/ |
56
|
|
View Code Duplication |
public function register_routes() { |
|
|
|
|
57
|
|
|
register_rest_route( $this->namespace, '/' . $this->rest_base, array( |
58
|
|
|
array( |
59
|
|
|
'methods' => WP_REST_Server::READABLE, |
60
|
|
|
'callback' => array( $this, 'get_items' ), |
61
|
|
|
'permission_callback' => array( $this, 'get_items_permissions_check' ), |
62
|
|
|
'args' => $this->get_collection_params(), |
63
|
|
|
), |
64
|
|
|
array( |
65
|
|
|
'methods' => WP_REST_Server::CREATABLE, |
66
|
|
|
'callback' => array( $this, 'create_item' ), |
67
|
|
|
'permission_callback' => array( $this, 'create_item_permissions_check' ), |
68
|
|
|
'args' => $this->get_endpoint_args_for_item_schema( WP_REST_Server::CREATABLE ), |
69
|
|
|
), |
70
|
|
|
'schema' => array( $this, 'get_public_item_schema' ), |
71
|
|
|
) ); |
72
|
|
|
|
73
|
|
|
register_rest_route( $this->namespace, '/' . $this->rest_base . '/(?P<id>[\d]+)', array( |
74
|
|
|
array( |
75
|
|
|
'methods' => WP_REST_Server::READABLE, |
76
|
|
|
'callback' => array( $this, 'get_item' ), |
77
|
|
|
'permission_callback' => array( $this, 'get_item_permissions_check' ), |
78
|
|
|
'args' => array( |
79
|
|
|
'context' => $this->get_context_param( array( 'default' => 'view' ) ), |
80
|
|
|
), |
81
|
|
|
), |
82
|
|
|
array( |
83
|
|
|
'methods' => WP_REST_Server::EDITABLE, |
84
|
|
|
'callback' => array( $this, 'update_item' ), |
85
|
|
|
'permission_callback' => array( $this, 'update_item_permissions_check' ), |
86
|
|
|
'args' => $this->get_endpoint_args_for_item_schema( WP_REST_Server::EDITABLE ), |
87
|
|
|
), |
88
|
|
|
array( |
89
|
|
|
'methods' => WP_REST_Server::DELETABLE, |
90
|
|
|
'callback' => array( $this, 'delete_item' ), |
91
|
|
|
'permission_callback' => array( $this, 'delete_item_permissions_check' ), |
92
|
|
|
'args' => array( |
93
|
|
|
'force' => array( |
94
|
|
|
'default' => false, |
95
|
|
|
'description' => __( 'Whether to bypass trash and force deletion.', 'woocommerce' ), |
96
|
|
|
), |
97
|
|
|
'reassign' => array(), |
98
|
|
|
), |
99
|
|
|
), |
100
|
|
|
'schema' => array( $this, 'get_public_item_schema' ), |
101
|
|
|
) ); |
102
|
|
|
|
103
|
|
|
register_rest_route( $this->namespace, '/' . $this->rest_base . '/batch', array( |
104
|
|
|
array( |
105
|
|
|
'methods' => WP_REST_Server::EDITABLE, |
106
|
|
|
'callback' => array( $this, 'batch_items' ), |
107
|
|
|
'permission_callback' => array( $this, 'batch_items_permissions_check' ), |
108
|
|
|
'args' => $this->get_endpoint_args_for_item_schema( WP_REST_Server::EDITABLE ), |
109
|
|
|
), |
110
|
|
|
'schema' => array( $this, 'get_public_batch_schema' ), |
111
|
|
|
) ); |
112
|
|
|
} |
113
|
|
|
|
114
|
|
|
/** |
115
|
|
|
* Prepare a single order output for response. |
116
|
|
|
* |
117
|
|
|
* @param WP_Post $post Post object. |
118
|
|
|
* @param WP_REST_Request $request Request object. |
119
|
|
|
* @return WP_REST_Response $data |
120
|
|
|
*/ |
121
|
|
|
public function prepare_item_for_response( $post, $request ) { |
122
|
|
|
global $wpdb; |
123
|
|
|
|
124
|
|
|
$order = wc_get_order( $post ); |
125
|
|
|
$dp = $request['dp']; |
126
|
|
|
|
127
|
|
|
$data = array( |
128
|
|
|
'id' => $order->id, |
129
|
|
|
'parent_id' => $post->post_parent, |
130
|
|
|
'status' => $order->get_status(), |
131
|
|
|
'order_key' => $order->order_key, |
132
|
|
|
'currency' => $order->get_order_currency(), |
133
|
|
|
'version' => $order->order_version, |
134
|
|
|
'prices_include_tax' => $order->prices_include_tax, |
135
|
|
|
'date_created' => wc_rest_prepare_date_response( $post->post_date_gmt ), |
136
|
|
|
'date_modified' => wc_rest_prepare_date_response( $post->post_modified_gmt ), |
137
|
|
|
'customer_id' => $order->get_user_id(), |
138
|
|
|
'discount_total' => wc_format_decimal( $order->get_total_discount(), $dp ), |
139
|
|
|
'discount_tax' => wc_format_decimal( $order->cart_discount_tax, $dp ), |
140
|
|
|
'shipping_total' => wc_format_decimal( $order->get_total_shipping(), $dp ), |
141
|
|
|
'shipping_tax' => wc_format_decimal( $order->get_shipping_tax(), $dp ), |
142
|
|
|
'cart_tax' => wc_format_decimal( $order->get_cart_tax(), $dp ), |
143
|
|
|
'total' => wc_format_decimal( $order->get_total(), $dp ), |
144
|
|
|
'total_tax' => wc_format_decimal( $order->get_total_tax(), $dp ), |
145
|
|
|
'billing' => array(), |
146
|
|
|
'shipping' => array(), |
147
|
|
|
'payment_method' => $order->payment_method, |
148
|
|
|
'payment_method_title' => $order->payment_method_title, |
149
|
|
|
'transaction_id' => $order->get_transaction_id(), |
150
|
|
|
'customer_ip_address' => $order->customer_ip_address, |
151
|
|
|
'customer_user_agent' => $order->customer_user_agent, |
152
|
|
|
'created_via' => $order->created_via, |
153
|
|
|
'customer_note' => $order->customer_note, |
154
|
|
|
'date_completed' => wc_rest_prepare_date_response( $order->completed_date ), |
155
|
|
|
'date_paid' => $order->paid_date, |
156
|
|
|
'cart_hash' => $order->cart_hash, |
157
|
|
|
'line_items' => array(), |
158
|
|
|
'tax_lines' => array(), |
159
|
|
|
'shipping_lines' => array(), |
160
|
|
|
'fee_lines' => array(), |
161
|
|
|
'coupon_lines' => array(), |
162
|
|
|
'refunds' => array(), |
163
|
|
|
); |
164
|
|
|
|
165
|
|
|
// Add addresses. |
166
|
|
|
$data['billing'] = $order->get_address( 'billing' ); |
167
|
|
|
$data['shipping'] = $order->get_address( 'shipping' ); |
168
|
|
|
|
169
|
|
|
// Add line items. |
170
|
|
View Code Duplication |
foreach ( $order->get_items() as $item_id => $item ) { |
|
|
|
|
171
|
|
|
$product = $order->get_product_from_item( $item ); |
172
|
|
|
$product_id = 0; |
173
|
|
|
$variation_id = 0; |
174
|
|
|
$product_sku = null; |
175
|
|
|
|
176
|
|
|
// Check if the product exists. |
177
|
|
|
if ( is_object( $product ) ) { |
178
|
|
|
$product_id = $product->id; |
179
|
|
|
$variation_id = $product->variation_id; |
180
|
|
|
$product_sku = $product->get_sku(); |
181
|
|
|
} |
182
|
|
|
|
183
|
|
|
$meta = new WC_Order_Item_Meta( $item, $product ); |
184
|
|
|
|
185
|
|
|
$item_meta = array(); |
186
|
|
|
|
187
|
|
|
$hideprefix = 'true' === $request['all_item_meta'] ? null : '_'; |
188
|
|
|
|
189
|
|
|
foreach ( $meta->get_formatted( $hideprefix ) as $meta_key => $formatted_meta ) { |
190
|
|
|
$item_meta[] = array( |
191
|
|
|
'key' => $formatted_meta['key'], |
192
|
|
|
'label' => $formatted_meta['label'], |
193
|
|
|
'value' => $formatted_meta['value'], |
194
|
|
|
); |
195
|
|
|
} |
196
|
|
|
|
197
|
|
|
$line_item = array( |
198
|
|
|
'id' => $item_id, |
199
|
|
|
'name' => $item['name'], |
200
|
|
|
'sku' => $product_sku, |
201
|
|
|
'product_id' => (int) $product_id, |
202
|
|
|
'variation_id' => (int) $variation_id, |
203
|
|
|
'quantity' => wc_stock_amount( $item['qty'] ), |
204
|
|
|
'tax_class' => ! empty( $item['tax_class'] ) ? $item['tax_class'] : '', |
205
|
|
|
'price' => wc_format_decimal( $order->get_item_total( $item, false, false ), $dp ), |
206
|
|
|
'subtotal' => wc_format_decimal( $order->get_line_subtotal( $item, false, false ), $dp ), |
207
|
|
|
'subtotal_tax' => wc_format_decimal( $item['line_subtotal_tax'], $dp ), |
208
|
|
|
'total' => wc_format_decimal( $order->get_line_total( $item, false, false ), $dp ), |
209
|
|
|
'total_tax' => wc_format_decimal( $item['line_tax'], $dp ), |
210
|
|
|
'taxes' => array(), |
211
|
|
|
'meta' => $item_meta, |
212
|
|
|
); |
213
|
|
|
|
214
|
|
|
$item_line_taxes = maybe_unserialize( $item['line_tax_data'] ); |
215
|
|
|
if ( isset( $item_line_taxes['total'] ) ) { |
216
|
|
|
$line_tax = array(); |
217
|
|
|
|
218
|
|
|
foreach ( $item_line_taxes['total'] as $tax_rate_id => $tax ) { |
219
|
|
|
$line_tax[ $tax_rate_id ] = array( |
220
|
|
|
'id' => $tax_rate_id, |
221
|
|
|
'total' => $tax, |
222
|
|
|
'subtotal' => '', |
223
|
|
|
); |
224
|
|
|
} |
225
|
|
|
|
226
|
|
|
foreach ( $item_line_taxes['subtotal'] as $tax_rate_id => $tax ) { |
227
|
|
|
$line_tax[ $tax_rate_id ]['subtotal'] = $tax; |
228
|
|
|
} |
229
|
|
|
|
230
|
|
|
$line_item['taxes'] = array_values( $line_tax ); |
231
|
|
|
} |
232
|
|
|
|
233
|
|
|
$data['line_items'][] = $line_item; |
234
|
|
|
} |
235
|
|
|
|
236
|
|
|
// Add taxes. |
237
|
|
|
foreach ( $order->get_items( 'tax' ) as $key => $tax ) { |
238
|
|
|
$tax_line = array( |
239
|
|
|
'id' => $key, |
240
|
|
|
'rate_code' => $tax['name'], |
241
|
|
|
'rate_id' => $tax['rate_id'], |
242
|
|
|
'label' => isset( $tax['label'] ) ? $tax['label'] : $tax['name'], |
243
|
|
|
'compound' => (bool) $tax['compound'], |
244
|
|
|
'tax_total' => wc_format_decimal( $tax['tax_amount'], $dp ), |
245
|
|
|
'shipping_tax_total' => wc_format_decimal( $tax['shipping_tax_amount'], $dp ), |
246
|
|
|
); |
247
|
|
|
|
248
|
|
|
$data['tax_lines'][] = $tax_line; |
249
|
|
|
} |
250
|
|
|
|
251
|
|
|
// Add shipping. |
252
|
|
|
foreach ( $order->get_shipping_methods() as $shipping_item_id => $shipping_item ) { |
253
|
|
|
$shipping_line = array( |
254
|
|
|
'id' => $shipping_item_id, |
255
|
|
|
'method_title' => $shipping_item['name'], |
256
|
|
|
'method_id' => $shipping_item['method_id'], |
257
|
|
|
'total' => wc_format_decimal( $shipping_item['cost'], $dp ), |
258
|
|
|
'total_tax' => wc_format_decimal( '', $dp ), |
259
|
|
|
'taxes' => array(), |
260
|
|
|
); |
261
|
|
|
|
262
|
|
|
$shipping_taxes = maybe_unserialize( $shipping_item['taxes'] ); |
263
|
|
|
|
264
|
|
|
if ( ! empty( $shipping_taxes ) ) { |
265
|
|
|
$shipping_line['total_tax'] = wc_format_decimal( array_sum( $shipping_taxes ), $dp ); |
266
|
|
|
|
267
|
|
|
foreach ( $shipping_taxes as $tax_rate_id => $tax ) { |
268
|
|
|
$shipping_line['taxes'][] = array( |
269
|
|
|
'id' => $tax_rate_id, |
270
|
|
|
'total' => $tax, |
271
|
|
|
); |
272
|
|
|
} |
273
|
|
|
} |
274
|
|
|
|
275
|
|
|
$data['shipping_lines'][] = $shipping_line; |
276
|
|
|
} |
277
|
|
|
|
278
|
|
|
// Add fees. |
279
|
|
|
foreach ( $order->get_fees() as $fee_item_id => $fee_item ) { |
280
|
|
|
$fee_line = array( |
281
|
|
|
'id' => $fee_item_id, |
282
|
|
|
'name' => $fee_item['name'], |
283
|
|
|
'tax_class' => ! empty( $fee_item['tax_class'] ) ? $fee_item['tax_class'] : '', |
284
|
|
|
'tax_status' => 'taxable', |
285
|
|
|
'total' => wc_format_decimal( $order->get_line_total( $fee_item ), $dp ), |
286
|
|
|
'total_tax' => wc_format_decimal( $order->get_line_tax( $fee_item ), $dp ), |
287
|
|
|
'taxes' => array(), |
288
|
|
|
); |
289
|
|
|
|
290
|
|
|
$fee_line_taxes = maybe_unserialize( $fee_item['line_tax_data'] ); |
291
|
|
|
if ( isset( $fee_line_taxes['total'] ) ) { |
292
|
|
|
$fee_tax = array(); |
293
|
|
|
|
294
|
|
|
foreach ( $fee_line_taxes['total'] as $tax_rate_id => $tax ) { |
295
|
|
|
$fee_tax[ $tax_rate_id ] = array( |
296
|
|
|
'id' => $tax_rate_id, |
297
|
|
|
'total' => $tax, |
298
|
|
|
'subtotal' => '', |
299
|
|
|
); |
300
|
|
|
} |
301
|
|
|
|
302
|
|
|
foreach ( $fee_line_taxes['subtotal'] as $tax_rate_id => $tax ) { |
303
|
|
|
$fee_tax[ $tax_rate_id ]['subtotal'] = $tax; |
304
|
|
|
} |
305
|
|
|
|
306
|
|
|
$fee_line['taxes'] = array_values( $fee_tax ); |
307
|
|
|
} |
308
|
|
|
|
309
|
|
|
$data['fee_lines'][] = $fee_line; |
310
|
|
|
} |
311
|
|
|
|
312
|
|
|
// Add coupons. |
313
|
|
|
foreach ( $order->get_items( 'coupon' ) as $coupon_item_id => $coupon_item ) { |
314
|
|
|
$coupon_line = array( |
315
|
|
|
'id' => $coupon_item_id, |
316
|
|
|
'code' => $coupon_item['name'], |
317
|
|
|
'discount' => wc_format_decimal( $coupon_item['discount_amount'], $dp ), |
318
|
|
|
'discount_tax' => wc_format_decimal( $coupon_item['discount_amount_tax'], $dp ), |
319
|
|
|
); |
320
|
|
|
|
321
|
|
|
$data['coupon_lines'][] = $coupon_line; |
322
|
|
|
} |
323
|
|
|
|
324
|
|
|
// Add refunds. |
325
|
|
|
foreach ( $order->get_refunds() as $refund ) { |
326
|
|
|
$data['refunds'][] = array( |
327
|
|
|
'id' => $refund->id, |
328
|
|
|
'refund' => $refund->get_refund_reason() ? $refund->get_refund_reason() : '', |
329
|
|
|
'total' => '-' . wc_format_decimal( $refund->get_refund_amount(), $dp ), |
330
|
|
|
); |
331
|
|
|
} |
332
|
|
|
|
333
|
|
|
$context = ! empty( $request['context'] ) ? $request['context'] : 'view'; |
334
|
|
|
$data = $this->add_additional_fields_to_object( $data, $request ); |
335
|
|
|
$data = $this->filter_response_by_context( $data, $context ); |
336
|
|
|
|
337
|
|
|
// Wrap the data in a response object. |
338
|
|
|
$response = rest_ensure_response( $data ); |
339
|
|
|
|
340
|
|
|
$response->add_links( $this->prepare_links( $order ) ); |
|
|
|
|
341
|
|
|
|
342
|
|
|
/** |
343
|
|
|
* Filter the data for a response. |
344
|
|
|
* |
345
|
|
|
* The dynamic portion of the hook name, $this->post_type, refers to post_type of the post being |
346
|
|
|
* prepared for the response. |
347
|
|
|
* |
348
|
|
|
* @param WP_REST_Response $response The response object. |
349
|
|
|
* @param WP_Post $post Post object. |
350
|
|
|
* @param WP_REST_Request $request Request object. |
351
|
|
|
*/ |
352
|
|
|
return apply_filters( "woocommerce_rest_prepare_{$this->post_type}", $response, $post, $request ); |
353
|
|
|
} |
354
|
|
|
|
355
|
|
|
/** |
356
|
|
|
* Prepare links for the request. |
357
|
|
|
* |
358
|
|
|
* @param WC_Order $order Order object. |
359
|
|
|
* @return array Links for the given order. |
360
|
|
|
*/ |
361
|
|
|
protected function prepare_links( $order ) { |
362
|
|
|
$links = array( |
363
|
|
|
'self' => array( |
364
|
|
|
'href' => rest_url( sprintf( '/%s/%s/%d', $this->namespace, $this->rest_base, $order->id ) ), |
365
|
|
|
), |
366
|
|
|
'collection' => array( |
367
|
|
|
'href' => rest_url( sprintf( '/%s/%s', $this->namespace, $this->rest_base ) ), |
368
|
|
|
), |
369
|
|
|
); |
370
|
|
|
|
371
|
|
|
if ( 0 !== (int) $order->get_user_id() ) { |
372
|
|
|
$links['customer'] = array( |
373
|
|
|
'href' => rest_url( sprintf( '/%s/customers/%d', $this->namespace, $order->get_user_id() ) ), |
374
|
|
|
); |
375
|
|
|
} |
376
|
|
|
|
377
|
|
View Code Duplication |
if ( 0 !== (int) $order->post->post_parent ) { |
|
|
|
|
378
|
|
|
$links['up'] = array( |
379
|
|
|
'href' => rest_url( sprintf( '/%s/orders/%d', $this->namespace, $order->post->post_parent ) ), |
380
|
|
|
); |
381
|
|
|
} |
382
|
|
|
|
383
|
|
|
return $links; |
384
|
|
|
} |
385
|
|
|
|
386
|
|
|
/** |
387
|
|
|
* Query args. |
388
|
|
|
* |
389
|
|
|
* @param array $args |
390
|
|
|
* @param WP_REST_Request $request |
391
|
|
|
* @return array |
392
|
|
|
*/ |
393
|
|
|
public function query_args( $args, $request ) { |
394
|
|
|
global $wpdb; |
395
|
|
|
|
396
|
|
|
// Set post_status. |
397
|
|
|
if ( 'any' !== $request['status'] ) { |
398
|
|
|
$args['post_status'] = 'wc-' . $request['status']; |
399
|
|
|
} else { |
400
|
|
|
$args['post_status'] = 'any'; |
401
|
|
|
} |
402
|
|
|
|
403
|
|
View Code Duplication |
if ( ! empty( $request['customer'] ) ) { |
|
|
|
|
404
|
|
|
if ( ! empty( $args['meta_query'] ) ) { |
405
|
|
|
$args['meta_query'] = array(); |
406
|
|
|
} |
407
|
|
|
|
408
|
|
|
$args['meta_query'][] = array( |
409
|
|
|
'key' => '_customer_user', |
410
|
|
|
'value' => $request['customer'], |
411
|
|
|
'type' => 'NUMERIC', |
412
|
|
|
); |
413
|
|
|
} |
414
|
|
|
|
415
|
|
|
if ( ! empty( $request['product'] ) ) { |
416
|
|
|
$order_ids = $wpdb->get_col( $wpdb->prepare( " |
417
|
|
|
SELECT order_id |
418
|
|
|
FROM {$wpdb->prefix}woocommerce_order_items |
419
|
|
|
WHERE order_item_id IN ( SELECT order_item_id FROM {$wpdb->prefix}woocommerce_order_itemmeta WHERE meta_key = '_product_id' AND meta_value = %d ) |
420
|
|
|
AND order_item_type = 'line_item' |
421
|
|
|
", $request['product'] ) ); |
422
|
|
|
|
423
|
|
|
// Force WP_Query return empty if don't found any order. |
424
|
|
|
$order_ids = ! empty( $order_ids ) ? $order_ids : array( 0 ); |
425
|
|
|
|
426
|
|
|
$args['post__in'] = $order_ids; |
427
|
|
|
} |
428
|
|
|
|
429
|
|
|
return $args; |
430
|
|
|
} |
431
|
|
|
|
432
|
|
|
/** |
433
|
|
|
* Create order. |
434
|
|
|
* |
435
|
|
|
* @param WP_REST_Request $request Full details about the request. |
436
|
|
|
* @return int|WP_Error |
437
|
|
|
*/ |
438
|
|
|
protected function create_order( $request ) { |
439
|
|
|
wc_transaction_query( 'start' ); |
440
|
|
|
|
441
|
|
|
try { |
442
|
|
|
// Make sure customer exists. |
443
|
|
|
if ( 0 !== $request['customer_id'] && false === get_user_by( 'id', $request['customer_id'] ) ) { |
444
|
|
|
throw new WC_REST_Exception( 'woocommerce_rest_invalid_customer_id',__( 'Customer ID is invalid.', 'woocommerce' ), 400 ); |
445
|
|
|
} |
446
|
|
|
|
447
|
|
|
$order = $this->create_base_order( array( |
448
|
|
|
'status' => $request['status'], |
449
|
|
|
'customer_id' => $request['customer_id'], |
450
|
|
|
'customer_note' => $request['customer_note'], |
451
|
|
|
'created_via' => 'rest-api', |
452
|
|
|
), $request ); |
453
|
|
|
|
454
|
|
View Code Duplication |
if ( is_wp_error( $order ) ) { |
|
|
|
|
455
|
|
|
throw new WC_REST_Exception( 'woocommerce_rest_cannot_create_order', sprintf( __( 'Cannot create order: %s.', 'woocommerce' ), implode( ', ', $order->get_error_messages() ) ), 400 ); |
456
|
|
|
} |
457
|
|
|
|
458
|
|
|
// Set addresses. |
459
|
|
|
if ( is_array( $request['billing'] ) ) { |
460
|
|
|
$this->update_address( $order, $request['billing'], 'billing' ); |
461
|
|
|
} |
462
|
|
|
if ( is_array( $request['shipping'] ) ) { |
463
|
|
|
$this->update_address( $order, $request['shipping'], 'shipping' ); |
464
|
|
|
} |
465
|
|
|
|
466
|
|
|
// Set currency. |
467
|
|
|
update_post_meta( $order->id, '_order_currency', $request['currency'] ); |
468
|
|
|
|
469
|
|
|
// Set lines. |
470
|
|
|
$lines = array( |
471
|
|
|
'line_item' => 'line_items', |
472
|
|
|
'shipping' => 'shipping_lines', |
473
|
|
|
'fee' => 'fee_lines', |
474
|
|
|
'coupon' => 'coupon_lines', |
475
|
|
|
); |
476
|
|
|
|
477
|
|
View Code Duplication |
foreach ( $lines as $line_type => $line ) { |
|
|
|
|
478
|
|
|
if ( is_array( $request[ $line ] ) ) { |
479
|
|
|
foreach ( $request[ $line ] as $item ) { |
480
|
|
|
$set_item = 'set_' . $line_type; |
481
|
|
|
$this->$set_item( $order, $item, 'create' ); |
482
|
|
|
} |
483
|
|
|
} |
484
|
|
|
} |
485
|
|
|
|
486
|
|
|
// Calculate totals and set them. |
487
|
|
|
$order->calculate_totals(); |
488
|
|
|
|
489
|
|
|
// Set payment method. |
490
|
|
|
if ( ! empty( $request['payment_method'] ) ) { |
491
|
|
|
update_post_meta( $order->id, '_payment_method', $request['payment_method'] ); |
492
|
|
|
} |
493
|
|
|
if ( ! empty( $request['payment_method_title'] ) ) { |
494
|
|
|
update_post_meta( $order->id, '_payment_method_title', $request['payment_method'] ); |
495
|
|
|
} |
496
|
|
|
if ( true === $request['set_paid'] ) { |
497
|
|
|
$order->payment_complete( $request['transaction_id'] ); |
498
|
|
|
} |
499
|
|
|
|
500
|
|
|
// Set meta data. |
501
|
|
View Code Duplication |
if ( ! empty( $request['meta_data'] ) && is_array( $request['meta_data'] ) ) { |
|
|
|
|
502
|
|
|
$this->update_meta_data( $order->id, $request['meta_data'] ); |
503
|
|
|
} |
504
|
|
|
|
505
|
|
|
wc_transaction_query( 'commit' ); |
506
|
|
|
|
507
|
|
|
return $order->id; |
508
|
|
|
} catch ( WC_REST_Exception $e ) { |
509
|
|
|
wc_transaction_query( 'rollback' ); |
510
|
|
|
|
511
|
|
|
return new WP_Error( $e->getErrorCode(), $e->getMessage(), array( 'status' => $e->getCode() ) ); |
512
|
|
|
} |
513
|
|
|
} |
514
|
|
|
|
515
|
|
|
/** |
516
|
|
|
* Update address. |
517
|
|
|
* |
518
|
|
|
* @param WC_Order $order |
519
|
|
|
* @param array $posted |
520
|
|
|
* @param string $type |
521
|
|
|
*/ |
522
|
|
|
protected function update_address( $order, $posted, $type = 'billing' ) { |
523
|
|
|
$fields = $order->get_address( $type ); |
524
|
|
|
|
525
|
|
|
foreach ( array_keys( $fields ) as $field ) { |
526
|
|
|
if ( isset( $posted[ $field ] ) ) { |
527
|
|
|
$fields[ $field ] = $posted[ $field ]; |
528
|
|
|
} |
529
|
|
|
} |
530
|
|
|
|
531
|
|
|
// Set address. |
532
|
|
|
$order->set_address( $fields, $type ); |
533
|
|
|
|
534
|
|
|
// Update user meta. |
535
|
|
|
if ( $order->get_user_id() ) { |
536
|
|
|
foreach ( $fields as $key => $value ) { |
537
|
|
|
update_user_meta( $order->get_user_id(), $type . '_' . $key, $value ); |
538
|
|
|
} |
539
|
|
|
} |
540
|
|
|
} |
541
|
|
|
|
542
|
|
|
/** |
543
|
|
|
* Create or update a line item. |
544
|
|
|
* |
545
|
|
|
* @param WC_Order $order Order data. |
546
|
|
|
* @param array $item Line item data. |
547
|
|
|
* @param string $action 'create' to add line item or 'update' to update it. |
548
|
|
|
* @throws WC_REST_Exception Invalid data, server error. |
549
|
|
|
*/ |
550
|
|
|
protected function set_line_item( $order, $item, $action = 'create' ) { |
551
|
|
|
$creating = 'create' === $action; |
552
|
|
|
$item_args = array(); |
553
|
|
|
|
554
|
|
|
// Product is always required. |
555
|
|
|
if ( empty( $item['product_id'] ) && empty( $item['sku'] ) && empty( $item['variation_id'] ) ) { |
556
|
|
|
throw new WC_REST_Exception( 'woocommerce_rest_required_product_reference', __( 'Product ID or SKU is required.', 'woocommerce' ), 400 ); |
557
|
|
|
} |
558
|
|
|
|
559
|
|
|
if ( ! empty( $item['sku'] ) ) { |
560
|
|
|
$product_id = (int) wc_get_product_id_by_sku( $item['sku'] ); |
561
|
|
|
} elseif ( ! empty( $item['product_id'] ) && empty( $item['variation_id'] ) ) { |
562
|
|
|
$product_id = (int) $item['product_id']; |
563
|
|
|
} elseif ( ! empty( $item['variation_id'] ) ) { |
564
|
|
|
$product_id = (int) $item['variation_id']; |
565
|
|
|
} |
566
|
|
|
|
567
|
|
|
// When updating, ensure product ID provided matches. |
568
|
|
|
if ( 'update' === $action && ! empty( $item['id'] ) ) { |
569
|
|
|
$item_product_id = (int) wc_get_order_item_meta( $item['id'], '_product_id' ); |
570
|
|
|
$item_variation_id = (int) wc_get_order_item_meta( $item['id'], '_variation_id' ); |
571
|
|
|
|
572
|
|
|
if ( $product_id !== $item_product_id && $product_id !== $item_variation_id ) { |
573
|
|
|
throw new WC_REST_Exception( 'woocommerce_rest_required_product_reference', __( 'Product ID or variation ID provided does not match this line item.', 'woocommerce' ), 400 ); |
574
|
|
|
} |
575
|
|
|
} |
576
|
|
|
|
577
|
|
|
$product = wc_get_product( $product_id ); |
578
|
|
|
|
579
|
|
|
// Must be a valid WC_Product. |
580
|
|
|
if ( ! is_object( $product ) ) { |
581
|
|
|
throw new WC_REST_Exception( 'woocommerce_rest_invalid_product', __( 'Product is invalid.', 'woocommerce' ), 400 ); |
582
|
|
|
} |
583
|
|
|
|
584
|
|
|
// Quantity must be positive float. |
585
|
|
View Code Duplication |
if ( isset( $item['quantity'] ) && 0 >= floatval( $item['quantity'] ) ) { |
|
|
|
|
586
|
|
|
throw new WC_REST_Exception( 'woocommerce_rest_invalid_product_quantity', __( 'Product quantity must be a positive float.', 'woocommerce' ), 400 ); |
587
|
|
|
} |
588
|
|
|
|
589
|
|
|
// Quantity is required when creating. |
590
|
|
View Code Duplication |
if ( $creating && ! isset( $item['quantity'] ) ) { |
|
|
|
|
591
|
|
|
throw new WC_REST_Exception( 'woocommerce_rest_invalid_product_quantity', __( 'Product quantity is required.', 'woocommerce' ), 400 ); |
592
|
|
|
} |
593
|
|
|
|
594
|
|
|
// Get variation attributes. |
595
|
|
|
if ( method_exists( $product, 'get_variation_attributes' ) ) { |
596
|
|
|
$item_args['variation'] = $product->get_variation_attributes(); |
597
|
|
|
} |
598
|
|
|
|
599
|
|
|
// Quantity. |
600
|
|
|
if ( isset( $item['quantity'] ) ) { |
601
|
|
|
$item_args['qty'] = $item['quantity']; |
602
|
|
|
} |
603
|
|
|
|
604
|
|
|
// Total. |
605
|
|
|
if ( isset( $item['total'] ) ) { |
606
|
|
|
$item_args['totals']['total'] = floatval( $item['total'] ); |
607
|
|
|
} |
608
|
|
|
|
609
|
|
|
// Total tax. |
610
|
|
|
if ( isset( $item['total_tax'] ) ) { |
611
|
|
|
$item_args['totals']['tax'] = floatval( $item['total_tax'] ); |
612
|
|
|
} |
613
|
|
|
|
614
|
|
|
// Subtotal. |
615
|
|
|
if ( isset( $item['subtotal'] ) ) { |
616
|
|
|
$item_args['totals']['subtotal'] = floatval( $item['subtotal'] ); |
617
|
|
|
} |
618
|
|
|
|
619
|
|
|
// Subtotal tax. |
620
|
|
|
if ( isset( $item['subtotal_tax'] ) ) { |
621
|
|
|
$item_args['totals']['subtotal_tax'] = floatval( $item['subtotal_tax'] ); |
622
|
|
|
} |
623
|
|
|
|
624
|
|
View Code Duplication |
if ( $creating ) { |
|
|
|
|
625
|
|
|
$item_id = $order->add_product( $product, $item_args['qty'], $item_args ); |
626
|
|
|
if ( ! $item_id ) { |
627
|
|
|
throw new WC_REST_Exception( 'woocommerce_rest_cannot_create_line_item', __( 'Cannot create line item, try again.', 'woocommerce' ), 500 ); |
628
|
|
|
} |
629
|
|
|
} else { |
630
|
|
|
$item_id = $order->update_product( $item['id'], $product, $item_args ); |
631
|
|
|
if ( ! $item_id ) { |
632
|
|
|
throw new WC_REST_Exception( 'woocommerce_rest_cannot_update_line_item', __( 'Cannot update line item, try again.', 'woocommerce' ), 500 ); |
633
|
|
|
} |
634
|
|
|
} |
635
|
|
|
} |
636
|
|
|
|
637
|
|
|
/** |
638
|
|
|
* Create or update an order shipping method. |
639
|
|
|
* |
640
|
|
|
* @param WC_Order $order Order data. |
641
|
|
|
* @param array $shipping Item data. |
642
|
|
|
* @param string $action 'create' to add shipping or 'update' to update it. |
643
|
|
|
* @throws WC_REST_Exception Invalid data, server error. |
644
|
|
|
*/ |
645
|
|
|
protected function set_shipping( $order, $shipping, $action ) { |
646
|
|
|
// Total must be a positive float. |
647
|
|
|
if ( ! empty( $shipping['total'] ) && 0 > floatval( $shipping['total'] ) ) { |
648
|
|
|
throw new WC_REST_Exception( 'woocommerce_rest_invalid_shipping_total', __( 'Shipping total must be a positive amount.', 'woocommerce' ), 400 ); |
649
|
|
|
} |
650
|
|
|
|
651
|
|
|
if ( 'create' === $action ) { |
652
|
|
|
// Method ID is required. |
653
|
|
|
if ( empty( $shipping['method_id'] ) ) { |
654
|
|
|
throw new WC_REST_Exception( 'woocommerce_rest_invalid_shipping_item', __( 'Shipping method ID is required.', 'woocommerce' ), 400 ); |
655
|
|
|
} |
656
|
|
|
|
657
|
|
|
$rate = new WC_Shipping_Rate( $shipping['method_id'], isset( $shipping['method_title'] ) ? $shipping['method_title'] : '', isset( $shipping['total'] ) ? floatval( $shipping['total'] ) : 0, array(), $shipping['method_id'] ); |
658
|
|
|
|
659
|
|
|
$shipping_id = $order->add_shipping( $rate ); |
660
|
|
|
|
661
|
|
|
if ( ! $shipping_id ) { |
662
|
|
|
throw new WC_REST_Exception( 'woocommerce_rest_cannot_create_shipping', __( 'Cannot create shipping method, try again.', 'woocommerce' ), 500 ); |
663
|
|
|
} |
664
|
|
|
|
665
|
|
View Code Duplication |
} else { |
|
|
|
|
666
|
|
|
$shipping_args = array(); |
667
|
|
|
|
668
|
|
|
if ( isset( $shipping['method_id'] ) ) { |
669
|
|
|
$shipping_args['method_id'] = $shipping['method_id']; |
670
|
|
|
} |
671
|
|
|
|
672
|
|
|
if ( isset( $shipping['method_title'] ) ) { |
673
|
|
|
$shipping_args['method_title'] = $shipping['method_title']; |
674
|
|
|
} |
675
|
|
|
|
676
|
|
|
if ( isset( $shipping['total'] ) ) { |
677
|
|
|
$shipping_args['cost'] = floatval( $shipping['total'] ); |
678
|
|
|
} |
679
|
|
|
|
680
|
|
|
$shipping_id = $order->update_shipping( $shipping['id'], $shipping_args ); |
681
|
|
|
|
682
|
|
|
if ( ! $shipping_id ) { |
683
|
|
|
throw new WC_REST_Exception( 'woocommerce_rest_cannot_update_shipping', __( 'Cannot update shipping method, try again.', 'woocommerce' ), 500 ); |
684
|
|
|
} |
685
|
|
|
} |
686
|
|
|
} |
687
|
|
|
|
688
|
|
|
/** |
689
|
|
|
* Create or update an order fee. |
690
|
|
|
* |
691
|
|
|
* @param WC_Order $order Order data. |
692
|
|
|
* @param array $fee Item data. |
693
|
|
|
* @param string $action 'create' to add fee or 'update' to update it. |
694
|
|
|
* @throws WC_REST_Exception Invalid data, server error. |
695
|
|
|
*/ |
696
|
|
|
protected function set_fee( $order, $fee, $action ) { |
697
|
|
|
if ( 'create' === $action ) { |
698
|
|
|
|
699
|
|
|
// Fee name is required. |
700
|
|
|
if ( empty( $fee['name'] ) ) { |
701
|
|
|
throw new WC_REST_Exception( 'woocommerce_rest_invalid_fee_item', __( 'Fee name is required.', 'woocommerce' ), 400 ); |
702
|
|
|
} |
703
|
|
|
|
704
|
|
|
$fee_data = new stdClass(); |
705
|
|
|
$fee_data->id = sanitize_title( $fee['name'] ); |
706
|
|
|
$fee_data->name = $fee['name']; |
707
|
|
|
$fee_data->amount = isset( $fee['total'] ) ? floatval( $fee['total'] ) : 0; |
708
|
|
|
$fee_data->taxable = false; |
709
|
|
|
$fee_data->tax = 0; |
710
|
|
|
$fee_data->tax_data = array(); |
711
|
|
|
$fee_data->tax_class = ''; |
712
|
|
|
|
713
|
|
|
// If taxable, tax class and total are required. |
714
|
|
|
if ( isset( $fee['tax_status'] ) && 'taxable' === $fee['tax_status'] ) { |
715
|
|
|
|
716
|
|
|
if ( ! isset( $fee['tax_class'] ) ) { |
717
|
|
|
throw new WC_REST_Exception( 'woocommerce_rest_invalid_fee_item', __( 'Fee tax class is required when fee is taxable.', 'woocommerce' ), 400 ); |
718
|
|
|
} |
719
|
|
|
|
720
|
|
|
$fee_data->taxable = true; |
721
|
|
|
$fee_data->tax_class = $fee['tax_class']; |
722
|
|
|
|
723
|
|
|
if ( isset( $fee['total_tax'] ) ) { |
724
|
|
|
$fee_data->tax = isset( $fee['total_tax'] ) ? wc_format_refund_total( $fee['total_tax'] ) : 0; |
725
|
|
|
} |
726
|
|
|
} |
727
|
|
|
|
728
|
|
|
$fee_id = $order->add_fee( $fee_data ); |
729
|
|
|
|
730
|
|
|
if ( ! $fee_id ) { |
731
|
|
|
throw new WC_REST_Exception( 'woocommerce_rest_cannot_create_fee', __( 'Cannot create fee, try again.', 'woocommerce' ), 500 ); |
732
|
|
|
} |
733
|
|
|
|
734
|
|
|
} else { |
735
|
|
|
$fee_args = array(); |
736
|
|
|
|
737
|
|
|
if ( isset( $fee['name'] ) ) { |
738
|
|
|
$fee_args['name'] = $fee['name']; |
739
|
|
|
} |
740
|
|
|
|
741
|
|
|
if ( isset( $fee['tax_class'] ) ) { |
742
|
|
|
$fee_args['tax_class'] = $fee['tax_class']; |
743
|
|
|
} |
744
|
|
|
|
745
|
|
|
if ( isset( $fee['total'] ) ) { |
746
|
|
|
$fee_args['line_total'] = floatval( $fee['total'] ); |
747
|
|
|
} |
748
|
|
|
|
749
|
|
|
if ( isset( $fee['total_tax'] ) ) { |
750
|
|
|
$fee_args['line_tax'] = floatval( $fee['total_tax'] ); |
751
|
|
|
} |
752
|
|
|
|
753
|
|
|
$fee_id = $order->update_fee( $fee['id'], $fee_args ); |
754
|
|
|
|
755
|
|
|
if ( ! $fee_id ) { |
756
|
|
|
throw new WC_REST_Exception( 'woocommerce_rest_cannot_update_fee', __( 'Cannot update fee, try again.', 'woocommerce' ), 500 ); |
757
|
|
|
} |
758
|
|
|
} |
759
|
|
|
} |
760
|
|
|
|
761
|
|
|
/** |
762
|
|
|
* Create or update an order coupon. |
763
|
|
|
* |
764
|
|
|
* @param WC_Order $order Order data. |
765
|
|
|
* @param array $coupon Item data. |
766
|
|
|
* @param string $action 'create' to add coupon or 'update' to update it. |
767
|
|
|
* @throws WC_REST_Exception Invalid data, server error. |
768
|
|
|
*/ |
769
|
|
|
protected function set_coupon( $order, $coupon, $action ) { |
770
|
|
|
// Coupon discount must be positive float. |
771
|
|
View Code Duplication |
if ( isset( $coupon['discount'] ) && 0 > floatval( $coupon['discount'] ) ) { |
|
|
|
|
772
|
|
|
throw new WC_REST_Exception( 'woocommerce_rest_invalid_coupon_total', __( 'Coupon discount must be a positive amount.', 'woocommerce' ), 400 ); |
773
|
|
|
} |
774
|
|
|
|
775
|
|
View Code Duplication |
if ( 'create' === $action ) { |
|
|
|
|
776
|
|
|
// Coupon code is required. |
777
|
|
|
if ( empty( $coupon['code'] ) ) { |
778
|
|
|
throw new WC_REST_Exception( 'woocommerce_rest_invalid_coupon_coupon', __( 'Coupon code is required.', 'woocommerce' ), 400 ); |
779
|
|
|
} |
780
|
|
|
|
781
|
|
|
$coupon_id = $order->add_coupon( $coupon['code'], floatval( $coupon['discount'] ) ); |
782
|
|
|
|
783
|
|
|
if ( ! $coupon_id ) { |
784
|
|
|
throw new WC_REST_Exception( 'woocommerce_rest_cannot_create_order_coupon', __( 'Cannot create coupon, try again.', 'woocommerce' ), 500 ); |
785
|
|
|
} |
786
|
|
|
|
787
|
|
|
} else { |
788
|
|
|
$coupon_args = array(); |
789
|
|
|
|
790
|
|
|
if ( isset( $coupon['code'] ) ) { |
791
|
|
|
$coupon_args['code'] = $coupon['code']; |
792
|
|
|
} |
793
|
|
|
|
794
|
|
|
if ( isset( $coupon['discount'] ) ) { |
795
|
|
|
$coupon_args['discount_amount'] = floatval( $coupon['discount'] ); |
796
|
|
|
} |
797
|
|
|
|
798
|
|
|
$coupon_id = $order->update_coupon( $coupon['id'], $coupon_args ); |
799
|
|
|
|
800
|
|
|
if ( ! $coupon_id ) { |
801
|
|
|
throw new WC_REST_Exception( 'woocommerce_rest_cannot_update_order_coupon', __( 'Cannot update coupon, try again.', 'woocommerce' ), 500 ); |
802
|
|
|
} |
803
|
|
|
} |
804
|
|
|
} |
805
|
|
|
|
806
|
|
|
/** |
807
|
|
|
* Helper method to add/update meta data, with two restrictions: |
808
|
|
|
* |
809
|
|
|
* 1) Only non-protected meta (no leading underscore) can be set |
810
|
|
|
* 2) Meta values must be scalar (int, string, bool) |
811
|
|
|
* |
812
|
|
|
* @param WC_Order $order Order data. |
|
|
|
|
813
|
|
|
* @param array $meta_data Meta data in array( 'meta_key' => 'meta_value' ) format. |
814
|
|
|
*/ |
815
|
|
View Code Duplication |
protected function update_meta_data( $order_id, $meta_data ) { |
|
|
|
|
816
|
|
|
foreach ( $meta_data as $meta_key => $meta_value ) { |
817
|
|
|
if ( is_string( $meta_key ) && ! is_protected_meta( $meta_key ) && is_scalar( $meta_value ) ) { |
818
|
|
|
update_post_meta( $order_id, $meta_key, $meta_value ); |
819
|
|
|
} |
820
|
|
|
} |
821
|
|
|
} |
822
|
|
|
|
823
|
|
|
/** |
824
|
|
|
* Create a single item. |
825
|
|
|
* |
826
|
|
|
* @param WP_REST_Request $request Full details about the request. |
827
|
|
|
* @return WP_Error|WP_REST_Response |
828
|
|
|
*/ |
829
|
|
|
public function create_item( $request ) { |
830
|
|
|
if ( ! empty( $request['id'] ) ) { |
831
|
|
|
return new WP_Error( "woocommerce_rest_{$this->post_type}_exists", sprintf( __( 'Cannot create existing %s.', 'woocommerce' ), $this->post_type ), array( 'status' => 400 ) ); |
832
|
|
|
} |
833
|
|
|
|
834
|
|
|
$order_id = $this->create_order( $request ); |
835
|
|
|
if ( is_wp_error( $order_id ) ) { |
836
|
|
|
return $order_id; |
837
|
|
|
} |
838
|
|
|
|
839
|
|
|
// Clear transients. |
840
|
|
|
wc_delete_shop_order_transients( $order_id ); |
841
|
|
|
|
842
|
|
|
$post = get_post( $order_id ); |
843
|
|
|
$this->update_additional_fields_for_object( $post, $request ); |
844
|
|
|
|
845
|
|
|
/** |
846
|
|
|
* Fires after a single item is created or updated via the REST API. |
847
|
|
|
* |
848
|
|
|
* @param object $post Inserted object (not a WP_Post object). |
849
|
|
|
* @param WP_REST_Request $request Request object. |
850
|
|
|
* @param boolean $creating True when creating item, false when updating. |
851
|
|
|
*/ |
852
|
|
|
do_action( "woocommerce_rest_insert_{$this->post_type}", $post, $request, true ); |
853
|
|
|
|
854
|
|
|
$request->set_param( 'context', 'edit' ); |
855
|
|
|
$response = $this->prepare_item_for_response( $post, $request ); |
856
|
|
|
$response = rest_ensure_response( $response ); |
857
|
|
|
$response->set_status( 201 ); |
858
|
|
|
$response->header( 'Location', rest_url( sprintf( '/%s/%s/%d', $this->namespace, $this->rest_base, $post->ID ) ) ); |
859
|
|
|
|
860
|
|
|
return $response; |
861
|
|
|
} |
862
|
|
|
|
863
|
|
|
/** |
864
|
|
|
* Wrapper method to create/update order items. |
865
|
|
|
* When updating, the item ID provided is checked to ensure it is associated |
866
|
|
|
* with the order. |
867
|
|
|
* |
868
|
|
|
* @param WC_Order $order order |
869
|
|
|
* @param string $item_type |
870
|
|
|
* @param array $item item provided in the request body |
871
|
|
|
* @param string $action either 'create' or 'update' |
872
|
|
|
* @throws WC_REST_Exception If item ID is not associated with order |
873
|
|
|
*/ |
874
|
|
View Code Duplication |
protected function set_item( $order, $item_type, $item, $action ) { |
|
|
|
|
875
|
|
|
global $wpdb; |
876
|
|
|
|
877
|
|
|
$set_method = 'set_' . $item_type; |
878
|
|
|
|
879
|
|
|
// Verify provided line item ID is associated with order. |
880
|
|
|
if ( 'update' === $action ) { |
881
|
|
|
$result = $wpdb->get_row( |
882
|
|
|
$wpdb->prepare( "SELECT * FROM {$wpdb->prefix}woocommerce_order_items WHERE order_item_id = %d AND order_id = %d", |
883
|
|
|
absint( $item['id'] ), |
884
|
|
|
absint( $order->id ) |
885
|
|
|
) ); |
886
|
|
|
|
887
|
|
|
if ( is_null( $result ) ) { |
888
|
|
|
throw new WC_REST_Exception( 'woocommerce_rest_invalid_item_id', __( 'Order item ID provided is not associated with order.', 'woocommerce' ), 400 ); |
889
|
|
|
} |
890
|
|
|
} |
891
|
|
|
|
892
|
|
|
$this->$set_method( $order, $item, $action ); |
893
|
|
|
} |
894
|
|
|
|
895
|
|
|
/** |
896
|
|
|
* Helper method to check if the resource ID associated with the provided item is null. |
897
|
|
|
* Items can be deleted by setting the resource ID to null. |
898
|
|
|
* |
899
|
|
|
* @param array $item Item provided in the request body. |
900
|
|
|
* @return bool True if the item resource ID is null, false otherwise. |
901
|
|
|
*/ |
902
|
|
|
protected function item_is_null( $item ) { |
903
|
|
|
$keys = array( 'product_id', 'method_id', 'title', 'code' ); |
904
|
|
|
|
905
|
|
|
foreach ( $keys as $key ) { |
906
|
|
|
if ( array_key_exists( $key, $item ) && is_null( $item[ $key ] ) ) { |
907
|
|
|
return true; |
908
|
|
|
} |
909
|
|
|
} |
910
|
|
|
|
911
|
|
|
return false; |
912
|
|
|
} |
913
|
|
|
|
914
|
|
|
/** |
915
|
|
|
* Update order. |
916
|
|
|
* |
917
|
|
|
* @param WP_REST_Request $request Full details about the request. |
918
|
|
|
* @param WP_Post $post Post data. |
919
|
|
|
* @return int|WP_Error |
920
|
|
|
*/ |
921
|
|
|
protected function update_order( $request, $post ) { |
922
|
|
|
try { |
923
|
|
|
$update_totals = false; |
924
|
|
|
$order = wc_get_order( $post ); |
925
|
|
|
$order_args = array( 'order_id' => $order->id ); |
926
|
|
|
|
927
|
|
|
// Customer note. |
928
|
|
|
if ( isset( $request['customer_note'] ) ) { |
929
|
|
|
$order_args['customer_note'] = $request['customer_note']; |
930
|
|
|
} |
931
|
|
|
|
932
|
|
|
// Customer ID. |
933
|
|
View Code Duplication |
if ( isset( $request['customer_id'] ) && $request['customer_id'] != $order->get_user_id() ) { |
|
|
|
|
934
|
|
|
// Make sure customer exists. |
935
|
|
|
if ( false === get_user_by( 'id', $request['customer_id'] ) ) { |
936
|
|
|
throw new WC_REST_Exception( 'woocommerce_rest_invalid_customer_id', __( 'Customer ID is invalid.', 'woocommerce' ), 400 ); |
937
|
|
|
} |
938
|
|
|
|
939
|
|
|
update_post_meta( $order->id, '_customer_user', $request['customer_id'] ); |
940
|
|
|
} |
941
|
|
|
|
942
|
|
|
// Update addresses. |
943
|
|
|
if ( is_array( $request['billing'] ) ) { |
944
|
|
|
$this->update_address( $order, $request['billing'], 'billing' ); |
|
|
|
|
945
|
|
|
} |
946
|
|
|
if ( is_array( $request['shipping'] ) ) { |
947
|
|
|
$this->update_address( $order, $request['shipping'], 'shipping' ); |
|
|
|
|
948
|
|
|
} |
949
|
|
|
|
950
|
|
|
$lines = array( |
951
|
|
|
'line_item' => 'line_items', |
952
|
|
|
'shipping' => 'shipping_lines', |
953
|
|
|
'fee' => 'fee_lines', |
954
|
|
|
'coupon' => 'coupon_lines', |
955
|
|
|
); |
956
|
|
|
|
957
|
|
View Code Duplication |
foreach ( $lines as $line_type => $line ) { |
|
|
|
|
958
|
|
|
if ( isset( $request[ $line ] ) && is_array( $request[ $line ] ) ) { |
959
|
|
|
$update_totals = true; |
960
|
|
|
foreach ( $request[ $line ] as $item ) { |
961
|
|
|
// Item ID is always required. |
962
|
|
|
if ( ! array_key_exists( 'id', $item ) ) { |
963
|
|
|
throw new WC_REST_Exception( 'woocommerce_rest_invalid_item_id', __( 'Order item ID is required.', 'woocommerce' ), 400 ); |
964
|
|
|
} |
965
|
|
|
|
966
|
|
|
// Create item. |
967
|
|
|
if ( is_null( $item['id'] ) ) { |
968
|
|
|
$this->set_item( $order, $line_type, $item, 'create' ); |
|
|
|
|
969
|
|
|
} elseif ( $this->item_is_null( $item ) ) { |
970
|
|
|
// Delete item. |
971
|
|
|
wc_delete_order_item( $item['id'] ); |
972
|
|
|
} else { |
973
|
|
|
// Update item. |
974
|
|
|
$this->set_item( $order, $line_type, $item, 'update' ); |
|
|
|
|
975
|
|
|
} |
976
|
|
|
} |
977
|
|
|
} |
978
|
|
|
} |
979
|
|
|
|
980
|
|
|
// Set payment method. |
981
|
|
|
if ( ! empty( $request['payment_method'] ) ) { |
982
|
|
|
update_post_meta( $order->id, '_payment_method', $request['payment_method'] ); |
983
|
|
|
} |
984
|
|
|
if ( ! empty( $request['payment_method_title'] ) ) { |
985
|
|
|
update_post_meta( $order->id, '_payment_method_title', $request['payment_method'] ); |
986
|
|
|
} |
987
|
|
|
if ( $order->needs_payment() && isset( $request['set_paid'] ) && true === $request['set_paid'] ) { |
988
|
|
|
$order->payment_complete( ! empty( $request['transaction_id'] ) ? $request['transaction_id'] : '' ); |
989
|
|
|
} |
990
|
|
|
|
991
|
|
|
// Set order currency. |
992
|
|
|
if ( isset( $request['currency'] ) ) { |
993
|
|
|
update_post_meta( $order->id, '_order_currency', $request['currency'] ); |
994
|
|
|
} |
995
|
|
|
|
996
|
|
|
// If items have changed, recalculate order totals. |
997
|
|
|
if ( $update_totals ) { |
998
|
|
|
$order->calculate_totals(); |
999
|
|
|
} |
1000
|
|
|
|
1001
|
|
|
// Update meta data. |
1002
|
|
View Code Duplication |
if ( ! empty( $request['meta_data'] ) && is_array( $request['meta_data'] ) ) { |
|
|
|
|
1003
|
|
|
$this->update_meta_data( $order->id, $request['meta_data'] ); |
1004
|
|
|
} |
1005
|
|
|
|
1006
|
|
|
// Update the order post to set customer note/modified date. |
1007
|
|
|
wc_update_order( $order_args ); |
1008
|
|
|
|
1009
|
|
|
// Order status. |
1010
|
|
View Code Duplication |
if ( ! empty( $request['status'] ) ) { |
|
|
|
|
1011
|
|
|
$order->update_status( $request['status'], isset( $request['status_note'] ) ? $request['status_note'] : '' ); |
1012
|
|
|
} |
1013
|
|
|
|
1014
|
|
|
return $order->id; |
1015
|
|
|
} catch ( WC_REST_Exception $e ) { |
1016
|
|
|
return new WP_Error( $e->getErrorCode(), $e->getMessage(), array( 'status' => $e->getCode() ) ); |
1017
|
|
|
} |
1018
|
|
|
} |
1019
|
|
|
|
1020
|
|
|
/** |
1021
|
|
|
* Update a single order. |
1022
|
|
|
* |
1023
|
|
|
* @param WP_REST_Request $request Full details about the request. |
1024
|
|
|
* @return WP_Error|WP_REST_Response |
1025
|
|
|
*/ |
1026
|
|
|
public function update_item( $request ) { |
1027
|
|
|
$id = (int) $request['id']; |
1028
|
|
|
$post = get_post( $id ); |
1029
|
|
|
|
1030
|
|
|
if ( empty( $id ) || empty( $post->ID ) || $this->post_type !== $post->post_type ) { |
1031
|
|
|
return new WP_Error( "woocommerce_rest_{$this->post_type}_invalid_id", __( 'ID is invalid.', 'woocommerce' ), array( 'status' => 400 ) ); |
1032
|
|
|
} |
1033
|
|
|
|
1034
|
|
|
$order_id = $this->update_order( $request, $post ); |
1035
|
|
|
if ( is_wp_error( $order_id ) ) { |
1036
|
|
|
return $order_id; |
1037
|
|
|
} |
1038
|
|
|
|
1039
|
|
|
// Clear transients. |
1040
|
|
|
wc_delete_shop_order_transients( $order_id ); |
1041
|
|
|
|
1042
|
|
|
$post = get_post( $order_id ); |
1043
|
|
|
$this->update_additional_fields_for_object( $post, $request ); |
1044
|
|
|
|
1045
|
|
|
/** |
1046
|
|
|
* Fires after a single item is created or updated via the REST API. |
1047
|
|
|
* |
1048
|
|
|
* @param object $post Inserted object (not a WP_Post object). |
1049
|
|
|
* @param WP_REST_Request $request Request object. |
1050
|
|
|
* @param boolean $creating True when creating item, false when updating. |
1051
|
|
|
*/ |
1052
|
|
|
do_action( "woocommerce_rest_insert_{$this->post_type}", $post, $request, false ); |
1053
|
|
|
|
1054
|
|
|
$request->set_param( 'context', 'edit' ); |
1055
|
|
|
$response = $this->prepare_item_for_response( $post, $request ); |
1056
|
|
|
return rest_ensure_response( $response ); |
1057
|
|
|
} |
1058
|
|
|
|
1059
|
|
|
/** |
1060
|
|
|
* Get order statuses. |
1061
|
|
|
* |
1062
|
|
|
* @return array |
1063
|
|
|
*/ |
1064
|
|
|
protected function get_order_statuses() { |
1065
|
|
|
$order_statuses = array(); |
1066
|
|
|
|
1067
|
|
|
foreach ( array_keys( wc_get_order_statuses() ) as $status ) { |
1068
|
|
|
$order_statuses[] = str_replace( 'wc-', '', $status ); |
1069
|
|
|
} |
1070
|
|
|
|
1071
|
|
|
return $order_statuses; |
1072
|
|
|
} |
1073
|
|
|
|
1074
|
|
|
/** |
1075
|
|
|
* Create base WC Order object. |
1076
|
|
|
* |
1077
|
|
|
* @since 2.6.0 |
1078
|
|
|
* @param array $args Order args. |
1079
|
|
|
* @param WP_REST_Request $request Full details about the request. |
|
|
|
|
1080
|
|
|
* @return WC_Order|WP_Error |
1081
|
|
|
*/ |
1082
|
|
|
protected function create_base_order( $args, $data ) { |
|
|
|
|
1083
|
|
|
return wc_create_order( $args ); |
1084
|
|
|
} |
1085
|
|
|
|
1086
|
|
|
/** |
1087
|
|
|
* Get the Order's schema, conforming to JSON Schema. |
1088
|
|
|
* |
1089
|
|
|
* @return array |
1090
|
|
|
*/ |
1091
|
|
|
public function get_item_schema() { |
1092
|
|
|
$schema = array( |
1093
|
|
|
'$schema' => 'http://json-schema.org/draft-04/schema#', |
1094
|
|
|
'title' => $this->post_type, |
1095
|
|
|
'type' => 'object', |
1096
|
|
|
'properties' => array( |
1097
|
|
|
'id' => array( |
1098
|
|
|
'description' => __( 'Unique identifier for the resource.', 'woocommerce' ), |
1099
|
|
|
'type' => 'integer', |
1100
|
|
|
'context' => array( 'view', 'edit' ), |
1101
|
|
|
'readonly' => true, |
1102
|
|
|
), |
1103
|
|
|
'parent_id' => array( |
1104
|
|
|
'description' => __( 'Parent order ID.', 'woocommerce' ), |
1105
|
|
|
'type' => 'integer', |
1106
|
|
|
'context' => array( 'view', 'edit' ), |
1107
|
|
|
), |
1108
|
|
|
'status' => array( |
1109
|
|
|
'description' => __( 'Order status.', 'woocommerce' ), |
1110
|
|
|
'type' => 'string', |
1111
|
|
|
'default' => 'pending', |
1112
|
|
|
'enum' => $this->get_order_statuses(), |
1113
|
|
|
'context' => array( 'view', 'edit' ), |
1114
|
|
|
), |
1115
|
|
|
'order_key' => array( |
1116
|
|
|
'description' => __( 'Order key.', 'woocommerce' ), |
1117
|
|
|
'type' => 'string', |
1118
|
|
|
'context' => array( 'view', 'edit' ), |
1119
|
|
|
'readonly' => true, |
1120
|
|
|
), |
1121
|
|
|
'currency' => array( |
1122
|
|
|
'description' => __( 'Currency the order was created with, in ISO format.', 'woocommerce' ), |
1123
|
|
|
'type' => 'string', |
1124
|
|
|
'default' => get_woocommerce_currency(), |
1125
|
|
|
'enum' => array_keys( get_woocommerce_currencies() ), |
1126
|
|
|
'context' => array( 'view', 'edit' ), |
1127
|
|
|
), |
1128
|
|
|
'version' => array( |
1129
|
|
|
'description' => __( 'Version of WooCommerce when the order was made.', 'woocommerce' ), |
1130
|
|
|
'type' => 'integer', |
1131
|
|
|
'context' => array( 'view', 'edit' ), |
1132
|
|
|
'readonly' => true, |
1133
|
|
|
), |
1134
|
|
|
'prices_include_tax' => array( |
1135
|
|
|
'description' => __( 'Shows if the prices included tax during checkout.', 'woocommerce' ), |
1136
|
|
|
'type' => 'boolean', |
1137
|
|
|
'context' => array( 'view', 'edit' ), |
1138
|
|
|
'readonly' => true, |
1139
|
|
|
), |
1140
|
|
|
'date_created' => array( |
1141
|
|
|
'description' => __( "The date the order was created, in the site's timezone.", 'woocommerce' ), |
1142
|
|
|
'type' => 'date-time', |
1143
|
|
|
'context' => array( 'view', 'edit' ), |
1144
|
|
|
'readonly' => true, |
1145
|
|
|
), |
1146
|
|
|
'date_modified' => array( |
1147
|
|
|
'description' => __( "The date the order was last modified, in the site's timezone.", 'woocommerce' ), |
1148
|
|
|
'type' => 'date-time', |
1149
|
|
|
'context' => array( 'view', 'edit' ), |
1150
|
|
|
'readonly' => true, |
1151
|
|
|
), |
1152
|
|
|
'customer_id' => array( |
1153
|
|
|
'description' => __( 'User ID who owns the order. 0 for guests.', 'woocommerce' ), |
1154
|
|
|
'type' => 'integer', |
1155
|
|
|
'default' => 0, |
1156
|
|
|
'context' => array( 'view', 'edit' ), |
1157
|
|
|
), |
1158
|
|
|
'discount_total' => array( |
1159
|
|
|
'description' => __( 'Total discount amount for the order.', 'woocommerce' ), |
1160
|
|
|
'type' => 'string', |
1161
|
|
|
'context' => array( 'view', 'edit' ), |
1162
|
|
|
'readonly' => true, |
1163
|
|
|
), |
1164
|
|
|
'discount_tax' => array( |
1165
|
|
|
'description' => __( 'Total discount tax amount for the order.', 'woocommerce' ), |
1166
|
|
|
'type' => 'string', |
1167
|
|
|
'context' => array( 'view', 'edit' ), |
1168
|
|
|
'readonly' => true, |
1169
|
|
|
), |
1170
|
|
|
'shipping_total' => array( |
1171
|
|
|
'description' => __( 'Total shipping amount for the order.', 'woocommerce' ), |
1172
|
|
|
'type' => 'string', |
1173
|
|
|
'context' => array( 'view', 'edit' ), |
1174
|
|
|
'readonly' => true, |
1175
|
|
|
), |
1176
|
|
|
'shipping_tax' => array( |
1177
|
|
|
'description' => __( 'Total shipping tax amount for the order.', 'woocommerce' ), |
1178
|
|
|
'type' => 'string', |
1179
|
|
|
'context' => array( 'view', 'edit' ), |
1180
|
|
|
'readonly' => true, |
1181
|
|
|
), |
1182
|
|
|
'cart_tax' => array( |
1183
|
|
|
'description' => __( 'Sum of line item taxes only.', 'woocommerce' ), |
1184
|
|
|
'type' => 'string', |
1185
|
|
|
'context' => array( 'view', 'edit' ), |
1186
|
|
|
'readonly' => true, |
1187
|
|
|
), |
1188
|
|
|
'total' => array( |
1189
|
|
|
'description' => __( 'Grand total.', 'woocommerce' ), |
1190
|
|
|
'type' => 'string', |
1191
|
|
|
'context' => array( 'view', 'edit' ), |
1192
|
|
|
'readonly' => true, |
1193
|
|
|
), |
1194
|
|
|
'total_tax' => array( |
1195
|
|
|
'description' => __( 'Sum of all taxes.', 'woocommerce' ), |
1196
|
|
|
'type' => 'string', |
1197
|
|
|
'context' => array( 'view', 'edit' ), |
1198
|
|
|
'readonly' => true, |
1199
|
|
|
), |
1200
|
|
|
'billing' => array( |
1201
|
|
|
'description' => __( 'Billing address.', 'woocommerce' ), |
1202
|
|
|
'type' => 'array', |
1203
|
|
|
'context' => array( 'view', 'edit' ), |
1204
|
|
|
'properties' => array( |
1205
|
|
|
'first_name' => array( |
1206
|
|
|
'description' => __( 'First name.', 'woocommerce' ), |
1207
|
|
|
'type' => 'string', |
1208
|
|
|
'context' => array( 'view', 'edit' ), |
1209
|
|
|
), |
1210
|
|
|
'last_name' => array( |
1211
|
|
|
'description' => __( 'Last name.', 'woocommerce' ), |
1212
|
|
|
'type' => 'string', |
1213
|
|
|
'context' => array( 'view', 'edit' ), |
1214
|
|
|
), |
1215
|
|
|
'company' => array( |
1216
|
|
|
'description' => __( 'Company name.', 'woocommerce' ), |
1217
|
|
|
'type' => 'string', |
1218
|
|
|
'context' => array( 'view', 'edit' ), |
1219
|
|
|
), |
1220
|
|
|
'address_1' => array( |
1221
|
|
|
'description' => __( 'Address line 1.', 'woocommerce' ), |
1222
|
|
|
'type' => 'string', |
1223
|
|
|
'context' => array( 'view', 'edit' ), |
1224
|
|
|
), |
1225
|
|
|
'address_2' => array( |
1226
|
|
|
'description' => __( 'Address line 2.', 'woocommerce' ), |
1227
|
|
|
'type' => 'string', |
1228
|
|
|
'context' => array( 'view', 'edit' ), |
1229
|
|
|
), |
1230
|
|
|
'city' => array( |
1231
|
|
|
'description' => __( 'City name.', 'woocommerce' ), |
1232
|
|
|
'type' => 'string', |
1233
|
|
|
'context' => array( 'view', 'edit' ), |
1234
|
|
|
), |
1235
|
|
|
'state' => array( |
1236
|
|
|
'description' => __( 'ISO code or name of the state, province or district.', 'woocommerce' ), |
1237
|
|
|
'type' => 'string', |
1238
|
|
|
'context' => array( 'view', 'edit' ), |
1239
|
|
|
), |
1240
|
|
|
'postcode' => array( |
1241
|
|
|
'description' => __( 'Postal code.', 'woocommerce' ), |
1242
|
|
|
'type' => 'string', |
1243
|
|
|
'context' => array( 'view', 'edit' ), |
1244
|
|
|
), |
1245
|
|
|
'country' => array( |
1246
|
|
|
'description' => __( 'Country code in ISO 3166-1 alpha-2 format.', 'woocommerce' ), |
1247
|
|
|
'type' => 'string', |
1248
|
|
|
'context' => array( 'view', 'edit' ), |
1249
|
|
|
), |
1250
|
|
|
'email' => array( |
1251
|
|
|
'description' => __( 'Email address.', 'woocommerce' ), |
1252
|
|
|
'type' => 'string', |
1253
|
|
|
'format' => 'email', |
1254
|
|
|
'context' => array( 'view', 'edit' ), |
1255
|
|
|
), |
1256
|
|
|
'phone' => array( |
1257
|
|
|
'description' => __( 'Phone number.', 'woocommerce' ), |
1258
|
|
|
'type' => 'string', |
1259
|
|
|
'context' => array( 'view', 'edit' ), |
1260
|
|
|
), |
1261
|
|
|
), |
1262
|
|
|
), |
1263
|
|
|
'shipping' => array( |
1264
|
|
|
'description' => __( 'Shipping address.', 'woocommerce' ), |
1265
|
|
|
'type' => 'array', |
1266
|
|
|
'context' => array( 'view', 'edit' ), |
1267
|
|
|
'properties' => array( |
1268
|
|
|
'first_name' => array( |
1269
|
|
|
'description' => __( 'First name.', 'woocommerce' ), |
1270
|
|
|
'type' => 'string', |
1271
|
|
|
'context' => array( 'view', 'edit' ), |
1272
|
|
|
), |
1273
|
|
|
'last_name' => array( |
1274
|
|
|
'description' => __( 'Last name.', 'woocommerce' ), |
1275
|
|
|
'type' => 'string', |
1276
|
|
|
'context' => array( 'view', 'edit' ), |
1277
|
|
|
), |
1278
|
|
|
'company' => array( |
1279
|
|
|
'description' => __( 'Company name.', 'woocommerce' ), |
1280
|
|
|
'type' => 'string', |
1281
|
|
|
'context' => array( 'view', 'edit' ), |
1282
|
|
|
), |
1283
|
|
|
'address_1' => array( |
1284
|
|
|
'description' => __( 'Address line 1.', 'woocommerce' ), |
1285
|
|
|
'type' => 'string', |
1286
|
|
|
'context' => array( 'view', 'edit' ), |
1287
|
|
|
), |
1288
|
|
|
'address_2' => array( |
1289
|
|
|
'description' => __( 'Address line 2.', 'woocommerce' ), |
1290
|
|
|
'type' => 'string', |
1291
|
|
|
'context' => array( 'view', 'edit' ), |
1292
|
|
|
), |
1293
|
|
|
'city' => array( |
1294
|
|
|
'description' => __( 'City name.', 'woocommerce' ), |
1295
|
|
|
'type' => 'string', |
1296
|
|
|
'context' => array( 'view', 'edit' ), |
1297
|
|
|
), |
1298
|
|
|
'state' => array( |
1299
|
|
|
'description' => __( 'ISO code or name of the state, province or district.', 'woocommerce' ), |
1300
|
|
|
'type' => 'string', |
1301
|
|
|
'context' => array( 'view', 'edit' ), |
1302
|
|
|
), |
1303
|
|
|
'postcode' => array( |
1304
|
|
|
'description' => __( 'Postal code.', 'woocommerce' ), |
1305
|
|
|
'type' => 'string', |
1306
|
|
|
'context' => array( 'view', 'edit' ), |
1307
|
|
|
), |
1308
|
|
|
'country' => array( |
1309
|
|
|
'description' => __( 'Country code in ISO 3166-1 alpha-2 format.', 'woocommerce' ), |
1310
|
|
|
'type' => 'string', |
1311
|
|
|
'context' => array( 'view', 'edit' ), |
1312
|
|
|
), |
1313
|
|
|
), |
1314
|
|
|
), |
1315
|
|
|
'payment_method' => array( |
1316
|
|
|
'description' => __( 'Payment method ID.', 'woocommerce' ), |
1317
|
|
|
'type' => 'string', |
1318
|
|
|
'context' => array( 'view', 'edit' ), |
1319
|
|
|
), |
1320
|
|
|
'payment_method_title' => array( |
1321
|
|
|
'description' => __( 'Payment method title.', 'woocommerce' ), |
1322
|
|
|
'type' => 'string', |
1323
|
|
|
'context' => array( 'view', 'edit' ), |
1324
|
|
|
), |
1325
|
|
|
'set_paid' => array( |
1326
|
|
|
'description' => __( 'Define if the order is paid. It will set the status to processing and reduce stock items.', 'woocommerce' ), |
1327
|
|
|
'type' => 'boolean', |
1328
|
|
|
'default' => false, |
1329
|
|
|
'context' => array( 'edit' ), |
1330
|
|
|
), |
1331
|
|
|
'transaction_id' => array( |
1332
|
|
|
'description' => __( 'Unique transaction ID.', 'woocommerce' ), |
1333
|
|
|
'type' => 'string', |
1334
|
|
|
'context' => array( 'view', 'edit' ), |
1335
|
|
|
), |
1336
|
|
|
'customer_ip_address' => array( |
1337
|
|
|
'description' => __( "Customer's IP address.", 'woocommerce' ), |
1338
|
|
|
'type' => 'string', |
1339
|
|
|
'context' => array( 'view', 'edit' ), |
1340
|
|
|
'readonly' => true, |
1341
|
|
|
), |
1342
|
|
|
'customer_user_agent' => array( |
1343
|
|
|
'description' => __( 'User agent of the customer.', 'woocommerce' ), |
1344
|
|
|
'type' => 'string', |
1345
|
|
|
'context' => array( 'view', 'edit' ), |
1346
|
|
|
'readonly' => true, |
1347
|
|
|
), |
1348
|
|
|
'created_via' => array( |
1349
|
|
|
'description' => __( 'Shows where the order was created.', 'woocommerce' ), |
1350
|
|
|
'type' => 'string', |
1351
|
|
|
'context' => array( 'view', 'edit' ), |
1352
|
|
|
'readonly' => true, |
1353
|
|
|
), |
1354
|
|
|
'customer_note' => array( |
1355
|
|
|
'description' => __( 'Note left by customer during checkout.', 'woocommerce' ), |
1356
|
|
|
'type' => 'string', |
1357
|
|
|
'context' => array( 'view', 'edit' ), |
1358
|
|
|
), |
1359
|
|
|
'date_completed' => array( |
1360
|
|
|
'description' => __( "The date the order was completed, in the site's timezone.", 'woocommerce' ), |
1361
|
|
|
'type' => 'date-time', |
1362
|
|
|
'context' => array( 'view', 'edit' ), |
1363
|
|
|
'readonly' => true, |
1364
|
|
|
), |
1365
|
|
|
'date_paid' => array( |
1366
|
|
|
'description' => __( "The date the order has been paid, in the site's timezone.", 'woocommerce' ), |
1367
|
|
|
'type' => 'date-time', |
1368
|
|
|
'context' => array( 'view', 'edit' ), |
1369
|
|
|
'readonly' => true, |
1370
|
|
|
), |
1371
|
|
|
'cart_hash' => array( |
1372
|
|
|
'description' => __( 'MD5 hash of cart items to ensure orders are not modified.', 'woocommerce' ), |
1373
|
|
|
'type' => 'string', |
1374
|
|
|
'context' => array( 'view', 'edit' ), |
1375
|
|
|
'readonly' => true, |
1376
|
|
|
), |
1377
|
|
|
'line_items' => array( |
1378
|
|
|
'description' => __( 'Line items data.', 'woocommerce' ), |
1379
|
|
|
'type' => 'array', |
1380
|
|
|
'context' => array( 'view', 'edit' ), |
1381
|
|
|
'properties' => array( |
1382
|
|
|
'id' => array( |
1383
|
|
|
'description' => __( 'Item ID.', 'woocommerce' ), |
1384
|
|
|
'type' => 'integer', |
1385
|
|
|
'context' => array( 'view', 'edit' ), |
1386
|
|
|
'readonly' => true, |
1387
|
|
|
), |
1388
|
|
|
'name' => array( |
1389
|
|
|
'description' => __( 'Product name.', 'woocommerce' ), |
1390
|
|
|
'type' => 'string', |
1391
|
|
|
'context' => array( 'view', 'edit' ), |
1392
|
|
|
'readonly' => true, |
1393
|
|
|
), |
1394
|
|
|
'sku' => array( |
1395
|
|
|
'description' => __( 'Product SKU.', 'woocommerce' ), |
1396
|
|
|
'type' => 'string', |
1397
|
|
|
'context' => array( 'view', 'edit' ), |
1398
|
|
|
'readonly' => true, |
1399
|
|
|
), |
1400
|
|
|
'product_id' => array( |
1401
|
|
|
'description' => __( 'Product ID.', 'woocommerce' ), |
1402
|
|
|
'type' => 'integer', |
1403
|
|
|
'context' => array( 'view', 'edit' ), |
1404
|
|
|
), |
1405
|
|
|
'variation_id' => array( |
1406
|
|
|
'description' => __( 'Variation ID, if applicable.', 'woocommerce' ), |
1407
|
|
|
'type' => 'integer', |
1408
|
|
|
'context' => array( 'view', 'edit' ), |
1409
|
|
|
), |
1410
|
|
|
'quantity' => array( |
1411
|
|
|
'description' => __( 'Quantity ordered.', 'woocommerce' ), |
1412
|
|
|
'type' => 'integer', |
1413
|
|
|
'context' => array( 'view', 'edit' ), |
1414
|
|
|
), |
1415
|
|
|
'tax_class' => array( |
1416
|
|
|
'description' => __( 'Tax class of product.', 'woocommerce' ), |
1417
|
|
|
'type' => 'integer', |
1418
|
|
|
'context' => array( 'view', 'edit' ), |
1419
|
|
|
'readonly' => true, |
1420
|
|
|
), |
1421
|
|
|
'price' => array( |
1422
|
|
|
'description' => __( 'Product price.', 'woocommerce' ), |
1423
|
|
|
'type' => 'string', |
1424
|
|
|
'context' => array( 'view', 'edit' ), |
1425
|
|
|
'readonly' => true, |
1426
|
|
|
), |
1427
|
|
|
'subtotal' => array( |
1428
|
|
|
'description' => __( 'Line subtotal (before discounts).', 'woocommerce' ), |
1429
|
|
|
'type' => 'string', |
1430
|
|
|
'context' => array( 'view', 'edit' ), |
1431
|
|
|
), |
1432
|
|
|
'subtotal_tax' => array( |
1433
|
|
|
'description' => __( 'Line subtotal tax (before discounts).', 'woocommerce' ), |
1434
|
|
|
'type' => 'string', |
1435
|
|
|
'context' => array( 'view', 'edit' ), |
1436
|
|
|
), |
1437
|
|
|
'total' => array( |
1438
|
|
|
'description' => __( 'Line total (after discounts).', 'woocommerce' ), |
1439
|
|
|
'type' => 'string', |
1440
|
|
|
'context' => array( 'view', 'edit' ), |
1441
|
|
|
), |
1442
|
|
|
'total_tax' => array( |
1443
|
|
|
'description' => __( 'Line total tax (after discounts).', 'woocommerce' ), |
1444
|
|
|
'type' => 'string', |
1445
|
|
|
'context' => array( 'view', 'edit' ), |
1446
|
|
|
), |
1447
|
|
|
'taxes' => array( |
1448
|
|
|
'description' => __( 'Line taxes.', 'woocommerce' ), |
1449
|
|
|
'type' => 'array', |
1450
|
|
|
'context' => array( 'view', 'edit' ), |
1451
|
|
|
'readonly' => true, |
1452
|
|
|
'properties' => array( |
1453
|
|
|
'id' => array( |
1454
|
|
|
'description' => __( 'Tax rate ID.', 'woocommerce' ), |
1455
|
|
|
'type' => 'integer', |
1456
|
|
|
'context' => array( 'view', 'edit' ), |
1457
|
|
|
'readonly' => true, |
1458
|
|
|
), |
1459
|
|
|
'total' => array( |
1460
|
|
|
'description' => __( 'Tax total.', 'woocommerce' ), |
1461
|
|
|
'type' => 'string', |
1462
|
|
|
'context' => array( 'view', 'edit' ), |
1463
|
|
|
'readonly' => true, |
1464
|
|
|
), |
1465
|
|
|
'subtotal' => array( |
1466
|
|
|
'description' => __( 'Tax subtotal.', 'woocommerce' ), |
1467
|
|
|
'type' => 'string', |
1468
|
|
|
'context' => array( 'view', 'edit' ), |
1469
|
|
|
'readonly' => true, |
1470
|
|
|
), |
1471
|
|
|
), |
1472
|
|
|
), |
1473
|
|
|
'meta' => array( |
1474
|
|
|
'description' => __( 'Line item meta data.', 'woocommerce' ), |
1475
|
|
|
'type' => 'array', |
1476
|
|
|
'context' => array( 'view', 'edit' ), |
1477
|
|
|
'readonly' => true, |
1478
|
|
|
'properties' => array( |
1479
|
|
|
'key' => array( |
1480
|
|
|
'description' => __( 'Meta key.', 'woocommerce' ), |
1481
|
|
|
'type' => 'string', |
1482
|
|
|
'context' => array( 'view', 'edit' ), |
1483
|
|
|
'readonly' => true, |
1484
|
|
|
), |
1485
|
|
|
'label' => array( |
1486
|
|
|
'description' => __( 'Meta label.', 'woocommerce' ), |
1487
|
|
|
'type' => 'string', |
1488
|
|
|
'context' => array( 'view', 'edit' ), |
1489
|
|
|
'readonly' => true, |
1490
|
|
|
), |
1491
|
|
|
'value' => array( |
1492
|
|
|
'description' => __( 'Meta value.', 'woocommerce' ), |
1493
|
|
|
'type' => 'string', |
1494
|
|
|
'context' => array( 'view', 'edit' ), |
1495
|
|
|
'readonly' => true, |
1496
|
|
|
), |
1497
|
|
|
), |
1498
|
|
|
), |
1499
|
|
|
), |
1500
|
|
|
), |
1501
|
|
|
'tax_lines' => array( |
1502
|
|
|
'description' => __( 'Tax lines data.', 'woocommerce' ), |
1503
|
|
|
'type' => 'array', |
1504
|
|
|
'context' => array( 'view', 'edit' ), |
1505
|
|
|
'readonly' => true, |
1506
|
|
|
'properties' => array( |
1507
|
|
|
'id' => array( |
1508
|
|
|
'description' => __( 'Item ID.', 'woocommerce' ), |
1509
|
|
|
'type' => 'integer', |
1510
|
|
|
'context' => array( 'view', 'edit' ), |
1511
|
|
|
'readonly' => true, |
1512
|
|
|
), |
1513
|
|
|
'rate_code' => array( |
1514
|
|
|
'description' => __( 'Tax rate code.', 'woocommerce' ), |
1515
|
|
|
'type' => 'string', |
1516
|
|
|
'context' => array( 'view', 'edit' ), |
1517
|
|
|
'readonly' => true, |
1518
|
|
|
), |
1519
|
|
|
'rate_id' => array( |
1520
|
|
|
'description' => __( 'Tax rate ID.', 'woocommerce' ), |
1521
|
|
|
'type' => 'string', |
1522
|
|
|
'context' => array( 'view', 'edit' ), |
1523
|
|
|
'readonly' => true, |
1524
|
|
|
), |
1525
|
|
|
'label' => array( |
1526
|
|
|
'description' => __( 'Tax rate label.', 'woocommerce' ), |
1527
|
|
|
'type' => 'string', |
1528
|
|
|
'context' => array( 'view', 'edit' ), |
1529
|
|
|
'readonly' => true, |
1530
|
|
|
), |
1531
|
|
|
'compound' => array( |
1532
|
|
|
'description' => __( 'Show if is a compound tax rate.', 'woocommerce' ), |
1533
|
|
|
'type' => 'boolean', |
1534
|
|
|
'context' => array( 'view', 'edit' ), |
1535
|
|
|
'readonly' => true, |
1536
|
|
|
), |
1537
|
|
|
'tax_total' => array( |
1538
|
|
|
'description' => __( 'Tax total (not including shipping taxes).', 'woocommerce' ), |
1539
|
|
|
'type' => 'string', |
1540
|
|
|
'context' => array( 'view', 'edit' ), |
1541
|
|
|
'readonly' => true, |
1542
|
|
|
), |
1543
|
|
|
'shipping_tax_total' => array( |
1544
|
|
|
'description' => __( 'Shipping tax total.', 'woocommerce' ), |
1545
|
|
|
'type' => 'string', |
1546
|
|
|
'context' => array( 'view', 'edit' ), |
1547
|
|
|
'readonly' => true, |
1548
|
|
|
), |
1549
|
|
|
), |
1550
|
|
|
), |
1551
|
|
|
'shipping_lines' => array( |
1552
|
|
|
'description' => __( 'Shipping lines data.', 'woocommerce' ), |
1553
|
|
|
'type' => 'array', |
1554
|
|
|
'context' => array( 'view', 'edit' ), |
1555
|
|
|
'properties' => array( |
1556
|
|
|
'id' => array( |
1557
|
|
|
'description' => __( 'Item ID.', 'woocommerce' ), |
1558
|
|
|
'type' => 'integer', |
1559
|
|
|
'context' => array( 'view', 'edit' ), |
1560
|
|
|
'readonly' => true, |
1561
|
|
|
), |
1562
|
|
|
'method_title' => array( |
1563
|
|
|
'description' => __( 'Shipping method name.', 'woocommerce' ), |
1564
|
|
|
'type' => 'string', |
1565
|
|
|
'context' => array( 'view', 'edit' ), |
1566
|
|
|
), |
1567
|
|
|
'method_id' => array( |
1568
|
|
|
'description' => __( 'Shipping method ID.', 'woocommerce' ), |
1569
|
|
|
'type' => 'string', |
1570
|
|
|
'context' => array( 'view', 'edit' ), |
1571
|
|
|
), |
1572
|
|
|
'total' => array( |
1573
|
|
|
'description' => __( 'Line total (after discounts).', 'woocommerce' ), |
1574
|
|
|
'type' => 'string', |
1575
|
|
|
'context' => array( 'view', 'edit' ), |
1576
|
|
|
), |
1577
|
|
|
'total_tax' => array( |
1578
|
|
|
'description' => __( 'Line total tax (after discounts).', 'woocommerce' ), |
1579
|
|
|
'type' => 'string', |
1580
|
|
|
'context' => array( 'view', 'edit' ), |
1581
|
|
|
'readonly' => true, |
1582
|
|
|
), |
1583
|
|
|
'taxes' => array( |
1584
|
|
|
'description' => __( 'Line taxes.', 'woocommerce' ), |
1585
|
|
|
'type' => 'array', |
1586
|
|
|
'context' => array( 'view', 'edit' ), |
1587
|
|
|
'readonly' => true, |
1588
|
|
|
'properties' => array( |
1589
|
|
|
'id' => array( |
1590
|
|
|
'description' => __( 'Tax rate ID.', 'woocommerce' ), |
1591
|
|
|
'type' => 'integer', |
1592
|
|
|
'context' => array( 'view', 'edit' ), |
1593
|
|
|
'readonly' => true, |
1594
|
|
|
), |
1595
|
|
|
'total' => array( |
1596
|
|
|
'description' => __( 'Tax total.', 'woocommerce' ), |
1597
|
|
|
'type' => 'string', |
1598
|
|
|
'context' => array( 'view', 'edit' ), |
1599
|
|
|
'readonly' => true, |
1600
|
|
|
), |
1601
|
|
|
), |
1602
|
|
|
), |
1603
|
|
|
), |
1604
|
|
|
), |
1605
|
|
|
'fee_lines' => array( |
1606
|
|
|
'description' => __( 'Fee lines data.', 'woocommerce' ), |
1607
|
|
|
'type' => 'array', |
1608
|
|
|
'context' => array( 'view', 'edit' ), |
1609
|
|
|
'properties' => array( |
1610
|
|
|
'id' => array( |
1611
|
|
|
'description' => __( 'Item ID.', 'woocommerce' ), |
1612
|
|
|
'type' => 'integer', |
1613
|
|
|
'context' => array( 'view', 'edit' ), |
1614
|
|
|
'readonly' => true, |
1615
|
|
|
), |
1616
|
|
|
'name' => array( |
1617
|
|
|
'description' => __( 'Fee name.', 'woocommerce' ), |
1618
|
|
|
'type' => 'string', |
1619
|
|
|
'context' => array( 'view', 'edit' ), |
1620
|
|
|
), |
1621
|
|
|
'tax_class' => array( |
1622
|
|
|
'description' => __( 'Tax class of fee.', 'woocommerce' ), |
1623
|
|
|
'type' => 'string', |
1624
|
|
|
'context' => array( 'view', 'edit' ), |
1625
|
|
|
), |
1626
|
|
|
'tax_status' => array( |
1627
|
|
|
'description' => __( 'Tax status of fee.', 'woocommerce' ), |
1628
|
|
|
'type' => 'string', |
1629
|
|
|
'context' => array( 'view', 'edit' ), |
1630
|
|
|
), |
1631
|
|
|
'total' => array( |
1632
|
|
|
'description' => __( 'Line total (after discounts).', 'woocommerce' ), |
1633
|
|
|
'type' => 'string', |
1634
|
|
|
'context' => array( 'view', 'edit' ), |
1635
|
|
|
), |
1636
|
|
|
'total_tax' => array( |
1637
|
|
|
'description' => __( 'Line total tax (after discounts).', 'woocommerce' ), |
1638
|
|
|
'type' => 'string', |
1639
|
|
|
'context' => array( 'view', 'edit' ), |
1640
|
|
|
), |
1641
|
|
|
'taxes' => array( |
1642
|
|
|
'description' => __( 'Line taxes.', 'woocommerce' ), |
1643
|
|
|
'type' => 'array', |
1644
|
|
|
'context' => array( 'view', 'edit' ), |
1645
|
|
|
'readonly' => true, |
1646
|
|
|
'properties' => array( |
1647
|
|
|
'id' => array( |
1648
|
|
|
'description' => __( 'Tax rate ID.', 'woocommerce' ), |
1649
|
|
|
'type' => 'integer', |
1650
|
|
|
'context' => array( 'view', 'edit' ), |
1651
|
|
|
'readonly' => true, |
1652
|
|
|
), |
1653
|
|
|
'total' => array( |
1654
|
|
|
'description' => __( 'Tax total.', 'woocommerce' ), |
1655
|
|
|
'type' => 'string', |
1656
|
|
|
'context' => array( 'view', 'edit' ), |
1657
|
|
|
'readonly' => true, |
1658
|
|
|
), |
1659
|
|
|
'subtotal' => array( |
1660
|
|
|
'description' => __( 'Tax subtotal.', 'woocommerce' ), |
1661
|
|
|
'type' => 'string', |
1662
|
|
|
'context' => array( 'view', 'edit' ), |
1663
|
|
|
'readonly' => true, |
1664
|
|
|
), |
1665
|
|
|
), |
1666
|
|
|
), |
1667
|
|
|
), |
1668
|
|
|
), |
1669
|
|
|
'coupon_lines' => array( |
1670
|
|
|
'description' => __( 'Coupons line data.', 'woocommerce' ), |
1671
|
|
|
'type' => 'array', |
1672
|
|
|
'context' => array( 'view', 'edit' ), |
1673
|
|
|
'properties' => array( |
1674
|
|
|
'id' => array( |
1675
|
|
|
'description' => __( 'Item ID.', 'woocommerce' ), |
1676
|
|
|
'type' => 'integer', |
1677
|
|
|
'context' => array( 'view', 'edit' ), |
1678
|
|
|
'readonly' => true, |
1679
|
|
|
), |
1680
|
|
|
'code' => array( |
1681
|
|
|
'description' => __( 'Coupon code.', 'woocommerce' ), |
1682
|
|
|
'type' => 'string', |
1683
|
|
|
'context' => array( 'view', 'edit' ), |
1684
|
|
|
), |
1685
|
|
|
'discount' => array( |
1686
|
|
|
'description' => __( 'Discount total.', 'woocommerce' ), |
1687
|
|
|
'type' => 'string', |
1688
|
|
|
'context' => array( 'view', 'edit' ), |
1689
|
|
|
), |
1690
|
|
|
'discount_tax' => array( |
1691
|
|
|
'description' => __( 'Discount total tax.', 'woocommerce' ), |
1692
|
|
|
'type' => 'string', |
1693
|
|
|
'context' => array( 'view', 'edit' ), |
1694
|
|
|
'readonly' => true, |
1695
|
|
|
), |
1696
|
|
|
), |
1697
|
|
|
), |
1698
|
|
|
'refunds' => array( |
1699
|
|
|
'description' => __( 'List of refunds.', 'woocommerce' ), |
1700
|
|
|
'type' => 'array', |
1701
|
|
|
'context' => array( 'view', 'edit' ), |
1702
|
|
|
'readonly' => true, |
1703
|
|
|
'properties' => array( |
1704
|
|
|
'id' => array( |
1705
|
|
|
'description' => __( 'Refund ID.', 'woocommerce' ), |
1706
|
|
|
'type' => 'integer', |
1707
|
|
|
'context' => array( 'view', 'edit' ), |
1708
|
|
|
'readonly' => true, |
1709
|
|
|
), |
1710
|
|
|
'reason' => array( |
1711
|
|
|
'description' => __( 'Refund reason.', 'woocommerce' ), |
1712
|
|
|
'type' => 'string', |
1713
|
|
|
'context' => array( 'view', 'edit' ), |
1714
|
|
|
'readonly' => true, |
1715
|
|
|
), |
1716
|
|
|
'total' => array( |
1717
|
|
|
'description' => __( 'Refund total.', 'woocommerce' ), |
1718
|
|
|
'type' => 'string', |
1719
|
|
|
'context' => array( 'view', 'edit' ), |
1720
|
|
|
'readonly' => true, |
1721
|
|
|
), |
1722
|
|
|
), |
1723
|
|
|
), |
1724
|
|
|
), |
1725
|
|
|
); |
1726
|
|
|
|
1727
|
|
|
return $this->add_additional_fields_schema( $schema ); |
1728
|
|
|
} |
1729
|
|
|
|
1730
|
|
|
/** |
1731
|
|
|
* Get the query params for collections. |
1732
|
|
|
* |
1733
|
|
|
* @return array |
1734
|
|
|
*/ |
1735
|
|
|
public function get_collection_params() { |
1736
|
|
|
$params = parent::get_collection_params(); |
1737
|
|
|
|
1738
|
|
|
$params['status'] = array( |
1739
|
|
|
'default' => 'any', |
1740
|
|
|
'description' => __( 'Limit result set to orders assigned a specific status.', 'woocommerce' ), |
1741
|
|
|
'type' => 'string', |
1742
|
|
|
'enum' => array_merge( array( 'any' ), $this->get_order_statuses() ), |
1743
|
|
|
'sanitize_callback' => 'sanitize_key', |
1744
|
|
|
'validate_callback' => 'rest_validate_request_arg', |
1745
|
|
|
); |
1746
|
|
|
$params['customer'] = array( |
1747
|
|
|
'description' => __( 'Limit result set to orders assigned a specific customer.', 'woocommerce' ), |
1748
|
|
|
'type' => 'integer', |
1749
|
|
|
'sanitize_callback' => 'absint', |
1750
|
|
|
'validate_callback' => 'rest_validate_request_arg', |
1751
|
|
|
); |
1752
|
|
|
$params['product'] = array( |
1753
|
|
|
'description' => __( 'Limit result set to orders assigned a specific product.', 'woocommerce' ), |
1754
|
|
|
'type' => 'integer', |
1755
|
|
|
'sanitize_callback' => 'absint', |
1756
|
|
|
'validate_callback' => 'rest_validate_request_arg', |
1757
|
|
|
); |
1758
|
|
|
$params['dp'] = array( |
1759
|
|
|
'default' => 2, |
1760
|
|
|
'description' => __( 'Number of decimal points to use in each resource.', 'woocommerce' ), |
1761
|
|
|
'type' => 'integer', |
1762
|
|
|
'sanitize_callback' => 'absint', |
1763
|
|
|
'validate_callback' => 'rest_validate_request_arg', |
1764
|
|
|
); |
1765
|
|
|
|
1766
|
|
|
return $params; |
1767
|
|
|
} |
1768
|
|
|
} |
1769
|
|
|
|
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.