Passed
Push — master ( aa41b1...2b3c87 )
by Mike
04:52
created

Products::get_collection_params()   B

Complexity

Conditions 2
Paths 2

Size

Total Lines 130
Code Lines 92

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 92
nc 2
nop 0
dl 0
loc 130
rs 8.1745
c 0
b 0
f 0

How to fix   Long Method   

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

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

905
		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...
906
			$search         = "'%" . $wpdb->esc_like( $wp_query->get( 'search' ) ) . "%'";
907
			$args['join']   = $this->append_product_sorting_table_join( $args['join'] );
908
			$args['where'] .= " AND ({$wpdb->posts}.post_title LIKE {$search}";
909
			$args['where'] .= wc_product_sku_enabled() ? ' OR wc_product_meta_lookup.sku LIKE ' . $search . ')' : ')';
910
		}
911
912
		if ( $wp_query->get( 'sku' ) ) {
913
			$skus = explode( ',', $wp_query->get( 'sku' ) );
914
			// Include the current string as a SKU too.
915
			if ( 1 < count( $skus ) ) {
916
				$skus[] = $wp_query->get( 'sku' );
917
			}
918
			$args['join']   = $this->append_product_sorting_table_join( $args['join'] );
919
			$args['where'] .= ' AND wc_product_meta_lookup.sku IN ("' . implode( '","', array_map( 'esc_sql', $skus ) ) . '")';
920
		}
921
922
		if ( $wp_query->get( 'min_price' ) ) {
923
			$args['join']   = $this->append_product_sorting_table_join( $args['join'] );
924
			$args['where'] .= $wpdb->prepare( ' AND wc_product_meta_lookup.min_price >= %f ', floatval( $wp_query->get( 'min_price' ) ) );
925
		}
926
927
		if ( $wp_query->get( 'max_price' ) ) {
928
			$args['join']   = $this->append_product_sorting_table_join( $args['join'] );
929
			$args['where'] .= $wpdb->prepare( ' AND wc_product_meta_lookup.max_price <= %f ', floatval( $wp_query->get( 'max_price' ) ) );
930
		}
931
932
		if ( $wp_query->get( 'stock_status' ) ) {
933
			$args['join']   = $this->append_product_sorting_table_join( $args['join'] );
934
			$args['where'] .= $wpdb->prepare( ' AND wc_product_meta_lookup.stock_status = %s ', $wp_query->get( 'stock_status' ) );
935
		}
936
937
		if ( $wp_query->get( 'low_in_stock' ) ) {
938
			$low_stock      = absint( max( get_option( 'woocommerce_notify_low_stock_amount' ), 1 ) );
939
			$args['join']   = $this->append_product_sorting_table_join( $args['join'] );
940
			$args['where'] .= $wpdb->prepare( ' AND wc_product_meta_lookup.stock_quantity <= %d', $low_stock );
941
		}
942
943
		return $args;
944
	}
945
946
	/**
947
	 * Join wc_product_meta_lookup to posts if not already joined.
948
	 *
949
	 * @param string $sql SQL join.
950
	 * @return string
951
	 */
952
	protected function append_product_sorting_table_join( $sql ) {
953
		global $wpdb;
954
955
		if ( ! strstr( $sql, 'wc_product_meta_lookup' ) ) {
956
			$sql .= " LEFT JOIN {$wpdb->wc_product_meta_lookup} wc_product_meta_lookup ON $wpdb->posts.ID = wc_product_meta_lookup.product_id ";
957
		}
958
		return $sql;
959
	}
960
961
	/**
962
	 * Make extra product orderby features supported by WooCommerce available to the WC API.
963
	 * This includes 'price', 'popularity', and 'rating'.
964
	 *
965
	 * @param \WP_REST_Request $request Request data.
966
	 * @return array
967
	 */
