Completed
Push — master ( 6e0f26...ca93e0 )
by Mike
08:52
created

WC_REST_Orders_Controller::create_base_order()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
cc 1
eloc 2
c 2
b 0
f 0
nc 1
nop 2
dl 0
loc 3
rs 10
1
<?php
1 ignored issue
show
Coding Style Compatibility introduced by
For compatibility and reusability of your code, PSR1 recommends that a file should introduce either new symbols (like classes, functions, etc.) or have side-effects (like outputting something, or including other files), but not both at the same time. The first symbol is defined on line 23 and the first side effect is on line 14.

The PSR-1: Basic Coding Standard recommends that a file should either introduce new symbols, that is classes, functions, constants or similar, or have side effects. Side effects are anything that executes logic, like for example printing output, changing ini settings or writing to a file.

The idea behind this recommendation is that merely auto-loading a class should not change the state of an application. It also promotes a cleaner style of programming and makes your code less prone to errors, because the logic is not spread out all over the place.

To learn more about the PSR-1, please see the PHP-FIG site on the PSR-1.

Loading history...
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
	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, true ),
0 ignored issues
show
Documentation introduced by
true is of type boolean, but the function expects a string|null.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
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
		);
163
164
		// Add addresses.
165
		$data['billing']  = $order->get_address( 'billing' );
166
		$data['shipping'] = $order->get_address( 'shipping' );
167
168
		// Add line items.
169 View Code Duplication
		foreach ( $order->get_items() as $item_id => $item ) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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.

Loading history...
170
			$product      = $order->get_product_from_item( $item );
171
			$product_id   = 0;
172
			$variation_id = 0;
173
			$product_sku  = null;
174
175
			// Check if the product exists.
176
			if ( is_object( $product ) ) {
177
				$product_id   = $product->id;
178
				$variation_id = $product->variation_id;
179
				$product_sku  = $product->get_sku();
180
			}
181
182
			$meta = new WC_Order_Item_Meta( $item, $product );
183
184
			$item_meta = array();
185
186
			$hideprefix = 'true' === $request['all_item_meta'] ? null : '_';
187
188
			foreach ( $meta->get_formatted( $hideprefix ) as $meta_key => $formatted_meta ) {
189
				$item_meta[] = array(
190
					'key'   => $formatted_meta['key'],
191
					'label' => $formatted_meta['label'],
192
					'value' => $formatted_meta['value'],
193
				);
194
			}
195
196
			$line_item = array(
197
				'id'           => $item_id,
198
				'name'         => $item['name'],
199
				'sku'          => $product_sku,
200
				'product_id'   => (int) $product_id,
201
				'variation_id' => (int) $variation_id,
202
				'quantity'     => wc_stock_amount( $item['qty'] ),
203
				'tax_class'    => ! empty( $item['tax_class'] ) ? $item['tax_class'] : '',
204
				'price'        => wc_format_decimal( $order->get_item_total( $item, false, false ), $dp ),
205
				'subtotal'     => wc_format_decimal( $order->get_line_subtotal( $item, false, false ), $dp ),
206
				'subtotal_tax' => wc_format_decimal( $item['line_subtotal_tax'], $dp ),
207
				'total'        => wc_format_decimal( $order->get_line_total( $item, false, false ), $dp ),
208
				'total_tax'    => wc_format_decimal( $item['line_tax'], $dp ),
209
				'taxes'        => array(),
210
				'meta'         => $item_meta,
211
			);
212
213
			$item_line_taxes = maybe_unserialize( $item['line_tax_data'] );
214
			if ( isset( $item_line_taxes['total'] ) ) {
215
				$line_tax = array();
216
217
				foreach ( $item_line_taxes['total'] as $tax_rate_id => $tax ) {
218
					$line_tax[ $tax_rate_id ] = array(
219
						'id'       => $tax_rate_id,
220
						'total'    => $tax,
221
						'subtotal' => '',
222
					);
223
				}
224
225
				foreach ( $item_line_taxes['subtotal'] as $tax_rate_id => $tax ) {
226
					$line_tax[ $tax_rate_id ]['subtotal'] = $tax;
227
				}
228
229
				$line_item['taxes'] = array_values( $line_tax );
230
			}
231
232
			$data['line_items'][] = $line_item;
233
		}
234
235
		// Add taxes.
236
		foreach ( $order->get_items( 'tax' ) as $key => $tax ) {
237
			$tax_line = array(
238
				'id'                 => $key,
239
				'rate_code'          => $tax['name'],
240
				'rate_id'            => $tax['rate_id'],
241
				'label'              => isset( $tax['label'] ) ? $tax['label'] : $tax['name'],
242
				'compound'           => (bool) $tax['compound'],
243
				'tax_total'          => wc_format_decimal( $tax['tax_amount'], $dp ),
244
				'shipping_tax_total' => wc_format_decimal( $tax['shipping_tax_amount'], $dp ),
245
			);
246
247
			$data['tax_lines'][] = $tax_line;
248
		}
249
250
		// Add shipping.
251
		foreach ( $order->get_shipping_methods() as $shipping_item_id => $shipping_item ) {
252
			$shipping_line = array(
253
				'id'           => $shipping_item_id,
254
				'method_title' => $shipping_item['name'],
255
				'method_id'    => $shipping_item['method_id'],
256
				'total'        => wc_format_decimal( $shipping_item['cost'], $dp ),
257
				'total_tax'    => wc_format_decimal( '', $dp ),
258
				'taxes'        => array(),
259
			);
260
261
			$shipping_taxes = maybe_unserialize( $shipping_item['taxes'] );
262
263
			if ( ! empty( $shipping_taxes ) ) {
264
				$shipping_line['total_tax'] = wc_format_decimal( array_sum( $shipping_taxes ), $dp );
265
266
				foreach ( $shipping_taxes as $tax_rate_id => $tax ) {
267
					$shipping_line['taxes'][] = array(
268
						'id'       => $tax_rate_id,
269
						'total'    => $tax,
270
					);
271
				}
272
			}
273
274
			$data['shipping_lines'][] = $shipping_line;
275
		}
276
277
		// Add fees.
278
		foreach ( $order->get_fees() as $fee_item_id => $fee_item ) {
279
			$fee_line = array(
280
				'id'         => $fee_item_id,
281
				'name'       => $fee_item['name'],
282
				'tax_class'  => ! empty( $fee_item['tax_class'] ) ? $fee_item['tax_class'] : '',
283
				'tax_status' => 'taxable',
284
				'total'      => wc_format_decimal( $order->get_line_total( $fee_item ), $dp ),
285
				'total_tax'  => wc_format_decimal( $order->get_line_tax( $fee_item ), $dp ),
286
				'taxes'      => array(),
287
			);
288
289
			$fee_line_taxes = maybe_unserialize( $fee_item['line_tax_data'] );
290
			if ( isset( $fee_line_taxes['total'] ) ) {
291
				$fee_tax = array();
292
293
				foreach ( $fee_line_taxes['total'] as $tax_rate_id => $tax ) {
294
					$fee_tax[ $tax_rate_id ] = array(
295
						'id'       => $tax_rate_id,
296
						'total'    => $tax,
297
						'subtotal' => '',
298
					);
299
				}
300
301
				foreach ( $fee_line_taxes['subtotal'] as $tax_rate_id => $tax ) {
302
					$fee_tax[ $tax_rate_id ]['subtotal'] = $tax;
303
				}
304
305
				$fee_line['taxes'] = array_values( $fee_tax );
306
			}
307
308
			$data['fee_lines'][] = $fee_line;
309
		}
310
311
		// Add coupons.
312
		foreach ( $order->get_items( 'coupon' ) as $coupon_item_id => $coupon_item ) {
313
			$coupon_line = array(
314
				'id'           => $coupon_item_id,
315
				'code'         => $coupon_item['name'],
316
				'discount'     => wc_format_decimal( $coupon_item['discount_amount'], $dp ),
317
				'discount_tax' => wc_format_decimal( $coupon_item['discount_amount_tax'], $dp ),
318
			);
319
320
			$data['coupon_lines'][] = $coupon_line;
321
		}
322
323
		$context = ! empty( $request['context'] ) ? $request['context'] : 'view';
324
		$data    = $this->add_additional_fields_to_object( $data, $request );
325
		$data    = $this->filter_response_by_context( $data, $context );
326
327
		// Wrap the data in a response object.
328
		$response = rest_ensure_response( $data );
