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

Products   B

Complexity

Total Complexity 52

Size/Duplication

Total Lines 1205
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 767
dl 0
loc 1205
rs 7.273
c 0
b 0
f 0
wmc 52

11 Methods

Rating   Name   Duplication   Size   Complexity  
B get_collection_params() 0 130 2
A get_object() 0 2 1
B get_item_schema() 0 624 1
F prepare_objects_query() 0 121 20
B get_items_query_clauses() 0 42 9
A append_product_sorting_table_join() 0 7 2
C delete_item() 0 119 11
A prepare_links() 0 17 2
A prepare_object_for_database() 0 19 2
A get_data_for_response() 0 4 1
A get_items() 0 5 1

How to fix   Complexity   

Complex Class

Complex classes like Products 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 Products, and based on these observations, apply Extract Interface, too.

1
<?php
2
/**
3
 * REST API Products controller
4
 *
5
 * Handles requests to the /products endpoint.
6
 *
7
 * @package WooCommerce/RestApi
8
 */
9
10
namespace WooCommerce\RestApi\Controllers\Version4;
11
12
defined( 'ABSPATH' ) || exit;
13
14
use WooCommerce\RestApi\Controllers\Version4\Requests\ProductRequest;
15
use WooCommerce\RestApi\Controllers\Version4\Responses\ProductResponse;
16
use WooCommerce\RestApi\Controllers\Version4\Utilities\Permissions;
17
18
/**
19
 * REST API Products controller class.
20
 */