968
	protected function prepare_objects_query( $request ) {
969
		$args = parent::prepare_objects_query( $request );
970
971
		// Set post_status.
972
		$args['post_status'] = $request['status'];
973
974
		// Set custom args to handle later during clauses.
975
		$custom_keys = array(
976
			'sku',
977
			'min_price',
978
			'max_price',
979
			'stock_status',
980
			'low_in_stock',
981
		);
982
		foreach ( $custom_keys as $key ) {
983
			if ( ! empty( $request[ $key ] ) ) {
984
				$args[ $key ] = $request[ $key ];
985
			}
986
		}
987
988
		// Taxonomy query to filter products by type, category,
989
		// tag, shipping class, and attribute.
990
		$tax_query = array();
991
992
		// Map between taxonomy name and arg's key.
993
		$taxonomies = array(
994
			'product_cat'            => 'category',
995
			'product_tag'            => 'tag',
996
			'product_shipping_class' => 'shipping_class',
997
		);
998
999
		// Set tax_query for each passed arg.
1000
		foreach ( $taxonomies as $taxonomy => $key ) {
1001
			if ( ! empty( $request[ $key ] ) ) {
1002
				$tax_query[] = array(
1003
					'taxonomy' => $taxonomy,
1004
					'field'    => 'term_id',
1005
					'terms'    => $request[ $key ],
1006
				);
1007
			}
1008
		}
1009
1010
		// Filter product type by slug.
1011
		if ( ! empty( $request['type'] ) ) {
1012
			$tax_query[] = array(
1013
				'taxonomy' => 'product_type',
1014
				'field'    => 'slug',
1015
				'terms'    => $request['type'],
1016
			);
1017
		}
1018
1019
		// Filter by attribute and term.
1020
		if ( ! empty( $request['attribute'] ) && ! empty( $request['attribute_term'] ) ) {
1021
			if ( in_array( $request['attribute'], wc_get_attribute_taxonomy_names(), true ) ) {
1022
				$tax_query[] = array(
1023
					'taxonomy' => $request['attribute'],
1024
					'field'    => 'term_id',
1025
					'terms'    => $request['attribute_term'],
1026
				);
1027
			}
1028
		}
1029
1030
		// Build tax_query if taxonomies are set.
1031
		if ( ! empty( $tax_query ) ) {
1032
			if ( ! empty( $args['tax_query'] ) ) {
1033
				$args['tax_query'] = array_merge( $tax_query, $args['tax_query'] ); // WPCS: slow query ok.
1034
			} else {
1035
				$args['tax_query'] = $tax_query; // WPCS: slow query ok.
1036
			}
1037
		}
1038
1039
		// Filter featured.
1040
		if ( is_bool( $request['featured'] ) ) {
1041
			$args['tax_query'][] = array(
1042
				'taxonomy' => 'product_visibility',
1043
				'field'    => 'name',
1044
				'terms'    => 'featured',
1045
				'operator' => true === $request['featured'] ? 'IN' : 'NOT IN',
1046
			);
1047
		}
1048
1049
		// Filter by tax class.
1050
		if ( ! empty( $request['tax_class'] ) ) {
1051
			$args['meta_query'] = $this->add_meta_query( // WPCS: slow query ok.
1052
				$args,
1053
				array(
1054
					'key'   => '_tax_class',
1055
					'value' => 'standard' !== $request['tax_class'] ? $request['tax_class'] : '',
1056
				)
1057
			);
1058
		}
1059
1060
		// Filter by on sale products.
1061
		if ( is_bool( $request['on_sale'] ) ) {
1062
			$on_sale_key = $request['on_sale'] ? 'post__in' : 'post__not_in';
1063
			$on_sale_ids = wc_get_product_ids_on_sale();
1064
1065
			// Use 0 when there's no on sale products to avoid return all products.
1066
			$on_sale_ids = empty( $on_sale_ids ) ? array( 0 ) : $on_sale_ids;
1067
1068
			$args[ $on_sale_key ] += $on_sale_ids;
1069
		}
1070
1071
		// Force the post_type argument, since it's not a user input variable.
1072
		if ( ! empty( $request['sku'] ) ) {
1073
			$args['post_type'] = array( 'product', 'product_variation' );
1074
		} else {
1075
			$args['post_type'] = $this->post_type;
1076
		}
1077
1078
		$orderby = $request->get_param( 'orderby' );
1079
		$order   = $request->get_param( 'order' );
1080
1081
		$ordering_args   = WC()->query->get_catalog_ordering_args( $orderby, $order );
1082
		$args['orderby'] = $ordering_args['orderby'];
1083
		$args['order']   = $ordering_args['order'];
1084
		if ( $ordering_args['meta_key'] ) {
1085
			$args['meta_key'] = $ordering_args['meta_key']; // WPCS: slow query ok.
1086
		}
1087
1088
		return $args;
1089
	}
1090
1091
	/**
1092
	 * Prepare links for the request.
1093
	 *
1094
	 * @param \WC_Data         $object  Object data.
1095
	 * @param \WP_REST_Request $request Request object.
1096
	 *
1097
	 * @return array                   Links for the given post.
1098
	 */
