Passed
Push — master ( 6176aa...f7c939 )
by Mike
03:08
created

Taxes   B

Complexity

Total Complexity 50

Size/Duplication

Total Lines 635
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 344
dl 0
loc 635
rs 8.4
c 0
b 0
f 0
wmc 50

11 Methods

Rating   Name   Duplication   Size   Complexity  
C create_or_update_tax() 0 61 16
B prepare_item_for_response() 0 54 6
B get_collection_params() 0 70 1
B get_item_schema() 0 76 1
A get_item() 0 12 3
C get_items() 0 101 10
A create_item() 0 25 2
A prepare_links() 0 11 1
A register_routes() 0 64 1
A delete_item() 0 36 6
A update_item() 0 26 3

How to fix   Complexity   

Complex Class

Complex classes like Taxes often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use Taxes, and based on these observations, apply Extract Interface, too.

1
<?php
2
/**
3
 * REST API Taxes controller
4
 *
5
 * Handles requests to the /taxes endpoint.
6
 *
7
 * @package WooCommerce/RestApi
8
 */
9
10
namespace WooCommerce\RestApi\Controllers\Version4;
11
12
defined( 'ABSPATH' ) || exit;
13
14
/**
15
 * REST API Taxes controller class.
16
 */
17
class Taxes extends AbstractController {
18
19
	/**
20
	 * Route base.
21
	 *
22
	 * @var string
23
	 */
24
	protected $rest_base = 'taxes';
25
26
	/**
27
	 * Permission to check.
28
	 *
29
	 * @var string
30
	 */
31
	protected $resource_type = 'settings';
32
33
	/**
34
	 * Register the routes for taxes.
35
	 */
36
	public function register_routes() {
37
		register_rest_route(
38
			$this->namespace,
39
			'/' . $this->rest_base,
40
			array(
41
				array(
42
					'methods'             => \WP_REST_Server::READABLE,
43
					'callback'            => array( $this, 'get_items' ),
44
					'permission_callback' => array( $this, 'get_items_permissions_check' ),
45
					'args'                => $this->get_collection_params(),
46
				),
47
				array(
48
					'methods'             => \WP_REST_Server::CREATABLE,
49
					'callback'            => array( $this, 'create_item' ),
50
					'permission_callback' => array( $this, 'create_item_permissions_check' ),
51
					'args'                => $this->get_endpoint_args_for_item_schema( \WP_REST_Server::CREATABLE ),
52
				),
53
				'schema' => array( $this, 'get_public_item_schema' ),
54
			),
55
			true
56
		);
57
58
		register_rest_route(
59
			$this->namespace,
60
			'/' . $this->rest_base . '/(?P<id>[\d]+)',
61
			array(
62
				'args' => array(
63
					'id' => array(
64
						'description' => __( 'Unique identifier for the resource.', 'woocommerce' ),
65
						'type'        => 'integer',
66
					),
67
				),
68
				array(
69
					'methods'             => \WP_REST_Server::READABLE,
70
					'callback'            => array( $this, 'get_item' ),
71
					'permission_callback' => array( $this, 'get_item_permissions_check' ),
72
					'args'                => array(
73
						'context' => $this->get_context_param( array( 'default' => 'view' ) ),
74
					),
75
				),
76
				array(
77
					'methods'             => \WP_REST_Server::EDITABLE,
78
					'callback'            => array( $this, 'update_item' ),
79
					'permission_callback' => array( $this, 'update_item_permissions_check' ),
80
					'args'                => $this->get_endpoint_args_for_item_schema( \WP_REST_Server::EDITABLE ),
81
				),
82
				array(
83
					'methods'             => \WP_REST_Server::DELETABLE,
84
					'callback'            => array( $this, 'delete_item' ),
85
					'permission_callback' => array( $this, 'delete_item_permissions_check' ),
86
					'args'                => array(
87
						'force' => array(
88
							'default'     => false,
89
							'type'        => 'boolean',
90
							'description' => __( 'Required to be true, as resource does not support trashing.', 'woocommerce' ),
91
						),
92
					),
93
				),
94
				'schema' => array( $this, 'get_public_item_schema' ),
95
			),
96
			true
97
		);
98
99
		$this->register_batch_route();
100
	}
101
102
	/**
103
	 * Get all taxes and allow filtering by tax code.
104
	 *
105
	 * @param \WP_REST_Request $request Full details about the request.
106
	 * @return \WP_Error|\WP_REST_Response
107
	 */
108
	public function get_items( $request ) {
109
		global $wpdb;
110
111
		$prepared_args           = array();
112
		$prepared_args['order']  = $request['order'];
113
		$prepared_args['number'] = $request['per_page'];
114
		if ( ! empty( $request['offset'] ) ) {
115
			$prepared_args['offset'] = $request['offset'];
116
		} else {
117
			$prepared_args['offset'] = ( $request['page'] - 1 ) * $prepared_args['number'];
118
		}
119
		$orderby_possibles        = array(
120
			'id'    => 'tax_rate_id',
121
			'order' => 'tax_rate_order',
122
		);
123
		$prepared_args['orderby'] = $orderby_possibles[ $request['orderby'] ];
124
		$prepared_args['class']   = $request['class'];
125
		$prepared_args['code']    = $request['code'];
126
		$prepared_args['include'] = $request['include'];
127
128
		/**
129
		 * Filter arguments, before passing to $wpdb->get_results(), when querying taxes via the REST API.
130
		 *
131
		 * @param array           $prepared_args Array of arguments for $wpdb->get_results().
132
		 * @param \WP_REST_Request $request       The current request.
133
		 */
134
		$prepared_args = apply_filters( 'woocommerce_rest_tax_query', $prepared_args, $request );
135
136
		$query = "
137
			SELECT *
138
			FROM {$wpdb->prefix}woocommerce_tax_rates
139
			WHERE 1 = 1
140
		";
141
142
		// Filter by tax class.
143
		if ( ! empty( $prepared_args['class'] ) ) {
144
			$class  = 'standard' !== $prepared_args['class'] ? sanitize_title( $prepared_args['class'] ) : '';
145
			$query .= " AND tax_rate_class = '$class'";
146
		}
147
148
		// Filter by tax code.
149
		$tax_code_search = $prepared_args['code'];
150
		if ( $tax_code_search ) {
151
			$tax_code_search = $wpdb->esc_like( $tax_code_search );
152
			$tax_code_search = ' \'%' . $tax_code_search . '%\'';
153
			$query          .= ' AND CONCAT_WS( "-", NULLIF(tax_rate_country, ""), NULLIF(tax_rate_state, ""), NULLIF(tax_rate_name, ""), NULLIF(tax_rate_priority, "") ) LIKE ' . $tax_code_search;
154
		}
155
156
		// Filter by included tax rate IDs.
157
		$included_taxes = $prepared_args['include'];
158
		if ( ! empty( $included_taxes ) ) {
159
			$included_taxes = implode( ',', $prepared_args['include'] );
160
			$query         .= " AND tax_rate_id IN ({$included_taxes})";
161
		}
162
163
		// Order tax rates.
164
		$order_by = sprintf( ' ORDER BY %s', sanitize_key( $prepared_args['orderby'] ) );
165
166
		// Pagination.
167
		$pagination = sprintf( ' LIMIT %d, %d', $prepared_args['offset'], $prepared_args['number'] );
168
169
		// Query taxes.
170
		$results = $wpdb->get_results( $query . $order_by . $pagination ); // @codingStandardsIgnoreLine.
171
172
		$taxes = array();
173
		foreach ( $results as $tax ) {
174
			$data    = $this->prepare_item_for_response( $tax, $request );
175
			$taxes[] = $this->prepare_response_for_collection( $data );
176
		}
177
178
		$response = rest_ensure_response( $taxes );
179
180
		// Store pagination values for headers then unset for count query.
181
		$per_page = (int) $prepared_args['number'];
182
		$page     = ceil( ( ( (int) $prepared_args['offset'] ) / $per_page ) + 1 );
183
184
		// Query only for ids.
185
		$wpdb->get_results( str_replace( 'SELECT *', 'SELECT tax_rate_id', $query ) ); // @codingStandardsIgnoreLine.
186
187
		// Calculate totals.
188
		$total_taxes = (int) $wpdb->num_rows;
189
		$response->header( 'X-WP-Total', (int) $total_taxes );
190
		$max_pages = ceil( $total_taxes / $per_page );
191
		$response->header( 'X-WP-TotalPages', (int) $max_pages );
192
193
		$base = add_query_arg( $request->get_query_params(), rest_url( sprintf( '/%s/%s', $this->namespace, $this->rest_base ) ) );
194
		if ( $page > 1 ) {
195
			$prev_page = $page - 1;
196
			if ( $prev_page > $max_pages ) {
197
				$prev_page = $max_pages;
198
			}
199
			$prev_link = add_query_arg( 'page', $prev_page, $base );
200
			$response->link_header( 'prev', $prev_link );
201
		}
202
		if ( $max_pages > $page ) {
203
			$next_page = $page + 1;
204
			$next_link = add_query_arg( 'page', $next_page, $base );
205
			$response->link_header( 'next', $next_link );
206
		}
207
208
		return $response;
209
	}
210
211
	/**
212
	 * Take tax data from the request and return the updated or newly created rate.
213
	 *
214
	 * @param \WP_REST_Request $request Full details about the request.
215
	 * @param \stdClass|null   $current Existing tax object.
216
	 * @return object
217
	 */
218
	protected function create_or_update_tax( $request, $current = null ) {
219
		$id          = absint( isset( $request['id'] ) ? $request['id'] : 0 );
220
		$data        = array();
221
		$fields      = array(
222
			'tax_rate_country',
223
			'tax_rate_state',
224
			'tax_rate',
225
			'tax_rate_name',
226
			'tax_rate_priority',
227
			'tax_rate_compound',
228
			'tax_rate_shipping',
229
			'tax_rate_order',
230
			'tax_rate_class',
231
		);
232
233
		foreach ( $fields as $field ) {
234
			// Keys via API differ from the stored names returned by _get_tax_rate.
235
			$key = 'tax_rate' === $field ? 'rate' : str_replace( 'tax_rate_', '', $field );
236
237
			// Remove data that was not posted.
238
			if ( ! isset( $request[ $key ] ) ) {
239
				continue;
240
			}
241
242
			// Test new data against current data.
243
			if ( $current && $current->$field === $request[ $key ] ) {
244
				continue;
245
			}
246
247
			// Add to data array.
248
			switch ( $key ) {
249
				case 'tax_rate_priority':
250
				case 'tax_rate_compound':
251
				case 'tax_rate_shipping':
252
				case 'tax_rate_order':
253
					$data[ $field ] = absint( $request[ $key ] );
254
					break;
255
				case 'tax_rate_class':
256
					$data[ $field ] = 'standard' !== $request['tax_rate_class'] ? $request['tax_rate_class'] : '';
257
					break;
258
				default:
259
					$data[ $field ] = wc_clean( $request[ $key ] );
260
					break;
261
			}
262
		}
263
264
		if ( $id ) {
265
			\WC_Tax::_update_tax_rate( $id, $data );
266
		} else {
267
			$id = \WC_Tax::_insert_tax_rate( $data );
268
		}
269
270
		// Add locales.
271
		if ( ! empty( $request['postcode'] ) ) {
272
			\WC_Tax::_update_tax_rate_postcodes( $id, wc_clean( $request['postcode'] ) );
0 ignored issues
show
Bug introduced by
It seems like wc_clean($request['postcode']) can also be of type array; however, parameter $postcodes of WC_Tax::_update_tax_rate_postcodes() does only seem to accept string, 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

272
			\WC_Tax::_update_tax_rate_postcodes( $id, /** @scrutinizer ignore-type */ wc_clean( $request['postcode'] ) );
Loading history...
273
		}
274
		if ( ! empty( $request['city'] ) ) {
275
			\WC_Tax::_update_tax_rate_cities( $id, wc_clean( $request['city'] ) );
0 ignored issues
show
Bug introduced by
It seems like wc_clean($request['city']) can also be of type array; however, parameter $cities of WC_Tax::_update_tax_rate_cities() does only seem to accept string, 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

275
			\WC_Tax::_update_tax_rate_cities( $id, /** @scrutinizer ignore-type */ wc_clean( $request['city'] ) );
Loading history...
276
		}
277
278
		return \WC_Tax::_get_tax_rate( $id, OBJECT );
279
	}
280
281
	/**
282
	 * Create a single tax.
283
	 *
284
	 * @param \WP_REST_Request $request Full details about the request.
285
	 * @return \WP_Error|\WP_REST_Response
286
	 */
287
	public function create_item( $request ) {
288
		if ( ! empty( $request['id'] ) ) {
289
			return new \WP_Error( 'woocommerce_rest_tax_exists', __( 'Cannot create existing resource.', 'woocommerce' ), array( 'status' => 400 ) );
290
		}
291
292
		$tax = $this->create_or_update_tax( $request );
293
294
		$this->update_additional_fields_for_object( $tax, $request );
0 ignored issues
show
Bug introduced by
$tax of type object 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

294
		$this->update_additional_fields_for_object( /** @scrutinizer ignore-type */ $tax, $request );
Loading history...
295
296
		/**
297
		 * Fires after a tax is created or updated via the REST API.
298
		 *
299
		 * @param \stdClass        $tax       Data used to create the tax.
300
		 * @param \WP_REST_Request $request   Request object.
301
		 * @param boolean         $creating  True when creating tax, false when updating tax.
302
		 */
303
		do_action( 'woocommerce_rest_insert_tax', $tax, $request, true );
304
305
		$request->set_param( 'context', 'edit' );
306
		$response = $this->prepare_item_for_response( $tax, $request );
307
		$response = rest_ensure_response( $response );
308
		$response->set_status( 201 );
309
		$response->header( 'Location', rest_url( sprintf( '/%s/%s/%d', $this->namespace, $this->rest_base, $tax->tax_rate_id ) ) );
310
311
		return $response;
312
	}
313
314
	/**
315
	 * Get a single tax.
316
	 *
317
	 * @param \WP_REST_Request $request Full details about the request.
318
	 * @return \WP_Error|\WP_REST_Response
319
	 */
320
	public function get_item( $request ) {
321
		$id      = (int) $request['id'];
322
		$tax_obj = \WC_Tax::_get_tax_rate( $id, OBJECT );
323
324
		if ( empty( $id ) || empty( $tax_obj ) ) {
325
			return new \WP_Error( 'woocommerce_rest_invalid_id', __( 'Invalid resource ID.', 'woocommerce' ), array( 'status' => 404 ) );
326
		}
327
328
		$tax      = $this->prepare_item_for_response( $tax_obj, $request );
0 ignored issues
show
Bug introduced by
It seems like $tax_obj can also be of type array; however, parameter $tax of WooCommerce\RestApi\Cont...are_item_for_response() does only seem to accept stdClass, 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

328
		$tax      = $this->prepare_item_for_response( /** @scrutinizer ignore-type */ $tax_obj, $request );
Loading history...
329
		$response = rest_ensure_response( $tax );
330
331
		return $response;
332
	}
333
334
	/**
335
	 * Update a single tax.
336
	 *
337
	 * @param \WP_REST_Request $request Full details about the request.
338
	 * @return \WP_Error|\WP_REST_Response
339
	 */
340
	public function update_item( $request ) {
341
		$id      = (int) $request['id'];
342
		$tax_obj = \WC_Tax::_get_tax_rate( $id, OBJECT );
343
344
		if ( empty( $id ) || empty( $tax_obj ) ) {
345
			return new \WP_Error( 'woocommerce_rest_invalid_id', __( 'Invalid resource ID.', 'woocommerce' ), array( 'status' => 404 ) );
346
		}
347
348
		$tax = $this->create_or_update_tax( $request, $tax_obj );
0 ignored issues
show
Bug introduced by
It seems like $tax_obj can also be of type array; however, parameter $current of WooCommerce\RestApi\Cont...:create_or_update_tax() does only seem to accept null|stdClass, 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

348
		$tax = $this->create_or_update_tax( $request, /** @scrutinizer ignore-type */ $tax_obj );
Loading history...
349
350
		$this->update_additional_fields_for_object( $tax, $request );
0 ignored issues
show
Bug introduced by
$tax of type object 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

350
		$this->update_additional_fields_for_object( /** @scrutinizer ignore-type */ $tax, $request );
Loading history...
351
352
		/**
353
		 * Fires after a tax is created or updated via the REST API.
354
		 *
355
		 * @param \stdClass        $tax       Data used to create the tax.
356
		 * @param \WP_REST_Request $request   Request object.
357
		 * @param boolean         $creating  True when creating tax, false when updating tax.
358
		 */
359
		do_action( 'woocommerce_rest_insert_tax', $tax, $request, false );
360
361
		$request->set_param( 'context', 'edit' );
362
		$response = $this->prepare_item_for_response( $tax, $request );
363
		$response = rest_ensure_response( $response );
364
365
		return $response;
366
	}
367
368
	/**
369
	 * Delete a single tax.
370
	 *
371
	 * @param \WP_REST_Request $request Full details about the request.
372
	 * @return \WP_Error|\WP_REST_Response
373
	 */
374
	public function delete_item( $request ) {
375
		global $wpdb;
376
377
		$id    = (int) $request['id'];
378
		$force = isset( $request['force'] ) ? (bool) $request['force'] : false;
379
380
		// We don't support trashing for this type, error out.
381
		if ( ! $force ) {
382
			return new \WP_Error( 'woocommerce_rest_trash_not_supported', __( 'Taxes do not support trashing.', 'woocommerce' ), array( 'status' => 501 ) );
383
		}
384
385
		$tax = \WC_Tax::_get_tax_rate( $id, OBJECT );
386
387
		if ( empty( $id ) || empty( $tax ) ) {
388
			return new \WP_Error( 'woocommerce_rest_invalid_id', __( 'Invalid resource ID.', 'woocommerce' ), array( 'status' => 400 ) );
389
		}
390
391
		$request->set_param( 'context', 'edit' );
392
		$response = $this->prepare_item_for_response( $tax, $request );
0 ignored issues
show
Bug introduced by
It seems like $tax can also be of type array; however, parameter $tax of WooCommerce\RestApi\Cont...are_item_for_response() does only seem to accept stdClass, 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

392
		$response = $this->prepare_item_for_response( /** @scrutinizer ignore-type */ $tax, $request );
Loading history...
393
394
		\WC_Tax::_delete_tax_rate( $id );
395
396
		if ( 0 === $wpdb->rows_affected ) {
397
			return new \WP_Error( 'woocommerce_rest_cannot_delete', __( 'The resource cannot be deleted.', 'woocommerce' ), array( 'status' => 500 ) );
398
		}
399
400
		/**
401
		 * Fires after a tax is deleted via the REST API.
402
		 *
403
		 * @param \stdClass         $tax      The tax data.
404
		 * @param \WP_REST_Response $response The response returned from the API.
405
		 * @param \WP_REST_Request  $request  The request sent to the API.
406
		 */
407
		do_action( 'woocommerce_rest_delete_tax', $tax, $response, $request );
408
409
		return $response;
410
	}
411
412
	/**
413
	 * Prepare a single tax output for response.
414
	 *
415
	 * @param \stdClass        $tax Tax object.
416
	 * @param \WP_REST_Request $request Request object.
417
	 * @return \WP_REST_Response $response Response data.
418
	 */
419
	public function prepare_item_for_response( $tax, $request ) {
420
		global $wpdb;
421
422
		$id   = (int) $tax->tax_rate_id;
423
		$data = array(
424
			'id'       => $id,
425
			'country'  => $tax->tax_rate_country,
426
			'state'    => $tax->tax_rate_state,
427
			'postcode' => '',
428
			'city'     => '',
429
			'rate'     => $tax->tax_rate,
430
			'name'     => $tax->tax_rate_name,
431
			'priority' => (int) $tax->tax_rate_priority,
432
			'compound' => (bool) $tax->tax_rate_compound,
433
			'shipping' => (bool) $tax->tax_rate_shipping,
434
			'order'    => (int) $tax->tax_rate_order,
435
			'class'    => $tax->tax_rate_class ? $tax->tax_rate_class : 'standard',
436
		);
437
438
		// Get locales from a tax rate.
439
		$locales = $wpdb->get_results(
440
			$wpdb->prepare(
441
				"
442
				SELECT location_code, location_type
443
				FROM {$wpdb->prefix}woocommerce_tax_rate_locations
444
				WHERE tax_rate_id = %d
445
				",
446
				$id
447
			)
448
		);
449
450
		if ( ! is_wp_error( $tax ) && ! is_null( $tax ) ) {
451
			foreach ( $locales as $locale ) {
452
				$data[ $locale->location_type ] = $locale->location_code;
453
			}
454
		}
455
456
		$context = ! empty( $request['context'] ) ? $request['context'] : 'view';
457
		$data    = $this->add_additional_fields_to_object( $data, $request );
458
		$data    = $this->filter_response_by_context( $data, $context );
459
460
		// Wrap the data in a response object.
461
		$response = rest_ensure_response( $data );
462
463
		$response->add_links( $this->prepare_links( $tax ) );
464
465
		/**
466
		 * Filter tax object returned from the REST API.
467
		 *
468
		 * @param \WP_REST_Response $response The response object.
469
		 * @param \stdClass         $tax      Tax object used to create response.
470
		 * @param \WP_REST_Request  $request  Request object.
471
		 */
472
		return apply_filters( 'woocommerce_rest_prepare_tax', $response, $tax, $request );
473
	}
474
475
	/**
476
	 * Prepare links for the request.
477
	 *
478
	 * @param \stdClass $tax Tax object.
479
	 * @return array Links for the given tax.
480
	 */
481
	protected function prepare_links( $tax ) {
482
		$links = array(
483
			'self' => array(
484
				'href' => rest_url( sprintf( '/%s/%s/%d', $this->namespace, $this->rest_base, $tax->tax_rate_id ) ),
485
			),
486
			'collection' => array(
487
				'href' => rest_url( sprintf( '/%s/%s', $this->namespace, $this->rest_base ) ),
488
			),
489
		);
490
491
		return $links;
492
	}
493
494
	/**
495
	 * Get the Taxes schema, conforming to JSON Schema.
496
	 *
497
	 * @return array
498
	 */
499
	public function get_item_schema() {
500
		$schema = array(
501
			'$schema'    => 'http://json-schema.org/draft-04/schema#',
502
			'title'      => 'tax',
503
			'type'       => 'object',
504
			'properties' => array(
505
				'id' => array(
506
					'description' => __( 'Unique identifier for the resource.', 'woocommerce' ),
507
					'type'        => 'integer',
508
					'context'     => array( 'view', 'edit' ),
509
					'readonly'    => true,
510
				),
511
				'country' => array(
512
					'description' => __( 'Country ISO 3166 code.', 'woocommerce' ),
513
					'type'        => 'string',
514
					'context'     => array( 'view', 'edit' ),
515
				),
516
				'state' => array(
517
					'description' => __( 'State code.', 'woocommerce' ),
518
					'type'        => 'string',
519
					'context'     => array( 'view', 'edit' ),
520
				),
521
				'postcode' => array(
522
					'description' => __( 'Postcode / ZIP.', 'woocommerce' ),
523
					'type'        => 'string',
524
					'context'     => array( 'view', 'edit' ),
525
				),
526
				'city' => array(
527
					'description' => __( 'City name.', 'woocommerce' ),
528
					'type'        => 'string',
529
					'context'     => array( 'view', 'edit' ),
530
				),
531
				'rate' => array(
532
					'description' => __( 'Tax rate.', 'woocommerce' ),
533
					'type'        => 'string',
534
					'context'     => array( 'view', 'edit' ),
535
				),
536
				'name' => array(
537
					'description' => __( 'Tax rate name.', 'woocommerce' ),
538
					'type'        => 'string',
539
					'context'     => array( 'view', 'edit' ),
540
				),
541
				'priority' => array(
542
					'description' => __( 'Tax priority.', 'woocommerce' ),
543
					'type'        => 'integer',
544
					'default'     => 1,
545
					'context'     => array( 'view', 'edit' ),
546
				),
547
				'compound' => array(
548
					'description' => __( 'Whether or not this is a compound rate.', 'woocommerce' ),
549
					'type'        => 'boolean',
550
					'default'     => false,
551
					'context'     => array( 'view', 'edit' ),
552
				),
553
				'shipping' => array(
554
					'description' => __( 'Whether or not this tax rate also gets applied to shipping.', 'woocommerce' ),
555
					'type'        => 'boolean',
556
					'default'     => true,
557
					'context'     => array( 'view', 'edit' ),
558
				),
559
				'order' => array(
560
					'description' => __( 'Indicates the order that will appear in queries.', 'woocommerce' ),
561
					'type'        => 'integer',
562
					'context'     => array( 'view', 'edit' ),
563
				),
564
				'class' => array(
565
					'description' => __( 'Tax class.', 'woocommerce' ),
566
					'type'        => 'string',
567
					'default'     => 'standard',
568
					'enum'        => array_merge( array( 'standard' ), \WC_Tax::get_tax_class_slugs() ),
569
					'context'     => array( 'view', 'edit' ),
570
				),
571
			),
572
		);
573
574
		return $this->add_additional_fields_schema( $schema );
575
	}
576
577
	/**
578
	 * Get the query params for collections.
579
	 *
580
	 * @return array
581
	 */
582
	public function get_collection_params() {
583
		$params                       = array();
584
		$params['context']            = $this->get_context_param();
585
		$params['context']['default'] = 'view';
586
587
		$params['page'] = array(
588
			'description'        => __( 'Current page of the collection.', 'woocommerce' ),
589
			'type'               => 'integer',
590
			'default'            => 1,
591
			'sanitize_callback'  => 'absint',
592
			'validate_callback'  => 'rest_validate_request_arg',
593
			'minimum'            => 1,
594
		);
595
		$params['per_page'] = array(
596
			'description'        => __( 'Maximum number of items to be returned in result set.', 'woocommerce' ),
597
			'type'               => 'integer',
598
			'default'            => 10,
599
			'minimum'            => 1,
600
			'maximum'            => 100,
601
			'sanitize_callback'  => 'absint',
602
			'validate_callback'  => 'rest_validate_request_arg',
603
		);
604
		$params['offset'] = array(
605
			'description'        => __( 'Offset the result set by a specific number of items.', 'woocommerce' ),
606
			'type'               => 'integer',
607
			'sanitize_callback'  => 'absint',
608
			'validate_callback'  => 'rest_validate_request_arg',
609
		);
610
		$params['order'] = array(
611
			'default'            => 'asc',
612
			'description'        => __( 'Order sort attribute ascending or descending.', 'woocommerce' ),
613
			'enum'               => array( 'asc', 'desc' ),
614
			'sanitize_callback'  => 'sanitize_key',
615
			'type'               => 'string',
616
			'validate_callback'  => 'rest_validate_request_arg',
617
		);
618
		$params['orderby'] = array(
619
			'default'            => 'order',
620
			'description'        => __( 'Sort collection by object attribute.', 'woocommerce' ),
621
			'enum'               => array(
622
				'id',
623
				'order',
624
			),
625
			'sanitize_callback'  => 'sanitize_key',
626
			'type'               => 'string',
627
			'validate_callback'  => 'rest_validate_request_arg',
628
		);
629
		$params['class'] = array(
630
			'description'        => __( 'Sort by tax class.', 'woocommerce' ),
631
			'enum'               => array_merge( array( 'standard' ), \WC_Tax::get_tax_class_slugs() ),
632
			'sanitize_callback'  => 'sanitize_title',
633
			'type'               => 'string',
634
			'validate_callback'  => 'rest_validate_request_arg',
635
		);
636
		$params['code']    = array(
637
			'description'       => __( 'Search by similar tax code.', 'woocommerce' ),
638
			'type'              => 'string',
639
			'validate_callback' => 'rest_validate_request_arg',
640
		);
641
		$params['include'] = array(
642
			'description'       => __( 'Limit result set to items that have the specified rate ID(s) assigned.', 'woocommerce' ),
643
			'type'              => 'array',
644
			'items'             => array(
645
				'type' => 'integer',
646
			),
647
			'default'           => array(),
648
			'validate_callback' => 'rest_validate_request_arg',
649
		);
650
651
		return $params;
652
	}
653
}
654