Abstract_WC_Order_Data_Store_CPT

Abstract Order Data Store: Stored in CPT.

Defined (1)

The class is defined in the following location(s).

/includes/data-stores/abstract-wc-order-data-store-cpt.php  
  1. abstract class Abstract_WC_Order_Data_Store_CPT extends WC_Data_Store_WP implements WC_Object_Data_Store_Interface, WC_Abstract_Order_Data_Store_Interface { 
  2.  
  3. /** 
  4. * Internal meta type used to store order data. 
  5. * @var string 
  6. */ 
  7. protected $meta_type = 'post'; 
  8.  
  9. /** 
  10. * Data stored in meta keys, but not considered "meta" for an order. 
  11. * @since 3.0.0 
  12. * @var array 
  13. */ 
  14. protected $internal_meta_keys = array( 
  15. '_order_currency',  
  16. '_cart_discount',  
  17. '_cart_discount_tax',  
  18. '_order_shipping',  
  19. '_order_shipping_tax',  
  20. '_order_tax',  
  21. '_order_total',  
  22. '_order_version',  
  23. '_prices_include_tax',  
  24. '_payment_tokens',  
  25. ); 
  26.  
  27. /** 
  28. |-------------------------------------------------------------------------- 
  29. | CRUD Methods 
  30. |-------------------------------------------------------------------------- 
  31. */ 
  32.  
  33. /** 
  34. * Method to create a new order in the database. 
  35. * @param WC_Order $order 
  36. */ 
  37. public function create( &$order ) { 
  38. $order->set_version( WC_VERSION ); 
  39. $order->set_date_created( current_time( 'timestamp', true ) ); 
  40. $order->set_currency( $order->get_currency() ? $order->get_currency() : get_woocommerce_currency() ); 
  41.  
  42. $id = wp_insert_post( apply_filters( 'woocommerce_new_order_data', array( 
  43. 'post_date' => gmdate( 'Y-m-d H:i:s', $order->get_date_created( 'edit' )->getOffsetTimestamp() ),  
  44. 'post_date_gmt' => gmdate( 'Y-m-d H:i:s', $order->get_date_created( 'edit' )->getTimestamp() ),  
  45. 'post_type' => $order->get_type( 'edit' ),  
  46. 'post_status' => 'wc-' . ( $order->get_status( 'edit' ) ? $order->get_status( 'edit' ) : apply_filters( 'woocommerce_default_order_status', 'pending' ) ),  
  47. 'ping_status' => 'closed',  
  48. 'post_author' => 1,  
  49. 'post_title' => $this->get_post_title(),  
  50. 'post_password' => uniqid( 'order_' ),  
  51. 'post_parent' => $order->get_parent_id( 'edit' ),  
  52. 'post_excerpt' => $this->get_post_excerpt( $order ),  
  53. ) ), true ); 
  54.  
  55. if ( $id && ! is_wp_error( $id ) ) { 
  56. $order->set_id( $id ); 
  57. $this->update_post_meta( $order ); 
  58. $order->save_meta_data(); 
  59. $order->apply_changes(); 
  60. $this->clear_caches( $order ); 
  61.  
  62. /** 
  63. * Method to read an order from the database. 
  64. * @param WC_Order 
  65. */ 
  66. public function read( &$order ) { 
  67. $order->set_defaults(); 
  68.  
  69. if ( ! $order->get_id() || ! ( $post_object = get_post( $order->get_id() ) ) || ! in_array( $post_object->post_type, wc_get_order_types() ) ) { 
  70. throw new Exception( __( 'Invalid order.', 'woocommerce' ) ); 
  71.  
  72. $id = $order->get_id(); 
  73. $order->set_props( array( 
  74. 'parent_id' => $post_object->post_parent,  
  75. 'date_created' => 0 < $post_object->post_date_gmt ? wc_string_to_timestamp( $post_object->post_date_gmt ) : null,  
  76. 'date_modified' => 0 < $post_object->post_modified_gmt ? wc_string_to_timestamp( $post_object->post_modified_gmt ) : null,  
  77. 'status' => $post_object->post_status,  
  78. ) ); 
  79.  
  80. $this->read_order_data( $order, $post_object ); 
  81. $order->read_meta_data(); 
  82. $order->set_object_read( true ); 
  83.  
  84. /** 
  85. * In older versions, discounts may have been stored differently. 
  86. * Update them now so if the object is saved, the correct values are 
  87. * stored. @todo When meta is flattened, handle this during migration. 
  88. */ 
  89. if ( version_compare( $order->get_version( 'edit' ), '2.3.7', '<' ) && $order->get_prices_include_tax( 'edit' ) ) { 
  90. $order->set_discount_total( (double) get_post_meta( $order->get_id(), '_cart_discount', true ) - (double) get_post_meta( $order->get_id(), '_cart_discount_tax', true ) ); 
  91.  
  92. /** 
  93. * Method to update an order in the database. 
  94. * @param WC_Order $order 
  95. */ 
  96. public function update( &$order ) { 
  97. $order->save_meta_data(); 
  98. $order->set_version( WC_VERSION ); 
  99.  
  100. $changes = $order->get_changes(); 
  101.  
  102. // Only update the post when the post data changes. 
  103. if ( array_intersect( array( 'date_created', 'date_modified', 'status', 'parent_id', 'post_excerpt' ), array_keys( $changes ) ) ) { 
  104. $post_data = array( 
  105. 'post_date' => gmdate( 'Y-m-d H:i:s', $order->get_date_created( 'edit' )->getOffsetTimestamp() ),  
  106. 'post_date_gmt' => gmdate( 'Y-m-d H:i:s', $order->get_date_created( 'edit' )->getTimestamp() ),  
  107. 'post_status' => 'wc-' . ( $order->get_status( 'edit' ) ? $order->get_status( 'edit' ) : apply_filters( 'woocommerce_default_order_status', 'pending' ) ),  
  108. 'post_parent' => $order->get_parent_id(),  
  109. 'post_excerpt' => $this->get_post_excerpt( $order ),  
  110. 'post_modified' => isset( $changes['date_modified'] ) ? gmdate( 'Y-m-d H:i:s', $order->get_date_modified( 'edit' )->getOffsetTimestamp() ) : current_time( 'mysql' ),  
  111. 'post_modified_gmt' => isset( $changes['date_modified'] ) ? gmdate( 'Y-m-d H:i:s', $order->get_date_modified( 'edit' )->getTimestamp() ) : current_time( 'mysql', 1 ),  
  112. ); 
  113.  
  114. /** 
  115. * When updating this object, to prevent infinite loops, use $wpdb 
  116. * to update data, since wp_update_post spawns more calls to the 
  117. * save_post action. 
  118. * This ensures hooks are fired by either WP itself (admin screen save),  
  119. * or an update purely from CRUD. 
  120. */ 
  121. if ( doing_action( 'save_post' ) ) { 
  122. $GLOBALS['wpdb']->update( $GLOBALS['wpdb']->posts, $post_data, array( 'ID' => $order->get_id() ) ); 
  123. clean_post_cache( $order->get_id() ); 
  124. } else { 
  125. wp_update_post( array_merge( array( 'ID' => $order->get_id() ), $post_data ) ); 
  126. $order->read_meta_data( true ); // Refresh internal meta data, in case things were hooked into `save_post` or another WP hook. 
  127. $this->update_post_meta( $order ); 
  128. $order->apply_changes(); 
  129. $this->clear_caches( $order ); 
  130.  
  131. /** 
  132. * Method to delete an order from the database. 
  133. * @param WC_Order 
  134. * @param array $args Array of args to pass to the delete method. 
  135. */ 
  136. public function delete( &$order, $args = array() ) { 
  137. $id = $order->get_id(); 
  138. $args = wp_parse_args( $args, array( 
  139. 'force_delete' => false,  
  140. ) ); 
  141.  
  142. if ( $args['force_delete'] ) { 
  143. wp_delete_post( $id ); 
  144. $order->set_id( 0 ); 
  145. do_action( 'woocommerce_delete_order', $id ); 
  146. } else { 
  147. wp_trash_post( $id ); 
  148. $order->set_status( 'trash' ); 
  149. do_action( 'woocommerce_trash_order', $id ); 
  150.  
  151. /** 
  152. |-------------------------------------------------------------------------- 
  153. | Additional Methods 
  154. |-------------------------------------------------------------------------- 
  155. */ 
  156.  
  157. /** 
  158. * Excerpt for post. 
  159. * @param WC_order $order 
  160. * @return string 
  161. */ 
  162. protected function get_post_excerpt( $order ) { 
  163. return ''; 
  164.  
  165. /** 
  166. * Get a title for the new post type. 
  167. * @return string 
  168. */ 
  169. protected function get_post_title() { 
  170. // @codingStandardsIgnoreStart 
  171. /** translators: %s: Order date */ 
  172. return sprintf( __( 'Order – %s', 'woocommerce' ), strftime( _x( '%b %d, %Y @ %I:%M %p', 'Order date parsed by strftime', 'woocommerce' ) ) ); 
  173. // @codingStandardsIgnoreEnd 
  174.  
  175. /** 
  176. * Read order data. Can be overridden by child classes to load other props. 
  177. * @param WC_Order 
  178. * @param object $post_object 
  179. * @since 3.0.0 
  180. */ 
  181. protected function read_order_data( &$order, $post_object ) { 
  182. $id = $order->get_id(); 
  183.  
  184. $order->set_props( array( 
  185. 'currency' => get_post_meta( $id, '_order_currency', true ),  
  186. 'discount_total' => get_post_meta( $id, '_cart_discount', true ),  
  187. 'discount_tax' => get_post_meta( $id, '_cart_discount_tax', true ),  
  188. 'shipping_total' => get_post_meta( $id, '_order_shipping', true ),  
  189. 'shipping_tax' => get_post_meta( $id, '_order_shipping_tax', true ),  
  190. 'cart_tax' => get_post_meta( $id, '_order_tax', true ),  
  191. 'total' => get_post_meta( $id, '_order_total', true ),  
  192. 'version' => get_post_meta( $id, '_order_version', true ),  
  193. 'prices_include_tax' => metadata_exists( 'post', $id, '_prices_include_tax' ) ? 'yes' === get_post_meta( $id, '_prices_include_tax', true ) : 'yes' === get_option( 'woocommerce_prices_include_tax' ),  
  194. ) ); 
  195.  
  196. // Gets extra data associated with the order if needed. 
  197. foreach ( $order->get_extra_data_keys() as $key ) { 
  198. $function = 'set_' . $key; 
  199. if ( is_callable( array( $order, $function ) ) ) { 
  200. $order->{$function}( get_post_meta( $order->get_id(), '_' . $key, true ) ); 
  201.  
  202. /** 
  203. * Helper method that updates all the post meta for an order based on it's settings in the WC_Order class. 
  204. * @param $order WC_Order 
  205. * @since 3.0.0 
  206. */ 
  207. protected function update_post_meta( &$order ) { 
  208. $updated_props = array(); 
  209. $meta_key_to_props = array( 
  210. '_order_currency' => 'currency',  
  211. '_cart_discount' => 'discount_total',  
  212. '_cart_discount_tax' => 'discount_tax',  
  213. '_order_shipping' => 'shipping_total',  
  214. '_order_shipping_tax' => 'shipping_tax',  
  215. '_order_tax' => 'cart_tax',  
  216. '_order_total' => 'total',  
  217. '_order_version' => 'version',  
  218. '_prices_include_tax' => 'prices_include_tax',  
  219. ); 
  220.  
  221. $props_to_update = $this->get_props_to_update( $order, $meta_key_to_props ); 
  222.  
  223. foreach ( $props_to_update as $meta_key => $prop ) { 
  224. $value = $order->{"get_$prop"}( 'edit' ); 
  225.  
  226. if ( 'prices_include_tax' === $prop ) { 
  227. $value = $value ? 'yes' : 'no'; 
  228.  
  229. if ( update_post_meta( $order->get_id(), $meta_key, $value ) ) { 
  230. $updated_props[] = $prop; 
  231.  
  232. do_action( 'woocommerce_order_object_updated_props', $order, $updated_props ); 
  233.  
  234. /** 
  235. * Clear any caches. 
  236. * @param WC_Order 
  237. * @since 3.0.0 
  238. */ 
  239. protected function clear_caches( &$order ) { 
  240. clean_post_cache( $order->get_id() ); 
  241. wc_delete_shop_order_transients( $order ); 
  242. wp_cache_delete( 'order-items-' . $order->get_id(), 'orders' ); 
  243.  
  244. /** 
  245. * Read order items of a specific type from the database for this order. 
  246. * @param WC_Order $order 
  247. * @param string $type 
  248. * @return array 
  249. */ 
  250. public function read_items( $order, $type ) { 
  251. global $wpdb; 
  252.  
  253. // Get from cache if available. 
  254. $items = wp_cache_get( 'order-items-' . $order->get_id(), 'orders' ); 
  255.  
  256. if ( false === $items ) { 
  257. $get_items_sql = $wpdb->prepare( "SELECT order_item_type, order_item_id, order_id, order_item_name FROM {$wpdb->prefix}woocommerce_order_items WHERE order_id = %d ORDER BY order_item_id;", $order->get_id() ); 
  258. $items = $wpdb->get_results( $get_items_sql ); 
  259. foreach ( $items as $item ) { 
  260. wp_cache_set( 'item-' . $item->order_item_id, $item, 'order-items' ); 
  261. wp_cache_set( 'order-items-' . $order->get_id(), $items, 'orders' ); 
  262.  
  263. $items = wp_list_filter( $items, array( 'order_item_type' => $type ) ); 
  264.  
  265. if ( ! empty( $items ) ) { 
  266. $items = array_map( array( 'WC_Order_Factory', 'get_order_item' ), array_combine( wp_list_pluck( $items, 'order_item_id' ), $items ) ); 
  267. } else { 
  268. $items = array(); 
  269.  
  270. return $items; 
  271.  
  272. /** 
  273. * Remove all line items (products, coupons, shipping, taxes) from the order. 
  274. * @param WC_Order 
  275. * @param string $type Order item type. Default null. 
  276. */ 
  277. public function delete_items( $order, $type = null ) { 
  278. global $wpdb; 
  279. if ( ! empty( $type ) ) { 
  280. $wpdb->query( $wpdb->prepare( "DELETE FROM itemmeta USING {$wpdb->prefix}woocommerce_order_itemmeta itemmeta INNER JOIN {$wpdb->prefix}woocommerce_order_items items WHERE itemmeta.order_item_id = items.order_item_id AND items.order_id = %d AND items.order_item_type = %s", $order->get_id(), $type ) ); 
  281. $wpdb->query( $wpdb->prepare( "DELETE FROM {$wpdb->prefix}woocommerce_order_items WHERE order_id = %d AND order_item_type = %s", $order->get_id(), $type ) ); 
  282. } else { 
  283. $wpdb->query( $wpdb->prepare( "DELETE FROM itemmeta USING {$wpdb->prefix}woocommerce_order_itemmeta itemmeta INNER JOIN {$wpdb->prefix}woocommerce_order_items items WHERE itemmeta.order_item_id = items.order_item_id and items.order_id = %d", $order->get_id() ) ); 
  284. $wpdb->query( $wpdb->prepare( "DELETE FROM {$wpdb->prefix}woocommerce_order_items WHERE order_id = %d", $order->get_id() ) ); 
  285. $this->clear_caches( $order ); 
  286.  
  287. /** 
  288. * Get token ids for an order. 
  289. * @param WC_Order 
  290. * @return array 
  291. */ 
  292. public function get_payment_token_ids( $order ) { 
  293. $token_ids = array_filter( (array) get_post_meta( $order->get_id(), '_payment_tokens', true ) ); 
  294. return $token_ids; 
  295.  
  296. /** 
  297. * Update token ids for an order. 
  298. * @param WC_Order 
  299. * @param array $token_ids 
  300. */ 
  301. public function update_payment_token_ids( $order, $token_ids ) { 
  302. update_post_meta( $order->get_id(), '_payment_tokens', $token_ids );