Completed
Push — master ( f47a1d...37f03f )
by Claudio
28:06
created

WC_REST_Posts_Controller::prepare_links()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 12
Code Lines 7

Duplication

Lines 12
Ratio 100 %
Metric Value
dl 12
loc 12
rs 9.4285
nc 1
cc 1
eloc 7
nop 1
1
<?php
1 ignored issue
show
Coding Style Compatibility introduced by
For compatibility and reusability of your code, PSR1 recommends that a file should introduce either new symbols (like classes, functions, etc.) or have side-effects (like outputting something, or including other files), but not both at the same time. The first symbol is defined on line 15 and the first side effect is on line 4.

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

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

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

Loading history...
2
3
if ( ! defined( 'ABSPATH' ) ) {
4
	exit;
5
}
6
7
/**
8
 * Abstract Rest Posts Controler Class
9
 *
10
 * @author   WooThemes
11
 * @category API
12
 * @package  WooCommerce/Abstracts
13
 * @version  2.6.0
14
 */
15
abstract class WC_REST_Posts_Controller extends WP_REST_Controller {
16
17
	/**
18
	 * Endpoint namespace.
19
	 *
20
	 * @var string
21
	 */
22
	protected $namespace = 'wc/v1';
23
24
	/**
25
	 * Route base.
26
	 *
27
	 * @var string
28
	 */
29
	protected $rest_base = '';
30
31
	/**
32
	 * Post type.
33
	 *
34
	 * @var string
35
	 */
36
	protected $post_type = '';
37
38
	/**
39
	 * Controls visibility on frontend.
40
	 *
41
	 * @var string
42
	 */
43
	protected $public = false;
44
45
	/**
46
	 * Check if a given request has access to read items.
47
	 *
48
	 * @param  WP_REST_Request $request Full details about the request.
49
	 * @return WP_Error|boolean
50
	 */
51
	public function get_items_permissions_check( $request ) {
52
		if ( ! wc_rest_check_post_permissions( $this->post_type, 'read' ) ) {
53
			return new WP_Error( 'woocommerce_rest_cannot_view', __( 'Sorry, you cannot list resources.', 'woocommerce' ), array( 'status' => rest_authorization_required_code() ) );
54
		}
55
56
		return true;
57
	}
58
59
	/**
60
	 * Check if a given request has access to create an item.
61
	 *
62
	 * @param  WP_REST_Request $request Full details about the request.
63
	 * @return WP_Error|boolean
64
	 */
65
	public function create_item_permissions_check( $request ) {
66
		if ( ! wc_rest_check_post_permissions( $this->post_type, 'create' ) ) {
67
			return new WP_Error( 'woocommerce_rest_cannot_create', __( 'Sorry, you are not allowed to create resources.', 'woocommerce' ), array( 'status' => rest_authorization_required_code() ) );
68
		}
69
70
		return true;
71
	}
72
73
	/**
74
	 * Check if a given request has access to read an item.
75
	 *
76
	 * @param  WP_REST_Request $request Full details about the request.
77
	 * @return WP_Error|boolean
78
	 */
79 View Code Duplication
	public function get_item_permissions_check( $request ) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
80
		$post = get_post( (int) $request['id'] );
81
82
		if ( $post && ! wc_rest_check_post_permissions( $this->post_type, 'read', $post->ID ) ) {
83
			return new WP_Error( 'woocommerce_rest_cannot_view', __( 'Sorry, you cannot view this resource.', 'woocommerce' ), array( 'status' => rest_authorization_required_code() ) );
84
		}
85
86
		return true;
87
	}
88
89
	/**
90
	 * Check if a given request has access to update an item.
91
	 *
92
	 * @param  WP_REST_Request $request Full details about the request.
93
	 * @return WP_Error|boolean
94
	 */
95 View Code Duplication
	public function update_item_permissions_check( $request ) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
96
		$post = get_post( $request['id'] );