329
330
		$response->add_links( $this->prepare_links( $order ) );
331
332
		/**
333
		 * Filter the data for a response.
334
		 *
335
		 * The dynamic portion of the hook name, $this->post_type, refers to post_type of the post being
336
		 * prepared for the response.
337
		 *
338
		 * @param WP_REST_Response   $response   The response object.
339
		 * @param WP_Post            $post       Post object.
340
		 * @param WP_REST_Request    $request    Request object.
341
		 */
342
		return apply_filters( "woocommerce_rest_prepare_{$this->post_type}", $response, $post, $request );
343
	}
344
345
	/**
346
	 * Prepare links for the request.
347
	 *
348
	 * @param WC_Order $order Order object.
349
	 * @return array Links for the given order.
350
	 */
351
	protected function prepare_links( $order ) {
352
		$links = array(
353
			'self' => array(
354
				'href' => rest_url( sprintf( '/%s/%s/%d', $this->namespace, $this->rest_base, $order->id ) ),
355
			),
356
			'collection' => array(
357
				'href' => rest_url( sprintf( '/%s/%s', $this->namespace, $this->rest_base ) ),
358
			),
359
		);
360
361
		if ( 0 !== (int) $order->get_user_id() ) {
362
			$links['customer'] = array(
363
				'href' => rest_url( sprintf( '/%s/customers/%d', $this->namespace, $order->get_user_id() ) ),
364
			);
365
		}
366
367 View Code Duplication
		if ( 0 !== (int) $order->post->post_parent ) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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.

Loading history...
368
			$links['up'] = array(
369
				'href' => rest_url( sprintf( '/%s/orders/%d', $this->namespace, $order->post->post_parent ) ),
370
			);
371
		}
372
373
		return $links;
374
	}
375
376
	/**
377
	 * Query args.
378
	 *
379
	 * @param array $args
380
	 * @param WP_REST_Request $request
381
	 * @return array
382
	 */
383
	public function query_args( $args, $request ) {
384
		global $wpdb;
385
386
		// Set post_status.
387
		if ( 'any' !== $request['status'] ) {
388
			$args['post_status'] = 'wc-' . $request['status'];
389
		} else {
390
			$args['post_status'] = 'any';
391
		}
392
393 View Code Duplication
		if ( ! empty( $request['customer'] ) ) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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.

Loading history...
394
			if ( ! empty( $args['meta_query'] ) ) {
395
				$args['meta_query'] = array();
396
			}
397
398
			$args['meta_query'][] = array(
399
				'key'   => '_customer_user',
400
				'value' => $request['customer'],
401
				'type'  => 'NUMERIC',
402
			);
403
		}
404
405
		if ( ! empty( $request['product'] ) ) {
406
			$order_ids = $wpdb->get_col( $wpdb->prepare( "
407
				SELECT order_id
408
				FROM {$wpdb->prefix}woocommerce_order_items
409
				WHERE order_item_id IN ( SELECT order_item_id FROM {$wpdb->prefix}woocommerce_order_itemmeta WHERE meta_key = '_product_id' AND meta_value = %d )
410
				AND order_item_type = 'line_item'
411
			 ", $request['product'] ) );
412
413
			// Force WP_Query return empty if don't found any order.
414
			$order_ids = ! empty( $order_ids ) ? $order_ids : array( 0 );
415
416
			$args['post__in'] = $order_ids;
417
		}
418
419
		return $args;
420
	}
421
422
	/**
423
	 * Create order.
424
	 *
425
	 * @param WP_REST_Request $request Full details about the request.
426
	 * @return int|WP_Error
427
	 */
428
	protected function create_order( $request ) {
429
		wc_transaction_query( 'start' );
430
431
		try {
432
			// Make sure customer exists.
433
			if ( 0 !== $request['customer_id'] && false === get_user_by( 'id', $request['customer_id'] ) ) {
434
				throw new WC_REST_Exception( 'woocommerce_rest_invalid_customer_id',__( 'Customer ID is invalid.', 'woocommerce' ), 400 );
435
			}
436
437
			$order = $this->create_base_order( array(
438
				'status'        => $request['status'],
439
				'customer_id'   => $request['customer_id'],
440
				'customer_note' => $request['customer_note'],
441
				'created_via'   => 'rest-api',
442
			), $request );
443
444 View Code Duplication
			if ( is_wp_error( $order ) ) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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.

Loading history...
445
				throw new WC_REST_Exception( 'woocommerce_rest_cannot_create_order', sprintf( __( 'Cannot create order: %s.', 'woocommerce' ), implode( ', ', $order->get_error_messages() ) ), 400 );
1 ignored issue
show
Bug introduced by
The method get_error_messages() does not seem to exist on object<WC_Order>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
446
			}
447
448
			// Set addresses.
449
			if ( is_array( $request['billing'] ) ) {
450
				$this->update_address( $order, $request['billing'], 'billing' );
451
			}
452
			if ( is_array( $request['shipping'] ) ) {
453
				$this->update_address( $order, $request['shipping'], 'shipping' );
454
			}
455
456
			// Set currency.
457
			update_post_meta( $order->id, '_order_currency', $request['currency'] );
458
459
			// Set lines.
460
			$lines = array(
461
				'line_item' => 'line_items',
462
				'shipping'  => 'shipping_lines',
463
				'fee'       => 'fee_lines',
464
				'coupon'    => 'coupon_lines',
465
			);
466
467 View Code Duplication
			foreach ( $lines as $line_type => $line ) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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.

Loading history...
468
				if ( is_array( $request[ $line ] ) ) {
469
					foreach ( $request[ $line ] as $item ) {
470
						$set_item = 'set_' . $line_type;
471
						$new_item = $this->$set_item( $order, $item, 'create' );
0 ignored issues
show
Unused Code introduced by
$new_item is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
472
					}
473
				}
474
			}
475
476
			// Calculate totals and set them.
477
			$order->calculate_totals();
478
479
			// Set payment method.
480
			if ( ! empty( $request['payment_method'] ) ) {
481
				update_post_meta( $order->id, '_payment_method', $request['payment_method'] );
482
			}
483
			if ( ! empty( $request['payment_method_title'] ) ) {
484
				update_post_meta( $order->id, '_payment_method_title', $request['payment_method'] );
485
			}
486
			if ( true === $request['set_paid'] ) {
487
				$order->payment_complete( $request['transaction_id'] );
488
			}
489
490
			// Set meta data.
491 View Code Duplication
			if ( ! empty( $request['meta_data'] ) && is_array( $request['meta_data'] ) ) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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.

Loading history...
492
				$this->update_meta_data( $order->id, $request['meta_data'] );
493
			}
494
495
			wc_transaction_query( 'commit' );
496
497
			return $order->id;
498
		} catch ( WC_REST_Exception $e ) {
499
			wc_transaction_query( 'rollback' );
500
501
			return new WP_Error( $e->getErrorCode(), $e->getMessage(), array( 'status' => $e->getCode() ) );
502
		}
503
	}
504
505
	/**
506
	 * Update address.
507
	 *
508
	 * @param WC_Order $order
509
	 * @param array $posted
510
	 * @param string $type
511
	 */
512
	protected function update_address( $order, $posted, $type = 'billing' ) {
513
		$fields = $order->get_address( $type );
514
515
		foreach ( array_keys( $fields ) as $field ) {
516
			if ( isset( $posted[ $field ] ) ) {
517
				$fields[ $field ] = $posted[ $field ];
518
			}
519
		}
520
521
		// Set address.
522
		$order->set_address( $fields, $type );
523
524
		// Update user meta.
525
		if ( $order->get_user_id() ) {
526
			foreach ( $fields as $key => $value ) {
527
				update_user_meta( $order->get_user_id(), $type . '_' . $key, $value );
528
			}
529
		}
530
	}
531
532
	/**
533
	 * Create or update a line item.
534
	 *
535
	 * @param WC_Order $order Order data.
536
	 * @param array $item Line item data.
537
	 * @param string $action 'create' to add line item or 'update' to update it.
538
	 * @throws WC_REST_Exception Invalid data, server error.
539
	 */
