PageRenderTime 38ms CodeModel.GetById 11ms RepoModel.GetById 0ms app.codeStats 1ms

/wp-content/plugins/woocommerce/packages/woocommerce-admin/src/API/Orders.php

https://gitlab.com/campus-academy/krowkaramel
PHP | 278 lines | 189 code | 29 blank | 60 comment | 13 complexity | 5c2bef80398bd052410152c64ecf0aea MD5 | raw file
  1. <?php
  2. /**
  3. * REST API Orders Controller
  4. *
  5. * Handles requests to /orders/*
  6. */
  7. namespace Automattic\WooCommerce\Admin\API;
  8. defined( 'ABSPATH' ) || exit;
  9. use Automattic\WooCommerce\Admin\API\Reports\Controller as ReportsController;
  10. /**
  11. * Orders controller.
  12. *
  13. * @extends WC_REST_Orders_Controller
  14. */
  15. class Orders extends \WC_REST_Orders_Controller {
  16. /**
  17. * Endpoint namespace.
  18. *
  19. * @var string
  20. */
  21. protected $namespace = 'wc-analytics';
  22. /**
  23. * Get the query params for collections.
  24. *
  25. * @return array
  26. */
  27. public function get_collection_params() {
  28. $params = parent::get_collection_params();
  29. // This needs to remain a string to support extensions that filter Order Number.
  30. $params['number'] = array(
  31. 'description' => __( 'Limit result set to orders matching part of an order number.', 'woocommerce' ),
  32. 'type' => 'string',
  33. 'validate_callback' => 'rest_validate_request_arg',
  34. );
  35. // Fix the default 'status' value until it can be patched in core.
  36. $params['status']['default'] = array( 'any' );
  37. // Analytics settings may affect the allowed status list.
  38. $params['status']['items']['enum'] = ReportsController::get_order_statuses();
  39. return $params;
  40. }
  41. /**
  42. * Prepare objects query.
  43. *
  44. * @param WP_REST_Request $request Full details about the request.
  45. * @return array
  46. */
  47. protected function prepare_objects_query( $request ) {
  48. global $wpdb;
  49. $args = parent::prepare_objects_query( $request );
  50. // Search by partial order number.
  51. if ( ! empty( $request['number'] ) ) {
  52. $partial_number = trim( $request['number'] );
  53. $limit = intval( $args['posts_per_page'] );
  54. $order_ids = $wpdb->get_col(
  55. $wpdb->prepare(
  56. "SELECT ID
  57. FROM {$wpdb->prefix}posts
  58. WHERE post_type = 'shop_order'
  59. AND ID LIKE %s
  60. LIMIT %d",
  61. $wpdb->esc_like( absint( $partial_number ) ) . '%',
  62. $limit
  63. )
  64. );
  65. // Force WP_Query return empty if don't found any order.
  66. $order_ids = empty( $order_ids ) ? array( 0 ) : $order_ids;
  67. $args['post__in'] = $order_ids;
  68. }
  69. return $args;
  70. }
  71. /**
  72. * Get product IDs, names, and quantity from order ID.
  73. *
  74. * @param array $order_id ID of order.
  75. * @return array
  76. */
  77. protected function get_products_by_order_id( $order_id ) {
  78. global $wpdb;
  79. $order_items_table = $wpdb->prefix . 'woocommerce_order_items';
  80. $order_itemmeta_table = $wpdb->prefix . 'woocommerce_order_itemmeta';
  81. $products = $wpdb->get_results(
  82. $wpdb->prepare(
  83. // phpcs:disable WordPress.DB.PreparedSQL.InterpolatedNotPrepared
  84. "SELECT
  85. order_id,
  86. order_itemmeta.meta_value as product_id,
  87. order_itemmeta_2.meta_value as product_quantity,
  88. order_itemmeta_3.meta_value as variation_id,
  89. {$wpdb->posts}.post_title as product_name
  90. FROM {$order_items_table} order_items
  91. LEFT JOIN {$order_itemmeta_table} order_itemmeta on order_items.order_item_id = order_itemmeta.order_item_id
  92. LEFT JOIN {$order_itemmeta_table} order_itemmeta_2 on order_items.order_item_id = order_itemmeta_2.order_item_id
  93. LEFT JOIN {$order_itemmeta_table} order_itemmeta_3 on order_items.order_item_id = order_itemmeta_3.order_item_id
  94. LEFT JOIN {$wpdb->posts} on {$wpdb->posts}.ID = order_itemmeta.meta_value
  95. WHERE
  96. order_id = ( %d )
  97. AND order_itemmeta.meta_key = '_product_id'
  98. AND order_itemmeta_2.meta_key = '_qty'
  99. AND order_itemmeta_3.meta_key = '_variation_id'
  100. GROUP BY product_id
  101. ", // phpcs:enable WordPress.DB.PreparedSQL.InterpolatedNotPrepared
  102. $order_id
  103. ),
  104. ARRAY_A
  105. );
  106. return $products;
  107. }
  108. /**
  109. * Get customer data from customer_id.
  110. *
  111. * @param array $customer_id ID of customer.
  112. * @return array
  113. */
  114. protected function get_customer_by_id( $customer_id ) {
  115. global $wpdb;
  116. $customer_lookup_table = $wpdb->prefix . 'wc_customer_lookup';
  117. $customer = $wpdb->get_row(
  118. $wpdb->prepare(
  119. // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
  120. "SELECT * FROM {$customer_lookup_table} WHERE customer_id = ( %d )",
  121. $customer_id
  122. ),
  123. ARRAY_A
  124. );
  125. return $customer;
  126. }
  127. /**
  128. * Get formatted item data.
  129. *
  130. * @param WC_Data $object WC_Data instance.
  131. * @return array
  132. */
  133. protected function get_formatted_item_data( $object ) {
  134. $extra_fields = array( 'customer', 'products' );
  135. $fields = false;
  136. // Determine if the response fields were specified.
  137. if ( ! empty( $this->request['_fields'] ) ) {
  138. $fields = wp_parse_list( $this->request['_fields'] );
  139. if ( 0 === count( $fields ) ) {
  140. $fields = false;
  141. } else {
  142. $fields = array_map( 'trim', $fields );
  143. }
  144. }
  145. // Initially skip line items if we can.
  146. $using_order_class_override = is_a( $object, '\Automattic\WooCommerce\Admin\Overrides\Order' );
  147. if ( $using_order_class_override ) {
  148. $data = $object->get_data_without_line_items();
  149. } else {
  150. $data = $object->get_data();
  151. }
  152. $extra_fields = false === $fields ? array() : array_intersect( $extra_fields, $fields );
  153. $format_decimal = array( 'discount_total', 'discount_tax', 'shipping_total', 'shipping_tax', 'shipping_total', 'shipping_tax', 'cart_tax', 'total', 'total_tax' );
  154. $format_date = array( 'date_created', 'date_modified', 'date_completed', 'date_paid' );
  155. $format_line_items = array( 'line_items', 'tax_lines', 'shipping_lines', 'fee_lines', 'coupon_lines' );
  156. // Add extra data as necessary.
  157. $extra_data = array();
  158. foreach ( $extra_fields as $field ) {
  159. switch ( $field ) {
  160. case 'customer':
  161. $extra_data['customer'] = $this->get_customer_by_id( $data['customer_id'] );
  162. break;
  163. case 'products':
  164. $extra_data['products'] = $this->get_products_by_order_id( $object->get_id() );
  165. break;
  166. }
  167. }
  168. // Format decimal values.
  169. foreach ( $format_decimal as $key ) {
  170. $data[ $key ] = wc_format_decimal( $data[ $key ], $this->request['dp'] );
  171. }
  172. // format total with order currency.
  173. if ( $object instanceof \WC_Order ) {
  174. $data['total_formatted'] = wp_strip_all_tags( html_entity_decode( $object->get_formatted_order_total() ), true );
  175. }
  176. // Format date values.
  177. foreach ( $format_date as $key ) {
  178. $datetime = $data[ $key ];
  179. $data[ $key ] = wc_rest_prepare_date_response( $datetime, false );
  180. $data[ $key . '_gmt' ] = wc_rest_prepare_date_response( $datetime );
  181. }
  182. // Format the order status.
  183. $data['status'] = 'wc-' === substr( $data['status'], 0, 3 ) ? substr( $data['status'], 3 ) : $data['status'];
  184. // Format requested line items.
  185. $formatted_line_items = array();
  186. foreach ( $format_line_items as $key ) {
  187. if ( false === $fields || in_array( $key, $fields, true ) ) {
  188. if ( $using_order_class_override ) {
  189. $line_item_data = $object->get_line_item_data( $key );
  190. } else {
  191. $line_item_data = $data[ $key ];
  192. }
  193. $formatted_line_items[ $key ] = array_values( array_map( array( $this, 'get_order_item_data' ), $line_item_data ) );
  194. }
  195. }
  196. // Refunds.
  197. $data['refunds'] = array();
  198. foreach ( $object->get_refunds() as $refund ) {
  199. $data['refunds'][] = array(
  200. 'id' => $refund->get_id(),
  201. 'reason' => $refund->get_reason() ? $refund->get_reason() : '',
  202. 'total' => '-' . wc_format_decimal( $refund->get_amount(), $this->request['dp'] ),
  203. );
  204. }
  205. return array_merge(
  206. array(
  207. 'id' => $object->get_id(),
  208. 'parent_id' => $data['parent_id'],
  209. 'number' => $data['number'],
  210. 'order_key' => $data['order_key'],
  211. 'created_via' => $data['created_via'],
  212. 'version' => $data['version'],
  213. 'status' => $data['status'],
  214. 'currency' => $data['currency'],
  215. 'date_created' => $data['date_created'],
  216. 'date_created_gmt' => $data['date_created_gmt'],
  217. 'date_modified' => $data['date_modified'],
  218. 'date_modified_gmt' => $data['date_modified_gmt'],
  219. 'discount_total' => $data['discount_total'],
  220. 'discount_tax' => $data['discount_tax'],
  221. 'shipping_total' => $data['shipping_total'],
  222. 'shipping_tax' => $data['shipping_tax'],
  223. 'cart_tax' => $data['cart_tax'],
  224. 'total' => $data['total'],
  225. 'total_formatted' => isset( $data['total_formatted'] ) ? $data['total_formatted'] : $data['total'],
  226. 'total_tax' => $data['total_tax'],
  227. 'prices_include_tax' => $data['prices_include_tax'],
  228. 'customer_id' => $data['customer_id'],
  229. 'customer_ip_address' => $data['customer_ip_address'],
  230. 'customer_user_agent' => $data['customer_user_agent'],
  231. 'customer_note' => $data['customer_note'],
  232. 'billing' => $data['billing'],
  233. 'shipping' => $data['shipping'],
  234. 'payment_method' => $data['payment_method'],
  235. 'payment_method_title' => $data['payment_method_title'],
  236. 'transaction_id' => $data['transaction_id'],
  237. 'date_paid' => $data['date_paid'],
  238. 'date_paid_gmt' => $data['date_paid_gmt'],
  239. 'date_completed' => $data['date_completed'],
  240. 'date_completed_gmt' => $data['date_completed_gmt'],
  241. 'cart_hash' => $data['cart_hash'],
  242. 'meta_data' => $data['meta_data'],
  243. 'refunds' => $data['refunds'],
  244. ),
  245. $formatted_line_items,
  246. $extra_data
  247. );
  248. }
  249. }