1099
	protected function prepare_links( $object, $request ) {
1100
		$links = array(
1101
			'self'       => array(
1102
				'href' => rest_url( sprintf( '/%s/%s/%d', $this->namespace, $this->rest_base, $object->get_id() ) ),  // @codingStandardsIgnoreLine.
1103
			),
1104
			'collection' => array(
1105
				'href' => rest_url( sprintf( '/%s/%s', $this->namespace, $this->rest_base ) ),  // @codingStandardsIgnoreLine.
1106
			),
1107
		);
1108
1109
		if ( $object->get_parent_id() ) {
0 ignored issues
show
Bug introduced by
The method get_parent_id() does not exist on WC_Data. It seems like you code against a sub-type of WC_Data such as WC_Product or WC_Abstract_Order. ( Ignorable by Annotation )

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

1109
		if ( $object->/** @scrutinizer ignore-call */ get_parent_id() ) {
Loading history...
1110
			$links['up'] = array(
1111
				'href' => rest_url( sprintf( '/%s/products/%d', $this->namespace, $object->get_parent_id() ) ),  // @codingStandardsIgnoreLine.
1112
			);
1113
		}
1114
1115
		return $links;
1116
	}
1117
1118
	/**
1119
	 * Delete a single item.
1120
	 *
1121
	 * @param \WP_REST_Request $request Full details about the request.
1122
	 *
1123
	 * @return \WP_REST_Response|\WP_Error
1124
	 */
1125
	public function delete_item( $request ) {
1126
		$id     = (int) $request['id'];
1127
		$force  = (bool) $request['force'];
1128
		$object = $this->get_object( (int) $request['id'] );
1129
		$result = false;
1130
1131
		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...
1132
			return new \WP_Error(
1133
				"woocommerce_rest_{$this->post_type}_invalid_id",
1134
				__( 'Invalid ID.', 'woocommerce' ),
1135
				array(
1136
					'status' => 404,
1137
				)
1138
			);
1139
		}
1140
1141
		if ( 'variation' === $object->get_type() ) {
1142
			return new \WP_Error(
1143
				"woocommerce_rest_invalid_{$this->post_type}_id",
1144
				__( 'To manipulate product variations you should use the /products/&lt;product_id&gt;/variations/&lt;id&gt; endpoint.', 'woocommerce' ),
1145
				array(
1146
					'status' => 404,
1147
				)
1148
			);
1149
		}
1150
1151
		$supports_trash = EMPTY_TRASH_DAYS > 0 && is_callable( array( $object, 'get_status' ) );
1152
1153
		/**
1154
		 * Filter whether an object is trashable.
1155
		 *
1156
		 * Return false to disable trash support for the object.
1157
		 *
1158
		 * @param boolean $supports_trash Whether the object type support trashing.
1159
		 * @param \WC_Data $object         The object being considered for trashing support.
1160
		 */
1161
		$supports_trash = apply_filters( "woocommerce_rest_{$this->post_type}_object_trashable", $supports_trash, $object );
1162
1163
		if ( ! wc_rest_check_post_permissions( $this->post_type, 'delete', $object->get_id() ) ) {
1164
			return new \WP_Error(
1165
				"woocommerce_rest_user_cannot_delete_{$this->post_type}",
1166
				/* translators: %s: post type */
1167
				sprintf( __( 'Sorry, you are not allowed to delete %s.', 'woocommerce' ), $this->post_type ),
1168
				array(
1169
					'status' => rest_authorization_required_code(),
1170
				)
1171
			);
1172
		}
1173
1174
		$request->set_param( 'context', 'edit' );
1175
1176
		// If we're forcing, then delete permanently.
1177
		if ( $force ) {
1178
			$previous = $this->prepare_object_for_response( $object, $request );
1179
1180
			$object->delete( true );
1181
			$result = 0 === $object->get_id();
1182
1183
			$response = new \WP_REST_Response();
1184
			$response->set_data(
1185
				array(
1186
					'deleted'  => true,
1187
					'previous' => $previous->get_data(),
1188
				)
1189
			);
1190
		} else {
1191
			// If we don't support trashing for this type, error out.
1192
			if ( ! $supports_trash ) {
1193
				return new \WP_Error(
1194
					'woocommerce_rest_trash_not_supported',
1195
					/* translators: %s: post type */
1196
					sprintf( __( 'The %s does not support trashing.', 'woocommerce' ), $this->post_type ),
1197
					array(
1198
						'status' => 501,
1199
					)
1200
				);
1201
			}
1202
1203
			// Otherwise, only trash if we haven't already.
1204
			if ( is_callable( array( $object, 'get_status' ) ) ) {
1205
				if ( 'trash' === $object->get_status() ) {
1206
					return new \WP_Error(
1207
						'woocommerce_rest_already_trashed',
1208
						/* translators: %s: post type */
1209
						sprintf( __( 'The %s has already been deleted.', 'woocommerce' ), $this->post_type ),
1210
						array(
1211
							'status' => 410,
1212
						)
1213
					);
1214
				}
1215
1216
				$object->delete();
1217
				$result = 'trash' === $object->get_status();
1218
			}
1219
1220
			$response = $this->prepare_object_for_response( $object, $request );
1221
		}
1222
1223
		if ( ! $result ) {
1224
			return new \WP_Error(
1225
				'woocommerce_rest_cannot_delete',
1226
				/* translators: %s: post type */
1227
				sprintf( __( 'The %s cannot be deleted.', 'woocommerce' ), $this->post_type ),
1228
				array(
1229
					'status' => 500,
1230
				)
1231
			);
1232
		}
1233
1234
		/**
1235
		 * Fires after a single object is deleted or trashed via the REST API.
1236
		 *
1237
		 * @param \WC_Data          $object   The deleted or trashed object.
1238
		 * @param \WP_REST_Response $response The response data.
1239
		 * @param \WP_REST_Request  $request  The request sent to the API.
1240
		 */
1241
		do_action( "woocommerce_rest_delete_{$this->post_type}_object", $object, $response, $request );
1242
1243
		return $response;
1244
	}
1245
}
1246