540
	protected function set_line_item( $order, $item, $action = 'create' ) {
541
		$creating  = 'create' === $action;
542
		$item_args = array();
543
544
		// Product is always required.
545
		if ( empty( $item['product_id'] ) && empty( $item['sku'] ) && empty( $item['variation_id'] ) ) {
546
			throw new WC_REST_Exception( 'woocommerce_rest_required_product_reference', __( 'Product ID or SKU is required.', 'woocommerce' ), 400 );
547
		}
548
549
		if ( ! empty( $item['product_id'] ) ) {
550
			$product_id = (int) $item['product_id'];
551
		} else if ( ! empty( $item['sku'] ) ) {
552
			$product_id = (int) wc_get_product_id_by_sku( $item['sku'] );
553
		} else if ( ! empty( $item['variation_id'] ) ) {
554
			$product_id = (int) $item['variation_id'];
555
		}
556
557
		// When updating, ensure product ID provided matches.
558
		if ( 'update' === $action && ! empty( $item['id'] ) ) {
559
			$item_product_id   = (int) wc_get_order_item_meta( $item['id'], '_product_id' );
560
			$item_variation_id = (int) wc_get_order_item_meta( $item['id'], '_variation_id' );
561
562
			if ( $product_id !== $item_product_id && $product_id !== $item_variation_id ) {
563
				throw new WC_REST_Exception( 'woocommerce_rest_required_product_reference', __( 'Product ID or variation ID provided does not match this line item.', 'woocommerce' ), 400 );
564
			}
565
		}
566
567
		$product = wc_get_product( $product_id );
568
569
		// Must be a valid WC_Product.
570
		if ( ! is_object( $product ) ) {
571
			throw new WC_REST_Exception( 'woocommerce_rest_invalid_product', __( 'Product is invalid.', 'woocommerce' ), 400 );
572
		}
573
574
		// Quantity must be positive float.
575
		if ( isset( $item['quantity'] ) && 0 >= floatval( $item['quantity'] ) ) {
576
			throw new WC_REST_Exception( 'woocommerce_rest_invalid_product_quantity', __( 'Product quantity must be a positive float.', 'woocommerce' ), 400 );
577
		}
578
579
		// Quantity is required when creating.
580
		if ( $creating && ! isset( $item['quantity'] ) ) {
581
			throw new WC_REST_Exception( 'woocommerce_rest_invalid_product_quantity', __( 'Product quantity is required.', 'woocommerce' ), 400 );
582
		}
583
584
		// Get variation attributes.
585
		if ( method_exists( $product, 'get_variation_attributes' ) ) {
586
			$item_args['variation'] = $product->get_variation_attributes();
587
		}
588
589
		// Quantity.
590
		if ( isset( $item['quantity'] ) ) {
591
			$item_args['qty'] = $item['quantity'];
592
		}
593
594
		// Total.
595
		if ( isset( $item['total'] ) ) {
596
			$item_args['totals']['total'] = floatval( $item['total'] );
597
		}
598
599
		// Total tax.
600
		if ( isset( $item['total_tax'] ) ) {
601
			$item_args['totals']['tax'] = floatval( $item['total_tax'] );
602
		}
603
604
		// Subtotal.
605
		if ( isset( $item['subtotal'] ) ) {
606
			$item_args['totals']['subtotal'] = floatval( $item['subtotal'] );
607
		}
608
609
		// Subtotal tax.
610
		if ( isset( $item['subtotal_tax'] ) ) {
611
			$item_args['totals']['subtotal_tax'] = floatval( $item['subtotal_tax'] );
612
		}
613
614 View Code Duplication
		if ( $creating ) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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.

Loading history...
615
			$item_id = $order->add_product( $product, $item_args['qty'], $item_args );
616
			if ( ! $item_id ) {
617
				throw new WC_REST_Exception( 'woocommerce_rest_cannot_create_line_item', __( 'Cannot create line item, try again.', 'woocommerce' ), 500 );
618
			}
619
		} else {
620
			$item_id = $order->update_product( $item['id'], $product, $item_args );
621
			if ( ! $item_id ) {
622
				throw new WC_REST_Exception( 'woocommerce_rest_cannot_update_line_item', __( 'Cannot update line item, try again.', 'woocommerce' ), 500 );
623
			}
624
		}
625
	}
626
627
	/**
628
	 * Create or update an order shipping method.
629
	 *
630
	 * @param WC_Order $order Order data.
631
	 * @param array $shipping Item data.
632
	 * @param string $action 'create' to add shipping or 'update' to update it.
633
	 * @throws WC_REST_Exception Invalid data, server error.
634
	 */
635
	protected function set_shipping( $order, $shipping, $action ) {
636
		// Total must be a positive float.
637
		if ( ! empty( $shipping['total'] ) && 0 > floatval( $shipping['total'] ) ) {
638
			throw new WC_REST_Exception( 'woocommerce_rest_invalid_shipping_total', __( 'Shipping total must be a positive amount.', 'woocommerce' ), 400 );
639
		}
640
641
		if ( 'create' === $action ) {
642
			// Method ID is required.
643
			if ( empty( $shipping['method_id'] ) ) {
644
				throw new WC_REST_Exception( 'woocommerce_rest_invalid_shipping_item', __( 'Shipping method ID is required.', 'woocommerce' ), 400 );
645
			}
646
647
			$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'] );
648
649
			$shipping_id = $order->add_shipping( $rate );
650
651
			if ( ! $shipping_id ) {
652
				throw new WC_REST_Exception( 'woocommerce_rest_cannot_create_shipping', __( 'Cannot create shipping method, try again.', 'woocommerce' ), 500 );
653
			}
654
655
		} else {
656
			$shipping_args = array();
657
658
			if ( isset( $shipping['method_id'] ) ) {
659
				$shipping_args['method_id'] = $shipping['method_id'];
660
			}
661
662
			if ( isset( $shipping['method_title'] ) ) {
663
				$shipping_args['method_title'] = $shipping['method_title'];
664
			}
665
666
			if ( isset( $shipping['total'] ) ) {
667
				$shipping_args['cost'] = floatval( $shipping['total'] );
668
			}
669
670
			$shipping_id = $order->update_shipping( $shipping['id'], $shipping_args );
671
672
			if ( ! $shipping_id ) {
673
				throw new WC_REST_Exception( 'woocommerce_rest_cannot_update_shipping', __( 'Cannot update shipping method, try again.', 'woocommerce' ), 500 );
674
			}
675
		}
676
	}
677
678
	/**
679
	 * Create or update an order fee.
680
	 *
681
	 * @param WC_Order $order Order data.
682
	 * @param array $fee Item data.
683
	 * @param string $action 'create' to add fee or 'update' to update it.
684
	 * @throws WC_REST_Exception Invalid data, server error.
685
	 */
686
	protected function set_fee( $order, $fee, $action ) {
687
		if ( 'create' === $action ) {
688
689
			// Fee name is required.
690
			if ( empty( $fee['name'] ) ) {
691
				throw new WC_REST_Exception( 'woocommerce_rest_invalid_fee_item', __( 'Fee name is required.', 'woocommerce' ), 400 );
692
			}
693
694
			$fee_data            = new stdClass();
695
			$fee_data->id        = sanitize_title( $fee['name'] );
696
			$fee_data->name      = $fee['name'];
697
			$fee_data->amount    = isset( $fee['total'] ) ? floatval( $fee['total'] ) : 0;
698
			$fee_data->taxable   = false;
699
			$fee_data->tax       = 0;
700
			$fee_data->tax_data  = array();
701
			$fee_data->tax_class = '';
702
703
			// If taxable, tax class and total are required.
704
			if ( isset( $fee['tax_status'] ) && 'taxable' === $fee['tax_status'] ) {
705
706
				if ( ! isset( $fee['tax_class'] ) ) {
707
					throw new WC_REST_Exception( 'woocommerce_rest_invalid_fee_item', __( 'Fee tax class is required when fee is taxable.', 'woocommerce' ), 400 );
708
				}
709
710
				$fee_data->taxable   = true;
711
				$fee_data->tax_class = $fee['tax_class'];
712
713
				if ( isset( $fee['total_tax'] ) ) {
714
					$fee_data->tax = isset( $fee['total_tax'] ) ? wc_format_refund_total( $fee['total_tax'] ) : 0;
715
				}
716
			}
717
718
			$fee_id = $order->add_fee( $fee_data );
719
720
			if ( ! $fee_id ) {
721
				throw new WC_REST_Exception( 'woocommerce_rest_cannot_create_fee', __( 'Cannot create fee, try again.', 'woocommerce' ), 500 );
722
			}
723
724
		} else {
725
			$fee_args = array();
726
727
			if ( isset( $fee['name'] ) ) {
728
				$fee_args['name'] = $fee['name'];
729
			}
730
731
			if ( isset( $fee['tax_class'] ) ) {
732
				$fee_args['tax_class'] = $fee['tax_class'];
733
			}
734
735
			if ( isset( $fee['total'] ) ) {
736
				$fee_args['line_total'] = floatval( $fee['total'] );
737
			}
738
739
			if ( isset( $fee['total_tax'] ) ) {
740
				$fee_args['line_tax'] = floatval( $fee['total_tax'] );
741
			}
742
743
			$fee_id = $order->update_fee( $fee['id'], $fee_args );
744
745
			if ( ! $fee_id ) {
746
				throw new WC_REST_Exception( 'woocommerce_rest_cannot_update_fee', __( 'Cannot update fee, try again.', 'woocommerce' ), 500 );
747
			}
748
		}
749
	}