97
98
		if ( $post && ! wc_rest_check_post_permissions( $this->post_type, 'edit', $post->ID ) ) {
99
			return new WP_Error( 'woocommerce_rest_cannot_edit', __( 'Sorry, you are not allowed to edit this resource.', 'woocommerce' ), array( 'status' => rest_authorization_required_code() ) );
100
		}
101
102
		return true;
103
	}
104
105
	/**
106
	 * Check if a given request has access to delete an item.
107
	 *
108
	 * @param  WP_REST_Request $request Full details about the request.
109
	 * @return bool|WP_Error
110
	 */
111 View Code Duplication
	public function delete_item_permissions_check( $request ) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
112
		$post = get_post( $request['id'] );
113
114
		if ( $post && ! wc_rest_check_post_permissions( $this->post_type, 'delete', $post->ID ) ) {
115
			return new WP_Error( 'woocommerce_rest_cannot_delete', __( 'Sorry, you are not allowed to delete this resource.', 'woocommerce' ), array( 'status' => rest_authorization_required_code() ) );
116
		}
117
118
		return true;
119
	}
120
121
	/**
122
	 * Get a single item.
123
	 *
124
	 * @param WP_REST_Request $request Full details about the request.
125
	 * @return WP_Error|WP_REST_Response
126
	 */
127
	public function get_item( $request ) {
128
		$id   = (int) $request['id'];
129
		$post = get_post( $id );
130
131
		if ( empty( $id ) || empty( $post->ID ) || $this->post_type !== $post->post_type ) {
132
			return new WP_Error( "woocommerce_rest_invalid_{$this->post_type}_id", __( 'Invalid id.', 'woocommerce' ), array( 'status' => 404 ) );
133
		}
134
135
		$data = $this->prepare_item_for_response( $post, $request );
136
		$response = rest_ensure_response( $data );
137
138
		if ( $this->public ) {
139
			$response->link_header( 'alternate', get_permalink( $id ), array( 'type' => 'text/html' ) );
140
		}
141
142
		return $response;
143
	}
144
145
	/**
146
	 * Create a single item.
147
	 *
148
	 * @param WP_REST_Request $request Full details about the request.
149
	 * @return WP_Error|WP_REST_Response
150
	 */
151
	public function create_item( $request ) {
152
		if ( ! empty( $request['id'] ) ) {
153
			return new WP_Error( "woocommerce_rest_{$this->post_type}_exists", sprintf( __( 'Cannot create existing %s.', 'woocommerce' ), $this->post_type ), array( 'status' => 400 ) );
154
		}
155
156
		$post = $this->prepare_item_for_database( $request );
157
		if ( is_wp_error( $post ) ) {
158
			return $post;
159
		}
160
161
		$post->post_type = $this->post_type;
162
		$post_id         = wp_insert_post( $post, true );
163
164 View Code Duplication
		if ( is_wp_error( $post_id ) ) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
165
166
			if ( in_array( $post_id->get_error_code(), array( 'db_insert_error' ) ) ) {
167
				$post_id->add_data( array( 'status' => 500 ) );
168
			} else {
169
				$post_id->add_data( array( 'status' => 400 ) );
170
			}
171
			return $post_id;
172
		}
173
		$post->ID = $post_id;
174
		$schema   = $this->get_item_schema();
0 ignored issues
show
Unused Code introduced by
$schema is not used, you could remove the assignment.

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

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

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

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

Loading history...
175
		$post     = get_post( $post_id );
176
177
		$this->update_additional_fields_for_object( $post, $request );
178
179
		// Add meta fields.
180
		$meta_fields = $this->add_post_meta_fields( $post, $request );
181
		if ( is_wp_error( $meta_fields ) ) {
182
			// Remove post.
183
			$this->delete_post( $post );
184
185
			return $meta_fields;
186
		}
187
188
		/**
189
		 * Fires after a single item is created or updated via the REST API.
190
		 *
191
		 * @param object          $post      Inserted object (not a WP_Post object).
192
		 * @param WP_REST_Request $request   Request object.
193
		 * @param boolean         $creating  True when creating item, false when updating.
194
		 */
