abstract-wc-rest-posts-controller.php 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721
  1. <?php
  2. /**
  3. * Abstract Rest Posts Controller Class
  4. *
  5. * @class WC_REST_Posts_Controller
  6. * @package WooCommerce/Abstracts
  7. */
  8. if ( ! defined( 'ABSPATH' ) ) {
  9. exit;
  10. }
  11. /**
  12. * WC_REST_Posts_Controller
  13. *
  14. * @package WooCommerce/Abstracts
  15. * @version 2.6.0
  16. */
  17. abstract class WC_REST_Posts_Controller extends WC_REST_Controller {
  18. /**
  19. * Endpoint namespace.
  20. *
  21. * @var string
  22. */
  23. protected $namespace = 'wc/v1';
  24. /**
  25. * Route base.
  26. *
  27. * @var string
  28. */
  29. protected $rest_base = '';
  30. /**
  31. * Post type.
  32. *
  33. * @var string
  34. */
  35. protected $post_type = '';
  36. /**
  37. * Controls visibility on frontend.
  38. *
  39. * @var string
  40. */
  41. protected $public = false;
  42. /**
  43. * Check if a given request has access to read items.
  44. *
  45. * @param WP_REST_Request $request Full details about the request.
  46. * @return WP_Error|boolean
  47. */
  48. public function get_items_permissions_check( $request ) {
  49. if ( ! wc_rest_check_post_permissions( $this->post_type, 'read' ) ) {
  50. return new WP_Error( 'woocommerce_rest_cannot_view', __( 'Sorry, you cannot list resources.', 'woocommerce' ), array( 'status' => rest_authorization_required_code() ) );
  51. }
  52. return true;
  53. }
  54. /**
  55. * Check if a given request has access to create an item.
  56. *
  57. * @param WP_REST_Request $request Full details about the request.
  58. * @return WP_Error|boolean
  59. */
  60. public function create_item_permissions_check( $request ) {
  61. if ( ! wc_rest_check_post_permissions( $this->post_type, 'create' ) ) {
  62. return new WP_Error( 'woocommerce_rest_cannot_create', __( 'Sorry, you are not allowed to create resources.', 'woocommerce' ), array( 'status' => rest_authorization_required_code() ) );
  63. }
  64. return true;
  65. }
  66. /**
  67. * Check if a given request has access to read an item.
  68. *
  69. * @param WP_REST_Request $request Full details about the request.
  70. * @return WP_Error|boolean
  71. */
  72. public function get_item_permissions_check( $request ) {
  73. $post = get_post( (int) $request['id'] );
  74. if ( $post && ! wc_rest_check_post_permissions( $this->post_type, 'read', $post->ID ) ) {
  75. return new WP_Error( 'woocommerce_rest_cannot_view', __( 'Sorry, you cannot view this resource.', 'woocommerce' ), array( 'status' => rest_authorization_required_code() ) );
  76. }
  77. return true;
  78. }
  79. /**
  80. * Check if a given request has access to update an item.
  81. *
  82. * @param WP_REST_Request $request Full details about the request.
  83. * @return WP_Error|boolean
  84. */
  85. public function update_item_permissions_check( $request ) {
  86. $post = get_post( (int) $request['id'] );
  87. if ( $post && ! wc_rest_check_post_permissions( $this->post_type, 'edit', $post->ID ) ) {
  88. return new WP_Error( 'woocommerce_rest_cannot_edit', __( 'Sorry, you are not allowed to edit this resource.', 'woocommerce' ), array( 'status' => rest_authorization_required_code() ) );
  89. }
  90. return true;
  91. }
  92. /**
  93. * Check if a given request has access to delete an item.
  94. *
  95. * @param WP_REST_Request $request Full details about the request.
  96. * @return bool|WP_Error
  97. */
  98. public function delete_item_permissions_check( $request ) {
  99. $post = get_post( (int) $request['id'] );
  100. if ( $post && ! wc_rest_check_post_permissions( $this->post_type, 'delete', $post->ID ) ) {
  101. return new WP_Error( 'woocommerce_rest_cannot_delete', __( 'Sorry, you are not allowed to delete this resource.', 'woocommerce' ), array( 'status' => rest_authorization_required_code() ) );
  102. }
  103. return true;
  104. }
  105. /**
  106. * Check if a given request has access batch create, update and delete items.
  107. *
  108. * @param WP_REST_Request $request Full details about the request.
  109. *
  110. * @return boolean|WP_Error
  111. */
  112. public function batch_items_permissions_check( $request ) {
  113. if ( ! wc_rest_check_post_permissions( $this->post_type, 'batch' ) ) {
  114. return new WP_Error( 'woocommerce_rest_cannot_batch', __( 'Sorry, you are not allowed to batch manipulate this resource.', 'woocommerce' ), array( 'status' => rest_authorization_required_code() ) );
  115. }
  116. return true;
  117. }
  118. /**
  119. * Get a single item.
  120. *
  121. * @param WP_REST_Request $request Full details about the request.
  122. * @return WP_Error|WP_REST_Response
  123. */
  124. public function get_item( $request ) {
  125. $id = (int) $request['id'];
  126. $post = get_post( $id );
  127. if ( ! empty( $post->post_type ) && 'product_variation' === $post->post_type && 'product' === $this->post_type ) {
  128. return new WP_Error( "woocommerce_rest_invalid_{$this->post_type}_id", __( 'To manipulate product variations you should use the /products/&lt;product_id&gt;/variations/&lt;id&gt; endpoint.', 'woocommerce' ), array( 'status' => 404 ) );
  129. } elseif ( empty( $id ) || empty( $post->ID ) || $post->post_type !== $this->post_type ) {
  130. return new WP_Error( "woocommerce_rest_invalid_{$this->post_type}_id", __( 'Invalid ID.', 'woocommerce' ), array( 'status' => 404 ) );
  131. }
  132. $data = $this->prepare_item_for_response( $post, $request );
  133. $response = rest_ensure_response( $data );
  134. if ( $this->public ) {
  135. $response->link_header( 'alternate', get_permalink( $id ), array( 'type' => 'text/html' ) );
  136. }
  137. return $response;
  138. }
  139. /**
  140. * Create a single item.
  141. *
  142. * @param WP_REST_Request $request Full details about the request.
  143. * @return WP_Error|WP_REST_Response
  144. */
  145. public function create_item( $request ) {
  146. if ( ! empty( $request['id'] ) ) {
  147. /* translators: %s: post type */
  148. return new WP_Error( "woocommerce_rest_{$this->post_type}_exists", sprintf( __( 'Cannot create existing %s.', 'woocommerce' ), $this->post_type ), array( 'status' => 400 ) );
  149. }
  150. $post = $this->prepare_item_for_database( $request );
  151. if ( is_wp_error( $post ) ) {
  152. return $post;
  153. }
  154. $post->post_type = $this->post_type;
  155. $post_id = wp_insert_post( $post, true );
  156. if ( is_wp_error( $post_id ) ) {
  157. if ( in_array( $post_id->get_error_code(), array( 'db_insert_error' ) ) ) {
  158. $post_id->add_data( array( 'status' => 500 ) );
  159. } else {
  160. $post_id->add_data( array( 'status' => 400 ) );
  161. }
  162. return $post_id;
  163. }
  164. $post->ID = $post_id;
  165. $post = get_post( $post_id );
  166. $this->update_additional_fields_for_object( $post, $request );
  167. // Add meta fields.
  168. $meta_fields = $this->add_post_meta_fields( $post, $request );
  169. if ( is_wp_error( $meta_fields ) ) {
  170. // Remove post.
  171. $this->delete_post( $post );
  172. return $meta_fields;
  173. }
  174. /**
  175. * Fires after a single item is created or updated via the REST API.
  176. *
  177. * @param WP_Post $post Post object.
  178. * @param WP_REST_Request $request Request object.
  179. * @param boolean $creating True when creating item, false when updating.
  180. */
  181. do_action( "woocommerce_rest_insert_{$this->post_type}", $post, $request, true );
  182. $request->set_param( 'context', 'edit' );
  183. $response = $this->prepare_item_for_response( $post, $request );
  184. $response = rest_ensure_response( $response );
  185. $response->set_status( 201 );
  186. $response->header( 'Location', rest_url( sprintf( '/%s/%s/%d', $this->namespace, $this->rest_base, $post_id ) ) );
  187. return $response;
  188. }
  189. /**
  190. * Add post meta fields.
  191. *
  192. * @param WP_Post $post Post Object.
  193. * @param WP_REST_Request $request WP_REST_Request Object.
  194. * @return bool|WP_Error
  195. */
  196. protected function add_post_meta_fields( $post, $request ) {
  197. return true;
  198. }
  199. /**
  200. * Delete post.
  201. *
  202. * @param WP_Post $post Post object.
  203. */
  204. protected function delete_post( $post ) {
  205. wp_delete_post( $post->ID, true );
  206. }
  207. /**
  208. * Update a single post.
  209. *
  210. * @param WP_REST_Request $request Full details about the request.
  211. * @return WP_Error|WP_REST_Response
  212. */
  213. public function update_item( $request ) {
  214. $id = (int) $request['id'];
  215. $post = get_post( $id );
  216. if ( ! empty( $post->post_type ) && 'product_variation' === $post->post_type && 'product' === $this->post_type ) {
  217. return new WP_Error( "woocommerce_rest_invalid_{$this->post_type}_id", __( 'To manipulate product variations you should use the /products/&lt;product_id&gt;/variations/&lt;id&gt; endpoint.', 'woocommerce' ), array( 'status' => 404 ) );
  218. } elseif ( empty( $id ) || empty( $post->ID ) || $post->post_type !== $this->post_type ) {
  219. return new WP_Error( "woocommerce_rest_{$this->post_type}_invalid_id", __( 'ID is invalid.', 'woocommerce' ), array( 'status' => 400 ) );
  220. }
  221. $post = $this->prepare_item_for_database( $request );
  222. if ( is_wp_error( $post ) ) {
  223. return $post;
  224. }
  225. // Convert the post object to an array, otherwise wp_update_post will expect non-escaped input.
  226. $post_id = wp_update_post( (array) $post, true );
  227. if ( is_wp_error( $post_id ) ) {
  228. if ( in_array( $post_id->get_error_code(), array( 'db_update_error' ) ) ) {
  229. $post_id->add_data( array( 'status' => 500 ) );
  230. } else {
  231. $post_id->add_data( array( 'status' => 400 ) );
  232. }
  233. return $post_id;
  234. }
  235. $post = get_post( $post_id );
  236. $this->update_additional_fields_for_object( $post, $request );
  237. // Update meta fields.
  238. $meta_fields = $this->update_post_meta_fields( $post, $request );
  239. if ( is_wp_error( $meta_fields ) ) {
  240. return $meta_fields;
  241. }
  242. /**
  243. * Fires after a single item is created or updated via the REST API.
  244. *
  245. * @param WP_Post $post Post object.
  246. * @param WP_REST_Request $request Request object.
  247. * @param boolean $creating True when creating item, false when updating.
  248. */
  249. do_action( "woocommerce_rest_insert_{$this->post_type}", $post, $request, false );
  250. $request->set_param( 'context', 'edit' );
  251. $response = $this->prepare_item_for_response( $post, $request );
  252. return rest_ensure_response( $response );
  253. }
  254. /**
  255. * Get a collection of posts.
  256. *
  257. * @param WP_REST_Request $request Full details about the request.
  258. * @return WP_Error|WP_REST_Response
  259. */
  260. public function get_items( $request ) {
  261. $args = array();
  262. $args['offset'] = $request['offset'];
  263. $args['order'] = $request['order'];
  264. $args['orderby'] = $request['orderby'];
  265. $args['paged'] = $request['page'];
  266. $args['post__in'] = $request['include'];
  267. $args['post__not_in'] = $request['exclude'];
  268. $args['posts_per_page'] = $request['per_page'];
  269. $args['name'] = $request['slug'];
  270. $args['post_parent__in'] = $request['parent'];
  271. $args['post_parent__not_in'] = $request['parent_exclude'];
  272. $args['s'] = $request['search'];
  273. $args['date_query'] = array();
  274. // Set before into date query. Date query must be specified as an array of an array.
  275. if ( isset( $request['before'] ) ) {
  276. $args['date_query'][0]['before'] = $request['before'];
  277. }
  278. // Set after into date query. Date query must be specified as an array of an array.
  279. if ( isset( $request['after'] ) ) {
  280. $args['date_query'][0]['after'] = $request['after'];
  281. }
  282. if ( 'wc/v1' === $this->namespace ) {
  283. if ( is_array( $request['filter'] ) ) {
  284. $args = array_merge( $args, $request['filter'] );
  285. unset( $args['filter'] );
  286. }
  287. }
  288. // Force the post_type argument, since it's not a user input variable.
  289. $args['post_type'] = $this->post_type;
  290. /**
  291. * Filter the query arguments for a request.
  292. *
  293. * Enables adding extra arguments or setting defaults for a post
  294. * collection request.
  295. *
  296. * @param array $args Key value array of query var to query value.
  297. * @param WP_REST_Request $request The request used.
  298. */
  299. $args = apply_filters( "woocommerce_rest_{$this->post_type}_query", $args, $request );
  300. $query_args = $this->prepare_items_query( $args, $request );
  301. $posts_query = new WP_Query();
  302. $query_result = $posts_query->query( $query_args );
  303. $posts = array();
  304. foreach ( $query_result as $post ) {
  305. if ( ! wc_rest_check_post_permissions( $this->post_type, 'read', $post->ID ) ) {
  306. continue;
  307. }
  308. $data = $this->prepare_item_for_response( $post, $request );
  309. $posts[] = $this->prepare_response_for_collection( $data );
  310. }
  311. $page = (int) $query_args['paged'];
  312. $total_posts = $posts_query->found_posts;
  313. if ( $total_posts < 1 ) {
  314. // Out-of-bounds, run the query again without LIMIT for total count.
  315. unset( $query_args['paged'] );
  316. $count_query = new WP_Query();
  317. $count_query->query( $query_args );
  318. $total_posts = $count_query->found_posts;
  319. }
  320. $max_pages = ceil( $total_posts / (int) $query_args['posts_per_page'] );
  321. $response = rest_ensure_response( $posts );
  322. $response->header( 'X-WP-Total', (int) $total_posts );
  323. $response->header( 'X-WP-TotalPages', (int) $max_pages );
  324. $request_params = $request->get_query_params();
  325. if ( ! empty( $request_params['filter'] ) ) {
  326. // Normalize the pagination params.
  327. unset( $request_params['filter']['posts_per_page'] );
  328. unset( $request_params['filter']['paged'] );
  329. }
  330. $base = add_query_arg( $request_params, rest_url( sprintf( '/%s/%s', $this->namespace, $this->rest_base ) ) );
  331. if ( $page > 1 ) {
  332. $prev_page = $page - 1;
  333. if ( $prev_page > $max_pages ) {
  334. $prev_page = $max_pages;
  335. }
  336. $prev_link = add_query_arg( 'page', $prev_page, $base );
  337. $response->link_header( 'prev', $prev_link );
  338. }
  339. if ( $max_pages > $page ) {
  340. $next_page = $page + 1;
  341. $next_link = add_query_arg( 'page', $next_page, $base );
  342. $response->link_header( 'next', $next_link );
  343. }
  344. return $response;
  345. }
  346. /**
  347. * Delete a single item.
  348. *
  349. * @param WP_REST_Request $request Full details about the request.
  350. * @return WP_REST_Response|WP_Error
  351. */
  352. public function delete_item( $request ) {
  353. $id = (int) $request['id'];
  354. $force = (bool) $request['force'];
  355. $post = get_post( $id );
  356. if ( empty( $id ) || empty( $post->ID ) || $post->post_type !== $this->post_type ) {
  357. return new WP_Error( "woocommerce_rest_{$this->post_type}_invalid_id", __( 'ID is invalid.', 'woocommerce' ), array( 'status' => 404 ) );
  358. }
  359. $supports_trash = EMPTY_TRASH_DAYS > 0;
  360. /**
  361. * Filter whether an item is trashable.
  362. *
  363. * Return false to disable trash support for the item.
  364. *
  365. * @param boolean $supports_trash Whether the item type support trashing.
  366. * @param WP_Post $post The Post object being considered for trashing support.
  367. */
  368. $supports_trash = apply_filters( "woocommerce_rest_{$this->post_type}_trashable", $supports_trash, $post );
  369. if ( ! wc_rest_check_post_permissions( $this->post_type, 'delete', $post->ID ) ) {
  370. /* translators: %s: post type */
  371. 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() ) );
  372. }
  373. $request->set_param( 'context', 'edit' );
  374. $response = $this->prepare_item_for_response( $post, $request );
  375. // If we're forcing, then delete permanently.
  376. if ( $force ) {
  377. $result = wp_delete_post( $id, true );
  378. } else {
  379. // If we don't support trashing for this type, error out.
  380. if ( ! $supports_trash ) {
  381. /* translators: %s: post type */
  382. return new WP_Error( 'woocommerce_rest_trash_not_supported', sprintf( __( 'The %s does not support trashing.', 'woocommerce' ), $this->post_type ), array( 'status' => 501 ) );
  383. }
  384. // Otherwise, only trash if we haven't already.
  385. if ( 'trash' === $post->post_status ) {
  386. /* translators: %s: post type */
  387. return new WP_Error( 'woocommerce_rest_already_trashed', sprintf( __( 'The %s has already been deleted.', 'woocommerce' ), $this->post_type ), array( 'status' => 410 ) );
  388. }
  389. // (Note that internally this falls through to `wp_delete_post` if
  390. // the trash is disabled.)
  391. $result = wp_trash_post( $id );
  392. }
  393. if ( ! $result ) {
  394. /* translators: %s: post type */
  395. return new WP_Error( 'woocommerce_rest_cannot_delete', sprintf( __( 'The %s cannot be deleted.', 'woocommerce' ), $this->post_type ), array( 'status' => 500 ) );
  396. }
  397. /**
  398. * Fires after a single item is deleted or trashed via the REST API.
  399. *
  400. * @param object $post The deleted or trashed item.
  401. * @param WP_REST_Response $response The response data.
  402. * @param WP_REST_Request $request The request sent to the API.
  403. */
  404. do_action( "woocommerce_rest_delete_{$this->post_type}", $post, $response, $request );
  405. return $response;
  406. }
  407. /**
  408. * Prepare links for the request.
  409. *
  410. * @param WP_Post $post Post object.
  411. * @param WP_REST_Request $request Request object.
  412. * @return array Links for the given post.
  413. */
  414. protected function prepare_links( $post, $request ) {
  415. $links = array(
  416. 'self' => array(
  417. 'href' => rest_url( sprintf( '/%s/%s/%d', $this->namespace, $this->rest_base, $post->ID ) ),
  418. ),
  419. 'collection' => array(
  420. 'href' => rest_url( sprintf( '/%s/%s', $this->namespace, $this->rest_base ) ),
  421. ),
  422. );
  423. return $links;
  424. }
  425. /**
  426. * Determine the allowed query_vars for a get_items() response and
  427. * prepare for WP_Query.
  428. *
  429. * @param array $prepared_args Prepared arguments.
  430. * @param WP_REST_Request $request Request object.
  431. * @return array $query_args
  432. */
  433. protected function prepare_items_query( $prepared_args = array(), $request = null ) {
  434. $valid_vars = array_flip( $this->get_allowed_query_vars() );
  435. $query_args = array();
  436. foreach ( $valid_vars as $var => $index ) {
  437. if ( isset( $prepared_args[ $var ] ) ) {
  438. /**
  439. * Filter the query_vars used in `get_items` for the constructed query.
  440. *
  441. * The dynamic portion of the hook name, $var, refers to the query_var key.
  442. *
  443. * @param mixed $prepared_args[ $var ] The query_var value.
  444. */
  445. $query_args[ $var ] = apply_filters( "woocommerce_rest_query_var-{$var}", $prepared_args[ $var ] );
  446. }
  447. }
  448. $query_args['ignore_sticky_posts'] = true;
  449. if ( 'include' === $query_args['orderby'] ) {
  450. $query_args['orderby'] = 'post__in';
  451. } elseif ( 'id' === $query_args['orderby'] ) {
  452. $query_args['orderby'] = 'ID'; // ID must be capitalized.
  453. }
  454. return $query_args;
  455. }
  456. /**
  457. * Get all the WP Query vars that are allowed for the API request.
  458. *
  459. * @return array
  460. */
  461. protected function get_allowed_query_vars() {
  462. global $wp;
  463. /**
  464. * Filter the publicly allowed query vars.
  465. *
  466. * Allows adjusting of the default query vars that are made public.
  467. *
  468. * @param array Array of allowed WP_Query query vars.
  469. */
  470. $valid_vars = apply_filters( 'query_vars', $wp->public_query_vars );
  471. $post_type_obj = get_post_type_object( $this->post_type );
  472. if ( current_user_can( $post_type_obj->cap->edit_posts ) ) {
  473. /**
  474. * Filter the allowed 'private' query vars for authorized users.
  475. *
  476. * If the user has the `edit_posts` capability, we also allow use of
  477. * private query parameters, which are only undesirable on the
  478. * frontend, but are safe for use in query strings.
  479. *
  480. * To disable anyway, use
  481. * `add_filter( 'woocommerce_rest_private_query_vars', '__return_empty_array' );`
  482. *
  483. * @param array $private_query_vars Array of allowed query vars for authorized users.
  484. * }
  485. */
  486. $private = apply_filters( 'woocommerce_rest_private_query_vars', $wp->private_query_vars );
  487. $valid_vars = array_merge( $valid_vars, $private );
  488. }
  489. // Define our own in addition to WP's normal vars.
  490. $rest_valid = array(
  491. 'date_query',
  492. 'ignore_sticky_posts',
  493. 'offset',
  494. 'post__in',
  495. 'post__not_in',
  496. 'post_parent',
  497. 'post_parent__in',
  498. 'post_parent__not_in',
  499. 'posts_per_page',
  500. 'meta_query',
  501. 'tax_query',
  502. 'meta_key',
  503. 'meta_value',
  504. 'meta_compare',
  505. 'meta_value_num',
  506. );
  507. $valid_vars = array_merge( $valid_vars, $rest_valid );
  508. /**
  509. * Filter allowed query vars for the REST API.
  510. *
  511. * This filter allows you to add or remove query vars from the final allowed
  512. * list for all requests, including unauthenticated ones. To alter the
  513. * vars for editors only.
  514. *
  515. * @param array {
  516. * Array of allowed WP_Query query vars.
  517. *
  518. * @param string $allowed_query_var The query var to allow.
  519. * }
  520. */
  521. $valid_vars = apply_filters( 'woocommerce_rest_query_vars', $valid_vars );
  522. return $valid_vars;
  523. }
  524. /**
  525. * Get the query params for collections of attachments.
  526. *
  527. * @return array
  528. */
  529. public function get_collection_params() {
  530. $params = parent::get_collection_params();
  531. $params['context']['default'] = 'view';
  532. $params['after'] = array(
  533. 'description' => __( 'Limit response to resources published after a given ISO8601 compliant date.', 'woocommerce' ),
  534. 'type' => 'string',
  535. 'format' => 'date-time',
  536. 'validate_callback' => 'rest_validate_request_arg',
  537. );
  538. $params['before'] = array(
  539. 'description' => __( 'Limit response to resources published before a given ISO8601 compliant date.', 'woocommerce' ),
  540. 'type' => 'string',
  541. 'format' => 'date-time',
  542. 'validate_callback' => 'rest_validate_request_arg',
  543. );
  544. $params['exclude'] = array(
  545. 'description' => __( 'Ensure result set excludes specific IDs.', 'woocommerce' ),
  546. 'type' => 'array',
  547. 'items' => array(
  548. 'type' => 'integer',
  549. ),
  550. 'default' => array(),
  551. 'sanitize_callback' => 'wp_parse_id_list',
  552. );
  553. $params['include'] = array(
  554. 'description' => __( 'Limit result set to specific ids.', 'woocommerce' ),
  555. 'type' => 'array',
  556. 'items' => array(
  557. 'type' => 'integer',
  558. ),
  559. 'default' => array(),
  560. 'sanitize_callback' => 'wp_parse_id_list',
  561. );
  562. $params['offset'] = array(
  563. 'description' => __( 'Offset the result set by a specific number of items.', 'woocommerce' ),
  564. 'type' => 'integer',
  565. 'sanitize_callback' => 'absint',
  566. 'validate_callback' => 'rest_validate_request_arg',
  567. );
  568. $params['order'] = array(
  569. 'description' => __( 'Order sort attribute ascending or descending.', 'woocommerce' ),
  570. 'type' => 'string',
  571. 'default' => 'desc',
  572. 'enum' => array( 'asc', 'desc' ),
  573. 'validate_callback' => 'rest_validate_request_arg',
  574. );
  575. $params['orderby'] = array(
  576. 'description' => __( 'Sort collection by object attribute.', 'woocommerce' ),
  577. 'type' => 'string',
  578. 'default' => 'date',
  579. 'enum' => array(
  580. 'date',
  581. 'id',
  582. 'include',
  583. 'title',
  584. 'slug',
  585. ),
  586. 'validate_callback' => 'rest_validate_request_arg',
  587. );
  588. $post_type_obj = get_post_type_object( $this->post_type );
  589. if ( isset( $post_type_obj->hierarchical ) && $post_type_obj->hierarchical ) {
  590. $params['parent'] = array(
  591. 'description' => __( 'Limit result set to those of particular parent IDs.', 'woocommerce' ),
  592. 'type' => 'array',
  593. 'items' => array(
  594. 'type' => 'integer',
  595. ),
  596. 'sanitize_callback' => 'wp_parse_id_list',
  597. 'default' => array(),
  598. );
  599. $params['parent_exclude'] = array(
  600. 'description' => __( 'Limit result set to all items except those of a particular parent ID.', 'woocommerce' ),
  601. 'type' => 'array',
  602. 'items' => array(
  603. 'type' => 'integer',
  604. ),
  605. 'sanitize_callback' => 'wp_parse_id_list',
  606. 'default' => array(),
  607. );
  608. }
  609. if ( 'wc/v1' === $this->namespace ) {
  610. $params['filter'] = array(
  611. 'type' => 'object',
  612. 'description' => __( 'Use WP Query arguments to modify the response; private query vars require appropriate authorization.', 'woocommerce' ),
  613. );
  614. }
  615. return $params;
  616. }
  617. /**
  618. * Update post meta fields.
  619. *
  620. * @param WP_Post $post Post object.
  621. * @param WP_REST_Request $request Request object.
  622. * @return bool|WP_Error
  623. */
  624. protected function update_post_meta_fields( $post, $request ) {
  625. return true;
  626. }
  627. }