750
751
	/**
752
	 * Create or update an order coupon.
753
	 *
754
	 * @param WC_Order $order Order data.
755
	 * @param array $coupon Item data.
756
	 * @param string $action 'create' to add coupon or 'update' to update it.
757
	 * @throws WC_REST_Exception Invalid data, server error.
758
	 */
759
	protected function set_coupon( $order, $coupon, $action ) {
760
		// Coupon discount must be positive float.
761
		if ( isset( $coupon['discount'] ) && 0 > floatval( $coupon['discount'] ) ) {
762
			throw new WC_REST_Exception( 'woocommerce_rest_invalid_coupon_total', __( 'Coupon discount must be a positive amount.', 'woocommerce' ), 400 );
763
		}
764
765
		if ( 'create' === $action ) {
766
			// Coupon code is required.
767
			if ( empty( $coupon['code'] ) ) {
768
				throw new WC_REST_Exception( 'woocommerce_rest_invalid_coupon_coupon', __( 'Coupon code is required.', 'woocommerce' ), 400 );
769
			}
770
771
			$coupon_id = $order->add_coupon( $coupon['code'], floatval( $coupon['discount'] ) );
772
773
			if ( ! $coupon_id ) {
774
				throw new WC_REST_Exception( 'woocommerce_rest_cannot_create_order_coupon', __( 'Cannot create coupon, try again.', 'woocommerce' ), 500 );
775
			}
776
777
		} else {
778
			$coupon_args = array();
779
780
			if ( isset( $coupon['code'] ) ) {
781
				$coupon_args['code'] = $coupon['code'];
782
			}
783
784
			if ( isset( $coupon['discount'] ) ) {
785
				$coupon_args['discount_amount'] = floatval( $coupon['discount'] );
786
			}
787
788
			$coupon_id = $order->update_coupon( $coupon['id'], $coupon_args );
789
790
			if ( ! $coupon_id ) {
791
				throw new WC_REST_Exception( 'woocommerce_rest_cannot_update_order_coupon', __( 'Cannot update coupon, try again.', 'woocommerce' ), 500 );
792
			}
793
		}
794
	}
795
796
	/**
797
	 * Helper method to add/update meta data, with two restrictions:
798
	 *
799
	 * 1) Only non-protected meta (no leading underscore) can be set
800
	 * 2) Meta values must be scalar (int, string, bool)
801
	 *
802
	 * @param WC_Order $order Order data.
0 ignored issues
show
Bug introduced by
There is no parameter named $order. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
803
	 * @param array $meta_data Meta data in array( 'meta_key' => 'meta_value' ) format.
804
	 */
805 View Code Duplication
	protected function update_meta_data( $order_id, $meta_data ) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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.

Loading history...
806
		foreach ( $meta_data as $meta_key => $meta_value ) {
807
			if ( is_string( $meta_key ) && ! is_protected_meta( $meta_key ) && is_scalar( $meta_value ) ) {
808
				update_post_meta( $order_id, $meta_key, $meta_value );
809
			}
810
		}
811
	}
812
813
	/**
814
	 * Create a single item.
815
	 *
816
	 * @param WP_REST_Request $request Full details about the request.
817
	 * @return WP_Error|WP_REST_Response
818
	 */
819
	public function create_item( $request ) {
820
		if ( ! empty( $request['id'] ) ) {
821
			return new WP_Error( "woocommerce_rest_{$this->post_type}_exists", sprintf( __( 'Cannot create existing %s.', 'woocommerce' ), $this->post_type ), array( 'status' => 400 ) );
822
		}
823
824
		$order_id = $this->create_order( $request );
825
		if ( is_wp_error( $order_id ) ) {
826
			return $order_id;
827
		}
828
829
		// Clear transients.
830
		wc_delete_shop_order_transients( $order_id );
831
832
		$post = get_post( $order_id );
833
		$this->update_additional_fields_for_object( $post, $request );
834
835
		/**
836
		 * Fires after a single item is created or updated via the REST API.
837
		 *
838
		 * @param object          $post      Inserted object (not a WP_Post object).
839
		 * @param WP_REST_Request $request   Request object.
840
		 * @param boolean         $creating  True when creating item, false when updating.
841
		 */
842
		do_action( "woocommerce_rest_insert_{$this->post_type}", $post, $request, true );
843
844
		$request->set_param( 'context', 'edit' );
845
		$response = $this->prepare_item_for_response( $post, $request );
846
		$response = rest_ensure_response( $response );
847
		$response->set_status( 201 );
848
		$response->header( 'Location', rest_url( sprintf( '/%s/%s/%d', $this->namespace, $this->rest_base, $post->ID ) ) );
849
850
		return $response;
851
	}
852
853
	/**
854
	 * Wrapper method to create/update order items.
855
	 * When updating, the item ID provided is checked to ensure it is associated
856
	 * with the order.
857
	 *
858
	 * @param WC_Order $order order
859
	 * @param string $item_type
860
	 * @param array $item item provided in the request body
861
	 * @param string $action either 'create' or 'update'
862
	 * @throws WC_REST_Exception If item ID is not associated with order
863
	 */
864 View Code Duplication
	protected function set_item( $order, $item_type, $item, $action ) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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.

Loading history...
865
		global $wpdb;
866
867
		$set_method = 'set_' . $item_type;
868
869
		// Verify provided line item ID is associated with order.
870
		if ( 'update' === $action ) {
871
			$result = $wpdb->get_row(
872
				$wpdb->prepare( "SELECT * FROM {$wpdb->prefix}woocommerce_order_items WHERE order_item_id = %d AND order_id = %d",
873
				absint( $item['id'] ),
874
				absint( $order->id )
875
			) );
876
877
			if ( is_null( $result ) ) {
878
				throw new WC_REST_Exception( 'woocommerce_rest_invalid_item_id', __( 'Order item ID provided is not associated with order.', 'woocommerce' ), 400 );
879
			}
880
		}
881
882
		$this->$set_method( $order, $item, $action );
883
	}
884
885
	/**
886
	 * Helper method to check if the resource ID associated with the provided item is null.
887
	 * Items can be deleted by setting the resource ID to null.
888
	 *
889
	 * @param array $item Item provided in the request body.
890
	 * @return bool True if the item resource ID is null, false otherwise.
891
	 */
892
	protected function item_is_null( $item ) {
893
		$keys = array( 'product_id', 'method_id', 'title', 'code' );
894
895
		foreach ( $keys as $key ) {
896
			if ( array_key_exists( $key, $item ) && is_null( $item[ $key ] ) ) {
897
				return true;
898
			}
899
		}
900
901
		return false;
902
	}
903
904
	/**
905
	 * Update order.
906
	 *
907
	 * @param WP_REST_Request $request Full details about the request.
908
	 * @param WP_Post $post Post data.
909
	 * @return int|WP_Error
910
	 */