195
		do_action( "woocommerce_rest_insert_{$this->post_type}", $post, $request, true );
196
197
		$request->set_param( 'context', 'edit' );
198
		$response = $this->prepare_item_for_response( $post, $request );
199
		$response = rest_ensure_response( $response );
200
		$response->set_status( 201 );
201
		$response->header( 'Location', rest_url( sprintf( '/%s/%s/%d', $this->namespace, $this->rest_base, $post_id ) ) );
202
203
		return $response;
204
	}
205
206
	/**
207
	 * Add post meta fields.
208
	 *
209
	 * @param WP_Post $post
210
	 * @param WP_REST_Request $request
211
	 * @return bool|WP_Error
212
	 */
213
	protected function add_post_meta_fields( $post, $request ) {
214
		return true;
215
	}
216
217
	/**
218
	 * Delete post.
219
	 *
220
	 * @param WP_Post $post
221
	 */
222
	protected function delete_post( $post ) {
223
		wp_delete_post( $post->ID, true );
224
	}
225
226
	/**
227
	 * Update a single post.
228
	 *
229
	 * @param WP_REST_Request $request Full details about the request.
230
	 * @return WP_Error|WP_REST_Response
231
	 */
232
	public function update_item( $request ) {
233
		$id   = (int) $request['id'];
234
		$post = get_post( $id );
235
236
		if ( empty( $id ) || empty( $post->ID ) || $this->post_type !== $post->post_type ) {
237
			return new WP_Error( "woocommerce_rest_{$this->post_type}_invalid_id", __( 'ID is invalid.', 'woocommerce' ), array( 'status' => 400 ) );
238
		}
239
240
		$post = $this->prepare_item_for_database( $request );
241
		if ( is_wp_error( $post ) ) {
242
			return $post;
243
		}
244
		// Convert the post object to an array, otherwise wp_update_post will expect non-escaped input.
245
		$post_id = wp_update_post( (array) $post, true );
246 View Code Duplication
		if ( is_wp_error( $post_id ) ) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
247
			if ( in_array( $post_id->get_error_code(), array( 'db_update_error' ) ) ) {
248
				$post_id->add_data( array( 'status' => 500 ) );
249
			} else {
250
				$post_id->add_data( array( 'status' => 400 ) );
251
			}
252
			return $post_id;
253
		}
254
255
		$schema = $this->get_item_schema();
0 ignored issues
show
Unused Code introduced by
$schema is not used, you could remove the assignment.

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

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

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

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

Loading history...
256
257
		$post = get_post( $post_id );
258
		$this->update_additional_fields_for_object( $post, $request );
259
260
		// Update meta fields.
261
		$meta_fields = $this->update_post_meta_fields( $post, $request );
262
		if ( is_wp_error( $meta_fields ) ) {
263
			return $meta_fields;
264
		}
265
266
		/**
267
		 * Fires after a single item is created or updated via the REST API.
268
		 *
269
		 * @param object          $post      Inserted object (not a WP_Post object).
270
		 * @param WP_REST_Request $request   Request object.
271
		 * @param boolean         $creating  True when creating item, false when updating.
272
		 */
273
		do_action( "woocommerce_rest_insert_{$this->post_type}", $post, $request, false );
274
275
		$request->set_param( 'context', 'edit' );
276
		$response = $this->prepare_item_for_response( $post, $request );
277
		return rest_ensure_response( $response );
278
	}
279
280
	/**
281
	 * Get a collection of posts.
282
	 *
283
	 * @param WP_REST_Request $request Full details about the request.
284
	 * @return WP_Error|WP_REST_Response
285
	 */
