Passed
Push — master ( 5bd17a...71a32c )
by Mike
04:53
created

OrderRefunds::get_order_item_data()   C

Complexity

Conditions 14
Paths 180

Size

Total Lines 44
Code Lines 24

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 14
eloc 24
nc 180
nop 2
dl 0
loc 44
rs 5.6
c 0
b 0
f 0

How to fix   Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
/**
3
 * REST API Order Refunds controller
4
 *
5
 * Handles requests to the /orders/<order_id>/refunds endpoint.
6
 *
7
 * @package WooCommerce/RestApi
8
 */
9
10
namespace WooCommerce\RestApi\Controllers\Version4;
11
12
defined( 'ABSPATH' ) || exit;
13
14
/**
15
 * REST API Order Refunds controller class.
16
 */
17
class OrderRefunds extends Orders {
18
19
	/**
20
	 * Route base.
21
	 *
22
	 * @var string
23
	 */
24
	protected $rest_base = 'orders/(?P<order_id>[\d]+)/refunds';
25
26
	/**
27
	 * Post type.
28
	 *
29
	 * @var string
30
	 */
31
	protected $post_type = 'shop_order_refund';
32
33
	/**
34
	 * Order refunds actions.
35
	 */
36
	public function __construct() {
37
		add_filter( "woocommerce_rest_{$this->post_type}_object_trashable", '__return_false' );
38
	}
39
40
	/**
41
	 * Register the routes for order refunds.
42
	 */
43
	public function register_routes() {
44
		register_rest_route(
45
			$this->namespace,
46
			'/' . $this->rest_base,
47
			array(
48
				'args'   => array(
49
					'order_id' => array(
50
						'description' => __( 'The order ID.', 'woocommerce' ),
51
						'type'        => 'integer',
52
					),
53
				),
54
				array(
55
					'methods'             => \WP_REST_Server::READABLE,
56
					'callback'            => array( $this, 'get_items' ),
57
					'permission_callback' => array( $this, 'get_items_permissions_check' ),
58
					'args'                => $this->get_collection_params(),
59
				),
60
				array(
61
					'methods'             => \WP_REST_Server::CREATABLE,
62
					'callback'            => array( $this, 'create_item' ),
63
					'permission_callback' => array( $this, 'create_item_permissions_check' ),
64
					'args'                => $this->get_endpoint_args_for_item_schema( \WP_REST_Server::CREATABLE ),
65
				),
66
				'schema' => array( $this, 'get_public_item_schema' ),
67
			),
68
			true
69
		);
70
71
		register_rest_route(
72
			$this->namespace,
73
			'/' . $this->rest_base . '/(?P<id>[\d]+)',
74
			array(
75
				'args'   => array(
76
					'order_id' => array(
77
						'description' => __( 'The order ID.', 'woocommerce' ),
78
						'type'        => 'integer',
79
					),
80
					'id'       => array(
81
						'description' => __( 'Unique identifier for the resource.', 'woocommerce' ),
82
						'type'        => 'integer',
83
					),
84
				),
85
				array(
86
					'methods'             => \WP_REST_Server::READABLE,
87
					'callback'            => array( $this, 'get_item' ),
88
					'permission_callback' => array( $this, 'get_item_permissions_check' ),
89
					'args'                => array(
90
						'context' => $this->get_context_param( array( 'default' => 'view' ) ),
91
					),
92
				),
93
				array(
94
					'methods'             => \WP_REST_Server::DELETABLE,
95
					'callback'            => array( $this, 'delete_item' ),
96
					'permission_callback' => array( $this, 'delete_item_permissions_check' ),
97
					'args'                => array(
98
						'force' => array(
99
							'default'     => true,
100
							'type'        => 'boolean',
101
							'description' => __( 'Required to be true, as resource does not support trashing.', 'woocommerce' ),
102
						),
103
					),
104
				),
105
				'schema' => array( $this, 'get_public_item_schema' ),
106
			),
107
			true
108
		);
109
	}
110
111
	/**
112
	 * Get object.
113
	 *
114
	 * @since  3.0.0
115
	 * @param  int $id Object ID.
116
	 * @return \WC_Data|bool
117
	 */
118
	protected function get_object( $id ) {
119
		return wc_get_order( $id );
120
	}
121
122
	/**
123
	 * Get data for this object in the format of this endpoint's schema.
124
	 *
125
	 * @throws \WC_REST_Exception Exception on invalid data.
126
	 *
127
	 * @param mixed            $object Object to prepare.
128
	 * @param \WP_REST_Request $request Request object.
129
	 * @return array Array of data in the correct format.
130
	 */
131
	protected function get_data_for_response( $object, $request ) {
132
		$order = wc_get_order( (int) $request['order_id'] );
133
134
		if ( ! $order ) {
135
			throw new \WC_REST_Exception( 'woocommerce_rest_invalid_order_id', __( 'Invalid order ID.', 'woocommerce' ), 404 );
136
		}
137
138
		if ( ! $object || $object->get_parent_id() !== $order->get_id() ) {
139
			throw new \WC_REST_Exception( 'woocommerce_rest_invalid_order_refund_id', __( 'Invalid order refund ID.', 'woocommerce' ), 404 );
140
		}
141
142
		$data              = $object->get_data();
143
		$format_decimal    = array( 'amount' );
144
		$format_date       = array( 'date_created' );
145
		$format_line_items = array( 'line_items' );
146
		$dp                = is_null( $request['dp'] ) ? wc_get_price_decimals() : absint( $request['dp'] );
147
148
		// Format decimal values.
149
		foreach ( $format_decimal as $key ) {
150
			$data[ $key ] = wc_format_decimal( $data[ $key ], $dp );
151
		}
152
153
		// Format date values.
154
		foreach ( $format_date as $key ) {
155
			$datetime              = $data[ $key ];
156
			$data[ $key ]          = wc_rest_prepare_date_response( $datetime, false );
157
			$data[ $key . '_gmt' ] = wc_rest_prepare_date_response( $datetime );
158
		}
159
160
		// Format line items.
161
		foreach ( $format_line_items as $key ) {
162
			$data[ $key ] = array_values( array_map( array( $this, 'get_order_item_data' ), $data[ $key ], $request ) );
0 ignored issues
show
Bug introduced by
$request of type WP_REST_Request is incompatible with the type array expected by parameter $_ of array_map(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

162
			$data[ $key ] = array_values( array_map( array( $this, 'get_order_item_data' ), $data[ $key ], /** @scrutinizer ignore-type */ $request ) );
Loading history...
163
		}
164
165
		return array(
166
			'id'               => $object->get_id(),
167
			'date_created'     => $data['date_created'],
168
			'date_created_gmt' => $data['date_created_gmt'],
169
			'amount'           => $data['amount'],
170
			'reason'           => $data['reason'],
171
			'refunded_by'      => $data['refunded_by'],
172
			'refunded_payment' => $data['refunded_payment'],
173
			'meta_data'        => $data['meta_data'],
174
			'line_items'       => $data['line_items'],
175
		);
176
	}
177
178
	/**
179
	 * Expands an order item to get its data.
180
	 *
181
	 * @param \WC_Order_item    $item Order item data.
182
	 * @param \WP_REST_Response $response The response object.
183
	 * @return array
184
	 */
185
	protected function get_order_item_data( $item, $request ) {
186
		$data           = $item->get_data();
187
		$format_decimal = array( 'subtotal', 'subtotal_tax', 'total', 'total_tax', 'tax_total', 'shipping_tax_total' );
188
		$dp             = is_null( $request['dp'] ) ? wc_get_price_decimals() : absint( $request['dp'] );
189
190
		// Format decimal values.
191
		foreach ( $format_decimal as $key ) {
192
			if ( isset( $data[ $key ] ) ) {
193
				$data[ $key ] = wc_format_decimal( $data[ $key ], $this->request['dp'] );
0 ignored issues
show
Bug Best Practice introduced by
The property request does not exist on WooCommerce\RestApi\Cont...s\Version4\OrderRefunds. Did you maybe forget to declare it?
Loading history...
194
			}
195
		}
196
197
		// Add SKU and PRICE to products.
198
		if ( is_callable( array( $item, 'get_product' ) ) ) {
199
			$data['sku']   = $item->get_product() ? $item->get_product()->get_sku() : null;
0 ignored issues
show
Bug introduced by
The method get_product() does not exist on WC_Order_Item. Did you maybe mean get_prop()? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

199
			$data['sku']   = $item->/** @scrutinizer ignore-call */ get_product() ? $item->get_product()->get_sku() : null;

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...
200
			$data['price'] = $item->get_quantity() ? $item->get_total() / $item->get_quantity() : 0;
0 ignored issues
show
Bug introduced by
The method get_total() does not exist on WC_Order_Item. It seems like you code against a sub-type of said class. However, the method does not exist in WC_Order_Item_Tax or WC_Order_Item_Coupon. Are you sure you never get one of those? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

200
			$data['price'] = $item->get_quantity() ? $item->/** @scrutinizer ignore-call */ get_total() / $item->get_quantity() : 0;
Loading history...
201
		}
202
203
		// Format taxes.
204
		if ( ! empty( $data['taxes']['total'] ) ) {
205
			$taxes = array();
206
207
			foreach ( $data['taxes']['total'] as $tax_rate_id => $tax ) {
208
				$taxes[] = array(
209
					'id'       => $tax_rate_id,
210
					'total'    => $tax,
211
					'subtotal' => isset( $data['taxes']['subtotal'][ $tax_rate_id ] ) ? $data['taxes']['subtotal'][ $tax_rate_id ] : '',
212
				);
213
			}
214
			$data['taxes'] = $taxes;
215
		} elseif ( isset( $data['taxes'] ) ) {
216
			$data['taxes'] = array();
217
		}
218
219
		// Remove names for coupons, taxes and shipping.
220
		if ( isset( $data['code'] ) || isset( $data['rate_code'] ) || isset( $data['method_title'] ) ) {
221
			unset( $data['name'] );
222
		}
223
224
		// Remove props we don't want to expose.
225
		unset( $data['order_id'] );
226
		unset( $data['type'] );
227
228
		return $data;
229
	}
230
231
	/**
232
	 * Prepare links for the request.
233
	 *
234
	 * @param mixed            $item Object to prepare.
235
	 * @param \WP_REST_Request $request Request object.
236
	 * @return array
237
	 */
238
	protected function prepare_links( $item, $request ) {
239
		$base  = str_replace( '(?P<order_id>[\d]+)', $item->get_parent_id(), $this->rest_base );
240
		$links = array(
241
			'self'       => array(
242
				'href' => rest_url( sprintf( '/%s/%s/%d', $this->namespace, $base, $item->get_id() ) ),
243
			),
244
			'collection' => array(
245
				'href' => rest_url( sprintf( '/%s/%s', $this->namespace, $base ) ),
246
			),
247
			'up'         => array(
248
				'href' => rest_url( sprintf( '/%s/orders/%d', $this->namespace, $item->get_parent_id() ) ),
249
			),
250
		);
251
252
		return $links;
253
	}
254
255
	/**
256
	 * Prepare objects query.
257
	 *
258
	 * @since  3.0.0
259
	 * @param  \WP_REST_Request $request Full details about the request.
260
	 * @return array
261
	 */
262
	protected function prepare_objects_query( $request ) {
263
		$args = parent::prepare_objects_query( $request );
264
265
		$args['post_status']     = array_keys( wc_get_order_statuses() );
266
		$args['post_parent__in'] = array( absint( $request['order_id'] ) );
267
268
		return $args;
269
	}
270
271
	/**
272
	 * Create a single item.
273
	 *
274
	 * @param \WP_REST_Request $request Full details about the request.
275
	 * @return \WP_Error|\WP_REST_Response
276
	 */
277
	public function create_item( $request ) {
278
		if ( ! empty( $request['id'] ) ) {
279
			/* translators: %s: post type */
280
			return new \WP_Error( "woocommerce_rest_{$this->post_type}_exists", sprintf( __( 'Cannot create existing %s.', 'woocommerce' ), $this->post_type ), array( 'status' => 400 ) );
281
		}
282
283
		$order_data = get_post( (int) $request['order_id'] );
284
285
		if ( empty( $order_data ) ) {
286
			return new \WP_Error( 'woocommerce_rest_invalid_order', __( 'Order is invalid', 'woocommerce' ), 400 );
287
		}
288
289
		if ( 0 > $request['amount'] ) {
290
			return new \WP_Error( 'woocommerce_rest_invalid_order_refund', __( 'Refund amount must be greater than zero.', 'woocommerce' ), 400 );
291
		}
292
293
		// Create the refund.
294
		$refund = wc_create_refund(
295
			array(
296
				'order_id'       => $order_data->ID,
297
				'amount'         => $request['amount'],
298
				'reason'         => empty( $request['reason'] ) ? null : $request['reason'],
299
				'refund_payment' => is_bool( $request['api_refund'] ) ? $request['api_refund'] : true,
300
				'restock_items'  => true,
301
			)
302
		);
303
304
		if ( is_wp_error( $refund ) ) {
305
			return new \WP_Error( 'woocommerce_rest_cannot_create_order_refund', $refund->get_error_message(), 500 );
0 ignored issues
show
Bug introduced by
The method get_error_message() does not exist on WC_Order_Refund. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

305
			return new \WP_Error( 'woocommerce_rest_cannot_create_order_refund', $refund->/** @scrutinizer ignore-call */ get_error_message(), 500 );

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...
306
		}
307
308
		if ( ! $refund ) {
309
			return new \WP_Error( 'woocommerce_rest_cannot_create_order_refund', __( 'Cannot create order refund, please try again.', 'woocommerce' ), 500 );
310
		}
311
312
		$post = get_post( $refund->get_id() );
0 ignored issues
show
Bug introduced by
The method get_id() does not exist on WP_Error. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

312
		$post = get_post( $refund->/** @scrutinizer ignore-call */ get_id() );

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...
313
		$this->update_additional_fields_for_object( $post, $request );
0 ignored issues
show
Bug introduced by
$post of type WP_Post is incompatible with the type array expected by parameter $object of WP_REST_Controller::upda...nal_fields_for_object(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

313
		$this->update_additional_fields_for_object( /** @scrutinizer ignore-type */ $post, $request );
Loading history...
314
315
		/**
316
		 * Fires after a single item is created or updated via the REST API.
317
		 *
318
		 * @param \WP_Post         $post      Post object.
319
		 * @param \WP_REST_Request $request   Request object.
320
		 * @param boolean         $creating  True when creating item, false when updating.
321
		 */
322
		do_action( "woocommerce_rest_insert_{$this->post_type}", $post, $request, true );
323
324
		$request->set_param( 'context', 'edit' );
325
		$response = $this->prepare_item_for_response( $post, $request );
326
		$response = rest_ensure_response( $response );
327
		$response->set_status( 201 );
328
		$response->header( 'Location', rest_url( sprintf( '/%s/%s/%d', $this->namespace, $this->rest_base, $post->ID ) ) );
329
330
		return $response;
331
	}
332
333
	/**
334
	 * Prepares one object for create or update operation.
335
	 *
336
	 * @since  3.0.0
337
	 * @param  \WP_REST_Request $request Request object.
338
	 * @param  bool             $creating If is creating a new object.
339
	 * @return \WP_Error|\WC_Data The prepared item, or \WP_Error object on failure.
340
	 */
341
	protected function prepare_object_for_database( $request, $creating = false ) {
342
		$order = wc_get_order( (int) $request['order_id'] );
343
344
		if ( ! $order ) {
345
			return new \WP_Error( 'woocommerce_rest_invalid_order_id', __( 'Invalid order ID.', 'woocommerce' ), 404 );
346
		}
347
348
		if ( 0 > $request['amount'] ) {
349
			return new \WP_Error( 'woocommerce_rest_invalid_order_refund', __( 'Refund amount must be greater than zero.', 'woocommerce' ), 400 );
350
		}
351
352
		// Create the refund.
353
		$refund = wc_create_refund(
354
			array(
355
				'order_id'       => $order->get_id(),
356
				'amount'         => $request['amount'],
357
				'reason'         => empty( $request['reason'] ) ? null : $request['reason'],
358
				'line_items'     => empty( $request['line_items'] ) ? array() : $request['line_items'],
359
				'refund_payment' => is_bool( $request['api_refund'] ) ? $request['api_refund'] : true,
360
				'restock_items'  => true,
361
			)
362
		);
363
364
		if ( is_wp_error( $refund ) ) {
365
			return new \WP_Error( 'woocommerce_rest_cannot_create_order_refund', $refund->get_error_message(), 500 );
366
		}
367
368
		if ( ! $refund ) {
369
			return new \WP_Error( 'woocommerce_rest_cannot_create_order_refund', __( 'Cannot create order refund, please try again.', 'woocommerce' ), 500 );
370
		}
371
372
		if ( ! empty( $request['meta_data'] ) && is_array( $request['meta_data'] ) ) {
373
			foreach ( $request['meta_data'] as $meta ) {
374
				$refund->update_meta_data( $meta['key'], $meta['value'], isset( $meta['id'] ) ? $meta['id'] : '' );
0 ignored issues
show
Bug introduced by
The method update_meta_data() does not exist on WP_Error. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

374
				$refund->/** @scrutinizer ignore-call */ 
375
             update_meta_data( $meta['key'], $meta['value'], isset( $meta['id'] ) ? $meta['id'] : '' );

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...
Bug introduced by
It seems like IssetNode ? $meta['id'] : '' can also be of type string; however, parameter $meta_id of WC_Data::update_meta_data() does only seem to accept integer, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

374
				$refund->update_meta_data( $meta['key'], $meta['value'], /** @scrutinizer ignore-type */ isset( $meta['id'] ) ? $meta['id'] : '' );
Loading history...
375
			}
376
			$refund->save_meta_data();
0 ignored issues
show
Bug introduced by
The method save_meta_data() does not exist on WP_Error. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

376
			$refund->/** @scrutinizer ignore-call */ 
377
            save_meta_data();

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...
377
		}
378
379
		/**
380
		 * Filters an object before it is inserted via the REST API.
381
		 *
382
		 * The dynamic portion of the hook name, `$this->post_type`,
383
		 * refers to the object type slug.
384
		 *
385
		 * @param \WC_Data         $coupon   Object object.
386
		 * @param \WP_REST_Request $request  Request object.
387
		 * @param bool            $creating If is creating a new object.
388
		 */
389
		return apply_filters( "woocommerce_rest_pre_insert_{$this->post_type}_object", $refund, $request, $creating );
390
	}
391
392
	/**
393
	 * Save an object data.
394
	 *
395
	 * @since  3.0.0
396
	 * @param  \WP_REST_Request $request  Full details about the request.
397
	 * @param  bool             $creating If is creating a new object.
398
	 * @return \WC_Data|\WP_Error
399
	 */
400
	protected function save_object( $request, $creating = false ) {
401
		try {
402
			$object = $this->prepare_object_for_database( $request, $creating );
403
404
			if ( is_wp_error( $object ) ) {
405
				return $object;
406
			}
407
408
			return $this->get_object( $object->get_id() );
409
		} catch ( \WC_Data_Exception $e ) {
410
			return new \WP_Error( $e->getErrorCode(), $e->getMessage(), $e->getErrorData() );
411
		} catch ( \WC_REST_Exception $e ) {
412
			return new \WP_Error( $e->getErrorCode(), $e->getMessage(), array( 'status' => $e->getCode() ) );
413
		}
414
	}
415
416
	/**
417
	 * Get the Order's schema, conforming to JSON Schema.
418
	 *
419
	 * @return array
420
	 */
421
	public function get_item_schema() {
422
		$schema = array(
423
			'$schema'    => 'http://json-schema.org/draft-04/schema#',
424
			'title'      => $this->post_type,
425
			'type'       => 'object',
426
			'properties' => array(
427
				'id'               => array(
428
					'description' => __( 'Unique identifier for the resource.', 'woocommerce' ),
429
					'type'        => 'integer',
430
					'context'     => array( 'view', 'edit' ),
431
					'readonly'    => true,
432
				),
433
				'date_created'     => array(
434
					'description' => __( "The date the order refund was created, in the site's timezone.", 'woocommerce' ),
435
					'type'        => 'date-time',
436
					'context'     => array( 'view', 'edit' ),
437
					'readonly'    => true,
438
				),
439
				'date_created_gmt' => array(
440
					'description' => __( 'The date the order refund was created, as GMT.', 'woocommerce' ),
441
					'type'        => 'date-time',
442
					'context'     => array( 'view', 'edit' ),
443
					'readonly'    => true,
444
				),
445
				'amount'           => array(
446
					'description' => __( 'Refund amount.', 'woocommerce' ),
447
					'type'        => 'string',
448
					'context'     => array( 'view', 'edit' ),
449
				),
450
				'reason'           => array(
451
					'description' => __( 'Reason for refund.', 'woocommerce' ),
452
					'type'        => 'string',
453
					'context'     => array( 'view', 'edit' ),
454
				),
455
				'refunded_by'      => array(
456
					'description' => __( 'User ID of user who created the refund.', 'woocommerce' ),
457
					'type'        => 'integer',
458
					'context'     => array( 'view', 'edit' ),
459
				),
460
				'refunded_payment' => array(
461
					'description' => __( 'If the payment was refunded via the API.', 'woocommerce' ),
462
					'type'        => 'boolean',
463
					'context'     => array( 'view' ),
464
					'readonly'    => true,
465
				),
466
				'meta_data'        => array(
467
					'description' => __( 'Meta data.', 'woocommerce' ),
468
					'type'        => 'array',
469
					'context'     => array( 'view', 'edit' ),
470
					'items'       => array(
471
						'type'       => 'object',
472
						'properties' => array(
473
							'id'    => array(
474
								'description' => __( 'Meta ID.', 'woocommerce' ),
475
								'type'        => 'integer',
476
								'context'     => array( 'view', 'edit' ),
477
								'readonly'    => true,
478
							),
479
							'key'   => array(
480
								'description' => __( 'Meta key.', 'woocommerce' ),
481
								'type'        => 'string',
482
								'context'     => array( 'view', 'edit' ),
483
							),
484
							'value' => array(
485
								'description' => __( 'Meta value.', 'woocommerce' ),
486
								'type'        => 'mixed',
487
								'context'     => array( 'view', 'edit' ),
488
							),
489
						),
490
					),
491
				),
492
				'line_items'       => array(
493
					'description' => __( 'Line items data.', 'woocommerce' ),
494
					'type'        => 'array',
495
					'context'     => array( 'view', 'edit' ),
496
					'readonly'    => true,
497
					'items'       => array(
498
						'type'       => 'object',
499
						'properties' => array(
500
							'id'           => array(
501
								'description' => __( 'Item ID.', 'woocommerce' ),
502
								'type'        => 'integer',
503
								'context'     => array( 'view', 'edit' ),
504
								'readonly'    => true,
505
							),
506
							'name'         => array(
507
								'description' => __( 'Product name.', 'woocommerce' ),
508
								'type'        => 'mixed',
509
								'context'     => array( 'view', 'edit' ),
510
								'readonly'    => true,
511
							),
512
							'product_id'   => array(
513
								'description' => __( 'Product ID.', 'woocommerce' ),
514
								'type'        => 'mixed',
515
								'context'     => array( 'view', 'edit' ),
516
								'readonly'    => true,
517
							),
518
							'variation_id' => array(
519
								'description' => __( 'Variation ID, if applicable.', 'woocommerce' ),
520
								'type'        => 'integer',
521
								'context'     => array( 'view', 'edit' ),
522
								'readonly'    => true,
523
							),
524
							'quantity'     => array(
525
								'description' => __( 'Quantity ordered.', 'woocommerce' ),
526
								'type'        => 'integer',
527
								'context'     => array( 'view', 'edit' ),
528
								'readonly'    => true,
529
							),
530
							'tax_class'    => array(
531
								'description' => __( 'Tax class of product.', 'woocommerce' ),
532
								'type'        => 'string',
533
								'context'     => array( 'view', 'edit' ),
534
								'readonly'    => true,
535
							),
536
							'subtotal'     => array(
537
								'description' => __( 'Line subtotal (before discounts).', 'woocommerce' ),
538
								'type'        => 'string',
539
								'context'     => array( 'view', 'edit' ),
540
								'readonly'    => true,
541
							),
542
							'subtotal_tax' => array(
543
								'description' => __( 'Line subtotal tax (before discounts).', 'woocommerce' ),
544
								'type'        => 'string',
545
								'context'     => array( 'view', 'edit' ),
546
								'readonly'    => true,
547
							),
548
							'total'        => array(
549
								'description' => __( 'Line total (after discounts).', 'woocommerce' ),
550
								'type'        => 'string',
551
								'context'     => array( 'view', 'edit' ),
552
								'readonly'    => true,
553
							),
554
							'total_tax'    => array(
555
								'description' => __( 'Line total tax (after discounts).', 'woocommerce' ),
556
								'type'        => 'string',
557
								'context'     => array( 'view', 'edit' ),
558
								'readonly'    => true,
559
							),
560
							'taxes'        => array(
561
								'description' => __( 'Line taxes.', 'woocommerce' ),
562
								'type'        => 'array',
563
								'context'     => array( 'view', 'edit' ),
564
								'readonly'    => true,
565
								'items'       => array(
566
									'type'       => 'object',
567
									'properties' => array(
568
										'id'       => array(
569
											'description' => __( 'Tax rate ID.', 'woocommerce' ),
570
											'type'        => 'integer',
571
											'context'     => array( 'view', 'edit' ),
572
											'readonly'    => true,
573
										),
574
										'total'    => array(
575
											'description' => __( 'Tax total.', 'woocommerce' ),
576
											'type'        => 'string',
577
											'context'     => array( 'view', 'edit' ),
578
											'readonly'    => true,
579
										),
580
										'subtotal' => array(
581
											'description' => __( 'Tax subtotal.', 'woocommerce' ),
582
											'type'        => 'string',
583
											'context'     => array( 'view', 'edit' ),
584
											'readonly'    => true,
585
										),
586
									),
587
								),
588
							),
589
							'meta_data'    => array(
590
								'description' => __( 'Meta data.', 'woocommerce' ),
591
								'type'        => 'array',
592
								'context'     => array( 'view', 'edit' ),
593
								'readonly'    => true,
594
								'items'       => array(
595
									'type'       => 'object',
596
									'properties' => array(
597
										'id'    => array(
598
											'description' => __( 'Meta ID.', 'woocommerce' ),
599
											'type'        => 'integer',
600
											'context'     => array( 'view', 'edit' ),
601
											'readonly'    => true,
602
										),
603
										'key'   => array(
604
											'description' => __( 'Meta key.', 'woocommerce' ),
605
											'type'        => 'string',
606
											'context'     => array( 'view', 'edit' ),
607
											'readonly'    => true,
608
										),
609
										'value' => array(
610
											'description' => __( 'Meta value.', 'woocommerce' ),
611
											'type'        => 'mixed',
612
											'context'     => array( 'view', 'edit' ),
613
											'readonly'    => true,
614
										),
615
									),
616
								),
617
							),
618
							'sku'          => array(
619
								'description' => __( 'Product SKU.', 'woocommerce' ),
620
								'type'        => 'string',
621
								'context'     => array( 'view', 'edit' ),
622
								'readonly'    => true,
623
							),
624
							'price'        => array(
625
								'description' => __( 'Product price.', 'woocommerce' ),
626
								'type'        => 'number',
627
								'context'     => array( 'view', 'edit' ),
628
								'readonly'    => true,
629
							),
630
						),
631
					),
632
				),
633
				'api_refund'       => array(
634
					'description' => __( 'When true, the payment gateway API is used to generate the refund.', 'woocommerce' ),
635
					'type'        => 'boolean',
636
					'context'     => array( 'edit' ),
637
					'default'     => true,
638
				),
639
			),
640
		);
641
642
		return $this->add_additional_fields_schema( $schema );
643
	}
644
645
	/**
646
	 * Get the query params for collections.
647
	 *
648
	 * @return array
649
	 */
650
	public function get_collection_params() {
651
		$params = parent::get_collection_params();
652
653
		$params['dp'] = array(
654
			'default'           => wc_get_price_decimals(),
655
			'description'       => __( 'Number of decimal points to use in each resource.', 'woocommerce' ),
656
			'type'              => 'integer',
657
			'sanitize_callback' => 'absint',
658
			'validate_callback' => 'rest_validate_request_arg',
659
		);
660
661
		unset( $params['status'], $params['customer'], $params['product'] );
662
663
		return $params;
664
	}
665
}
666