911
	protected function update_order( $request, $post ) {
912
		try {
913
			$update_totals = false;
914
			$order         = wc_get_order( $post );
915
			$order_args    = array( 'order_id' => $order->id );
916
917
			// Customer note.
918
			if ( isset( $request['customer_note'] ) ) {
919
				$order_args['customer_note'] = $request['customer_note'];
920
			}
921
922
			// Customer ID.
923
			if ( isset( $request['customer_id'] ) && $request['customer_id'] != $order->get_user_id() ) {
924
				// Make sure customer exists.
925
				if ( false === get_user_by( 'id', $request['customer_id'] ) ) {
926
					throw new WC_REST_Exception( 'woocommerce_rest_invalid_customer_id', __( 'Customer ID is invalid.', 'woocommerce' ), 400 );
927
				}
928
929
				update_post_meta( $order->id, '_customer_user', $request['customer_id'] );
930
			}
931
932
			// Update addresses.
933
			if ( is_array( $request['billing'] ) ) {
934
				$this->update_address( $order, $request['billing'], 'billing' );
935
			}
936
			if ( is_array( $request['shipping'] ) ) {
937
				$this->update_address( $order, $request['shipping'], 'shipping' );
938
			}
939
940
			$lines = array(
941
				'line_item' => 'line_items',
942
				'shipping'  => 'shipping_lines',
943
				'fee'       => 'fee_lines',
944
				'coupon'    => 'coupon_lines',
945
			);
946
947
			foreach ( $lines as $line_type => $line ) {
948
				if ( isset( $request[ $line ] ) && is_array( $request[ $line ] ) ) {
949
					$update_totals = true;
950
					foreach ( $request[ $line ] as $item ) {
951
						// Item ID is always required.
952
						if ( ! array_key_exists( 'id', $item ) ) {
953
							throw new WC_REST_Exception( 'woocommerce_rest_invalid_item_id', __( 'Order item ID is required.', 'woocommerce' ), 400 );
954
						}
955
956
						// Create item.
957
						if ( is_null( $item['id'] ) ) {
958
							$this->set_item( $order, $line_type, $item, 'create' );
959
						} elseif ( $this->item_is_null( $item ) ) {
960
							// Delete item.
961
							wc_delete_order_item( $item['id'] );
962
						} else {
963
							// Update item.
964
							$this->set_item( $order, $line_type, $item, 'update' );
965
						}
966
					}
967
				}
968
			}
969
970
			// Set payment method.
971
			if ( ! empty( $request['payment_method'] ) ) {
972
				update_post_meta( $order->id, '_payment_method', $request['payment_method'] );
973
			}
974
			if ( ! empty( $request['payment_method_title'] ) ) {
975
				update_post_meta( $order->id, '_payment_method_title', $request['payment_method'] );
976
			}
977
			if ( $order->needs_payment() && isset( $request['set_paid'] ) && true === $request['set_paid'] ) {
978
				$order->payment_complete( ! empty( $request['transaction_id'] ) ? $request['transaction_id'] : '' );
979
			}
980
981
			// Set order currency.
982
			if ( isset( $request['currency'] ) ) {
983
				update_post_meta( $order->id, '_order_currency', $request['currency'] );
984
			}
985
986
			// If items have changed, recalculate order totals.
987
			if ( $update_totals ) {
988
				$order->calculate_totals();
989
			}
990
991
			// Update meta data.
992 View Code Duplication
			if ( ! empty( $request['meta_data'] ) && is_array( $request['meta_data'] ) ) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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.

Loading history...
993
				$this->update_meta_data( $order->id, $request['meta_data'] );
994
			}
995
996
			// Update the order post to set customer note/modified date.
997
			wc_update_order( $order_args );
998
999
			// Order status.
1000 View Code Duplication
			if ( ! empty( $request['status'] ) ) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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.

Loading history...
1001
				$order->update_status( $request['status'], isset( $request['status_note'] ) ? $request['status_note'] : '' );
1002
			}
1003
1004
			return $order->id;
1005
		} catch ( WC_REST_Exception $e ) {
1006
			return new WP_Error( $e->getErrorCode(), $e->getMessage(), array( 'status' => $e->getCode() ) );
1007
		}
1008
	}
1009
1010
	/**
1011
	 * Update a single order.
1012
	 *
1013
	 * @param WP_REST_Request $request Full details about the request.
1014
	 * @return WP_Error|WP_REST_Response
1015
	 */
1016
	public function update_item( $request ) {
1017
		$id   = (int) $request['id'];
1018
		$post = get_post( $id );
1019
1020
		if ( empty( $id ) || empty( $post->ID ) || $this->post_type !== $post->post_type ) {
1021
			return new WP_Error( "woocommerce_rest_{$this->post_type}_invalid_id", __( 'ID is invalid.', 'woocommerce' ), array( 'status' => 400 ) );
1022
		}
1023
1024
		$order_id = $this->update_order( $request, $post );
1025
		if ( is_wp_error( $order_id ) ) {
1026
			return $order_id;
1027
		}
1028
1029
		// Clear transients.
1030
		wc_delete_shop_order_transients( $order_id );
1031
1032
		$post = get_post( $order_id );
1033
		$this->update_additional_fields_for_object( $post, $request );
1034
1035
		/**
1036
		 * Fires after a single item is created or updated via the REST API.
1037
		 *
1038
		 * @param object          $post      Inserted object (not a WP_Post object).
1039
		 * @param WP_REST_Request $request   Request object.
1040
		 * @param boolean         $creating  True when creating item, false when updating.
1041
		 */
1042
		do_action( "woocommerce_rest_insert_{$this->post_type}", $post, $request, false );
1043
1044
		$request->set_param( 'context', 'edit' );
1045
		$response = $this->prepare_item_for_response( $post, $request );
1046
		return rest_ensure_response( $response );
1047
	}
1048
1049
	/**
1050
	 * Get order statuses.
1051
	 *
1052
	 * @return array
1053
	 */
1054
	protected function get_order_statuses() {
1055
		$order_statuses = array();
1056
1057
		foreach ( array_keys( wc_get_order_statuses() ) as $status ) {
1058
			$order_statuses[] = str_replace( 'wc-', '', $status );
1059
		}
1060
1061
		return $order_statuses;
1062
	}
1063
1064
	/**
1065
	 * Get the Order's schema, conforming to JSON Schema.
1066
	 *
1067
	 * @return array
1068
	 */