286
	public function get_items( $request ) {
287
		$args                         = array();
288
		$args['offset']               = $request['offset'];
289
		$args['order']                = $request['order'];
290
		$args['orderby']              = $request['orderby'];
291
		$args['paged']                = $request['page'];
292
		$args['post__in']             = $request['include'];
293
		$args['post__not_in']         = $request['exclude'];
294
		$args['posts_per_page']       = $request['per_page'];
295
		$args['name']                 = $request['slug'];
296
		$args['post_parent__in']      = $request['parent'];
297
		$args['post_parent__not_in']  = $request['parent_exclude'];
298
		$args['s']                    = $request['search'];
299
300
		$args['date_query'] = array();
301
		// Set before into date query. Date query must be specified as an array of an array.
302
		if ( isset( $request['before'] ) ) {
303
			$args['date_query'][0]['before'] = $request['before'];
304
		}
305
306
		// Set after into date query. Date query must be specified as an array of an array.
307
		if ( isset( $request['after'] ) ) {
308
			$args['date_query'][0]['after'] = $request['after'];
309
		}
310
311
		if ( is_array( $request['filter'] ) ) {
312
			$args = array_merge( $args, $request['filter'] );
313
			unset( $args['filter'] );
314
		}
315
316
		// Force the post_type argument, since it's not a user input variable.
317
		$args['post_type'] = $this->post_type;
318
319
		/**
320
		 * Filter the query arguments for a request.
321
		 *
322
		 * Enables adding extra arguments or setting defaults for a post
323
		 * collection request.
324
		 *
325
		 * @param array           $args    Key value array of query var to query value.
326
		 * @param WP_REST_Request $request The request used.
327
		 */
328
		$args = apply_filters( "woocommerce_rest_{$this->post_type}_query", $args, $request );
329
		$query_args = $this->prepare_items_query( $args, $request );
330
331
		$posts_query = new WP_Query();
332
		$query_result = $posts_query->query( $query_args );
333
334
		$posts = array();
335
		foreach ( $query_result as $post ) {
336
			if ( ! wc_rest_check_post_permissions( $this->post_type, 'read', $post->ID ) ) {
337
				continue;
338
			}
339
340
			$data = $this->prepare_item_for_response( $post, $request );
341
			$posts[] = $this->prepare_response_for_collection( $data );
342
		}
343
344
		$page = (int) $query_args['paged'];
345
		$total_posts = $posts_query->found_posts;
346
347
		if ( $total_posts < 1 ) {
348
			// Out-of-bounds, run the query again without LIMIT for total count
349
			unset( $query_args['paged'] );
350
			$count_query = new WP_Query();
351
			$count_query->query( $query_args );
352
			$total_posts = $count_query->found_posts;
353
		}
354
355
		$max_pages = ceil( $total_posts / (int) $query_args['posts_per_page'] );
356
357
		$response = rest_ensure_response( $posts );
358
		$response->header( 'X-WP-Total', (int) $total_posts );
359
		$response->header( 'X-WP-TotalPages', (int) $max_pages );
360
361
		$request_params = $request->get_query_params();
362
		if ( ! empty( $request_params['filter'] ) ) {
363
			// Normalize the pagination params.
364
			unset( $request_params['filter']['posts_per_page'] );
365
			unset( $request_params['filter']['paged'] );
366
		}
367
		$base = add_query_arg( $request_params, rest_url( sprintf( '/%s/%s', $this->namespace, $this->rest_base ) ) );
368
369 View Code Duplication
		if ( $page > 1 ) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
370
			$prev_page = $page - 1;
371
			if ( $prev_page > $max_pages ) {
372
				$prev_page = $max_pages;
373
			}
374
			$prev_link = add_query_arg( 'page', $prev_page, $base );
375
			$response->link_header( 'prev', $prev_link );
376
		}
377 View Code Duplication
		if ( $max_pages > $page ) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
378
			$next_page = $page + 1;
379
			$next_link = add_query_arg( 'page', $next_page, $base );
380
			$response->link_header( 'next', $next_link );
381
		}
382
383
		return $response;
384
	}
