/includes/api/legacy/class-wc-rest-legacy-orders-controller.php

  1. <?php 
  2. /** 
  3. * REST API Legacy Orders controller 
  4. * 
  5. * Handles requests to the /orders endpoint. 
  6. * 
  7. * @author WooThemes 
  8. * @category API 
  9. * @package WooCommerce/API 
  10. * @since 3.0.0 
  11. */ 
  12.  
  13. if ( ! defined( 'ABSPATH' ) ) { 
  14. exit; 
  15.  
  16. /** 
  17. * REST API Legacy Orders controller class. 
  18. * 
  19. * @package WooCommerce/API 
  20. * @extends WC_REST_CRUD_Controller 
  21. */ 
  22. class WC_REST_Legacy_Orders_Controller extends WC_REST_CRUD_Controller { 
  23.  
  24. /** 
  25. * Endpoint namespace. 
  26. * 
  27. * @var string 
  28. */ 
  29. protected $namespace = 'wc/v2'; 
  30.  
  31. /** 
  32. * Query args. 
  33. * 
  34. * @deprecated 3.0 
  35. * 
  36. * @param array $args 
  37. * @param WP_REST_Request $request 
  38. * @return array 
  39. */ 
  40. public function query_args( $args, $request ) { 
  41. global $wpdb; 
  42.  
  43. // Set post_status. 
  44. if ( 'any' !== $request['status'] ) { 
  45. $args['post_status'] = 'wc-' . $request['status']; 
  46. } else { 
  47. $args['post_status'] = 'any'; 
  48.  
  49. if ( ! empty( $request['customer'] ) ) { 
  50. if ( ! empty( $args['meta_query'] ) ) { 
  51. $args['meta_query'] = array(); 
  52.  
  53. $args['meta_query'][] = array( 
  54. 'key' => '_customer_user',  
  55. 'value' => $request['customer'],  
  56. 'type' => 'NUMERIC',  
  57. ); 
  58.  
  59. // Search by product. 
  60. if ( ! empty( $request['product'] ) ) { 
  61. $order_ids = $wpdb->get_col( $wpdb->prepare( " 
  62. SELECT order_id 
  63. FROM {$wpdb->prefix}woocommerce_order_items 
  64. WHERE order_item_id IN ( SELECT order_item_id FROM {$wpdb->prefix}woocommerce_order_itemmeta WHERE meta_key = '_product_id' AND meta_value = %d ) 
  65. AND order_item_type = 'line_item' 
  66. ", $request['product'] ) ); 
  67.  
  68. // Force WP_Query return empty if don't found any order. 
  69. $order_ids = ! empty( $order_ids ) ? $order_ids : array( 0 ); 
  70.  
  71. $args['post__in'] = $order_ids; 
  72.  
  73. // Search. 
  74. if ( ! empty( $args['s'] ) ) { 
  75. $order_ids = wc_order_search( $args['s'] ); 
  76.  
  77. if ( ! empty( $order_ids ) ) { 
  78. unset( $args['s'] ); 
  79. $args['post__in'] = array_merge( $order_ids, array( 0 ) ); 
  80.  
  81. return $args; 
  82.  
  83. /** 
  84. * Prepare a single order output for response. 
  85. * 
  86. * @deprecated 3.0 
  87. * 
  88. * @param WP_Post $post Post object. 
  89. * @param WP_REST_Request $request Request object. 
  90. * @return WP_REST_Response $data 
  91. */ 
  92. public function prepare_item_for_response( $post, $request ) { 
  93. $this->request = $request; 
  94. $statuses = wc_get_order_statuses(); 
  95. $order = wc_get_order( $post ); 
  96. $data = array_merge( array( 'id' => $order->get_id() ), $order->get_data() ); 
  97. $format_decimal = array( 'discount_total', 'discount_tax', 'shipping_total', 'shipping_tax', 'shipping_total', 'shipping_tax', 'cart_tax', 'total', 'total_tax' ); 
  98. $format_date = array( 'date_created', 'date_modified', 'date_completed', 'date_paid' ); 
  99. $format_line_items = array( 'line_items', 'tax_lines', 'shipping_lines', 'fee_lines', 'coupon_lines' ); 
  100.  
  101. // Format decimal values. 
  102. foreach ( $format_decimal as $key ) { 
  103. $data[ $key ] = wc_format_decimal( $data[ $key ], $this->request['dp'] ); 
  104.  
  105. // Format date values. 
  106. foreach ( $format_date as $key ) { 
  107. $data[ $key ] = $data[ $key ] ? wc_rest_prepare_date_response( get_gmt_from_date( date( 'Y-m-d H:i:s', $data[ $key ] ) ) ) : false; 
  108.  
  109. // Format the order status. 
  110. $data['status'] = 'wc-' === substr( $data['status'], 0, 3 ) ? substr( $data['status'], 3 ) : $data['status']; 
  111.  
  112. // Format line items. 
  113. foreach ( $format_line_items as $key ) { 
  114. $data[ $key ] = array_values( array_map( array( $this, 'get_order_item_data' ), $data[ $key ] ) ); 
  115.  
  116. // Refunds. 
  117. $data['refunds'] = array(); 
  118. foreach ( $order->get_refunds() as $refund ) { 
  119. $data['refunds'][] = array( 
  120. 'id' => $refund->get_id(),  
  121. 'refund' => $refund->get_reason() ? $refund->get_reason() : '',  
  122. 'total' => '-' . wc_format_decimal( $refund->get_amount(), $this->request['dp'] ),  
  123. ); 
  124.  
  125. $context = ! empty( $request['context'] ) ? $request['context'] : 'view'; 
  126. $data = $this->add_additional_fields_to_object( $data, $request ); 
  127. $data = $this->filter_response_by_context( $data, $context ); 
  128. $response = rest_ensure_response( $data ); 
  129. $response->add_links( $this->prepare_links( $order, $request ) ); 
  130.  
  131. /** 
  132. * Filter the data for a response. 
  133. * 
  134. * The dynamic portion of the hook name, $this->post_type, refers to post_type of the post being 
  135. * prepared for the response. 
  136. * 
  137. * @param WP_REST_Response $response The response object. 
  138. * @param WP_Post $post Post object. 
  139. * @param WP_REST_Request $request Request object. 
  140. */ 
  141. return apply_filters( "woocommerce_rest_prepare_{$this->post_type}", $response, $post, $request ); 
  142.  
  143. /** 
  144. * Prepare a single order for create. 
  145. * 
  146. * @deprecated 3.0 
  147. * 
  148. * @param WP_REST_Request $request Request object. 
  149. * @return WP_Error|WC_Order $data Object. 
  150. */ 
  151. protected function prepare_item_for_database( $request ) { 
  152. $id = isset( $request['id'] ) ? absint( $request['id'] ) : 0; 
  153. $order = new WC_Order( $id ); 
  154. $schema = $this->get_item_schema(); 
  155. $data_keys = array_keys( array_filter( $schema['properties'], array( $this, 'filter_writable_props' ) ) ); 
  156.  
  157. // Handle all writable props 
  158. foreach ( $data_keys as $key ) { 
  159. $value = $request[ $key ]; 
  160.  
  161. if ( ! is_null( $value ) ) { 
  162. switch ( $key ) { 
  163. case 'billing' : 
  164. case 'shipping' : 
  165. $this->update_address( $order, $value, $key ); 
  166. break; 
  167. case 'line_items' : 
  168. case 'shipping_lines' : 
  169. case 'fee_lines' : 
  170. case 'coupon_lines' : 
  171. if ( is_array( $value ) ) { 
  172. foreach ( $value as $item ) { 
  173. if ( is_array( $item ) ) { 
  174. if ( $this->item_is_null( $item ) || ( isset( $item['quantity'] ) && 0 === $item['quantity'] ) ) { 
  175. $order->remove_item( $item['id'] ); 
  176. } else { 
  177. $this->set_item( $order, $key, $item ); 
  178. break; 
  179. case 'meta_data' : 
  180. if ( is_array( $value ) ) { 
  181. foreach ( $value as $meta ) { 
  182. $order->update_meta_data( $meta['key'], $meta['value'], isset( $meta['id'] ) ? $meta['id'] : '' ); 
  183. break; 
  184. default : 
  185. if ( is_callable( array( $order, "set_{$key}" ) ) ) { 
  186. $order->{"set_{$key}"}( $value ); 
  187. break; 
  188.  
  189. /** 
  190. * Filter the data for the insert. 
  191. * 
  192. * The dynamic portion of the hook name, $this->post_type, refers to post_type of the post being 
  193. * prepared for the response. 
  194. * 
  195. * @param WC_Order $order The prder object. 
  196. * @param WP_REST_Request $request Request object. 
  197. */ 
  198. return apply_filters( "woocommerce_rest_pre_insert_{$this->post_type}", $order, $request ); 
  199.  
  200. /** 
  201. * Create base WC Order object. 
  202. * 
  203. * @deprecated 3.0.0 
  204. * 
  205. * @param array $data 
  206. * @return WC_Order 
  207. */ 
  208. protected function create_base_order( $data ) { 
  209. return wc_create_order( $data ); 
  210.  
  211. /** 
  212. * Create order. 
  213. * 
  214. * @deprecated 3.0.0 
  215. * 
  216. * @param WP_REST_Request $request Full details about the request. 
  217. * @return int|WP_Error 
  218. */ 
  219. protected function create_order( $request ) { 
  220. try { 
  221. // Make sure customer exists. 
  222. if ( ! is_null( $request['customer_id'] ) && 0 !== $request['customer_id'] && false === get_user_by( 'id', $request['customer_id'] ) ) { 
  223. throw new WC_REST_Exception( 'woocommerce_rest_invalid_customer_id', __( 'Customer ID is invalid.', 'woocommerce' ), 400 ); 
  224.  
  225. $order = $this->prepare_item_for_database( $request ); 
  226. $order->set_created_via( 'rest-api' ); 
  227. $order->set_prices_include_tax( 'yes' === get_option( 'woocommerce_prices_include_tax' ) ); 
  228. $order->calculate_totals(); 
  229. $order->save(); 
  230.  
  231. // Handle set paid. 
  232. if ( true === $request['set_paid'] ) { 
  233. $order->payment_complete( $request['transaction_id'] ); 
  234.  
  235. return $order->get_id(); 
  236. } catch ( WC_Data_Exception $e ) { 
  237. return new WP_Error( $e->getErrorCode(), $e->getMessage(), $e->getErrorData() ); 
  238. } catch ( WC_REST_Exception $e ) { 
  239. return new WP_Error( $e->getErrorCode(), $e->getMessage(), array( 'status' => $e->getCode() ) ); 
  240.  
  241. /** 
  242. * Update order. 
  243. * 
  244. * @deprecated 3.0.0 
  245. * 
  246. * @param WP_REST_Request $request Full details about the request. 
  247. * @return int|WP_Error 
  248. */ 
  249. protected function update_order( $request ) { 
  250. try { 
  251. $order = $this->prepare_item_for_database( $request ); 
  252. $order->save(); 
  253.  
  254. // Handle set paid. 
  255. if ( $order->needs_payment() && true === $request['set_paid'] ) { 
  256. $order->payment_complete( $request['transaction_id'] ); 
  257.  
  258. // If items have changed, recalculate order totals. 
  259. if ( isset( $request['billing'] ) || isset( $request['shipping'] ) || isset( $request['line_items'] ) || isset( $request['shipping_lines'] ) || isset( $request['fee_lines'] ) || isset( $request['coupon_lines'] ) ) { 
  260. $order->calculate_totals(); 
  261.  
  262. return $order->get_id(); 
  263. } catch ( WC_Data_Exception $e ) { 
  264. return new WP_Error( $e->getErrorCode(), $e->getMessage(), $e->getErrorData() ); 
  265. } catch ( WC_REST_Exception $e ) { 
  266. return new WP_Error( $e->getErrorCode(), $e->getMessage(), array( 'status' => $e->getCode() ) ); 
.