1069
	public function get_item_schema() {
1070
		$schema = array(
1071
			'$schema'    => 'http://json-schema.org/draft-04/schema#',
1072
			'title'      => $this->post_type,
1073
			'type'       => 'object',
1074
			'properties' => array(
1075
				'id' => array(
1076
					'description' => __( 'Unique identifier for the resource.', 'woocommerce' ),
1077
					'type'        => 'integer',
1078
					'context'     => array( 'view', 'edit' ),
1079
					'readonly'    => true,
1080
				),
1081
				'parent_id' => array(
1082
					'description' => __( 'Parent order ID.', 'woocommerce' ),
1083
					'type'        => 'integer',
1084
					'context'     => array( 'view', 'edit' ),
1085
				),
1086
				'status' => array(
1087
					'description' => __( 'Order status.', 'woocommerce' ),
1088
					'type'        => 'string',
1089
					'default'     => 'pending',
1090
					'enum'        => $this->get_order_statuses(),
1091
					'context'     => array( 'view', 'edit' ),
1092
				),
1093
				'order_key' => array(
1094
					'description' => __( 'Order key.', 'woocommerce' ),
1095
					'type'        => 'string',
1096
					'context'     => array( 'view', 'edit' ),
1097
					'readonly'    => true,
1098
				),
1099
				'currency' => array(
1100
					'description' => __( 'Currency the order was created with, in ISO format.', 'woocommerce' ),
1101
					'type'        => 'string',
1102
					'default'     => get_woocommerce_currency(),
1103
					'enum'        => array_keys( get_woocommerce_currencies() ),
1104
					'context'     => array( 'view', 'edit' ),
1105
				),
1106
				'version' => array(
1107
					'description' => __( 'Version of WooCommerce when the order was made.', 'woocommerce' ),
1108
					'type'        => 'integer',
1109
					'context'     => array( 'view', 'edit' ),
1110
					'readonly'    => true,
1111
				),
1112
				'prices_include_tax' => array(
1113
					'description' => __( 'Shows if the prices included tax during checkout.', 'woocommerce' ),
1114
					'type'        => 'boolean',
1115
					'context'     => array( 'view', 'edit' ),
1116
					'readonly'    => true,
1117
				),
1118
				'date_created' => array(
1119
					'description' => __( "The date the order was created, in the site's timezone.", 'woocommerce' ),
1120
					'type'        => 'date-time',
1121
					'context'     => array( 'view', 'edit' ),
1122
					'readonly'    => true,
1123
				),
1124
				'date_modified' => array(
1125
					'description' => __( "The date the order was last modified, in the site's timezone.", 'woocommerce' ),
1126
					'type'        => 'date-time',
1127
					'context'     => array( 'view', 'edit' ),
1128
					'readonly'    => true,
1129
				),
1130
				'customer_id' => array(
1131
					'description' => __( 'User ID who owns the order. 0 for guests.', 'woocommerce' ),
1132
					'type'        => 'integer',
1133
					'default'     => 0,
1134
					'context'     => array( 'view', 'edit' ),
1135
				),
1136
				'discount_total' => array(
1137
					'description' => __( 'Total discount amount for the order.', 'woocommerce' ),
1138
					'type'        => 'string',
1139
					'context'     => array( 'view', 'edit' ),
1140
					'readonly'    => true,
1141
				),
1142
				'discount_tax' => array(
1143
					'description' => __( 'Total discount tax amount for the order.', 'woocommerce' ),
1144
					'type'        => 'string',
1145
					'context'     => array( 'view', 'edit' ),
1146
					'readonly'    => true,
1147
				),
1148
				'shipping_total' => array(
1149
					'description' => __( 'Total shipping amount for the order.', 'woocommerce' ),
1150
					'type'        => 'string',
1151
					'context'     => array( 'view', 'edit' ),
1152
					'readonly'    => true,
1153
				),
1154
				'shipping_tax' => array(
1155
					'description' => __( 'Total shipping tax amount for the order.', 'woocommerce' ),
1156
					'type'        => 'string',
1157
					'context'     => array( 'view', 'edit' ),
1158
					'readonly'    => true,
1159
				),
1160
				'cart_tax' => array(
1161
					'description' => __( 'Sum of line item taxes only.', 'woocommerce' ),
1162
					'type'        => 'string',
1163
					'context'     => array( 'view', 'edit' ),
1164
					'readonly'    => true,
1165
				),
1166
				'total' => array(
1167
					'description' => __( 'Grand total.', 'woocommerce' ),
1168
					'type'        => 'string',
1169
					'context'     => array( 'view', 'edit' ),
1170
					'readonly'    => true,
1171
				),
1172
				'total_tax' => array(
1173
					'description' => __( 'Sum of all taxes.', 'woocommerce' ),
1174
					'type'        => 'string',
1175
					'context'     => array( 'view', 'edit' ),
1176
					'readonly'    => true,
1177
				),
1178
				'billing' => array(
1179
					'description' => __( 'Billing address.', 'woocommerce' ),
1180
					'type'        => 'array',
1181
					'context'     => array( 'view', 'edit' ),
1182
					'properties'  => array(
1183
						'first_name' => array(
1184
							'description' => __( 'First name.', 'woocommerce' ),
1185
							'type'        => 'string',
1186
							'context'     => array( 'view', 'edit' ),
1187
						),
1188
						'last_name' => array(
1189
							'description' => __( 'Last name.', 'woocommerce' ),
1190
							'type'        => 'string',
1191
							'context'     => array( 'view', 'edit' ),
1192
						),
1193
						'company' => array(
1194
							'description' => __( 'Company name.', 'woocommerce' ),
1195
							'type'        => 'string',
1196
							'context'     => array( 'view', 'edit' ),
1197
						),
1198
						'address_1' => array(
1199
							'description' => __( 'Address line 1.', 'woocommerce' ),
1200
							'type'        => 'string',
1201
							'context'     => array( 'view', 'edit' ),
1202
						),
1203
						'address_2' => array(
1204
							'description' => __( 'Address line 2.', 'woocommerce' ),
1205
							'type'        => 'string',
1206
							'context'     => array( 'view', 'edit' ),
1207
						),
1208
						'city' => array(
1209
							'description' => __( 'City name.', 'woocommerce' ),
1210
							'type'        => 'string',
1211
							'context'     => array( 'view', 'edit' ),
1212
						),
1213
						'state' => array(
1214
							'description' => __( 'ISO code or name of the state, province or district.', 'woocommerce' ),
1215
							'type'        => 'string',
1216
							'context'     => array( 'view', 'edit' ),
1217
						),
1218
						'postcode' => array(
1219
							'description' => __( 'Postal code.', 'woocommerce' ),
1220
							'type'        => 'string',
1221
							'context'     => array( 'view', 'edit' ),
1222
						),
1223
						'country' => array(
1224
							'description' => __( 'Country code in ISO 3166-1 alpha-2 format.', 'woocommerce' ),
1225
							'type'        => 'string',
1226
							'context'     => array( 'view', 'edit' ),
1227
						),
1228
						'email' => array(
1229
							'description' => __( 'Email address.', 'woocommerce' ),
1230
							'type'        => 'string',
1231
							'format'      => 'email',
1232
							'context'     => array( 'view', 'edit' ),
1233
						),
1234
						'phone' => array(
1235
							'description' => __( 'Phone number.', 'woocommerce' ),
1236
							'type'        => 'string',
1237
							'context'     => array( 'view', 'edit' ),
1238
						),
1239
					),
1240
				),
1241
				'shipping' => array(
1242
					'description' => __( 'Shipping address.', 'woocommerce' ),
1243
					'type'        => 'array',
1244
					'context'     => array( 'view', 'edit' ),
1245
					'properties'  => array(
1246
						'first_name' => array(
1247
							'description' => __( 'First name.', 'woocommerce' ),
1248
							'type'        => 'string',
1249
							'context'     => array( 'view', 'edit' ),
1250
						),
1251
						'last_name' => array(
1252
							'description' => __( 'Last name.', 'woocommerce' ),
1253
							'type'        => 'string',
1254
							'context'     => array( 'view', 'edit' ),
1255
						),
1256
						'company' => array(
1257
							'description' => __( 'Company name.', 'woocommerce' ),
1258
							'type'        => 'string',
1259
							'context'     => array( 'view', 'edit' ),
1260
						),
1261
						'address_1' => array(
1262
							'description' => __( 'Address line 1.', 'woocommerce' ),
1263
							'type'        => 'string',
1264
							'context'     => array( 'view', 'edit' ),
1265
						),
1266
						'address_2' => array(
1267
							'description' => __( 'Address line 2.', 'woocommerce' ),
1268
							'type'        => 'string',
1269
							'context'     => array( 'view', 'edit' ),
1270
						),
1271
						'city' => array(
1272
							'description' => __( 'City name.', 'woocommerce' ),
1273
							'type'        => 'string',
1274
							'context'     => array( 'view', 'edit' ),
1275
						),
1276
						'state' => array(
1277
							'description' => __( 'ISO code or name of the state, province or district.', 'woocommerce' ),
1278
							'type'        => 'string',
1279
							'context'     => array( 'view', 'edit' ),
1280
						),
1281
						'postcode' => array(
1282
							'description' => __( 'Postal code.', 'woocommerce' ),
1283
							'type'        => 'string',
1284
							'context'     => array( 'view', 'edit' ),
1285
						),
1286
						'country' => array(
1287
							'description' => __( 'Country code in ISO 3166-1 alpha-2 format.', 'woocommerce' ),
1288
							'type'        => 'string',
1289
							'context'     => array( 'view', 'edit' ),
1290
						),
1291
					),
1292
				),
1293
				'payment_method' => array(
1294
					'description' => __( 'Payment method ID.', 'woocommerce' ),
1295
					'type'        => 'string',
1296
					'context'     => array( 'view', 'edit' ),
1297
				),
1298
				'payment_method_title' => array(
1299
					'description' => __( 'Payment method title.', 'woocommerce' ),
1300
					'type'        => 'string',
1301
					'context'     => array( 'view', 'edit' ),
1302
				),
1303
				'set_paid' => array(
1304
					'description' => __( 'Define if the order is paid. It will set the status to processing and reduce stock items.', 'woocommerce' ),
1305
					'type'        => 'boolean',
1306
					'default'     => false,
1307
					'context'     => array( 'view', 'edit' ),
1308
					'writeonly'   => true,
1309
				),
1310
				'transaction_id' => array(
1311
					'description' => __( 'Unique transaction ID.', 'woocommerce' ),
1312
					'type'        => 'boolean',
1313
					'context'     => array( 'view', 'edit' ),
1314
				),
1315
				'customer_ip_address' => array(
1316
					'description' => __( "Customer's IP address.", 'woocommerce' ),
1317
					'type'        => 'string',
1318
					'context'     => array( 'view', 'edit' ),
1319
					'readonly'    => true,
1320
				),
1321
				'customer_user_agent' => array(
1322
					'description' => __( 'User agent of the customer.', 'woocommerce' ),
1323
					'type'        => 'string',
1324
					'context'     => array( 'view', 'edit' ),
1325
					'readonly'    => true,
1326
				),
1327
				'created_via' => array(
1328
					'description' => __( 'Shows where the order was created.', 'woocommerce' ),
1329
					'type'        => 'string',
1330
					'context'     => array( 'view', 'edit' ),
1331
					'readonly'    => true,
1332
				),
1333
				'customer_note' => array(
1334
					'description' => __( 'Note left by customer during checkout.', 'woocommerce' ),
1335
					'type'        => 'string',
1336
					'context'     => array( 'view', 'edit' ),
1337
				),
1338
				'date_completed' => array(
1339
					'description' => __( "The date the order was completed, in the site's timezone.", 'woocommerce' ),
1340
					'type'        => 'date-time',
1341
					'context'     => array( 'view', 'edit' ),
1342
					'readonly'    => true,
1343
				),
1344
				'date_paid' => array(
1345
					'description' => __( "The date the order has been paid, in the site's timezone.", 'woocommerce' ),
1346
					'type'        => 'date-time',
1347
					'context'     => array( 'view', 'edit' ),
1348
					'readonly'    => true,
1349
				),
1350
				'cart_hash' => array(
1351
					'description' => __( 'MD5 hash of cart items to ensure orders are not modified.', 'woocommerce' ),
1352
					'type'        => 'float',
1353
					'context'     => array( 'view', 'edit' ),
1354
					'readonly'    => true,
1355
				),
1356
				'line_items' => array(
1357
					'description' => __( 'Line items data.', 'woocommerce' ),
1358
					'type'        => 'array',
1359
					'context'     => array( 'view', 'edit' ),
1360
					'properties'  => array(
1361
						'id' => array(
1362
							'description' => __( 'Item ID.', 'woocommerce' ),
1363
							'type'        => 'integer',
1364
							'context'     => array( 'view', 'edit' ),
1365
							'readonly'    => true,
1366
						),
1367
						'name' => array(
1368
							'description' => __( 'Product name.', 'woocommerce' ),
1369
							'type'        => 'integer',
1370
							'context'     => array( 'view', 'edit' ),
1371
							'readonly'    => true,
1372
						),
1373
						'sku' => array(
1374
							'description' => __( 'Product SKU.', 'woocommerce' ),
1375
							'type'        => 'string',
1376
							'context'     => array( 'view', 'edit' ),
1377
							'readonly'    => true,
1378
						),
1379
						'product_id' => array(
1380
							'description' => __( 'Product ID.', 'woocommerce' ),
1381
							'type'        => 'integer',
1382
							'context'     => array( 'view', 'edit' ),
1383
						),
1384
						'variation_id' => array(
1385
							'description' => __( 'Variation ID, if applicable.', 'woocommerce' ),
1386
							'type'        => 'integer',
1387
							'context'     => array( 'view', 'edit' ),
1388
						),
1389
						'quantity' => array(
1390
							'description' => __( 'Quantity ordered.', 'woocommerce' ),
1391
							'type'        => 'integer',
1392
							'context'     => array( 'view', 'edit' ),
1393
						),
1394
						'tax_class' => array(
1395
							'description' => __( 'Tax class of product.', 'woocommerce' ),
1396
							'type'        => 'integer',
1397
							'context'     => array( 'view', 'edit' ),
1398
							'readonly'    => true,
1399
						),
1400
						'price' => array(
1401
							'description' => __( 'Product price.', 'woocommerce' ),
1402
							'type'        => 'string',
1403
							'context'     => array( 'view', 'edit' ),
1404
							'readonly'    => true,
1405
						),
1406
						'subtotal' => array(
1407
							'description' => __( 'Line subtotal (before discounts).', 'woocommerce' ),
1408
							'type'        => 'string',
1409
							'context'     => array( 'view', 'edit' ),
1410
						),
1411
						'subtotal_tax' => array(
1412
							'description' => __( 'Line subtotal tax (before discounts).', 'woocommerce' ),
1413
							'type'        => 'string',
1414
							'context'     => array( 'view', 'edit' ),
1415
						),
1416
						'total' => array(
1417
							'description' => __( 'Line total (after discounts).', 'woocommerce' ),
1418
							'type'        => 'string',
1419
							'context'     => array( 'view', 'edit' ),
1420
						),
1421
						'total_tax' => array(
1422
							'description' => __( 'Line total tax (after discounts).', 'woocommerce' ),
1423
							'type'        => 'string',
1424
							'context'     => array( 'view', 'edit' ),
1425
						),
1426
						'taxes' => array(
1427
							'description' => __( 'Line total tax.', 'woocommerce' ),
1428
							'type'        => 'array',
1429
							'context'     => array( 'view', 'edit' ),
1430
							'readonly'    => true,
1431
							'properties'  => array(
1432
								'id' => array(
1433
									'description' => __( 'Tax rate ID.', 'woocommerce' ),
1434
									'type'        => 'integer',
1435
									'context'     => array( 'view', 'edit' ),
1436
									'readonly'    => true,
1437
								),
1438
								'total' => array(
1439
									'description' => __( 'Tax total.', 'woocommerce' ),
1440
									'type'        => 'string',
1441
									'context'     => array( 'view', 'edit' ),
1442
									'readonly'    => true,
1443
								),
1444
								'subtotal' => array(
1445
									'description' => __( 'Tax subtotal.', 'woocommerce' ),
1446
									'type'        => 'string',
1447
									'context'     => array( 'view', 'edit' ),
1448
									'readonly'    => true,
1449
								),
1450
							),
1451
						),
1452
						'meta' => array(
1453
							'description' => __( 'Line item meta data.', 'woocommerce' ),
1454
							'type'        => 'array',
1455
							'context'     => array( 'view', 'edit' ),
1456
							'readonly'    => true,
1457
							'properties'  => array(
1458
								'key' => array(
1459
									'description' => __( 'Meta key.', 'woocommerce' ),
1460
									'type'        => 'string',
1461
									'context'     => array( 'view', 'edit' ),
1462
									'readonly'    => true,
1463
								),
1464
								'label' => array(
1465
									'description' => __( 'Meta label.', 'woocommerce' ),
1466
									'type'        => 'string',
1467
									'context'     => array( 'view', 'edit' ),
1468
									'readonly'    => true,
1469
								),
1470
								'value' => array(
1471
									'description' => __( 'Meta value.', 'woocommerce' ),
1472
									'type'        => 'string',
1473
									'context'     => array( 'view', 'edit' ),
1474
									'readonly'    => true,
1475
								),
1476
							),
1477
						),
1478
					),
1479
				),
1480
				'tax_lines' => array(
1481
					'description' => __( 'Tax lines data.', 'woocommerce' ),
1482
					'type'        => 'array',
1483
					'context'     => array( 'view', 'edit' ),
1484
					'readonly'    => true,
1485
					'properties'  => array(
1486
						'id' => array(
1487
							'description' => __( 'Item ID.', 'woocommerce' ),
1488
							'type'        => 'integer',
1489
							'context'     => array( 'view', 'edit' ),
1490
							'readonly'    => true,
1491
						),
1492
						'rate_code' => array(
1493
							'description' => __( 'Tax rate code.', 'woocommerce' ),
1494
							'type'        => 'string',
1495
							'context'     => array( 'view', 'edit' ),
1496
							'readonly'    => true,
1497
						),
1498
						'rate_id' => array(
1499
							'description' => __( 'Tax rate ID.', 'woocommerce' ),
1500
							'type'        => 'string',
1501
							'context'     => array( 'view', 'edit' ),
1502
							'readonly'    => true,
1503
						),
1504
						'label' => array(
1505
							'description' => __( 'Tax rate label.', 'woocommerce' ),
1506
							'type'        => 'string',
1507
							'context'     => array( 'view', 'edit' ),
1508
							'readonly'    => true,
1509
						),
1510
						'compound' => array(
1511
							'description' => __( 'Show if is a compound tax rate.', 'woocommerce' ),
1512
							'type'        => 'boolean',
1513
							'context'     => array( 'view', 'edit' ),
1514
							'readonly'    => true,
1515
						),
1516
						'tax_total' => array(
1517
							'description' => __( 'Tax total (not including shipping taxes).', 'woocommerce' ),
1518
							'type'        => 'string',
1519
							'context'     => array( 'view', 'edit' ),
1520
							'readonly'    => true,
1521
						),
1522
						'shipping_tax_total' => array(
1523
							'description' => __( 'Shipping tax total.', 'woocommerce' ),
1524
							'type'        => 'string',
1525
							'context'     => array( 'view', 'edit' ),
1526
							'readonly'    => true,
1527
						),
1528
					),
1529
				),
1530
				'shipping_lines' => array(
1531
					'description' => __( 'Shipping lines data.', 'woocommerce' ),
1532
					'type'        => 'array',
1533
					'context'     => array( 'view', 'edit' ),
1534
					'properties'  => array(
1535
						'id' => array(
1536
							'description' => __( 'Item ID.', 'woocommerce' ),
1537
							'type'        => 'integer',
1538
							'context'     => array( 'view', 'edit' ),
1539
							'readonly'    => true,
1540
						),
1541
						'method_title' => array(
1542
							'description' => __( 'Shipping method name.', 'woocommerce' ),
1543
							'type'        => 'string',
1544
							'context'     => array( 'view', 'edit' ),
1545
						),
1546
						'method_id' => array(
1547
							'description' => __( 'Shipping method ID.', 'woocommerce' ),
1548
							'type'        => 'integer',
1549
							'context'     => array( 'view', 'edit' ),
1550
						),
1551
						'total' => array(
1552
							'description' => __( 'Line total (after discounts).', 'woocommerce' ),
1553
							'type'        => 'string',
1554
							'context'     => array( 'view', 'edit' ),
1555
						),
1556
						'total_tax' => array(
1557
							'description' => __( 'Line total tax (after discounts).', 'woocommerce' ),
1558
							'type'        => 'string',
1559
							'context'     => array( 'view', 'edit' ),
1560
							'readonly'    => true,
1561
						),
1562
						'taxes' => array(
1563
							'description' => __( 'Line total tax.', 'woocommerce' ),
1564
							'type'        => 'array',
1565
							'context'     => array( 'view', 'edit' ),
1566
							'readonly'    => true,
1567
							'properties'  => array(
1568
								'id' => array(
1569
									'description' => __( 'Tax rate ID.', 'woocommerce' ),
1570
									'type'        => 'integer',
1571
									'context'     => array( 'view', 'edit' ),
1572
									'readonly'    => true,
1573
								),
1574
								'total' => array(
1575
									'description' => __( 'Tax total.', 'woocommerce' ),
1576
									'type'        => 'string',
1577
									'context'     => array( 'view', 'edit' ),
1578
									'readonly'    => true,
1579
								),
1580
							),
1581
						),
1582
					),
1583
				),
1584
				'fee_lines' => array(
1585
					'description' => __( 'Fee lines data.', 'woocommerce' ),
1586
					'type'        => 'array',
1587
					'context'     => array( 'view', 'edit' ),
1588
					'properties'  => array(
1589
						'id' => array(
1590
							'description' => __( 'Item ID.', 'woocommerce' ),
1591
							'type'        => 'integer',
1592
							'context'     => array( 'view', 'edit' ),
1593
							'readonly'    => true,
1594
						),
1595
						'name' => array(
1596
							'description' => __( 'Fee name.', 'woocommerce' ),
1597
							'type'        => 'string',
1598
							'context'     => array( 'view', 'edit' ),
1599
						),
1600
						'tax_class' => array(
1601
							'description' => __( 'Tax class of fee.', 'woocommerce' ),
1602
							'type'        => 'string',
1603
							'context'     => array( 'view', 'edit' ),
1604
						),
1605
						'tax_status' => array(
1606
							'description' => __( 'Tax status of fee.', 'woocommerce' ),
1607
							'type'        => 'string',
1608
							'context'     => array( 'view', 'edit' ),
1609
						),
1610
						'total' => array(
1611
							'description' => __( 'Line total tax (after discounts).', 'woocommerce' ),
1612
							'type'        => 'string',
1613
							'context'     => array( 'view', 'edit' ),
1614
						),
1615
						'total_tax' => array(
1616
							'description' => __( 'Line total tax (after discounts).', 'woocommerce' ),
1617
							'type'        => 'string',
1618
							'context'     => array( 'view', 'edit' ),
1619
						),
1620
						'taxes' => array(
1621
							'description' => __( 'Line total tax.', 'woocommerce' ),
1622
							'type'        => 'array',
1623
							'context'     => array( 'view', 'edit' ),
1624
							'readonly'    => true,
1625
							'properties'  => array(
1626
								'id' => array(
1627
									'description' => __( 'Tax rate ID.', 'woocommerce' ),
1628
									'type'        => 'integer',
1629
									'context'     => array( 'view', 'edit' ),
1630
									'readonly'    => true,
1631
								),
1632
								'total' => array(
1633
									'description' => __( 'Tax total.', 'woocommerce' ),
1634
									'type'        => 'string',
1635
									'context'     => array( 'view', 'edit' ),
1636
									'readonly'    => true,
1637
								),
1638
								'subtotal' => array(
1639
									'description' => __( 'Tax subtotal.', 'woocommerce' ),
1640
									'type'        => 'string',
1641
									'context'     => array( 'view', 'edit' ),
1642
									'readonly'    => true,
1643
								),
1644
							),
1645
						),
1646
					),
1647
				),
1648
				'coupon_lines' => array(
1649
					'description' => __( 'Coupons line data.', 'woocommerce' ),
1650
					'type'        => 'array',
1651
					'context'     => array( 'view', 'edit' ),
1652
					'properties'  => array(
1653
						'id' => array(
1654
							'description' => __( 'Item ID.', 'woocommerce' ),
1655
							'type'        => 'integer',
1656
							'context'     => array( 'view', 'edit' ),
1657
							'readonly'    => true,
1658
						),
1659
						'code' => array(
1660
							'description' => __( 'Coupon code.', 'woocommerce' ),
1661
							'type'        => 'string',
1662
							'context'     => array( 'view', 'edit' ),
1663
						),
1664
						'discount' => array(
1665
							'description' => __( 'Discount total.', 'woocommerce' ),
1666
							'type'        => 'string',
1667
							'context'     => array( 'view', 'edit' ),
1668
						),
1669
						'discount_tax' => array(
1670
							'description' => __( 'Discount total tax.', 'woocommerce' ),
1671
							'type'        => 'string',
1672
							'context'     => array( 'view', 'edit' ),
1673
							'readonly'    => true,
1674
						),
1675
					),
1676
				),
1677
			),
1678
		);
1679
1680
		return $this->add_additional_fields_schema( $schema );
1681
	}