385
386
	/**
387
	 * Delete a single item.
388
	 *
389
	 * @param WP_REST_Request $request Full details about the request.
390
	 * @return WP_REST_Response|WP_Error
391
	 */
392
	public function delete_item( $request ) {
393
		$id    = (int) $request['id'];
394
		$force = (bool) $request['force'];
395
		$post  = get_post( $id );
396
397
		if ( empty( $id ) || empty( $post->ID ) || $this->post_type !== $post->post_type ) {
398
			return new WP_Error( "woocommerce_rest_{$this->post_type}_invalid_id", __( 'Invalid post id.', 'woocommerce' ), array( 'status' => 404 ) );
399
		}
400
401
		$supports_trash = EMPTY_TRASH_DAYS > 0;
402
403
		/**
404
		 * Filter whether an item is trashable.
405
		 *
406
		 * Return false to disable trash support for the item.
407
		 *
408
		 * @param boolean $supports_trash Whether the item type support trashing.
409
		 * @param WP_Post $post           The Post object being considered for trashing support.
410
		 */
411
		$supports_trash = apply_filters( "woocommerce_rest_{$this->post_type}_trashable", $supports_trash, $post );
412
413
		if ( ! wc_rest_check_post_permissions( $this->post_type, 'delete', $post->ID ) ) {
414
			return new WP_Error( "woocommerce_rest_user_cannot_delete_{$this->post_type}", sprintf( __( 'Sorry, you are not allowed to delete %s.', 'woocommerce' ), $this->post_type ), array( 'status' => rest_authorization_required_code() ) );
415
		}
416
417
		$request->set_param( 'context', 'edit' );
418
		$response = $this->prepare_item_for_response( $post, $request );
419
420
		// If we're forcing, then delete permanently.
421
		if ( $force ) {
422
			$result = wp_delete_post( $id, true );
423
		} else {
424
			// If we don't support trashing for this type, error out.
425
			if ( ! $supports_trash ) {
426
				return new WP_Error( 'woocommerce_rest_trash_not_supported', sprintf( __( 'The %s does not support trashing.', 'woocommerce' ), $this->post_type ), array( 'status' => 501 ) );
427
			}
428
429
			// Otherwise, only trash if we haven't already.
430
			if ( 'trash' === $post->post_status ) {
431
				return new WP_Error( 'woocommerce_rest_already_trashed', sprintf( __( 'The %s has already been deleted.', 'woocommerce' ), $this->post_type ), array( 'status' => 410 ) );
432
			}
433
434
			// (Note that internally this falls through to `wp_delete_post` if
435
			// the trash is disabled.)
436
			$result = wp_trash_post( $id );
437
		}
438
439
		if ( ! $result ) {
440
			return new WP_Error( 'woocommerce_rest_cannot_delete', sprintf( __( 'The %s cannot be deleted.', 'woocommerce' ), $this->post_type ), array( 'status' => 500 ) );
441
		}
442
443
		/**
444
		 * Fires after a single item is deleted or trashed via the REST API.
445
		 *
446
		 * @param object           $post     The deleted or trashed item.
447
		 * @param WP_REST_Response $response The response data.
448
		 * @param WP_REST_Request  $request  The request sent to the API.
449
		 */
450
		do_action( "woocommerce_rest_delete_{$this->post_type}", $post, $response, $request );
451
452
		return $response;
453
	}
454
455
	/**
456
	 * Prepare links for the request.
457
	 *
458
	 * @param WP_Post $post Post object.
459
	 * @return array Links for the given post.
460
	 */
461 View Code Duplication
	protected function prepare_links( $post ) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
462
		$links = array(
463
			'self' => array(
464
				'href' => rest_url( sprintf( '/%s/%s/%d', $this->namespace, $this->rest_base, $post->ID ) ),
465
			),
466
			'collection' => array(
467
				'href' => rest_url( sprintf( '/%s/%s', $this->namespace, $this->rest_base ) ),
468
			),
469
		);
470
471
		return $links;
