WC_POS_API_Orders

POS Orders Class duck punches the WC REST API.

Defined (1)

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

/includes/api/class-wc-pos-orders.php  
  1. class WC_POS_API_Orders extends WC_POS_API_Abstract { 
  2.  
  3. /** @var array Contains the raw order data */ 
  4. private $data = array(); 
  5. private $flag = false; 
  6.  
  7. /** 
  8. * Constructor 
  9. */ 
  10. public function __construct() { 
  11.  
  12. // order data 
  13. add_filter( 'woocommerce_api_create_order_data', array( $this, 'create_order_data') ); 
  14. add_filter( 'woocommerce_api_edit_order_data', array( $this, 'edit_order_data'), 10, 2 ); 
  15. add_action( 'woocommerce_api_create_order', array( $this, 'create_order') ); 
  16. add_action( 'woocommerce_api_edit_order', array( $this, 'edit_order') ); 
  17.  
  18. // payment 
  19. add_action( 'woocommerce_pos_process_payment', array( $this, 'process_payment' ), 10, 2 ); 
  20. add_action( 'woocommerce_payment_complete', array( $this, 'payment_complete' ), 10, 1 ); 
  21.  
  22. // order response 
  23. add_filter( 'woocommerce_api_order_response', array( $this, 'order_response' ), 10, 4 ); 
  24.  
  25. // order emails 
  26. add_filter( 'woocommerce_email', array( $this, 'woocommerce_email' ), 99 ); 
  27.  
  28. /** 
  29. * Create order data 
  30. * @param array $data 
  31. * @return array 
  32. */ 
  33. public function create_order_data(array $data) { 
  34.  
  35. // store raw http data 
  36. $this->data = $data; 
  37.  
  38. // add filters & actions for create order 
  39. add_filter( 'woocommerce_product_tax_class', array( $this, 'product_tax_class' ), 10, 2 ); 
  40. add_filter( 'woocommerce_get_product_from_item', array( $this, 'get_product_from_item' ), 10, 3 ); 
  41. add_filter( 'pre_option_woocommerce_tax_based_on', array( $this, 'woocommerce_tax_based_on' ) ); 
  42. add_filter( 'woocommerce_find_rates', array( $this, 'find_rates'), 10, 2 ); 
  43. add_action( 'woocommerce_order_add_product', array( $this, 'order_add_product'), 10, 5 ); 
  44. add_action( 'updated_order_item_meta', array( $this, 'updated_order_item_meta'), 10, 4 ); 
  45.  
  46. // WC API < 2.4 has a bug if $fee['taxable'] = false 
  47. // set $fee['taxable'] = true and use random tax_class so not tax is calculated 
  48. if( version_compare( WC()->version, '2.4', '<' ) && isset($this->data['fee_lines']) ) { 
  49. foreach( $this->data['fee_lines'] as &$fee ) { 
  50. if( !isset($fee['taxable']) || $fee['taxable'] == false ) { 
  51. $fee['taxable'] = true; 
  52. $fee['tax_class'] = 'upgrade-woocommerce-' . time(); 
  53.  
  54. // WC handling of shipping is FUBAR 
  55. // if order has shipping line, we'll have to calc the tax ourselves 
  56. // also recalc total tax for negative fee lines 
  57. $has_fee = isset($this->data['fee_lines']) && !empty($this->data['fee_lines']); 
  58. $has_shipping = isset($this->data['shipping_lines']) && !empty($this->data['shipping_lines']); 
  59.  
  60. if( $has_shipping ) { 
  61. add_filter( 'pre_option_woocommerce_shipping_tax_class', array( $this, 'woocommerce_shipping_tax_class' ) ); 
  62. add_action( 'woocommerce_order_add_shipping', array( $this, 'order_add_shipping'), 10, 3 ); 
  63.  
  64. if( $has_fee || $has_shipping ) 
  65. add_filter( 'update_post_metadata', array( $this, 'update_post_metadata'), 10, 5 ); 
  66.  
  67. // POS UI uses Fee 'name' for WC 3 compat 
  68. if( $has_fee ) { 
  69. foreach($this->data['fee_lines'] as &$fee) { 
  70. if( !isset($fee['title']) && isset( $fee['name'] ) ) { 
  71. $fee['title'] = $fee['name']; 
  72.  
  73. // populate customer data 
  74. $customer_id = isset( $data['customer_id'] ) ? $data['customer_id'] : 0 ; 
  75. if($customer_id) { 
  76. $this->data['billing_address'] = $this->get_customer_details($customer_id, 'billing'); 
  77. $this->data['shipping_address'] = $this->get_customer_details($customer_id, 'shipping'); 
  78.  
  79. return $this->data; 
  80.  
  81. /** 
  82. * Edit order data 
  83. * @param $data 
  84. * @param $order_id 
  85. * @return array 
  86. */ 
  87. public function edit_order_data(array $data, $order_id) { 
  88. // $this->delete_order_items($order_id); 
  89. return $this->create_order_data($data); 
  90.  
  91. /** 
  92. * Change the product tax_class 
  93. * @param $tax_class 
  94. * @param $product 
  95. * @return string 
  96. */ 
  97. public function product_tax_class($tax_class, $product) { 
  98.  
  99. $id = isset($product->id) ? $product->id: false; 
  100. $id = isset($product->variation_id) ? $product->variation_id: $id; 
  101.  
  102. if($id) { 
  103. $item = $this->get_line_item($id); 
  104. if( isset( $item['tax_class'] ) ) { 
  105. $tax_class = sanitize_text_field( $item['tax_class'] ); 
  106.  
  107. return $tax_class; 
  108.  
  109. /** 
  110. * Set taxable 
  111. * @param $product 
  112. * @param $item 
  113. * @param $WC_Product 
  114. * @return mixed 
  115. */ 
  116. public function get_product_from_item($product, $item, $WC_Product) { 
  117.  
  118. $id = isset($product->id) ? $product->id: false; 
  119. $id = isset($product->variation_id) ? $product->variation_id: $id; 
  120.  
  121. if($id) { 
  122. $data = $this->get_line_item($id); 
  123. if( isset( $data['taxable'] ) ) { 
  124. // api has options true/false 
  125. // tax_status has options taxable/shipping/none 
  126. $product->tax_status = $data['taxable'] ? 'taxable' : 'none'; 
  127.  
  128. return $product; 
  129.  
  130.  
  131. /** 
  132. * Opportunity to change title and add line_item meta 
  133. * @param $order_id 
  134. * @param $item_id 
  135. * @param $product 
  136. * @param $qty 
  137. * @param $args 
  138. */ 
  139. public function order_add_product($order_id, $item_id, $product, $qty, $args) { 
  140.  
  141. $id = isset($product->id) ? $product->id: false; 
  142. $id = isset($product->variation_id) ? $product->variation_id: $id; 
  143.  
  144. if($id) { 
  145. $data = $this->get_line_item($id); 
  146.  
  147. // update title 
  148. if( isset( $data['name'] ) ) { 
  149. wc_update_order_item( $item_id,  
  150. array( 
  151. 'order_item_name' => sanitize_text_field( $data['name'] ) 
  152. ); 
  153.  
  154. // update meta 
  155. if( isset( $data['meta'] ) && !empty( $data['meta'] ) ) { 
  156. $this->add_product_meta( $item_id, $data['meta'] ); 
  157.  
  158.  
  159.  
  160. /** 
  161. * Add product meta 
  162. * @param $item_id 
  163. * @param array $meta 
  164. */ 
  165. private function add_product_meta($item_id, array $meta) { 
  166.  
  167. // line meta 
  168. foreach($meta as $m) { 
  169. $label = isset($m['label']) ? $m['label'] : ''; 
  170. $value = isset($m['value']) ? $m['value'] : ''; 
  171. wc_add_order_item_meta( $item_id, $label, $value ); 
  172.  
  173.  
  174. /** 
  175. * @param $order_id 
  176. * @param $item_id 
  177. * @param $rate 
  178. */ 
  179. public function order_add_shipping($order_id, $item_id, $rate) { 
  180. $shipping_line = $this->get_shipping_line($rate, $item_id); 
  181.  
  182. if($shipping_line && isset($shipping_line['tax'])) { 
  183. $taxes = array(); 
  184. foreach($shipping_line['tax'] as $k => $tax) { 
  185. if( !empty($tax) ) { 
  186. $taxes[$k] = isset($tax['total']) ? wc_format_decimal( $tax['total'] ) : 0 ; 
  187. wc_update_order_item_meta( $item_id, 'taxes', $taxes ); 
  188.  
  189. /** 
  190. * Short circuit get_option('woocommerce_tax_based_on') as shop base 
  191. * @return string 
  192. */ 
  193. public function woocommerce_tax_based_on() { 
  194. return 'base'; 
  195.  
  196. /** 
  197. * Short circuit get_option('woocommerce_shipping_tax_class') as standard 
  198. * @return string 
  199. */ 
  200. public function woocommerce_shipping_tax_class() { 
  201. return 'standard'; 
  202.  
  203. /** 
  204. * Remove calc_shipping_tax 
  205. * @param $matched_tax_rates 
  206. * @param $args 
  207. * @return array 
  208. */ 
  209. public function find_rates( $matched_tax_rates, $args ) { 
  210. if ( $matched_tax_rates ) { 
  211. foreach ( $matched_tax_rates as &$rate ) { 
  212. $rate['shipping'] = 'no'; 
  213. return $matched_tax_rates; 
  214.  
  215. /** 
  216. * Retrieve line_item from raw data 
  217. * @param $product_id 
  218. */ 
  219. private function get_line_item($product_id) { 
  220. if(!isset($this->data['line_items'])) 
  221. return; 
  222.  
  223. foreach($this->data['line_items'] as $item) { 
  224. if( isset($item['product_id']) && $item['product_id'] == $product_id ) 
  225. return $item; 
  226.  
  227. /** 
  228. * Match $rate properties to raw data 
  229. * - there's no id to match so do best guess match id, title & cost 
  230. * @param $rate 
  231. * @param $item_id 
  232. */ 
  233. private function get_shipping_line($rate, $item_id) { 
  234. if(!isset($this->data['shipping_lines'])) 
  235. return; 
  236.  
  237. $lines = $this->data['shipping_lines']; 
  238. foreach($lines as $key => &$line) { 
  239. if( 
  240. $line['method_id'] == $rate->method_id && 
  241. $line['method_title'] == $rate->label && 
  242. $line['total'] == $rate->cost && 
  243. !isset( $line['id'] ) 
  244. $line['id'] = $item_id; 
  245. return $line; 
  246.  
  247. /** 
  248. * Fix item meta for negative product/fee values 
  249. * @param $meta_id 
  250. * @param $order_id 
  251. * @param $meta_key 
  252. * @param $meta_value 
  253. */ 
  254. public function updated_order_item_meta($meta_id, $order_id, $meta_key, $meta_value) { 
  255.  
  256. if($meta_key == '_line_tax_data') { 
  257. $line_subtotal_taxes = isset($meta_value['subtotal']) ? $meta_value['subtotal'] : array(); 
  258. $line_taxes = isset($meta_value['total']) ? $meta_value['total'] : array(); 
  259. $line_subtotal_tax = array_sum( $line_subtotal_taxes ); 
  260. $line_tax = array_sum( $line_taxes ); 
  261.  
  262. wc_update_order_item_meta( $order_id, '_line_subtotal_tax', wc_format_decimal( $line_subtotal_tax ) ); 
  263. wc_update_order_item_meta( $order_id, '_line_tax', wc_format_decimal( $line_tax ) ); 
  264.  
  265.  
  266. /** 
  267. * Apply shipping tax, fix order_tax 
  268. * - 
  269. * - filter has already passed $this->data['shipping_tax'] test 
  270. * @param $null 
  271. * @param $order_id 
  272. * @param $meta_key 
  273. * @param $meta_value 
  274. * @param $prev_value 
  275. * @return null 
  276. */ 
  277. public function update_post_metadata($null, $order_id, $meta_key, $meta_value, $prev_value) { 
  278.  
  279. // we want last update to _order_shipping after $order->calculate_taxes() 
  280. // set flag true on first pass 
  281. if( $meta_key == '_order_shipping_tax' ) 
  282. $this->flag = true; 
  283.  
  284. if( $meta_key != '_order_shipping' || ! $this->flag ) 
  285. return $null; 
  286.  
  287. // update order meta 
  288. $shipping_tax_total = isset($this->data['shipping_tax']) ? $this->data['shipping_tax'] : 0 ; 
  289. update_post_meta( $order_id, '_order_shipping_tax', wc_format_decimal( $shipping_tax_total ) ); 
  290.  
  291. // check each shipping tax line 
  292. // if order item meta already exists, update the shipping_tax_amount 
  293. // if order item meta not present, add the new tax 
  294. // ... nasty :( 
  295.  
  296. // first get an assoc array of $rate_id => $item_id 
  297. $tax_items = array(); 
  298. $order_tax = 0; 
  299. $order = wc_get_order( $order_id ); 
  300. foreach ( $order->get_tax_totals() as $code => $tax ) { 
  301. $tax_items[$tax->rate_id] = $tax->id; 
  302. $order_tax += $tax->amount; 
  303.  
  304. // fix total_tax calc 
  305. update_post_meta($order_id, '_order_tax', $order_tax); 
  306.  
  307. // now loop through the shipping_lines 
  308. if( isset( $shipping['shipping_lines'] ) ) : 
  309. foreach($this->data['shipping_lines'] as $shipping) : 
  310. if( isset( $shipping['tax'] ) ) : 
  311. foreach( $shipping['tax'] as $rate_id => $tax ) : 
  312. if( isset( $tax['total'] ) ) : 
  313.  
  314. if( array_key_exists( $rate_id, $tax_items ) ) { 
  315. wc_update_order_item_meta( $tax_items[$rate_id], 'shipping_tax_amount', wc_format_decimal( $tax['total'] ) ); 
  316. } else { 
  317. $order->add_tax( $rate_id, 0, $tax['total'] ); 
  318.  
  319. endif; 
  320. endforeach; 
  321. endif; 
  322. endforeach; 
  323. endif; 
  324.  
  325. return $null; 
  326.  
  327. /** 
  328. * Create order complete 
  329. * @param $order_id 
  330. */ 
  331. public function create_order( $order_id ) { 
  332. // pos meta 
  333. $current_user = wp_get_current_user(); 
  334.  
  335. update_post_meta( $order_id, '_pos', 1 ); 
  336. update_post_meta( $order_id, '_pos_user', $current_user->ID ); 
  337. update_post_meta( $order_id, '_pos_user_name', $current_user->user_firstname . ' ' . $current_user->user_lastname ); 
  338.  
  339. // check _order_tax and _order_shipping_tax for reports 
  340. if( ! get_post_meta( $order_id, '_order_tax', true ) ) { 
  341. update_post_meta( $order_id, '_order_tax', 0 ); 
  342.  
  343. if( ! get_post_meta( $order_id, '_order_shipping_tax', true ) ) { 
  344. update_post_meta( $order_id, '_order_shipping_tax', 0 ); 
  345.  
  346. // payment 
  347. do_action( 'woocommerce_pos_process_payment', $order_id, $this->data); 
  348.  
  349. /** 
  350. * Edit order complete 
  351. * @param $order_id 
  352. */ 
  353. public function edit_order( $order_id ) { 
  354. // payment 
  355. do_action( 'woocommerce_pos_process_payment', $order_id, $this->data); 
  356.  
  357. /** 
  358. * Process payment 
  359. * @param $order_id 
  360. * @param $data 
  361. */ 
  362. public function process_payment( $order_id, $data ) { 
  363.  
  364. if( !isset($data['payment_details']) ) { 
  365. return; 
  366.  
  367. // some gateways check if a user is signed in, so let's switch to customer 
  368. $logged_in_user = get_current_user_id(); 
  369. $customer_id = isset( $data['customer_id'] ) ? $data['customer_id'] : 0 ; 
  370. wp_set_current_user( $customer_id ); 
  371.  
  372. // load the gateways & process payment 
  373. $gateway_id = $data['payment_details']['method_id']; 
  374. add_filter('option_woocommerce_'. $gateway_id .'_settings', array($this, 'force_enable_gateway')); 
  375. $settings = WC_POS_Admin_Settings_Checkout::get_instance(); 
  376. $gateways = $settings->load_enabled_gateways(); 
  377. $response = $gateways[ $gateway_id ]->process_payment( $order_id ); 
  378.  
  379. if(isset($response['result']) && $response['result'] == 'success') { 
  380. $this->payment_success($gateway_id, $order_id, $response); 
  381. } else { 
  382. $this->payment_failure($gateway_id, $order_id, $response); 
  383.  
  384. // switch back to logged in user 
  385. wp_set_current_user( $logged_in_user ); 
  386.  
  387. // clear any payment gateway messages 
  388. wc_clear_notices(); 
  389.  
  390. /** 
  391. * Some gateways will check if enabled 
  392. * @param $data 
  393. * @return mixed 
  394. */ 
  395. public function force_enable_gateway($data) { 
  396. if(isset($data['enabled'])) { 
  397. $data['enabled'] = 'yes'; 
  398. return $data; 
  399.  
  400. /** 
  401. * @param $gateway_id 
  402. * @param $order_id 
  403. * @param $response 
  404. */ 
  405. private function payment_success($gateway_id, $order_id, $response) { 
  406.  
  407. // capture any instructions 
  408. ob_start(); 
  409. do_action( 'woocommerce_thankyou_' . $gateway_id, $order_id ); 
  410. $response['messages'] = ob_get_contents(); 
  411. ob_end_clean(); 
  412.  
  413. // redirect 
  414. if( isset($response['redirect']) ) { 
  415. $response['messages'] = $this->payment_redirect($gateway_id, $order_id, $response); 
  416.  
  417. update_post_meta( $order_id, '_pos_payment_result', 'success' ); 
  418. update_post_meta( $order_id, '_pos_payment_message', $response['messages'] ); 
  419.  
  420. /** 
  421. * @param $gateway_id 
  422. * @param $order_id 
  423. * @param $response 
  424. */ 
  425. private function payment_failure($gateway_id, $order_id, $response) { 
  426. $message = isset($response['messages']) ? $response['messages'] : wc_get_notices( 'error' ); 
  427.  
  428. // if messages empty give generic response 
  429. if(empty($message)) { 
  430. $message = __( 'There was an error processing the payment', 'woocommerce-pos'); 
  431.  
  432. update_post_meta( $order_id, '_pos_payment_result', 'failure' ); 
  433. update_post_meta( $order_id, '_pos_payment_message', $message ); 
  434.  
  435. /** 
  436. * @param $gateway_id 
  437. * @param $order_id 
  438. * @param $response 
  439. * @return string 
  440. */ 
  441. private function payment_redirect($gateway_id, $order_id, $response) { 
  442. $message = $response['messages']; 
  443.  
  444. // compare url fragments 
  445. $success_url = wc_get_endpoint_url( 'order-received', $order_id, get_permalink( wc_get_page_id( 'checkout' ) ) ); 
  446. $success = wp_parse_args( parse_url( $success_url ), array( 'host' => '', 'path' => '' )); 
  447. $redirect = wp_parse_args( parse_url( $response['redirect'] ), array( 'host' => '', 'path' => '' )); 
  448.  
  449. $offsite = $success['host'] !== $redirect['host']; 
  450. $reload = !$offsite && $success['path'] !== $redirect['path'] && $response['messages'] == ''; 
  451.  
  452. if($offsite || $reload) { 
  453. update_post_meta( $order_id, '_pos_payment_redirect', $response['redirect'] ); 
  454. $message = __('You are now being redirected offsite to complete the payment. ', 'woocommerce-pos'); 
  455. $message .= sprintf( __('<a href="%s">Click here</a> if you are not redirected automatically. ', 'woocommerce-pos'), $response['redirect'] ); 
  456.  
  457. return $message; 
  458.  
  459. /** 
  460. * @param $order_id 
  461. */ 
  462. public function payment_complete( $order_id ) { 
  463.  
  464. // update order status 
  465. $order = new WC_Order( $order_id ); 
  466. if( $order->status == 'processing' ) { 
  467. $message = __('POS Transaction completed.', 'woocommerce-pos'); 
  468. $order->update_status( wc_pos_get_option( 'checkout', 'order_status' ), $message ); 
  469.  
  470.  
  471. /** 
  472. * Add any payment messages to API response 
  473. * Also add subtotal_tax to receipt which is not included for some reason 
  474. * @param array $order_data 
  475. * @param $order 
  476. * @param $fields 
  477. * @param $server 
  478. * @return array 
  479. */ 
  480. public function order_response( $order_data, $order, $fields, $server ) { 
  481.  
  482. // add cashier data 
  483. $cashier_details = isset( $order_data['cashier'] ) ? $order_data['cashier'] : array(); 
  484. $order_data['cashier'] = $this->add_cashier_details( $order, $cashier_details ); 
  485.  
  486. // add pos payment info 
  487. $payment_details = isset( $order_data['payment_details'] ) ? $order_data['payment_details'] : array(); 
  488. $order_data['payment_details'] = $this->add_payment_details( $order, $payment_details ); 
  489.  
  490. // addresses 
  491. // $order_data['billing_address'] = $this->filter_address($order_data['billing_address'], $order); 
  492. // $order_data['shipping_address'] = $this->filter_address($order_data['shipping_address'], $order, 'shipping'); 
  493.  
  494. // allow decimal quantity 
  495. // fixed in WC 2.4+ 
  496. if( version_compare( WC()->version, '2.4', '<' ) && wc_pos_get_option( 'general', 'decimal_qty' ) ) { 
  497. $order_data['line_items'] = $this->filter_qty($order_data['line_items']); 
  498.  
  499. // add subtotal_tax 
  500. $subtotal_tax = 0; 
  501. foreach( $order_data['line_items'] as $item ) { 
  502. if(isset( $item['subtotal_tax'] )) { 
  503. $subtotal_tax += wc_format_decimal( $item['subtotal_tax'] ); 
  504. $order_data['subtotal_tax'] = wc_format_decimal( $subtotal_tax ); 
  505.  
  506. // add shipping tax 
  507. foreach( $order_data['shipping_lines'] as &$item ) { 
  508. if(isset( $item['id'] )) { 
  509. $taxes = wc_get_order_item_meta( $item['id'], 'taxes' ); 
  510. $item['total_tax'] = wc_format_decimal( array_sum($taxes) ); 
  511.  
  512. // compatibility for templates 
  513. foreach( $order_data['fee_lines'] as &$item ) { 
  514. if( !isset($item['name']) && isset($item['title'] ) ) { 
  515. $item['name'] = $item['title']; 
  516.  
  517. // add cart discount tax 
  518. $order_data['cart_discount_tax'] = get_post_meta($order->id, '_cart_discount_tax', true); 
  519.  
  520. // Backwards compatibility for WC legacy API 
  521. $order_data['discount_total'] = $order_data['total_discount']; 
  522.  
  523. return $order_data; 
  524.  
  525. /** 
  526. * @param $order 
  527. * @param array $cashier 
  528. * @return array 
  529. */ 
  530. private function add_cashier_details( $order ) { 
  531. if ( !$cashier_id = get_post_meta( $order->id, '_pos_user', true ) ) { 
  532. return; 
  533. $first_name = get_post_meta( $order->id, '_pos_user_first_name', true ); 
  534. $last_name = get_post_meta( $order->id, '_pos_user_last_name', true ); 
  535. if ( !$first_name && !$last_name && $user_info = get_userdata( $cashier_id ) ) { 
  536. $first_name = $user_info->first_name; 
  537. $last_name = $user_info->last_name; 
  538. $cashier = array( 
  539. 'id' => $cashier_id,  
  540. 'first_name' => $first_name,  
  541. 'last_name' => $last_name 
  542. ); 
  543. return apply_filters( 'woocommerce_pos_order_response_cashier', $cashier, $order ); 
  544.  
  545. /** 
  546. * @param $order 
  547. * @param array $payment 
  548. * @return array 
  549. */ 
  550. private function add_payment_details( $order, array $payment = array() ) { 
  551. $payment['result'] = get_post_meta( $order->id, '_pos_payment_result', true ); 
  552. $payment['message'] = get_post_meta( $order->id, '_pos_payment_message', true ); 
  553. $payment['redirect'] = get_post_meta( $order->id, '_pos_payment_redirect', true ); 
  554. if( isset( $payment['method_id'] ) && $payment['method_id'] == 'pos_cash' ) { 
  555. $payment = WC_POS_Gateways_Cash::payment_details( $payment, $order ); 
  556. return apply_filters( 'woocommerce_pos_order_response_payment_details', $payment, $order ); 
  557.  
  558. /** 
  559. * Adds support for custom address fields 
  560. * @param $address 
  561. * @param $order 
  562. * @param string $type 
  563. * @return array 
  564. */ 
  565. private function filter_address( $address, $order, $type = 'billing' ) { 
  566. $fields = apply_filters('woocommerce_admin_'.$type.'_fields', false); 
  567. if( $fields ) { 
  568. $address = array(); 
  569. foreach($fields as $key => $value) { 
  570. $address[$key] = $order->{$type.'_'.$key}; 
  571. return $address; 
  572.  
  573. /** 
  574. * Get customer details 
  575. * - mirrors woocommerce/includes/class-wc-ajax.php->get_customer_details() 
  576. * @param $user_id 
  577. * @param $type_to_load 
  578. * @return mixed|void 
  579. */ 
  580. private function get_customer_details( $user_id, $type_to_load ) { 
  581. $customer_data = array( 
  582. $type_to_load . '_first_name' => get_user_meta( $user_id, $type_to_load . '_first_name', true ),  
  583. $type_to_load . '_last_name' => get_user_meta( $user_id, $type_to_load . '_last_name', true ),  
  584. $type_to_load . '_company' => get_user_meta( $user_id, $type_to_load . '_company', true ),  
  585. $type_to_load . '_address_1' => get_user_meta( $user_id, $type_to_load . '_address_1', true ),  
  586. $type_to_load . '_address_2' => get_user_meta( $user_id, $type_to_load . '_address_2', true ),  
  587. $type_to_load . '_city' => get_user_meta( $user_id, $type_to_load . '_city', true ),  
  588. $type_to_load . '_postcode' => get_user_meta( $user_id, $type_to_load . '_postcode', true ),  
  589. $type_to_load . '_country' => get_user_meta( $user_id, $type_to_load . '_country', true ),  
  590. $type_to_load . '_state' => get_user_meta( $user_id, $type_to_load . '_state', true ),  
  591. $type_to_load . '_email' => get_user_meta( $user_id, $type_to_load . '_email', true ),  
  592. $type_to_load . '_phone' => get_user_meta( $user_id, $type_to_load . '_phone', true ),  
  593. ); 
  594. $customer_data = apply_filters( 'woocommerce_found_customer_details', $customer_data, $user_id, $type_to_load ); 
  595.  
  596. // remove billing_ or shipping_ prefix for WC REST API 
  597. $data = array(); 
  598. foreach( $customer_data as $key => $value ): if($value): 
  599. $key = str_replace( $type_to_load.'_', '', $key ); 
  600. $data[$key] = $value; 
  601. endif; endforeach; 
  602. return $data; 
  603.  
  604. /** 
  605. * @param $line_items 
  606. * @return mixed 
  607. */ 
  608. private function filter_qty($line_items) { 
  609. foreach( $line_items as &$item ) { 
  610. $qty = wc_get_order_item_meta( $item['id'], '_qty' ); 
  611. $item['quantity'] = wc_stock_amount( $qty ); 
  612. return $line_items; 
  613.  
  614. /** 
  615. * Returns array of all order ids 
  616. * optionally return ids updated_at_min 
  617. * @param $updated_at_min 
  618. * @return array 
  619. */ 
  620. public function get_ids($updated_at_min) { 
  621. $args = array( 
  622. 'post_type' => array('shop_order'),  
  623. 'post_status' => array('any'),  
  624. 'posts_per_page'=> -1,  
  625. 'fields' => 'ids' 
  626. ); 
  627.  
  628. if($updated_at_min) { 
  629. $args['date_query'][] = array( 
  630. 'column' => 'post_modified_gmt',  
  631. 'after' => $updated_at_min,  
  632. 'inclusive' => false 
  633. ); 
  634.  
  635. $query = new WP_Query( $args ); 
  636. return array_map( 'intval', $query->posts ); 
  637.  
  638. /** 
  639. * Delete all order items 
  640. * @param $order_id 
  641. */ 
  642. private function delete_order_items($order_id) { 
  643. global $wpdb; 
  644. $order_item_ids = $wpdb->get_col( $wpdb->prepare( " 
  645. SELECT order_item_id 
  646. FROM {$wpdb->prefix}woocommerce_order_items 
  647. WHERE order_id = %d 
  648. ", $order_id ) ); 
  649.  
  650. foreach($order_item_ids as $item_id) { 
  651. wc_delete_order_item($item_id); 
  652.  
  653. /** 
  654. * WC email notifications 
  655. * @param WC_Emails $wc_emails 
  656. */ 
  657. public function woocommerce_email(WC_Emails $wc_emails) { 
  658.  
  659. if( ! wc_pos_get_option( 'checkout', 'customer_emails' ) ) { 
  660. $this->remove_customer_emails($wc_emails); 
  661.  
  662. if( ! wc_pos_get_option( 'checkout', 'admin_emails' ) ) { 
  663. $this->remove_admin_emails($wc_emails); 
  664.  
  665. /** 
  666. * @param WC_Emails $wc_emails 
  667. */ 
  668. private function remove_customer_emails(WC_Emails $wc_emails) { 
  669. remove_action( 
  670. 'woocommerce_order_status_pending_to_processing_notification',  
  671. array( 
  672. $wc_emails->emails['WC_Email_Customer_Processing_Order'],  
  673. 'trigger' 
  674. ); 
  675. remove_action( 
  676. 'woocommerce_order_status_pending_to_on-hold_notification',  
  677. array( 
  678. $wc_emails->emails['WC_Email_Customer_Processing_Order'],  
  679. 'trigger' 
  680. ); 
  681. remove_action( 
  682. 'woocommerce_order_status_completed_notification',  
  683. array( 
  684. $wc_emails->emails['WC_Email_Customer_Completed_Order'],  
  685. 'trigger' 
  686. ); 
  687.  
  688. /** 
  689. * @param WC_Emails $wc_emails 
  690. */ 
  691. private function remove_admin_emails(WC_Emails $wc_emails) { 
  692. // send 'woocommerce_low_stock_notification' 
  693. // send 'woocommerce_no_stock_notification' 
  694. // send 'woocommerce_product_on_backorder_notification' 
  695. remove_action( 
  696. 'woocommerce_order_status_pending_to_processing_notification',  
  697. array( 
  698. $wc_emails->emails['WC_Email_New_Order'],  
  699. 'trigger' 
  700. ); 
  701. remove_action( 
  702. 'woocommerce_order_status_pending_to_completed_notification',  
  703. array( 
  704. $wc_emails->emails['WC_Email_New_Order'],  
  705. 'trigger' 
  706. ); 
  707. remove_action( 
  708. 'woocommerce_order_status_pending_to_on-hold_notification',  
  709. array( 
  710. $wc_emails->emails['WC_Email_New_Order'],  
  711. 'trigger' 
  712. ); 
  713. remove_action( 
  714. 'woocommerce_order_status_failed_to_processing_notification',  
  715. array( 
  716. $wc_emails->emails['WC_Email_New_Order'],  
  717. 'trigger' 
  718. ); 
  719. remove_action( 
  720. 'woocommerce_order_status_failed_to_completed_notification',  
  721. array( 
  722. $wc_emails->emails['WC_Email_New_Order'],  
  723. 'trigger' 
  724. ); 
  725. remove_action( 
  726. 'woocommerce_order_status_failed_to_on-hold_notification',  
  727. array( 
  728. $wc_emails->emails['WC_Email_New_Order'],  
  729. 'trigger' 
  730. ); 
  731.  
  732.