1682
1683
	/**
1684
	 * Get the query params for collections.
1685
	 *
1686
	 * @return array
1687
	 */
1688
	public function get_collection_params() {
1689
		$params = parent::get_collection_params();
1690
1691
		$params['status'] = array(
1692
			'default'           => 'any',
1693
			'description'       => __( 'Limit result set to orders assigned a specific status.', 'woocommerce' ),
1694
			'type'              => 'string',
1695
			'enum'              => array_merge( array( 'any' ), $this->get_order_statuses() ),
1696
			'sanitize_callback' => 'sanitize_key',
1697
			'validate_callback' => 'rest_validate_request_arg',
1698
		);
1699
		$params['customer'] = array(
1700
			'description'       => __( 'Limit result set to orders assigned a specific customer.', 'woocommerce' ),
1701
			'type'              => 'integer',
1702
			'sanitize_callback' => 'absint',
1703
			'validate_callback' => 'rest_validate_request_arg',
1704
		);
1705
		$params['product'] = array(
1706
			'description'       => __( 'Limit result set to orders assigned a specific product.', 'woocommerce' ),
1707
			'type'              => 'integer',
1708
			'sanitize_callback' => 'absint',
1709
			'validate_callback' => 'rest_validate_request_arg',
1710
		);
1711
		$params['dp'] = array(
1712
			'default'           => 2,
1713
			'description'       => __( 'Number of decimal points to use in each resource.', 'woocommerce' ),
1714
			'type'              => 'integer',
1715
			'sanitize_callback' => 'absint',
1716
			'validate_callback' => 'rest_validate_request_arg',
1717
		);
1718
1719
		return $params;
1720
	}
1721
1722
	/**
1723
	 * Create base WC Order object.
1724
	 *
1725
	 * @since 2.6
1726
	 * @param array $args
1727
	 * @param array $data
1728
	 * @return WC_Order
1729
	 */
1730
	protected function create_base_order( $args, $data ) {
0 ignored issues
show
Unused Code introduced by
The parameter $data is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
1731
		return wc_create_order( $args );
1732
	}
1733
}
1734