472
	}
473
474
	/**
475
	 * Determine the allowed query_vars for a get_items() response and
476
	 * prepare for WP_Query.
477
	 *
478
	 * @param array           $prepared_args
479
	 * @param WP_REST_Request $request
480
	 * @return array          $query_args
481
	 */
482
	protected function prepare_items_query( $prepared_args = array(), $request = null ) {
0 ignored issues
show
Unused Code introduced by
The parameter $request is not used and could be removed.

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

Loading history...
483
484
		$valid_vars = array_flip( $this->get_allowed_query_vars() );
485
		$query_args = array();
486
		foreach ( $valid_vars as $var => $index ) {
487
			if ( isset( $prepared_args[ $var ] ) ) {
488
				/**
489
				 * Filter the query_vars used in `get_items` for the constructed query.
490
				 *
491
				 * The dynamic portion of the hook name, $var, refers to the query_var key.
492
				 *
493
				 * @param mixed $prepared_args[ $var ] The query_var value.
494
				 *
495
				 */
496
				$query_args[ $var ] = apply_filters( "woocommerce_rest_query_var-{$var}", $prepared_args[ $var ] );
497
			}
498
		}
499
500
		$query_args['ignore_sticky_posts'] = true;
501
502
		if ( 'include' === $query_args['orderby'] ) {
503
			$query_args['orderby'] = 'post__in';
504
		}
505
506
		return $query_args;
507
	}
508
509
	/**
510
	 * Get all the WP Query vars that are allowed for the API request.
511
	 *
512
	 * @return array
513
	 */
514
	protected function get_allowed_query_vars() {
515
		global $wp;
516
517
		/**
518
		 * Filter the publicly allowed query vars.
519
		 *
520
		 * Allows adjusting of the default query vars that are made public.
521
		 *
522
		 * @param array  Array of allowed WP_Query query vars.
523
		 */
524
		$valid_vars = apply_filters( 'query_vars', $wp->public_query_vars );
525
526
		$post_type_obj = get_post_type_object( $this->post_type );
527
		if ( current_user_can( $post_type_obj->cap->edit_posts ) ) {
528
			/**
529
			 * Filter the allowed 'private' query vars for authorized users.
530
			 *
531
			 * If the user has the `edit_posts` capability, we also allow use of
532
			 * private query parameters, which are only undesirable on the
533
			 * frontend, but are safe for use in query strings.
534
			 *
535
			 * To disable anyway, use
536
			 * `add_filter( 'woocommerce_rest_private_query_vars', '__return_empty_array' );`
537
			 *
538
			 * @param array $private_query_vars Array of allowed query vars for authorized users.
539
			 * }
540
			 */
541
			$private = apply_filters( 'woocommerce_rest_private_query_vars', $wp->private_query_vars );
542
			$valid_vars = array_merge( $valid_vars, $private );
543
		}
544
		// Define our own in addition to WP's normal vars.
545
		$rest_valid = array(
546
			'date_query',
547
			'ignore_sticky_posts',
548
			'offset',
549
			'post__in',
550
			'post__not_in',
551
			'post_parent',
552
			'post_parent__in',
553
			'post_parent__not_in',
554
			'posts_per_page',
555
			'meta_query',
556
			'tax_query',
557
		);
558
		$valid_vars = array_merge( $valid_vars, $rest_valid );
559
560
		/**
561
		 * Filter allowed query vars for the REST API.
562
		 *
563
		 * This filter allows you to add or remove query vars from the final allowed
564
		 * list for all requests, including unauthenticated ones. To alter the
565
		 * vars for editors only.
566
		 *
567
		 * @param array {
568
		 *    Array of allowed WP_Query query vars.
569
		 *
570
		 *    @param string $allowed_query_var The query var to allow.
571
		 * }
572
		 */
573
		$valid_vars = apply_filters( 'woocommerce_rest_query_vars', $valid_vars );
574
575
		return $valid_vars;
576
	}