21
class Products extends AbstractObjectsController {
22
23
	/**
24
	 * Route base.
25
	 *
26
	 * @var string
27
	 */
28
	protected $rest_base = 'products';
29
30
	/**
31
	 * Post type.
32
	 *
33
	 * @var string
34
	 */
35
	protected $post_type = 'product';
36
37
	/**
38
	 * If object is hierarchical.
39
	 *
40
	 * @var bool
41
	 */
42
	protected $hierarchical = true;
43
44
	/**
45
	 * Get the Product's schema, conforming to JSON Schema.
46
	 *
47
	 * @return array
48
	 */
49
	public function get_item_schema() {
50
		$weight_unit    = get_option( 'woocommerce_weight_unit' );
51
		$dimension_unit = get_option( 'woocommerce_dimension_unit' );
52
		$schema         = array(
53
			'$schema'    => 'http://json-schema.org/draft-04/schema#',
54
			'title'      => 'product',
55
			'type'       => 'object',
56
			'properties' => array(
57
				'id'                    => array(
58
					'description' => __( 'Unique identifier for the resource.', 'woocommerce' ),
59
					'type'        => 'integer',
60
					'context'     => array( 'view', 'edit', 'embed' ),
61
					'readonly'    => true,
62
				),
63
				'name'                  => array(
64
					'description' => __( 'Product name.', 'woocommerce' ),
65
					'type'        => 'string',
66
					'context'     => array( 'view', 'edit', 'embed' ),
67
					'arg_options' => array(
68
						'sanitize_callback' => 'wp_filter_post_kses',
69
					),
70
				),
71
				'slug'                  => array(
72
					'description' => __( 'Product slug.', 'woocommerce' ),
73
					'type'        => 'string',
74
					'context'     => array( 'view', 'edit', 'embed' ),
75
				),
76
				'permalink'             => array(
77
					'description' => __( 'Product URL.', 'woocommerce' ),
78
					'type'        => 'string',
79
					'format'      => 'uri',
80
					'context'     => array( 'view', 'edit', 'embed' ),
81
					'readonly'    => true,
82
				),
83
				'date_created'          => array(
84
					'description' => __( "The date the product was created, in the site's timezone.", 'woocommerce' ),
85
					'type'        => 'date-time',
86
					'context'     => array( 'view', 'edit' ),
87
				),
88
				'date_created_gmt'      => array(
89
					'description' => __( 'The date the product was created, as GMT.', 'woocommerce' ),
90
					'type'        => 'date-time',
91
					'context'     => array( 'view', 'edit' ),
92
				),
93
				'date_modified'         => array(
94
					'description' => __( "The date the product was last modified, in the site's timezone.", 'woocommerce' ),
95
					'type'        => 'date-time',
96
					'context'     => array( 'view', 'edit' ),
97
					'readonly'    => true,
98
				),
99
				'date_modified_gmt'     => array(
100
					'description' => __( 'The date the product was last modified, as GMT.', 'woocommerce' ),
101
					'type'        => 'date-time',
102
					'context'     => array( 'view', 'edit' ),
103
					'readonly'    => true,
104
				),
105
				'type'                  => array(
106
					'description' => __( 'Product type.', 'woocommerce' ),
107
					'type'        => 'string',
108
					'default'     => 'simple',
109
					'enum'        => array_keys( wc_get_product_types() ),
110
					'context'     => array( 'view', 'edit' ),
111
				),
112
				'status'                => array(
113
					'description' => __( 'Product status (post status).', 'woocommerce' ),
114
					'type'        => 'string',
115
					'default'     => 'publish',
116
					'enum'        => array_merge( array_keys( get_post_statuses() ), array( 'future' ) ),
117
					'context'     => array( 'view', 'edit' ),
118
				),
119
				'featured'              => array(
120
					'description' => __( 'Featured product.', 'woocommerce' ),
121
					'type'        => 'boolean',
122
					'default'     => false,
123
					'context'     => array( 'view', 'edit' ),
124
				),
125
				'catalog_visibility'    => array(
126
					'description' => __( 'Catalog visibility.', 'woocommerce' ),
127
					'type'        => 'string',
128
					'default'     => 'visible',
129
					'enum'        => array( 'visible', 'catalog', 'search', 'hidden' ),
130
					'context'     => array( 'view', 'edit' ),
131
				),
132
				'description'           => array(
133
					'description' => __( 'Product description.', 'woocommerce' ),
134
					'type'        => 'string',
135
					'context'     => array( 'view', 'edit', 'embed' ),
136
					'arg_options' => array(
137
						'sanitize_callback' => 'wp_filter_post_kses',
138
					),
139
				),
140
				'short_description'     => array(
141
					'description' => __( 'Product short description.', 'woocommerce' ),
142
					'type'        => 'string',
143
					'context'     => array( 'view', 'edit', 'embed' ),
144
					'arg_options' => array(
145
						'sanitize_callback' => 'wp_filter_post_kses',
146
					),
147
				),
148
				'sku'                   => array(
149
					'description' => __( 'Unique identifier.', 'woocommerce' ),
150
					'type'        => 'string',
151
					'context'     => array( 'view', 'edit' ),
152
					'arg_options' => array(
153
						'sanitize_callback' => 'wc_clean',
154
					),
155
				),
156
				'price'                 => array(
157
					'description' => __( 'Current product price.', 'woocommerce' ),
158
					'type'        => 'string',
159
					'context'     => array( 'view', 'edit' ),
160
					'readonly'    => true,
161
				),
162
				'regular_price'         => array(
163
					'description' => __( 'Product regular price.', 'woocommerce' ),
164
					'type'        => 'string',
165
					'context'     => array( 'view', 'edit' ),
166
				),
167
				'sale_price'            => array(
168
					'description' => __( 'Product sale price.', 'woocommerce' ),
169
					'type'        => 'string',
170
					'context'     => array( 'view', 'edit' ),
171
				),
172
				'date_on_sale_from'     => array(
173
					'description' => __( "Start date of sale price, in the site's timezone.", 'woocommerce' ),
174
					'type'        => 'date-time',
175
					'context'     => array( 'view', 'edit' ),
176
				),
177
				'date_on_sale_from_gmt' => array(
178
					'description' => __( 'Start date of sale price, as GMT.', 'woocommerce' ),
179
					'type'        => 'date-time',
180
					'context'     => array( 'view', 'edit' ),
181
				),
182
				'date_on_sale_to'       => array(
183
					'description' => __( "End date of sale price, in the site's timezone.", 'woocommerce' ),
184
					'type'        => 'date-time',
185
					'context'     => array( 'view', 'edit' ),
186
				),
187
				'date_on_sale_to_gmt'   => array(
188
					'description' => __( "End date of sale price, in the site's timezone.", 'woocommerce' ),
189
					'type'        => 'date-time',
190
					'context'     => array( 'view', 'edit' ),
191
				),
192
				'price_html'            => array(
193
					'description' => __( 'Price formatted in HTML.', 'woocommerce' ),
194
					'type'        => 'string',
195
					'context'     => array( 'view', 'edit' ),
196
					'readonly'    => true,
197
				),
198
				'on_sale'               => array(
199
					'description' => __( 'Shows if the product is on sale.', 'woocommerce' ),
200
					'type'        => 'boolean',
201
					'context'     => array( 'view', 'edit' ),
202
					'readonly'    => true,
203
				),
204
				'purchasable'           => array(
205
					'description' => __( 'Shows if the product can be bought.', 'woocommerce' ),
206
					'type'        => 'boolean',
207
					'context'     => array( 'view', 'edit' ),
208
					'readonly'    => true,
209
				),
210
				'total_sales'           => array(
211
					'description' => __( 'Amount of sales.', 'woocommerce' ),
212
					'type'        => 'integer',
213
					'context'     => array( 'view', 'edit' ),
214
					'readonly'    => true,
215
				),
216
				'virtual'               => array(
217
					'description' => __( 'If the product is virtual.', 'woocommerce' ),
218
					'type'        => 'boolean',
219
					'default'     => false,
220
					'context'     => array( 'view', 'edit' ),
221
				),
222
				'downloadable'          => array(
223
					'description' => __( 'If the product is downloadable.', 'woocommerce' ),
224
					'type'        => 'boolean',
225
					'default'     => false,
226
					'context'     => array( 'view', 'edit' ),
227
				),
228
				'downloads'             => array(
229
					'description' => __( 'List of downloadable files.', 'woocommerce' ),
230
					'type'        => 'array',
231
					'context'     => array( 'view', 'edit' ),
232
					'items'       => array(
233
						'type'       => 'object',
234
						'properties' => array(
235
							'id'   => array(
236
								'description' => __( 'File ID.', 'woocommerce' ),
237
								'type'        => 'string',
238
								'context'     => array( 'view', 'edit' ),
239
							),
240
							'name' => array(
241
								'description' => __( 'File name.', 'woocommerce' ),
242
								'type'        => 'string',
243
								'context'     => array( 'view', 'edit' ),
244
							),
245
							'file' => array(
246
								'description' => __( 'File URL.', 'woocommerce' ),
247
								'type'        => 'string',
248
								'context'     => array( 'view', 'edit' ),
249
							),
250
						),
251
					),
252
				),
253
				'download_limit'        => array(
254
					'description' => __( 'Number of times downloadable files can be downloaded after purchase.', 'woocommerce' ),
255
					'type'        => 'integer',
256
					'default'     => -1,
257
					'context'     => array( 'view', 'edit' ),
258
				),
259
				'download_expiry'       => array(
260
					'description' => __( 'Number of days until access to downloadable files expires.', 'woocommerce' ),
261
					'type'        => 'integer',
262
					'default'     => -1,
263
					'context'     => array( 'view', 'edit' ),
264
				),
265
				'external_url'          => array(
266
					'description' => __( 'Product external URL. Only for external products.', 'woocommerce' ),
267
					'type'        => 'string',
268
					'format'      => 'uri',
269
					'context'     => array( 'view', 'edit' ),
270
				),
271
				'button_text'           => array(
272
					'description' => __( 'Product external button text. Only for external products.', 'woocommerce' ),
273
					'type'        => 'string',
274
					'context'     => array( 'view', 'edit' ),
275
				),
276
				'tax_status'            => array(
277
					'description' => __( 'Tax status.', 'woocommerce' ),
278
					'type'        => 'string',
279
					'default'     => 'taxable',
280
					'enum'        => array( 'taxable', 'shipping', 'none' ),
281
					'context'     => array( 'view', 'edit' ),
282
				),
283
				'tax_class'             => array(
284
					'description' => __( 'Tax class.', 'woocommerce' ),
285
					'type'        => 'string',
286
					'context'     => array( 'view', 'edit' ),
287
				),
288
				'manage_stock'          => array(
289
					'description' => __( 'Stock management at product level.', 'woocommerce' ),
290
					'type'        => 'boolean',
291
					'default'     => false,
292
					'context'     => array( 'view', 'edit' ),
293
				),
294
				'stock_quantity'        => array(
295
					'description' => __( 'Stock quantity.', 'woocommerce' ),
296
					'type'        => 'integer',
297
					'context'     => array( 'view', 'edit' ),
298
				),
299
				'stock_status'          => array(
300
					'description' => __( 'Controls the stock status of the product.', 'woocommerce' ),
301
					'type'        => 'string',
302
					'default'     => 'instock',
303
					'enum'        => array_keys( wc_get_product_stock_status_options() ),
304
					'context'     => array( 'view', 'edit' ),
305
				),
306
				'backorders'            => array(
307
					'description' => __( 'If managing stock, this controls if backorders are allowed.', 'woocommerce' ),
308
					'type'        => 'string',
309
					'default'     => 'no',
310
					'enum'        => array( 'no', 'notify', 'yes' ),
311
					'context'     => array( 'view', 'edit' ),
312
				),
313
				'backorders_allowed'    => array(
314
					'description' => __( 'Shows if backorders are allowed.', 'woocommerce' ),
315
					'type'        => 'boolean',
316
					'context'     => array( 'view', 'edit' ),
317
					'readonly'    => true,
318
				),
319
				'backordered'           => array(
320
					'description' => __( 'Shows if the product is on backordered.', 'woocommerce' ),
321
					'type'        => 'boolean',
322
					'context'     => array( 'view', 'edit' ),
323
					'readonly'    => true,
324
				),
325
				'sold_individually'     => array(
326
					'description' => __( 'Allow one item to be bought in a single order.', 'woocommerce' ),
327
					'type'        => 'boolean',
328
					'default'     => false,
329
					'context'     => array( 'view', 'edit' ),
330
				),
331
				'weight'                => array(
332
					/* translators: %s: weight unit */
333
					'description' => sprintf( __( 'Product weight (%s).', 'woocommerce' ), $weight_unit ),
0 ignored issues
show
Bug introduced by
It seems like $weight_unit can also be of type false; however, parameter $args of sprintf() 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

333
					'description' => sprintf( __( 'Product weight (%s).', 'woocommerce' ), /** @scrutinizer ignore-type */ $weight_unit ),
Loading history...
334
					'type'        => 'string',
335
					'context'     => array( 'view', 'edit' ),
336
				),
337
				'dimensions'            => array(
338
					'description' => __( 'Product dimensions.', 'woocommerce' ),
339
					'type'        => 'object',
340
					'context'     => array( 'view', 'edit' ),
341
					'properties'  => array(
342
						'length' => array(
343
							/* translators: %s: dimension unit */
344
							'description' => sprintf( __( 'Product length (%s).', 'woocommerce' ), $dimension_unit ),
345
							'type'        => 'string',
346
							'context'     => array( 'view', 'edit' ),
347
						),
348
						'width'  => array(
349
							/* translators: %s: dimension unit */
350
							'description' => sprintf( __( 'Product width (%s).', 'woocommerce' ), $dimension_unit ),
351
							'type'        => 'string',
352
							'context'     => array( 'view', 'edit' ),
353
						),
354
						'height' => array(
355
							/* translators: %s: dimension unit */
356
							'description' => sprintf( __( 'Product height (%s).', 'woocommerce' ), $dimension_unit ),
357
							'type'        => 'string',
358
							'context'     => array( 'view', 'edit' ),
359
						),
360
					),
361
				),
362
				'shipping_required'     => array(
363
					'description' => __( 'Shows if the product need to be shipped.', 'woocommerce' ),
364
					'type'        => 'boolean',
365
					'context'     => array( 'view', 'edit' ),
366
					'readonly'    => true,
367
				),
368
				'shipping_taxable'      => array(
369
					'description' => __( 'Shows whether or not the product shipping is taxable.', 'woocommerce' ),
370
					'type'        => 'boolean',
371
					'context'     => array( 'view', 'edit' ),
372
					'readonly'    => true,
373
				),
374
				'shipping_class'        => array(
375
					'description' => __( 'Shipping class slug.', 'woocommerce' ),
376
					'type'        => 'string',
377
					'context'     => array( 'view', 'edit' ),
378
				),
379
				'shipping_class_id'     => array(
380
					'description' => __( 'Shipping class ID.', 'woocommerce' ),
381
					'type'        => 'string',
382
					'context'     => array( 'view', 'edit' ),
383
					'readonly'    => true,
384
				),
385
				'reviews_allowed'       => array(
386
					'description' => __( 'Allow reviews.', 'woocommerce' ),
387
					'type'        => 'boolean',
388
					'default'     => true,
389
					'context'     => array( 'view', 'edit' ),
390
				),
391
				'average_rating'        => array(
392
					'description' => __( 'Reviews average rating.', 'woocommerce' ),
393
					'type'        => 'string',
394
					'context'     => array( 'view', 'edit' ),
395
					'readonly'    => true,
396
				),
397
				'rating_count'          => array(
398
					'description' => __( 'Amount of reviews that the product have.', 'woocommerce' ),
399
					'type'        => 'integer',
400
					'context'     => array( 'view', 'edit' ),
401
					'readonly'    => true,
402
				),
403
				'related_ids'           => array(
404
					'description' => __( 'List of related products IDs.', 'woocommerce' ),
405
					'type'        => 'array',
406
					'items'       => array(
407
						'type' => 'integer',
408
					),
409
					'context'     => array( 'view', 'edit' ),
410
					'readonly'    => true,
411
				),
412
				'upsell_ids'            => array(
413
					'description' => __( 'List of up-sell products IDs.', 'woocommerce' ),
414
					'type'        => 'array',
415
					'items'       => array(
416
						'type' => 'integer',
417
					),
418
					'context'     => array( 'view', 'edit' ),
419
				),
420
				'cross_sell_ids'        => array(
421
					'description' => __( 'List of cross-sell products IDs.', 'woocommerce' ),
422
					'type'        => 'array',
423
					'items'       => array(
424
						'type' => 'integer',
425
					),
426
					'context'     => array( 'view', 'edit' ),
427
				),
428
				'parent_id'             => array(
429
					'description' => __( 'Product parent ID.', 'woocommerce' ),
430
					'type'        => 'integer',
431
					'context'     => array( 'view', 'edit' ),
432
				),
433
				'purchase_note'         => array(
434
					'description' => __( 'Optional note to send the customer after purchase.', 'woocommerce' ),
435
					'type'        => 'string',
436
					'context'     => array( 'view', 'edit' ),
437
					'arg_options' => array(
438
						'sanitize_callback' => 'wp_kses_post',
439
					),
440
				),
441
				'categories'            => array(
442
					'description' => __( 'List of categories.', 'woocommerce' ),
443
					'type'        => 'array',
444
					'context'     => array( 'view', 'edit' ),
445
					'items'       => array(
446
						'type'       => 'object',
447
						'properties' => array(
448
							'id'   => array(
449
								'description' => __( 'Category ID.', 'woocommerce' ),
450
								'type'        => 'integer',
451
								'context'     => array( 'view', 'edit' ),
452
							),
453
							'name' => array(
454
								'description' => __( 'Category name.', 'woocommerce' ),
455
								'type'        => 'string',
456
								'context'     => array( 'view', 'edit' ),
457
								'readonly'    => true,
458
							),
459
							'slug' => array(
460
								'description' => __( 'Category slug.', 'woocommerce' ),
461
								'type'        => 'string',
462
								'context'     => array( 'view', 'edit' ),
463
								'readonly'    => true,
464
							),
465
						),
466
					),
467
				),
468
				'tags'                  => array(
469
					'description' => __( 'List of tags.', 'woocommerce' ),
470
					'type'        => 'array',
471
					'context'     => array( 'view', 'edit' ),
472
					'items'       => array(
473
						'type'       => 'object',
474
						'properties' => array(
475
							'id'   => array(
476
								'description' => __( 'Tag ID.', 'woocommerce' ),
477
								'type'        => 'integer',
478
								'context'     => array( 'view', 'edit' ),
479
							),
480
							'name' => array(
481
								'description' => __( 'Tag name.', 'woocommerce' ),
482
								'type'        => 'string',
483
								'context'     => array( 'view', 'edit' ),
484
								'readonly'    => true,
485
							),
486
							'slug' => array(
487
								'description' => __( 'Tag slug.', 'woocommerce' ),
488
								'type'        => 'string',
489
								'context'     => array( 'view', 'edit' ),
490
								'readonly'    => true,
491
							),
492
						),
493
					),
494
				),
495
				'images'                => array(
496
					'description' => __( 'List of images.', 'woocommerce' ),
497
					'type'        => 'object',
498
					'context'     => array( 'view', 'edit', 'embed' ),
499
					'items'       => array(
500
						'type'       => 'object',
501
						'properties' => array(
502
							'id'                => array(
503
								'description' => __( 'Image ID.', 'woocommerce' ),
504
								'type'        => 'integer',
505
								'context'     => array( 'view', 'edit' ),
506
							),
507
							'date_created'      => array(
508
								'description' => __( "The date the image was created, in the site's timezone.", 'woocommerce' ),
509
								'type'        => 'date-time',
510
								'context'     => array( 'view', 'edit' ),
511
								'readonly'    => true,
512
							),
513
							'date_created_gmt'  => array(
514
								'description' => __( 'The date the image was created, as GMT.', 'woocommerce' ),
515
								'type'        => 'date-time',
516
								'context'     => array( 'view', 'edit' ),
517
								'readonly'    => true,
518
							),
519
							'date_modified'     => array(
520
								'description' => __( "The date the image was last modified, in the site's timezone.", 'woocommerce' ),
521
								'type'        => 'date-time',
522
								'context'     => array( 'view', 'edit' ),
523
								'readonly'    => true,
524
							),
525
							'date_modified_gmt' => array(
526
								'description' => __( 'The date the image was last modified, as GMT.', 'woocommerce' ),
527
								'type'        => 'date-time',
528
								'context'     => array( 'view', 'edit' ),
529
								'readonly'    => true,
530
							),
531
							'src'               => array(
532
								'description' => __( 'Image URL.', 'woocommerce' ),
533
								'type'        => 'string',
534
								'format'      => 'uri',
535
								'context'     => array( 'view', 'edit' ),
536
							),
537
							'name'              => array(
538
								'description' => __( 'Image name.', 'woocommerce' ),
539
								'type'        => 'string',
540
								'context'     => array( 'view', 'edit' ),
541
							),
542
							'alt'               => array(
543
								'description' => __( 'Image alternative text.', 'woocommerce' ),
544
								'type'        => 'string',
545
								'context'     => array( 'view', 'edit' ),
546
							),
547
						),
548
					),
549
				),
550
				'attributes'            => array(
551
					'description' => __( 'List of attributes.', 'woocommerce' ),
552
					'type'        => 'array',
553
					'context'     => array( 'view', 'edit' ),
554
					'items'       => array(
555
						'type'       => 'object',
556
						'properties' => array(
557
							'id'        => array(
558
								'description' => __( 'Attribute ID.', 'woocommerce' ),
559
								'type'        => 'integer',
560
								'context'     => array( 'view', 'edit' ),
561
							),
562
							'name'      => array(
563
								'description' => __( 'Attribute name.', 'woocommerce' ),
564
								'type'        => 'string',
565
								'context'     => array( 'view', 'edit' ),
566
							),
567
							'position'  => array(
568
								'description' => __( 'Attribute position.', 'woocommerce' ),
569
								'type'        => 'integer',
570
								'context'     => array( 'view', 'edit' ),
571
							),
572
							'visible'   => array(
573
								'description' => __( "Define if the attribute is visible on the \"Additional information\" tab in the product's page.", 'woocommerce' ),
574
								'type'        => 'boolean',
575
								'default'     => false,
576
								'context'     => array( 'view', 'edit' ),
577
							),
578
							'variation' => array(
579
								'description' => __( 'Define if the attribute can be used as variation.', 'woocommerce' ),
580
								'type'        => 'boolean',
581
								'default'     => false,
582
								'context'     => array( 'view', 'edit' ),
583
							),
584
							'options'   => array(
585
								'description' => __( 'List of available term names of the attribute.', 'woocommerce' ),
586
								'type'        => 'array',
587
								'items'       => array(
588
									'type' => 'string',
589
								),
590
								'context'     => array( 'view', 'edit' ),
591
							),
592
						),
593
					),
594
				),
595
				'default_attributes'    => array(
596
					'description' => __( 'Defaults variation attributes.', 'woocommerce' ),
597
					'type'        => 'array',
598
					'context'     => array( 'view', 'edit' ),
599
					'items'       => array(
600
						'type'       => 'object',
601
						'properties' => array(
602
							'id'     => array(
603
								'description' => __( 'Attribute ID.', 'woocommerce' ),
604
								'type'        => 'integer',
605
								'context'     => array( 'view', 'edit' ),
606
							),
607
							'name'   => array(
608
								'description' => __( 'Attribute name.', 'woocommerce' ),
609
								'type'        => 'string',
610
								'context'     => array( 'view', 'edit' ),
611
							),
612
							'option' => array(
613
								'description' => __( 'Selected attribute term name.', 'woocommerce' ),
614
								'type'        => 'string',
615
								'context'     => array( 'view', 'edit' ),
616
							),
617
						),
618
					),
619
				),
620
				'variations'            => array(
621
					'description' => __( 'List of variations IDs.', 'woocommerce' ),
622
					'type'        => 'array',
623
					'context'     => array( 'view', 'edit' ),
624
					'items'       => array(
625
						'type' => 'integer',
626
					),
627
					'readonly'    => true,
628
				),
629
				'grouped_products'      => array(
630
					'description' => __( 'List of grouped products ID.', 'woocommerce' ),
631
					'type'        => 'array',
632
					'items'       => array(
633
						'type' => 'integer',
634
					),
635
					'context'     => array( 'view', 'edit' ),
636
					'readonly'    => true,
637
				),
638
				'menu_order'            => array(
639
					'description' => __( 'Menu order, used to custom sort products.', 'woocommerce' ),
640
					'type'        => 'integer',
641
					'context'     => array( 'view', 'edit' ),
642
				),
643
				'meta_data'             => array(
644
					'description' => __( 'Meta data.', 'woocommerce' ),
645
					'type'        => 'array',
646
					'context'     => array( 'view', 'edit' ),
647
					'items'       => array(
648
						'type'       => 'object',
649
						'properties' => array(
650
							'id'    => array(
651
								'description' => __( 'Meta ID.', 'woocommerce' ),
652
								'type'        => 'integer',
653
								'context'     => array( 'view', 'edit' ),
654
								'readonly'    => true,
655
							),
656
							'key'   => array(
657
								'description' => __( 'Meta key.', 'woocommerce' ),
658
								'type'        => 'string',
659
								'context'     => array( 'view', 'edit' ),
660
							),
661
							'value' => array(
662
								'description' => __( 'Meta value.', 'woocommerce' ),
663
								'type'        => 'mixed',
664
								'context'     => array( 'view', 'edit' ),
665
							),
666
						),
667
					),
668
				),
669
			),
670
		);
671
672
		return $this->add_additional_fields_schema( $schema );
673
	}
674
675
	/**
676
	 * Get the query params for collections of attachments.
677
	 *
678
	 * @return array
679
	 */
680
	public function get_collection_params() {
681
		$params = parent::get_collection_params();
682
683
		$params['slug'] = array(
684
			'description'       => __( 'Limit result set to products with a specific slug.', 'woocommerce' ),
685
			'type'              => 'string',
686
			'validate_callback' => 'rest_validate_request_arg',
687
		);
688
689
		$params['status'] = array(
690
			'default'           => 'any',
691
			'description'       => __( 'Limit result set to products assigned a specific status.', 'woocommerce' ),
692
			'type'              => 'string',
693
			'enum'              => array_merge( array( 'any', 'future' ), array_keys( get_post_statuses() ) ),
694
			'sanitize_callback' => 'sanitize_key',
695
			'validate_callback' => 'rest_validate_request_arg',
696
		);
697
698
		$params['type'] = array(
699
			'description'       => __( 'Limit result set to products assigned a specific type.', 'woocommerce' ),
700
			'type'              => 'string',
701
			'enum'              => array_keys( wc_get_product_types() ),
702
			'sanitize_callback' => 'sanitize_key',
703
			'validate_callback' => 'rest_validate_request_arg',
704
		);
705
706
		$params['sku'] = array(
707
			'description'       => __( 'Limit result set to products with specific SKU(s). Use commas to separate.', 'woocommerce' ),
708
			'type'              => 'string',
709
			'sanitize_callback' => 'sanitize_text_field',
710
			'validate_callback' => 'rest_validate_request_arg',
711
		);
712
713
		$params['featured'] = array(
714
			'description'       => __( 'Limit result set to featured products.', 'woocommerce' ),
715
			'type'              => 'boolean',
716
			'sanitize_callback' => 'wc_string_to_bool',
717
			'validate_callback' => 'rest_validate_request_arg',
718
		);
719
720
		$params['category'] = array(
721
			'description'       => __( 'Limit result set to products assigned a specific category ID.', 'woocommerce' ),
722
			'type'              => 'string',
723
			'sanitize_callback' => 'wp_parse_id_list',
724
			'validate_callback' => 'rest_validate_request_arg',
725
		);
726
727
		$params['tag'] = array(
728
			'description'       => __( 'Limit result set to products assigned a specific tag ID.', 'woocommerce' ),
729
			'type'              => 'string',
730
			'sanitize_callback' => 'wp_parse_id_list',
731
			'validate_callback' => 'rest_validate_request_arg',
732
		);
733
734
		$params['shipping_class'] = array(
735
			'description'       => __( 'Limit result set to products assigned a specific shipping class ID.', 'woocommerce' ),
736
			'type'              => 'string',
737
			'sanitize_callback' => 'wp_parse_id_list',
738
			'validate_callback' => 'rest_validate_request_arg',
739
		);
740
741
		$params['attribute'] = array(
742
			'description'       => __( 'Limit result set to products with a specific attribute. Use the taxonomy name/attribute slug.', 'woocommerce' ),
743
			'type'              => 'string',
744
			'sanitize_callback' => 'sanitize_text_field',
745
			'validate_callback' => 'rest_validate_request_arg',
746
		);
747
748
		$params['attribute_term'] = array(
749
			'description'       => __( 'Limit result set to products with a specific attribute term ID (required an assigned attribute).', 'woocommerce' ),
750
			'type'              => 'string',
751
			'sanitize_callback' => 'wp_parse_id_list',
752
			'validate_callback' => 'rest_validate_request_arg',
753
		);
754
755
		if ( wc_tax_enabled() ) {
756
			$params['tax_class'] = array(
757
				'description'       => __( 'Limit result set to products with a specific tax class.', 'woocommerce' ),
758
				'type'              => 'string',
759
				'enum'              => array_merge( array( 'standard' ), \WC_Tax::get_tax_class_slugs() ),
760
				'sanitize_callback' => 'sanitize_text_field',
761
				'validate_callback' => 'rest_validate_request_arg',
762
			);
763
		}
764
765
		$params['on_sale'] = array(
766
			'description'       => __( 'Limit result set to products on sale.', 'woocommerce' ),
767
			'type'              => 'boolean',
768
			'sanitize_callback' => 'wc_string_to_bool',
769
			'validate_callback' => 'rest_validate_request_arg',
770
		);
771
772
		$params['min_price'] = array(
773
			'description'       => __( 'Limit result set to products based on a minimum price.', 'woocommerce' ),
774
			'type'              => 'string',
775
			'sanitize_callback' => 'sanitize_text_field',
776
			'validate_callback' => 'rest_validate_request_arg',
777
		);
778
779
		$params['max_price'] = array(
780
			'description'       => __( 'Limit result set to products based on a maximum price.', 'woocommerce' ),
781
			'type'              => 'string',
782
			'sanitize_callback' => 'sanitize_text_field',
783
			'validate_callback' => 'rest_validate_request_arg',
784
		);
785
786
		$params['stock_status'] = array(
787
			'description'       => __( 'Limit result set to products with specified stock status.', 'woocommerce' ),
788
			'type'              => 'string',
789
			'enum'              => array_keys( wc_get_product_stock_status_options() ),
790
			'sanitize_callback' => 'sanitize_text_field',
791
			'validate_callback' => 'rest_validate_request_arg',
792
		);
793
794
		$params['low_in_stock'] = array(
795
			'description'       => __( 'Limit result set to products that are low or out of stock.', 'woocommerce' ),
796
			'type'              => 'boolean',
797
			'default'           => false,
798
			'sanitize_callback' => 'wc_string_to_bool',
799
		);
800
801
		$params['search'] = array(
802
			'description'       => __( 'Search by similar product name or sku.', 'woocommerce' ),
803
			'type'              => 'string',
804
			'validate_callback' => 'rest_validate_request_arg',
805
		);
806
807
		$params['orderby']['enum'] = array_merge( $params['orderby']['enum'], array( 'price', 'popularity', 'rating' ) );
808
809
		return $params;
810
	}
811
812
	/**
813
	 * Get object.
814
	 *
815
	 * @param int $id Object ID.
816
	 *
817
	 * @since  3.0.0
818
	 * @return \WC_Data|bool
819
	 */
820
	protected function get_object( $id ) {
821
		return wc_get_product( $id );
822
	}
823
824
	/**
825
	 * Get data for this object in the format of this endpoint's schema.
826
	 *
827
	 * @param \WC_Product      $object Object to prepare.
828
	 * @param \WP_REST_Request $request Request object.
829
	 * @return array Array of data in the correct format.
830
	 */
831
	protected function get_data_for_response( $object, $request ) {
832
		$formatter = new ProductResponse();
833
834
		return $formatter->prepare_response( $object, $this->get_request_context( $request ) );
835
	}
836
837
	/**
838
	 * Prepare a single product for create or update.
839
	 *
840
	 * @param  \WP_REST_Request $request Request object.
841
	 * @param  bool             $creating If is creating a new object.
842
	 * @return \WP_Error|\WC_Data
843
	 */
844
	protected function prepare_object_for_database( $request, $creating = false ) {
845
		try {
846
			$product_request = new ProductRequest( $request );
847
			$product         = $product_request->prepare_object();
848
		} catch ( \WC_REST_Exception $e ) {
849
			return new \WP_Error( $e->getErrorCode(), $e->getMessage(), array( 'status' => $e->getCode() ) );
850
		}
851
852
		/**
853
		 * Filters an object before it is inserted via the REST API.
854
		 *
855
		 * The dynamic portion of the hook name, `$this->post_type`,
856
		 * refers to the object type slug.
857
		 *
858
		 * @param \WC_Data         $product  Object object.
859
		 * @param \WP_REST_Request $request  Request object.
860
		 * @param bool            $creating If is creating a new object.
861
		 */
862
		return apply_filters( "woocommerce_rest_pre_insert_{$this->post_type}_object", $product, $request, $creating );
863
	}
864
865
	/**
866
	 * Get a collection of posts and add the post title filter option to \WP_Query.
867
	 *
868
	 * @param \WP_REST_Request $request Full details about the request.
869
	 * @return \WP_Error|\WP_REST_Response
870
	 */
871
	public function get_items( $request ) {
872
		add_filter( 'posts_clauses', array( $this, 'get_items_query_clauses' ), 10, 2 );
873
		$response = parent::get_items( $request );
874
		remove_filter( 'posts_clauses', array( $this, 'get_items_query_clauses' ), 10 );
875
		return $response;
876
	}
877
878
	/**
879
	 * Add in conditional search filters for products.
880
	 *
881
	 * @param array     $args Query args.
882
	 * @param \WC_Query $wp_query WC_Query object.
883
	 * @return array
884
	 */
885
	public function get_items_query_clauses( $args, $wp_query ) {
886
		global $wpdb;
887
888
		if ( $wp_query->get( 'search' ) ) {
0 ignored issues
show
Bug introduced by
The method get() does not exist on WC_Query. ( Ignorable by Annotation )

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

888
		if ( $wp_query->/** @scrutinizer ignore-call */ get( 'search' ) ) {

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...
889
			$search         = "'%" . $wpdb->esc_like( $wp_query->get( 'search' ) ) . "%'";
890
			$args['join']   = $this->append_product_sorting_table_join( $args['join'] );
891
			$args['where'] .= " AND ({$wpdb->posts}.post_title LIKE {$search}";
892
			$args['where'] .= wc_product_sku_enabled() ? ' OR wc_product_meta_lookup.sku LIKE ' . $search . ')' : ')';
893
		}
894
895
		if ( $wp_query->get( 'sku' ) ) {
896
			$skus = explode( ',', $wp_query->get( 'sku' ) );
897
			// Include the current string as a SKU too.
898
			if ( 1 < count( $skus ) ) {
899
				$skus[] = $wp_query->get( 'sku' );
900
			}
901
			$args['join']   = $this->append_product_sorting_table_join( $args['join'] );
902
			$args['where'] .= ' AND wc_product_meta_lookup.sku IN ("' . implode( '","', array_map( 'esc_sql', $skus ) ) . '")';
903
		}
904
905
		if ( $wp_query->get( 'min_price' ) ) {
906
			$args['join']   = $this->append_product_sorting_table_join( $args['join'] );
907
			$args['where'] .= $wpdb->prepare( ' AND wc_product_meta_lookup.min_price >= %f ', floatval( $wp_query->get( 'min_price' ) ) );
908
		}
909
910
		if ( $wp_query->get( 'max_price' ) ) {
911
			$args['join']   = $this->append_product_sorting_table_join( $args['join'] );
912
			$args['where'] .= $wpdb->prepare( ' AND wc_product_meta_lookup.max_price <= %f ', floatval( $wp_query->get( 'max_price' ) ) );
913
		}
914
915
		if ( $wp_query->get( 'stock_status' ) ) {
916
			$args['join']   = $this->append_product_sorting_table_join( $args['join'] );
917
			$args['where'] .= $wpdb->prepare( ' AND wc_product_meta_lookup.stock_status = %s ', $wp_query->get( 'stock_status' ) );
918
		}
919
920
		if ( $wp_query->get( 'low_in_stock' ) ) {
921
			$low_stock      = absint( max( get_option( 'woocommerce_notify_low_stock_amount' ), 1 ) );
922
			$args['join']   = $this->append_product_sorting_table_join( $args['join'] );
923
			$args['where'] .= $wpdb->prepare( ' AND wc_product_meta_lookup.stock_quantity <= %d', $low_stock );
924
		}
925
926
		return $args;
927
	}
928
929
	/**
930
	 * Join wc_product_meta_lookup to posts if not already joined.
931
	 *
932
	 * @param string $sql SQL join.
933
	 * @return string
934
	 */
935
	protected function append_product_sorting_table_join( $sql ) {
936
		global $wpdb;
937
938
		if ( ! strstr( $sql, 'wc_product_meta_lookup' ) ) {
939
			$sql .= " LEFT JOIN {$wpdb->wc_product_meta_lookup} wc_product_meta_lookup ON $wpdb->posts.ID = wc_product_meta_lookup.product_id ";
940
		}
941
		return $sql;
942
	}
943
944
	/**
945
	 * Make extra product orderby features supported by WooCommerce available to the WC API.
946
	 * This includes 'price', 'popularity', and 'rating'.
947
	 *
948
	 * @param \WP_REST_Request $request Request data.
949
	 * @return array
950
	 */
951
	protected function prepare_objects_query( $request ) {
952
		$args = parent::prepare_objects_query( $request );
953
954
		// Set post_status.
955
		$args['post_status'] = $request['status'];
956
957
		// Set custom args to handle later during clauses.
958
		$custom_keys = array(
959
			'sku',
960
			'min_price',
961
			'max_price',
962
			'stock_status',
963
			'low_in_stock',
964
		);
965
		foreach ( $custom_keys as $key ) {
966
			if ( ! empty( $request[ $key ] ) ) {
967
				$args[ $key ] = $request[ $key ];
968
			}
969
		}
970
971
		// Taxonomy query to filter products by type, category,
972
		// tag, shipping class, and attribute.
973
		$tax_query = array();
974
975
		// Map between taxonomy name and arg's key.
976
		$taxonomies = array(
977
			'product_cat'            => 'category',
978
			'product_tag'            => 'tag',
979
			'product_shipping_class' => 'shipping_class',
980
		);
981
982
		// Set tax_query for each passed arg.
983
		foreach ( $taxonomies as $taxonomy => $key ) {
984
			if ( ! empty( $request[ $key ] ) ) {
985
				$tax_query[] = array(
986
					'taxonomy' => $taxonomy,
987
					'field'    => 'term_id',
988
					'terms'    => $request[ $key ],
989
				);
990
			}
991
		}
992
993
		// Filter product type by slug.
994
		if ( ! empty( $request['type'] ) ) {
995
			$tax_query[] = array(
996
				'taxonomy' => 'product_type',
997
				'field'    => 'slug',
998
				'terms'    => $request['type'],
999
			);
1000
		}
1001
1002
		// Filter by attribute and term.
1003
		if ( ! empty( $request['attribute'] ) && ! empty( $request['attribute_term'] ) ) {
1004
			if ( in_array( $request['attribute'], wc_get_attribute_taxonomy_names(), true ) ) {
1005
				$tax_query[] = array(
1006
					'taxonomy' => $request['attribute'],
1007
					'field'    => 'term_id',
1008
					'terms'    => $request['attribute_term'],
1009
				);
1010
			}
1011
		}
1012
1013
		// Build tax_query if taxonomies are set.
1014
		if ( ! empty( $tax_query ) ) {
1015
			if ( ! empty( $args['tax_query'] ) ) {
1016
				$args['tax_query'] = array_merge( $tax_query, $args['tax_query'] ); // WPCS: slow query ok.
1017
			} else {
1018
				$args['tax_query'] = $tax_query; // WPCS: slow query ok.
1019
			}
1020
		}
1021
1022
		// Filter featured.
1023
		if ( is_bool( $request['featured'] ) ) {
1024
			$args['tax_query'][] = array(
1025
				'taxonomy' => 'product_visibility',
1026
				'field'    => 'name',
1027
				'terms'    => 'featured',
1028
				'operator' => true === $request['featured'] ? 'IN' : 'NOT IN',
1029
			);
1030
		}
1031
1032
		// Filter by tax class.
1033
		if ( ! empty( $request['tax_class'] ) ) {
1034
			$args['meta_query'] = $this->add_meta_query( // WPCS: slow query ok.
1035
				$args,
1036
				array(
1037
					'key'   => '_tax_class',
1038
					'value' => 'standard' !== $request['tax_class'] ? $request['tax_class'] : '',
1039
				)
1040
			);
1041
		}
1042
1043
		// Filter by on sale products.
1044
		if ( is_bool( $request['on_sale'] ) ) {
1045
			$on_sale_key = $request['on_sale'] ? 'post__in' : 'post__not_in';
1046
			$on_sale_ids = wc_get_product_ids_on_sale();
1047
1048
			// Use 0 when there's no on sale products to avoid return all products.
1049
			$on_sale_ids = empty( $on_sale_ids ) ? array( 0 ) : $on_sale_ids;
1050
1051
			$args[ $on_sale_key ] += $on_sale_ids;
1052
		}
1053
1054
		// Force the post_type argument, since it's not a user input variable.
1055
		if ( ! empty( $request['sku'] ) ) {
1056
			$args['post_type'] = array( 'product', 'product_variation' );
1057
		} else {
1058
			$args['post_type'] = $this->post_type;
1059
		}
1060
1061
		$orderby = $request->get_param( 'orderby' );
1062
		$order   = $request->get_param( 'order' );
1063
1064
		$ordering_args   = WC()->query->get_catalog_ordering_args( $orderby, $order );
1065
		$args['orderby'] = $ordering_args['orderby'];
1066
		$args['order']   = $ordering_args['order'];
1067
		if ( $ordering_args['meta_key'] ) {
1068
			$args['meta_key'] = $ordering_args['meta_key']; // WPCS: slow query ok.
1069
		}
1070
1071
		return $args;
1072
	}
1073
1074
	/**
1075
	 * Prepare links for the request.
1076
	 *
1077
	 * @param mixed            $item Object to prepare.
1078
	 * @param \WP_REST_Request $request Request object.
1079
	 * @return array
1080
	 */
1081
	protected function prepare_links( $item, $request ) {
1082
		$links = array(
1083
			'self'       => array(
1084
				'href' => rest_url( sprintf( '/%s/%s/%d', $this->namespace, $this->rest_base, $item->get_id() ) ),  // @codingStandardsIgnoreLine.
1085
			),
1086
			'collection' => array(
1087
				'href' => rest_url( sprintf( '/%s/%s', $this->namespace, $this->rest_base ) ),  // @codingStandardsIgnoreLine.
1088
			),
1089
		);
1090
1091
		if ( $item->get_parent_id() ) {
1092
			$links['up'] = array(
1093
				'href' => rest_url( sprintf( '/%s/products/%d', $this->namespace, $item->get_parent_id() ) ),  // @codingStandardsIgnoreLine.
1094
			);
1095
		}
1096
1097
		return $links;
1098
	}
1099
1100
	/**
1101
	 * Delete a single item.
1102
	 *
1103
	 * @param \WP_REST_Request $request Full details about the request.
1104
	 *
1105
	 * @return \WP_REST_Response|\WP_Error
1106
	 */
1107
	public function delete_item( $request ) {
1108
		$id     = (int) $request['id'];
1109
		$force  = (bool) $request['force'];
1110
		$object = $this->get_object( (int) $request['id'] );
1111
		$result = false;
1112
1113
		if ( ! $object || 0 === $object->get_id() ) {
0 ignored issues
show
introduced by
$object is of type WC_Product, thus it always evaluated to true.
Loading history...
1114
			return new \WP_Error(
1115
				"woocommerce_rest_{$this->post_type}_invalid_id",
1116
				__( 'Invalid ID.', 'woocommerce' ),
1117
				array(
1118
					'status' => 404,
1119
				)
1120
			);
1121
		}
1122
1123
		if ( 'variation' === $object->get_type() ) {
1124
			return new \WP_Error(
1125
				"woocommerce_rest_invalid_{$this->post_type}_id",
1126
				__( 'To manipulate product variations you should use the /products/&lt;product_id&gt;/variations/&lt;id&gt; endpoint.', 'woocommerce' ),
1127
				array(
1128
					'status' => 404,
1129
				)
1130
			);
1131
		}
1132
1133
		$supports_trash = EMPTY_TRASH_DAYS > 0 && is_callable( array( $object, 'get_status' ) );
1134
1135
		/**
1136
		 * Filter whether an object is trashable.
1137
		 *
1138
		 * Return false to disable trash support for the object.
1139
		 *
1140
		 * @param boolean $supports_trash Whether the object type support trashing.
1141
		 * @param \WC_Data $object         The object being considered for trashing support.
1142
		 */
1143
		$supports_trash = apply_filters( "woocommerce_rest_{$this->post_type}_object_trashable", $supports_trash, $object );
1144
1145
		if ( ! Permissions::user_can_delete( $this->post_type, $object->get_id() ) ) {
1146
			return new \WP_Error(
1147
				"woocommerce_rest_user_cannot_delete_{$this->post_type}",
1148
				/* translators: %s: post type */
1149
				sprintf( __( 'Sorry, you are not allowed to delete %s.', 'woocommerce' ), $this->post_type ),
1150
				array(
1151
					'status' => rest_authorization_required_code(),
1152
				)
1153
			);
1154
		}
1155
1156
		$request->set_param( 'context', 'edit' );
1157
1158
		// If we're forcing, then delete permanently.
1159
		if ( $force ) {
1160
			$previous = $this->prepare_item_for_response( $object, $request );
1161
1162
			$object->delete( true );
1163
			$result = 0 === $object->get_id();
1164
1165
			$response = new \WP_REST_Response();
1166
			$response->set_data(
1167
				array(
1168
					'deleted'  => true,
1169
					'previous' => $previous->get_data(),
1170
				)
1171
			);
1172
		} else {
1173
			// If we don't support trashing for this type, error out.
1174
			if ( ! $supports_trash ) {
1175
				return new \WP_Error(
1176
					'woocommerce_rest_trash_not_supported',
1177
					/* translators: %s: post type */
1178
					sprintf( __( 'The %s does not support trashing.', 'woocommerce' ), $this->post_type ),
1179
					array(
1180
						'status' => 501,
1181
					)
1182
				);
1183
			}
1184
1185
			// Otherwise, only trash if we haven't already.
1186
			if ( is_callable( array( $object, 'get_status' ) ) ) {
1187
				if ( 'trash' === $object->get_status() ) {
1188
					return new \WP_Error(
1189
						'woocommerce_rest_already_trashed',
1190
						/* translators: %s: post type */
1191
						sprintf( __( 'The %s has already been deleted.', 'woocommerce' ), $this->post_type ),
1192
						array(
1193
							'status' => 410,
1194
						)
1195
					);
1196
				}
1197
1198
				$object->delete();
1199
				$result = 'trash' === $object->get_status();
1200
			}
1201
1202
			$response = $this->prepare_item_for_response( $object, $request );
1203
		}
1204
1205
		if ( ! $result ) {
1206
			return new \WP_Error(
1207
				'woocommerce_rest_cannot_delete',
1208
				/* translators: %s: post type */
1209
				sprintf( __( 'The %s cannot be deleted.', 'woocommerce' ), $this->post_type ),
1210
				array(
1211
					'status' => 500,
1212
				)
1213
			);
1214
		}
1215
1216
		/**
1217
		 * Fires after a single object is deleted or trashed via the REST API.
1218
		 *
1219
		 * @param \WC_Data          $object   The deleted or trashed object.
1220
		 * @param \WP_REST_Response $response The response data.
1221
		 * @param \WP_REST_Request  $request  The request sent to the API.
1222
		 */
1223
		do_action( "woocommerce_rest_delete_{$this->post_type}_object", $object, $response, $request );
1224
1225
		return $response;
1226
	}
1227
}
1228