577
578
	/**
579
	 * Get the query params for collections of attachments.
580
	 *
581
	 * @return array
582
	 */
583
	public function get_collection_params() {
584
		$params = parent::get_collection_params();
585
586
		$params['context']['default'] = 'view';
587
588
		$params['after'] = array(
589
			'description'        => __( 'Limit response to resources published after a given ISO8601 compliant date.', 'woocommerce' ),
590
			'type'               => 'string',
591
			'format'             => 'date-time',
592
			'validate_callback'  => 'rest_validate_request_arg',
593
		);
594
		$params['before'] = array(
595
			'description'        => __( 'Limit response to resources published before a given ISO8601 compliant date.', 'woocommerce' ),
596
			'type'               => 'string',
597
			'format'             => 'date-time',
598
			'validate_callback'  => 'rest_validate_request_arg',
599
		);
600
		$params['exclude'] = array(
601
			'description'        => __( 'Ensure result set excludes specific ids.', 'woocommerce' ),
602
			'type'               => 'array',
603
			'default'            => array(),
604
			'sanitize_callback'  => 'wp_parse_id_list',
605
		);
606
		$params['include'] = array(
607
			'description'        => __( 'Limit result set to specific ids.', 'woocommerce' ),
608
			'type'               => 'array',
609
			'default'            => array(),
610
			'sanitize_callback'  => 'wp_parse_id_list',
611
		);
612
		$params['offset'] = array(
613
			'description'        => __( 'Offset the result set by a specific number of items.', 'woocommerce' ),
614
			'type'               => 'integer',
615
			'sanitize_callback'  => 'absint',
616
			'validate_callback'  => 'rest_validate_request_arg',
617
		);
618
		$params['order'] = array(
619
			'description'        => __( 'Order sort attribute ascending or descending.', 'woocommerce' ),
620
			'type'               => 'string',
621
			'default'            => 'desc',
622
			'enum'               => array( 'asc', 'desc' ),
623
			'validate_callback'  => 'rest_validate_request_arg',
624
		);
625
		$params['orderby'] = array(
626
			'description'        => __( 'Sort collection by object attribute.', 'woocommerce' ),
627
			'type'               => 'string',
628
			'default'            => 'date',
629
			'enum'               => array(
630
				'date',
631
				'id',
632
				'include',
633
				'title',
634
				'slug',
635
			),
636
			'validate_callback'  => 'rest_validate_request_arg',
637
		);
638
639
		$post_type_obj = get_post_type_object( $this->post_type );
640
		if ( $post_type_obj->hierarchical ) {
641
			$params['parent'] = array(
642
				'description'       => __( 'Limit result set to those of particular parent ids.', 'woocommerce' ),
643
				'type'              => 'array',
644
				'sanitize_callback' => 'wp_parse_id_list',
645
				'default'           => array(),
646
			);
647
			$params['parent_exclude'] = array(
648
				'description'       => __( 'Limit result set to all items except those of a particular parent id.', 'woocommerce' ),
649
				'type'              => 'array',
650
				'sanitize_callback' => 'wp_parse_id_list',
651
				'default'           => array(),
652
			);
653
		}
654
655
		$params['slug'] = array(
656
			'description'       => __( 'Limit result set to posts with a specific slug.', 'woocommerce', 'woocommerce' ),
657
			'type'              => 'string',
658
			'validate_callback' => 'rest_validate_request_arg',
659
		);
660
661
		$params['filter'] = array(
662
			'description' => __( 'Use WP Query arguments to modify the response; private query vars require appropriate authorization.', 'woocommerce' ),
663
		);
664
665
		return $params;
666
	}
667
668
	/**
669
	 * Update post meta fields.
670
	 *
671
	 * @param WP_Post $post
672
	 * @param WP_REST_Request $request
673
	 * @return bool|WP_Error
674
	 */
675
	protected function update_post_meta_fields( $post, $request ) {
676
		return true;
677
	}
678
}
679