WC_Order

Order Class.

Defined (1)

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

/includes/class-wc-order.php  
  1. class WC_Order extends WC_Abstract_Order { 
  2.  
  3. /** 
  4. * Stores data about status changes so relevant hooks can be fired. 
  5. * @var bool|array 
  6. */ 
  7. protected $status_transition = false; 
  8.  
  9. /** 
  10. * Order Data array. This is the core order data exposed in APIs since 3.0.0. 
  11. * @since 3.0.0 
  12. * @var array 
  13. */ 
  14. protected $data = array( 
  15. // Abstract order props 
  16. 'parent_id' => 0,  
  17. 'status' => '',  
  18. 'currency' => '',  
  19. 'version' => '',  
  20. 'prices_include_tax' => false,  
  21. 'date_created' => null,  
  22. 'date_modified' => null,  
  23. 'discount_total' => 0,  
  24. 'discount_tax' => 0,  
  25. 'shipping_total' => 0,  
  26. 'shipping_tax' => 0,  
  27. 'cart_tax' => 0,  
  28. 'total' => 0,  
  29. 'total_tax' => 0,  
  30.  
  31. // Order props 
  32. 'customer_id' => 0,  
  33. 'order_key' => '',  
  34. 'billing' => array( 
  35. 'first_name' => '',  
  36. 'last_name' => '',  
  37. 'company' => '',  
  38. 'address_1' => '',  
  39. 'address_2' => '',  
  40. 'city' => '',  
  41. 'state' => '',  
  42. 'postcode' => '',  
  43. 'country' => '',  
  44. 'email' => '',  
  45. 'phone' => '',  
  46. ),  
  47. 'shipping' => array( 
  48. 'first_name' => '',  
  49. 'last_name' => '',  
  50. 'company' => '',  
  51. 'address_1' => '',  
  52. 'address_2' => '',  
  53. 'city' => '',  
  54. 'state' => '',  
  55. 'postcode' => '',  
  56. 'country' => '',  
  57. ),  
  58. 'payment_method' => '',  
  59. 'payment_method_title' => '',  
  60. 'transaction_id' => '',  
  61. 'customer_ip_address' => '',  
  62. 'customer_user_agent' => '',  
  63. 'created_via' => '',  
  64. 'customer_note' => '',  
  65. 'date_completed' => null,  
  66. 'date_paid' => null,  
  67. 'cart_hash' => '',  
  68. ); 
  69.  
  70. /** 
  71. * When a payment is complete this function is called. 
  72. * Most of the time this should mark an order as 'processing' so that admin can process/post the items. 
  73. * If the cart contains only downloadable items then the order is 'completed' since the admin needs to take no action. 
  74. * Stock levels are reduced at this point. 
  75. * Sales are also recorded for products. 
  76. * Finally, record the date of payment. 
  77. * Order must exist. 
  78. * @param string $transaction_id Optional transaction id to store in post meta. 
  79. * @return bool success 
  80. */ 
  81. public function payment_complete( $transaction_id = '' ) { 
  82. try { 
  83. if ( ! $this->get_id() ) { 
  84. return false; 
  85. do_action( 'woocommerce_pre_payment_complete', $this->get_id() ); 
  86.  
  87. if ( ! empty( WC()->session ) ) { 
  88. WC()->session->set( 'order_awaiting_payment', false ); 
  89.  
  90. if ( $this->has_status( apply_filters( 'woocommerce_valid_order_statuses_for_payment_complete', array( 'on-hold', 'pending', 'failed', 'cancelled' ), $this ) ) ) { 
  91. if ( ! empty( $transaction_id ) ) { 
  92. $this->set_transaction_id( $transaction_id ); 
  93. if ( ! $this->get_date_paid( 'edit' ) ) { 
  94. $this->set_date_paid( current_time( 'timestamp', true ) ); 
  95. $this->set_status( apply_filters( 'woocommerce_payment_complete_order_status', $this->needs_processing() ? 'processing' : 'completed', $this->get_id(), $this ) ); 
  96. $this->save(); 
  97.  
  98. do_action( 'woocommerce_payment_complete', $this->get_id() ); 
  99. } else { 
  100. do_action( 'woocommerce_payment_complete_order_status_' . $this->get_status(), $this->get_id() ); 
  101. } catch ( Exception $e ) { 
  102. return false; 
  103. return true; 
  104.  
  105. /** 
  106. * Gets order total - formatted for display. 
  107. * @param string $tax_display Type of tax display. 
  108. * @param bool $display_refunded If should include refunded value. 
  109. * @return string 
  110. */ 
  111. public function get_formatted_order_total( $tax_display = '', $display_refunded = true ) { 
  112. $formatted_total = wc_price( $this->get_total(), array( 'currency' => $this->get_currency() ) ); 
  113. $order_total = $this->get_total(); 
  114. $total_refunded = $this->get_total_refunded(); 
  115. $tax_string = ''; 
  116.  
  117. // Tax for inclusive prices. 
  118. if ( wc_tax_enabled() && 'incl' == $tax_display ) { 
  119. $tax_string_array = array(); 
  120.  
  121. if ( 'itemized' == get_option( 'woocommerce_tax_total_display' ) ) { 
  122. foreach ( $this->get_tax_totals() as $code => $tax ) { 
  123. $tax_amount = ( $total_refunded && $display_refunded ) ? wc_price( WC_Tax::round( $tax->amount - $this->get_total_tax_refunded_by_rate_id( $tax->rate_id ) ), array( 'currency' => $this->get_currency() ) ) : $tax->formatted_amount; 
  124. $tax_string_array[] = sprintf( '%s %s', $tax_amount, $tax->label ); 
  125. } else { 
  126. $tax_amount = ( $total_refunded && $display_refunded ) ? $this->get_total_tax() - $this->get_total_tax_refunded() : $this->get_total_tax(); 
  127. $tax_string_array[] = sprintf( '%s %s', wc_price( $tax_amount, array( 'currency' => $this->get_currency() ) ), WC()->countries->tax_or_vat() ); 
  128. if ( ! empty( $tax_string_array ) ) { 
  129. $tax_string = ' <small class="includes_tax">' . sprintf( __( '(includes %s)', 'woocommerce' ), implode( ', ', $tax_string_array ) ) . '</small>'; 
  130.  
  131. if ( $total_refunded && $display_refunded ) { 
  132. $formatted_total = '<del>' . strip_tags( $formatted_total ) . '</del> <ins>' . wc_price( $order_total - $total_refunded, array( 'currency' => $this->get_currency() ) ) . $tax_string . '</ins>'; 
  133. } else { 
  134. $formatted_total .= $tax_string; 
  135.  
  136. /** 
  137. * Filter WooCommerce formatted order total. 
  138. * @param string $formatted_total Total to display. 
  139. * @param WC_Order $order Order data. 
  140. * @param string $tax_display Type of tax display. 
  141. * @param bool $display_refunded If should include refunded value. 
  142. */ 
  143. return apply_filters( 'woocommerce_get_formatted_order_total', $formatted_total, $this, $tax_display, $display_refunded ); 
  144.  
  145. /** 
  146. |-------------------------------------------------------------------------- 
  147. | CRUD methods 
  148. |-------------------------------------------------------------------------- 
  149. | Methods which create, read, update and delete orders from the database. 
  150. | Written in abstract fashion so that the way orders are stored can be 
  151. | changed more easily in the future. 
  152. | A save method is included for convenience (chooses update or create based 
  153. | on if the order exists yet). 
  154. */ 
  155.  
  156. /** 
  157. * Save data to the database. 
  158. * @since 3.0.0 
  159. * @return int order ID 
  160. */ 
  161. public function save() { 
  162. $this->maybe_set_user_billing_email(); 
  163. if ( $this->data_store ) { 
  164. // Trigger action before saving to the DB. Allows you to adjust object props before save. 
  165. do_action( 'woocommerce_before_' . $this->object_type . '_object_save', $this, $this->data_store ); 
  166.  
  167. if ( $this->get_id() ) { 
  168. $this->data_store->update( $this ); 
  169. } else { 
  170. $this->data_store->create( $this ); 
  171. $this->save_items(); 
  172. $this->status_transition(); 
  173. return $this->get_id(); 
  174.  
  175. /** 
  176. * Set order status. 
  177. * @since 3.0.0 
  178. * @param string $new_status Status to change the order to. No internal wc- prefix is required. 
  179. * @param string $note (default: '') Optional note to add. 
  180. * @param bool $manual_update is this a manual order status change? 
  181. * @param array details of change 
  182. */ 
  183. public function set_status( $new_status, $note = '', $manual_update = false ) { 
  184. $result = parent::set_status( $new_status ); 
  185.  
  186. if ( true === $this->object_read && ! empty( $result['from'] ) && $result['from'] !== $result['to'] ) { 
  187. $this->status_transition = array( 
  188. 'from' => ! empty( $this->status_transition['from'] ) ? $this->status_transition['from'] : $result['from'],  
  189. 'to' => $result['to'],  
  190. 'note' => $note,  
  191. 'manual' => (bool) $manual_update,  
  192. ); 
  193.  
  194. $this->maybe_set_date_paid(); 
  195. $this->maybe_set_date_completed(); 
  196.  
  197. return $result; 
  198.  
  199. /** 
  200. * Maybe set date paid. 
  201. * Sets the date paid variable when transitioning to the payment complete 
  202. * order status. This is either processing or completed. This is not filtered 
  203. * to avoid infinite loops e.g. if loading an order via the filter. 
  204. * Date paid is set once in this manner - only when it is not already set. 
  205. * This ensures the data exists even if a gateway does not use the 
  206. * `payment_complete` method. 
  207. * @since 3.0.0 
  208. */ 
  209. public function maybe_set_date_paid() { 
  210. if ( ! $this->get_date_paid( 'edit' ) && $this->has_status( apply_filters( 'woocommerce_payment_complete_order_status', $this->needs_processing() ? 'processing' : 'completed', $this->get_id(), $this ) ) ) { 
  211. $this->set_date_paid( current_time( 'timestamp' ) ); 
  212.  
  213. /** 
  214. * Maybe set date completed. 
  215. * Sets the date completed variable when transitioning to completed status. 
  216. * @since 3.0.0 
  217. */ 
  218. protected function maybe_set_date_completed() { 
  219. if ( $this->has_status( 'completed' ) ) { 
  220. $this->set_date_completed( current_time( 'timestamp', true ) ); 
  221.  
  222. /** 
  223. * Updates status of order immediately. Order must exist. 
  224. * @uses WC_Order::set_status() 
  225. * @return bool success 
  226. */ 
  227. public function update_status( $new_status, $note = '', $manual = false ) { 
  228. try { 
  229. if ( ! $this->get_id() ) { 
  230. return false; 
  231. $this->set_status( $new_status, $note, $manual ); 
  232. $this->save(); 
  233. } catch ( Exception $e ) { 
  234. return false; 
  235. return true; 
  236.  
  237. /** 
  238. * Handle the status transition. 
  239. */ 
  240. protected function status_transition() { 
  241. if ( $this->status_transition ) { 
  242. do_action( 'woocommerce_order_status_' . $this->status_transition['to'], $this->get_id(), $this ); 
  243.  
  244. if ( ! empty( $this->status_transition['from'] ) ) { 
  245. /** translators: 1: old order status 2: new order status */ 
  246. $transition_note = sprintf( __( 'Order status changed from %1$s to %2$s.', 'woocommerce' ), wc_get_order_status_name( $this->status_transition['from'] ), wc_get_order_status_name( $this->status_transition['to'] ) ); 
  247.  
  248. do_action( 'woocommerce_order_status_' . $this->status_transition['from'] . '_to_' . $this->status_transition['to'], $this->get_id(), $this ); 
  249. do_action( 'woocommerce_order_status_changed', $this->get_id(), $this->status_transition['from'], $this->status_transition['to'], $this ); 
  250. } else { 
  251. /** translators: %s: new order status */ 
  252. $transition_note = sprintf( __( 'Order status set to %s.', 'woocommerce' ), wc_get_order_status_name( $this->status_transition['to'] ) ); 
  253.  
  254. // Note the transition occurred 
  255. $this->add_order_note( trim( $this->status_transition['note'] . ' ' . $transition_note ), 0, $this->status_transition['manual'] ); 
  256.  
  257. // This has ran, so reset status transition variable 
  258. $this->status_transition = false; 
  259.  
  260. /** 
  261. |-------------------------------------------------------------------------- 
  262. | Getters 
  263. |-------------------------------------------------------------------------- 
  264. | Methods for getting data from the order object. 
  265. */ 
  266.  
  267. /** 
  268. * Get all class data in array format. 
  269. * @since 3.0.0 
  270. * @return array 
  271. */ 
  272. public function get_data() { 
  273. return array_merge( 
  274. array( 
  275. 'id' => $this->get_id(),  
  276. ),  
  277. $this->data,  
  278. array( 
  279. 'number' => $this->get_order_number(),  
  280. 'meta_data' => $this->get_meta_data(),  
  281. 'line_items' => $this->get_items( 'line_item' ),  
  282. 'tax_lines' => $this->get_items( 'tax' ),  
  283. 'shipping_lines' => $this->get_items( 'shipping' ),  
  284. 'fee_lines' => $this->get_items( 'fee' ),  
  285. 'coupon_lines' => $this->get_items( 'coupon' ),  
  286. ); 
  287.  
  288. /** 
  289. * Expands the shipping and billing information in the changes array. 
  290. */ 
  291. public function get_changes() { 
  292. $changed_props = parent::get_changes(); 
  293. $subs = array( 'shipping', 'billing' ); 
  294. foreach ( $subs as $sub ) { 
  295. if ( ! empty( $changed_props[ $sub ] ) ) { 
  296. foreach ( $changed_props[ $sub ] as $sub_prop => $value ) { 
  297. $changed_props[ $sub . '_' . $sub_prop ] = $value; 
  298. if ( isset( $changed_props['customer_note'] ) ) { 
  299. $changed_props['post_excerpt'] = $changed_props['customer_note']; 
  300. return $changed_props; 
  301.  
  302. /** 
  303. * get_order_number function. 
  304. * Gets the order number for display (by default, order ID). 
  305. * @return string 
  306. */ 
  307. public function get_order_number() { 
  308. return (string) apply_filters( 'woocommerce_order_number', $this->get_id(), $this ); 
  309.  
  310. /** 
  311. * Get order key. 
  312. * @since 3.0.0 
  313. * @param string $context 
  314. * @return string 
  315. */ 
  316. public function get_order_key( $context = 'view' ) { 
  317. return $this->get_prop( 'order_key', $context ); 
  318.  
  319. /** 
  320. * Get customer_id. 
  321. * @param string $context 
  322. * @return int 
  323. */ 
  324. public function get_customer_id( $context = 'view' ) { 
  325. return $this->get_prop( 'customer_id', $context ); 
  326.  
  327. /** 
  328. * Alias for get_customer_id(). 
  329. * @param string $context 
  330. * @return int 
  331. */ 
  332. public function get_user_id( $context = 'view' ) { 
  333. return $this->get_customer_id( $context ); 
  334.  
  335. /** 
  336. * Get the user associated with the order. False for guests. 
  337. * @return WP_User|false 
  338. */ 
  339. public function get_user() { 
  340. return $this->get_user_id() ? get_user_by( 'id', $this->get_user_id() ) : false; 
  341.  
  342. /** 
  343. * Gets a prop for a getter method. 
  344. * @since 3.0.0 
  345. * @param string $prop Name of prop to get. 
  346. * @param string $address billing or shipping. 
  347. * @param string $context What the value is for. Valid values are view and edit. 
  348. * @return mixed 
  349. */ 
  350. protected function get_address_prop( $prop, $address = 'billing', $context = 'view' ) { 
  351. $value = null; 
  352.  
  353. if ( array_key_exists( $prop, $this->data[ $address ] ) ) { 
  354. $value = isset( $this->changes[ $address ][ $prop ] ) ? $this->changes[ $address ][ $prop ] : $this->data[ $address ][ $prop ]; 
  355.  
  356. if ( 'view' === $context ) { 
  357. $value = apply_filters( $this->get_hook_prefix() . $address . '_' . $prop, $value, $this ); 
  358. return $value; 
  359.  
  360. /** 
  361. * Get billing_first_name. 
  362. * @param string $context 
  363. * @return string 
  364. */ 
  365. public function get_billing_first_name( $context = 'view' ) { 
  366. return $this->get_address_prop( 'first_name', 'billing', $context ); 
  367.  
  368. /** 
  369. * Get billing_last_name. 
  370. * @param string $context 
  371. * @return string 
  372. */ 
  373. public function get_billing_last_name( $context = 'view' ) { 
  374. return $this->get_address_prop( 'last_name', 'billing', $context ); 
  375.  
  376. /** 
  377. * Get billing_company. 
  378. * @param string $context 
  379. * @return string 
  380. */ 
  381. public function get_billing_company( $context = 'view' ) { 
  382. return $this->get_address_prop( 'company', 'billing', $context ); 
  383.  
  384. /** 
  385. * Get billing_address_1. 
  386. * @param string $context 
  387. * @return string 
  388. */ 
  389. public function get_billing_address_1( $context = 'view' ) { 
  390. return $this->get_address_prop( 'address_1', 'billing', $context ); 
  391.  
  392. /** 
  393. * Get billing_address_2. 
  394. * @param string $context 
  395. * @return string $value 
  396. */ 
  397. public function get_billing_address_2( $context = 'view' ) { 
  398. return $this->get_address_prop( 'address_2', 'billing', $context ); 
  399.  
  400. /** 
  401. * Get billing_city. 
  402. * @param string $context 
  403. * @return string $value 
  404. */ 
  405. public function get_billing_city( $context = 'view' ) { 
  406. return $this->get_address_prop( 'city', 'billing', $context ); 
  407.  
  408. /** 
  409. * Get billing_state. 
  410. * @param string $context 
  411. * @return string 
  412. */ 
  413. public function get_billing_state( $context = 'view' ) { 
  414. return $this->get_address_prop( 'state', 'billing', $context ); 
  415.  
  416. /** 
  417. * Get billing_postcode. 
  418. * @param string $context 
  419. * @return string 
  420. */ 
  421. public function get_billing_postcode( $context = 'view' ) { 
  422. return $this->get_address_prop( 'postcode', 'billing', $context ); 
  423.  
  424. /** 
  425. * Get billing_country. 
  426. * @param string $context 
  427. * @return string 
  428. */ 
  429. public function get_billing_country( $context = 'view' ) { 
  430. return $this->get_address_prop( 'country', 'billing', $context ); 
  431.  
  432. /** 
  433. * Get billing_email. 
  434. * @param string $context 
  435. * @return string 
  436. */ 
  437. public function get_billing_email( $context = 'view' ) { 
  438. return $this->get_address_prop( 'email', 'billing', $context ); 
  439.  
  440. /** 
  441. * Get billing_phone. 
  442. * @param string $context 
  443. * @return string 
  444. */ 
  445. public function get_billing_phone( $context = 'view' ) { 
  446. return $this->get_address_prop( 'phone', 'billing', $context ); 
  447.  
  448. /** 
  449. * Get shipping_first_name. 
  450. * @param string $context 
  451. * @return string 
  452. */ 
  453. public function get_shipping_first_name( $context = 'view' ) { 
  454. return $this->get_address_prop( 'first_name', 'shipping', $context ); 
  455.  
  456. /** 
  457. * Get shipping_last_name. 
  458. * @param string $context 
  459. * @return string 
  460. */ 
  461. public function get_shipping_last_name( $context = 'view' ) { 
  462. return $this->get_address_prop( 'last_name', 'shipping', $context ); 
  463.  
  464. /** 
  465. * Get shipping_company. 
  466. * @param string $context 
  467. * @return string 
  468. */ 
  469. public function get_shipping_company( $context = 'view' ) { 
  470. return $this->get_address_prop( 'company', 'shipping', $context ); 
  471.  
  472. /** 
  473. * Get shipping_address_1. 
  474. * @param string $context 
  475. * @return string 
  476. */ 
  477. public function get_shipping_address_1( $context = 'view' ) { 
  478. return $this->get_address_prop( 'address_1', 'shipping', $context ); 
  479.  
  480. /** 
  481. * Get shipping_address_2. 
  482. * @param string $context 
  483. * @return string 
  484. */ 
  485. public function get_shipping_address_2( $context = 'view' ) { 
  486. return $this->get_address_prop( 'address_2', 'shipping', $context ); 
  487.  
  488. /** 
  489. * Get shipping_city. 
  490. * @param string $context 
  491. * @return string 
  492. */ 
  493. public function get_shipping_city( $context = 'view' ) { 
  494. return $this->get_address_prop( 'city', 'shipping', $context ); 
  495.  
  496. /** 
  497. * Get shipping_state. 
  498. * @param string $context 
  499. * @return string 
  500. */ 
  501. public function get_shipping_state( $context = 'view' ) { 
  502. return $this->get_address_prop( 'state', 'shipping', $context ); 
  503.  
  504. /** 
  505. * Get shipping_postcode. 
  506. * @param string $context 
  507. * @return string 
  508. */ 
  509. public function get_shipping_postcode( $context = 'view' ) { 
  510. return $this->get_address_prop( 'postcode', 'shipping', $context ); 
  511.  
  512. /** 
  513. * Get shipping_country. 
  514. * @param string $context 
  515. * @return string 
  516. */ 
  517. public function get_shipping_country( $context = 'view' ) { 
  518. return $this->get_address_prop( 'country', 'shipping', $context ); 
  519.  
  520. /** 
  521. * Get the payment method. 
  522. * @param string $context 
  523. * @return string 
  524. */ 
  525. public function get_payment_method( $context = 'view' ) { 
  526. return $this->get_prop( 'payment_method', $context ); 
  527.  
  528. /** 
  529. * Get payment_method_title. 
  530. * @param string $context 
  531. * @return string 
  532. */ 
  533. public function get_payment_method_title( $context = 'view' ) { 
  534. return $this->get_prop( 'payment_method_title', $context ); 
  535.  
  536. /** 
  537. * Get transaction_id. 
  538. * @param string $context 
  539. * @return string 
  540. */ 
  541. public function get_transaction_id( $context = 'view' ) { 
  542. return $this->get_prop( 'transaction_id', $context ); 
  543.  
  544. /** 
  545. * Get customer_ip_address. 
  546. * @param string $context 
  547. * @return string 
  548. */ 
  549. public function get_customer_ip_address( $context = 'view' ) { 
  550. return $this->get_prop( 'customer_ip_address', $context ); 
  551.  
  552. /** 
  553. * Get customer_user_agent. 
  554. * @param string $context 
  555. * @return string 
  556. */ 
  557. public function get_customer_user_agent( $context = 'view' ) { 
  558. return $this->get_prop( 'customer_user_agent', $context ); 
  559.  
  560. /** 
  561. * Get created_via. 
  562. * @param string $context 
  563. * @return string 
  564. */ 
  565. public function get_created_via( $context = 'view' ) { 
  566. return $this->get_prop( 'created_via', $context ); 
  567.  
  568. /** 
  569. * Get customer_note. 
  570. * @param string $context 
  571. * @return string 
  572. */ 
  573. public function get_customer_note( $context = 'view' ) { 
  574. return $this->get_prop( 'customer_note', $context ); 
  575.  
  576. /** 
  577. * Get date_completed. 
  578. * @param string $context 
  579. * @return WC_DateTime|NULL object if the date is set or null if there is no date. 
  580. */ 
  581. public function get_date_completed( $context = 'view' ) { 
  582. return $this->get_prop( 'date_completed', $context ); 
  583.  
  584. /** 
  585. * Get date_paid. 
  586. * @param string $context 
  587. * @return WC_DateTime|NULL object if the date is set or null if there is no date. 
  588. */ 
  589. public function get_date_paid( $context = 'view' ) { 
  590. $date_paid = $this->get_prop( 'date_paid', $context ); 
  591.  
  592. if ( 'view' === $context && ! $date_paid && version_compare( $this->get_version( 'edit' ), '3.0', '<' ) && $this->has_status( apply_filters( 'woocommerce_payment_complete_order_status', $this->needs_processing() ? 'processing' : 'completed', $this->get_id(), $this ) ) ) { 
  593. // In view context, return a date if missing. 
  594. $date_paid = $this->get_date_created( 'edit' ); 
  595. return $date_paid; 
  596.  
  597. /** 
  598. * Get cart hash. 
  599. * @param string $context 
  600. * @return string 
  601. */ 
  602. public function get_cart_hash( $context = 'view' ) { 
  603. return $this->get_prop( 'cart_hash', $context ); 
  604.  
  605. /** 
  606. * Returns the requested address in raw, non-formatted way. 
  607. * Note: Merges raw data with get_prop data so changes are returned too. 
  608. * @since 2.4.0 
  609. * @param string $type Billing or shipping. Anything else besides 'billing' will return shipping address. 
  610. * @return array The stored address after filter. 
  611. */ 
  612. public function get_address( $type = 'billing' ) { 
  613. return apply_filters( 'woocommerce_get_order_address', array_merge( $this->data[ $type ], $this->get_prop( $type, 'view' ) ), $type, $this ); 
  614.  
  615. /** 
  616. * Get a formatted shipping address for the order. 
  617. * @return string 
  618. */ 
  619. public function get_shipping_address_map_url() { 
  620. $address = $this->get_address( 'shipping' ); 
  621.  
  622. // Remove name and company before generate the Google Maps URL. 
  623. unset( $address['first_name'], $address['last_name'], $address['company'] ); 
  624.  
  625. $address = apply_filters( 'woocommerce_shipping_address_map_url_parts', $address, $this ); 
  626.  
  627. return apply_filters( 'woocommerce_shipping_address_map_url', 'https://maps.google.com/maps?&q=' . urlencode( implode( ', ', $address ) ) . '&z=16', $this ); 
  628.  
  629. /** 
  630. * Get a formatted billing full name. 
  631. * @return string 
  632. */ 
  633. public function get_formatted_billing_full_name() { 
  634. /** translators: 1: first name 2: last name */ 
  635. return sprintf( _x( '%1$s %2$s', 'full name', 'woocommerce' ), $this->get_billing_first_name(), $this->get_billing_last_name() ); 
  636.  
  637. /** 
  638. * Get a formatted shipping full name. 
  639. * @return string 
  640. */ 
  641. public function get_formatted_shipping_full_name() { 
  642. /** translators: 1: first name 2: last name */ 
  643. return sprintf( _x( '%1$s %2$s', 'full name', 'woocommerce' ), $this->get_shipping_first_name(), $this->get_shipping_last_name() ); 
  644.  
  645. /** 
  646. * Get a formatted billing address for the order. 
  647. * @return string 
  648. */ 
  649. public function get_formatted_billing_address() { 
  650. return WC()->countries->get_formatted_address( apply_filters( 'woocommerce_order_formatted_billing_address', $this->get_address( 'billing' ), $this ) ); 
  651.  
  652. /** 
  653. * Get a formatted shipping address for the order. 
  654. * @return string 
  655. */ 
  656. public function get_formatted_shipping_address() { 
  657. if ( $this->has_shipping_address() ) { 
  658. return WC()->countries->get_formatted_address( apply_filters( 'woocommerce_order_formatted_shipping_address', $this->get_address( 'shipping' ), $this ) ); 
  659. } else { 
  660. return ''; 
  661.  
  662. /** 
  663. * Returns true if the order has a shipping address. 
  664. * @since 3.0.4 
  665. * @return boolean 
  666. */ 
  667. public function has_shipping_address() { 
  668. return $this->get_shipping_address_1() || $this->get_shipping_address_2(); 
  669.  
  670. /** 
  671. |-------------------------------------------------------------------------- 
  672. | Setters 
  673. |-------------------------------------------------------------------------- 
  674. | Functions for setting order data. These should not update anything in the 
  675. | database itself and should only change what is stored in the class 
  676. | object. However, for backwards compatibility pre 3.0.0 some of these 
  677. | setters may handle both. 
  678. */ 
  679.  
  680. /** 
  681. * Sets a prop for a setter method. 
  682. * @since 3.0.0 
  683. * @param string $prop Name of prop to set. 
  684. * @param string $address Name of address to set. billing or shipping. 
  685. * @param mixed $value Value of the prop. 
  686. */ 
  687. protected function set_address_prop( $prop, $address = 'billing', $value ) { 
  688. if ( array_key_exists( $prop, $this->data[ $address ] ) ) { 
  689. if ( true === $this->object_read ) { 
  690. if ( $value !== $this->data[ $address ][ $prop ] || ( isset( $this->changes[ $address ] ) && array_key_exists( $prop, $this->changes[ $address ] ) ) ) { 
  691. $this->changes[ $address ][ $prop ] = $value; 
  692. } else { 
  693. $this->data[ $address ][ $prop ] = $value; 
  694.  
  695. /** 
  696. * Set order_key. 
  697. * @param string $value Max length 22 chars. 
  698. * @throws WC_Data_Exception 
  699. */ 
  700. public function set_order_key( $value ) { 
  701. $this->set_prop( 'order_key', substr( $value, 0, 22 ) ); 
  702.  
  703. /** 
  704. * Set customer_id. 
  705. * @param int $value 
  706. * @throws WC_Data_Exception 
  707. */ 
  708. public function set_customer_id( $value ) { 
  709. $this->set_prop( 'customer_id', absint( $value ) ); 
  710.  
  711. /** 
  712. * Set billing_first_name. 
  713. * @param string $value 
  714. * @throws WC_Data_Exception 
  715. */ 
  716. public function set_billing_first_name( $value ) { 
  717. $this->set_address_prop( 'first_name', 'billing', $value ); 
  718.  
  719. /** 
  720. * Set billing_last_name. 
  721. * @param string $value 
  722. * @throws WC_Data_Exception 
  723. */ 
  724. public function set_billing_last_name( $value ) { 
  725. $this->set_address_prop( 'last_name', 'billing', $value ); 
  726.  
  727. /** 
  728. * Set billing_company. 
  729. * @param string $value 
  730. * @throws WC_Data_Exception 
  731. */ 
  732. public function set_billing_company( $value ) { 
  733. $this->set_address_prop( 'company', 'billing', $value ); 
  734.  
  735. /** 
  736. * Set billing_address_1. 
  737. * @param string $value 
  738. * @throws WC_Data_Exception 
  739. */ 
  740. public function set_billing_address_1( $value ) { 
  741. $this->set_address_prop( 'address_1', 'billing', $value ); 
  742.  
  743. /** 
  744. * Set billing_address_2. 
  745. * @param string $value 
  746. * @throws WC_Data_Exception 
  747. */ 
  748. public function set_billing_address_2( $value ) { 
  749. $this->set_address_prop( 'address_2', 'billing', $value ); 
  750.  
  751. /** 
  752. * Set billing_city. 
  753. * @param string $value 
  754. * @throws WC_Data_Exception 
  755. */ 
  756. public function set_billing_city( $value ) { 
  757. $this->set_address_prop( 'city', 'billing', $value ); 
  758.  
  759. /** 
  760. * Set billing_state. 
  761. * @param string $value 
  762. * @throws WC_Data_Exception 
  763. */ 
  764. public function set_billing_state( $value ) { 
  765. $this->set_address_prop( 'state', 'billing', $value ); 
  766.  
  767. /** 
  768. * Set billing_postcode. 
  769. * @param string $value 
  770. * @throws WC_Data_Exception 
  771. */ 
  772. public function set_billing_postcode( $value ) { 
  773. $this->set_address_prop( 'postcode', 'billing', $value ); 
  774.  
  775. /** 
  776. * Set billing_country. 
  777. * @param string $value 
  778. * @throws WC_Data_Exception 
  779. */ 
  780. public function set_billing_country( $value ) { 
  781. $this->set_address_prop( 'country', 'billing', $value ); 
  782.  
  783. /** 
  784. * Maybe set empty billing email to that of the user who owns the order. 
  785. */ 
  786. protected function maybe_set_user_billing_email() { 
  787. if ( ! $this->get_billing_email() && ( $user = $this->get_user() ) ) { 
  788. try { 
  789. $this->set_billing_email( $user->user_email ); 
  790. } catch( WC_Data_Exception $e ) { 
  791. unset( $e ); 
  792.  
  793. /** 
  794. * Set billing_email. 
  795. * @param string $value 
  796. * @throws WC_Data_Exception 
  797. */ 
  798. public function set_billing_email( $value ) { 
  799. if ( $value && ! is_email( $value ) ) { 
  800. $this->error( 'order_invalid_billing_email', __( 'Invalid billing email address', 'woocommerce' ) ); 
  801. $this->set_address_prop( 'email', 'billing', sanitize_email( $value ) ); 
  802.  
  803. /** 
  804. * Set billing_phone. 
  805. * @param string $value 
  806. * @throws WC_Data_Exception 
  807. */ 
  808. public function set_billing_phone( $value ) { 
  809. $this->set_address_prop( 'phone', 'billing', $value ); 
  810.  
  811. /** 
  812. * Set shipping_first_name. 
  813. * @param string $value 
  814. * @throws WC_Data_Exception 
  815. */ 
  816. public function set_shipping_first_name( $value ) { 
  817. $this->set_address_prop( 'first_name', 'shipping', $value ); 
  818.  
  819. /** 
  820. * Set shipping_last_name. 
  821. * @param string $value 
  822. * @throws WC_Data_Exception 
  823. */ 
  824. public function set_shipping_last_name( $value ) { 
  825. $this->set_address_prop( 'last_name', 'shipping', $value ); 
  826.  
  827. /** 
  828. * Set shipping_company. 
  829. * @param string $value 
  830. * @throws WC_Data_Exception 
  831. */ 
  832. public function set_shipping_company( $value ) { 
  833. $this->set_address_prop( 'company', 'shipping', $value ); 
  834.  
  835. /** 
  836. * Set shipping_address_1. 
  837. * @param string $value 
  838. * @throws WC_Data_Exception 
  839. */ 
  840. public function set_shipping_address_1( $value ) { 
  841. $this->set_address_prop( 'address_1', 'shipping', $value ); 
  842.  
  843. /** 
  844. * Set shipping_address_2. 
  845. * @param string $value 
  846. * @throws WC_Data_Exception 
  847. */ 
  848. public function set_shipping_address_2( $value ) { 
  849. $this->set_address_prop( 'address_2', 'shipping', $value ); 
  850.  
  851. /** 
  852. * Set shipping_city. 
  853. * @param string $value 
  854. * @throws WC_Data_Exception 
  855. */ 
  856. public function set_shipping_city( $value ) { 
  857. $this->set_address_prop( 'city', 'shipping', $value ); 
  858.  
  859. /** 
  860. * Set shipping_state. 
  861. * @param string $value 
  862. * @throws WC_Data_Exception 
  863. */ 
  864. public function set_shipping_state( $value ) { 
  865. $this->set_address_prop( 'state', 'shipping', $value ); 
  866.  
  867. /** 
  868. * Set shipping_postcode. 
  869. * @param string $value 
  870. * @throws WC_Data_Exception 
  871. */ 
  872. public function set_shipping_postcode( $value ) { 
  873. $this->set_address_prop( 'postcode', 'shipping', $value ); 
  874.  
  875. /** 
  876. * Set shipping_country. 
  877. * @param string $value 
  878. * @throws WC_Data_Exception 
  879. */ 
  880. public function set_shipping_country( $value ) { 
  881. $this->set_address_prop( 'country', 'shipping', $value ); 
  882.  
  883. /** 
  884. * Set the payment method. 
  885. * @param string $payment_method Supports WC_Payment_Gateway for bw compatibility with < 3.0 
  886. * @throws WC_Data_Exception 
  887. */ 
  888. public function set_payment_method( $payment_method = '' ) { 
  889. if ( is_object( $payment_method ) ) { 
  890. $this->set_payment_method( $payment_method->id ); 
  891. $this->set_payment_method_title( $payment_method->get_title() ); 
  892. } elseif ( '' === $payment_method ) { 
  893. $this->set_prop( 'payment_method', '' ); 
  894. $this->set_prop( 'payment_method_title', '' ); 
  895. } else { 
  896. $this->set_prop( 'payment_method', $payment_method ); 
  897.  
  898. /** 
  899. * Set payment_method_title. 
  900. * @param string $value 
  901. * @throws WC_Data_Exception 
  902. */ 
  903. public function set_payment_method_title( $value ) { 
  904. $this->set_prop( 'payment_method_title', $value ); 
  905.  
  906. /** 
  907. * Set transaction_id. 
  908. * @param string $value 
  909. * @throws WC_Data_Exception 
  910. */ 
  911. public function set_transaction_id( $value ) { 
  912. $this->set_prop( 'transaction_id', $value ); 
  913.  
  914. /** 
  915. * Set customer_ip_address. 
  916. * @param string $value 
  917. * @throws WC_Data_Exception 
  918. */ 
  919. public function set_customer_ip_address( $value ) { 
  920. $this->set_prop( 'customer_ip_address', $value ); 
  921.  
  922. /** 
  923. * Set customer_user_agent. 
  924. * @param string $value 
  925. * @throws WC_Data_Exception 
  926. */ 
  927. public function set_customer_user_agent( $value ) { 
  928. $this->set_prop( 'customer_user_agent', $value ); 
  929.  
  930. /** 
  931. * Set created_via. 
  932. * @param string $value 
  933. * @throws WC_Data_Exception 
  934. */ 
  935. public function set_created_via( $value ) { 
  936. $this->set_prop( 'created_via', $value ); 
  937.  
  938. /** 
  939. * Set customer_note. 
  940. * @param string $value 
  941. * @throws WC_Data_Exception 
  942. */ 
  943. public function set_customer_note( $value ) { 
  944. $this->set_prop( 'customer_note', $value ); 
  945.  
  946. /** 
  947. * Set date_completed. 
  948. * @param string|integer|null $date UTC timestamp, or ISO 8601 DateTime. If the DateTime string has no timezone or offset, WordPress site timezone will be assumed. Null if their is no date. 
  949. * @throws WC_Data_Exception 
  950. */ 
  951. public function set_date_completed( $date = null ) { 
  952. $this->set_date_prop( 'date_completed', $date ); 
  953.  
  954. /** 
  955. * Set date_paid. 
  956. * @param string|integer|null $date UTC timestamp, or ISO 8601 DateTime. If the DateTime string has no timezone or offset, WordPress site timezone will be assumed. Null if their is no date. 
  957. * @throws WC_Data_Exception 
  958. */ 
  959. public function set_date_paid( $date = null ) { 
  960. $this->set_date_prop( 'date_paid', $date ); 
  961.  
  962. /** 
  963. * Set cart hash. 
  964. * @param string $value 
  965. * @throws WC_Data_Exception 
  966. */ 
  967. public function set_cart_hash( $value ) { 
  968. $this->set_prop( 'cart_hash', $value ); 
  969.  
  970. /** 
  971. |-------------------------------------------------------------------------- 
  972. | Conditionals 
  973. |-------------------------------------------------------------------------- 
  974. | Checks if a condition is true or false. 
  975. */ 
  976.  
  977. /** 
  978. * Check if an order key is valid. 
  979. * @param mixed $key 
  980. * @return bool 
  981. */ 
  982. public function key_is_valid( $key ) { 
  983. return $key === $this->get_order_key(); 
  984.  
  985. /** 
  986. * See if order matches cart_hash. 
  987. * @return bool 
  988. */ 
  989. public function has_cart_hash( $cart_hash = '' ) { 
  990. return hash_equals( $this->get_cart_hash(), $cart_hash ); 
  991.  
  992. /** 
  993. * Checks if an order can be edited, specifically for use on the Edit Order screen. 
  994. * @return bool 
  995. */ 
  996. public function is_editable() { 
  997. return apply_filters( 'wc_order_is_editable', in_array( $this->get_status(), array( 'pending', 'on-hold', 'auto-draft' ) ), $this ); 
  998.  
  999. /** 
  1000. * Returns if an order has been paid for based on the order status. 
  1001. * @since 2.5.0 
  1002. * @return bool 
  1003. */ 
  1004. public function is_paid() { 
  1005. return apply_filters( 'woocommerce_order_is_paid', $this->has_status( wc_get_is_paid_statuses() ), $this ); 
  1006.  
  1007. /** 
  1008. * Checks if product download is permitted. 
  1009. * @return bool 
  1010. */ 
  1011. public function is_download_permitted() { 
  1012. return apply_filters( 'woocommerce_order_is_download_permitted', $this->has_status( 'completed' ) || ( 'yes' === get_option( 'woocommerce_downloads_grant_access_after_payment' ) && $this->has_status( 'processing' ) ), $this ); 
  1013.  
  1014. /** 
  1015. * Checks if an order needs display the shipping address, based on shipping method. 
  1016. * @return bool 
  1017. */ 
  1018. public function needs_shipping_address() { 
  1019. if ( 'no' === get_option( 'woocommerce_calc_shipping' ) ) { 
  1020. return false; 
  1021.  
  1022. $hide = apply_filters( 'woocommerce_order_hide_shipping_address', array( 'local_pickup' ), $this ); 
  1023. $needs_address = false; 
  1024.  
  1025. foreach ( $this->get_shipping_methods() as $shipping_method ) { 
  1026. // Remove any instance IDs after : 
  1027. $shipping_method_id = current( explode( ':', $shipping_method['method_id'] ) ); 
  1028.  
  1029. if ( ! in_array( $shipping_method_id, $hide ) ) { 
  1030. $needs_address = true; 
  1031. break; 
  1032.  
  1033. return apply_filters( 'woocommerce_order_needs_shipping_address', $needs_address, $hide, $this ); 
  1034.  
  1035. /** 
  1036. * Returns true if the order contains a downloadable product. 
  1037. * @return bool 
  1038. */ 
  1039. public function has_downloadable_item() { 
  1040. foreach ( $this->get_items() as $item ) { 
  1041. if ( $item->is_type( 'line_item' ) && ( $product = $item->get_product() ) && $product->is_downloadable() && $product->has_file() ) { 
  1042. return true; 
  1043. return false; 
  1044.  
  1045. /** 
  1046. * Checks if an order needs payment, based on status and order total. 
  1047. * @return bool 
  1048. */ 
  1049. public function needs_payment() { 
  1050. $valid_order_statuses = apply_filters( 'woocommerce_valid_order_statuses_for_payment', array( 'pending', 'failed' ), $this ); 
  1051. return apply_filters( 'woocommerce_order_needs_payment', ( $this->has_status( $valid_order_statuses ) && $this->get_total() > 0 ), $this, $valid_order_statuses ); 
  1052.  
  1053. /** 
  1054. * See if the order needs processing before it can be completed. 
  1055. * Orders which only contain virtual, downloadable items do not need admin 
  1056. * intervention. 
  1057. * @since 3.0.0 
  1058. * @return bool 
  1059. */ 
  1060. public function needs_processing() { 
  1061. $needs_processing = false; 
  1062.  
  1063. if ( sizeof( $this->get_items() ) > 0 ) { 
  1064. foreach ( $this->get_items() as $item ) { 
  1065. if ( $item->is_type( 'line_item' ) && ( $product = $item->get_product() ) ) { 
  1066. $virtual_downloadable_item = $product->is_downloadable() && $product->is_virtual(); 
  1067.  
  1068. if ( apply_filters( 'woocommerce_order_item_needs_processing', ! $virtual_downloadable_item, $product, $this->get_id() ) ) { 
  1069. $needs_processing = true; 
  1070. break; 
  1071.  
  1072. return $needs_processing; 
  1073.  
  1074. /** 
  1075. |-------------------------------------------------------------------------- 
  1076. | URLs and Endpoints 
  1077. |-------------------------------------------------------------------------- 
  1078. */ 
  1079.  
  1080. /** 
  1081. * Generates a URL so that a customer can pay for their (unpaid - pending) order. Pass 'true' for the checkout version which doesn't offer gateway choices. 
  1082. * @param bool $on_checkout 
  1083. * @return string 
  1084. */ 
  1085. public function get_checkout_payment_url( $on_checkout = false ) { 
  1086. $pay_url = wc_get_endpoint_url( 'order-pay', $this->get_id(), wc_get_page_permalink( 'checkout' ) ); 
  1087.  
  1088. if ( 'yes' == get_option( 'woocommerce_force_ssl_checkout' ) || is_ssl() ) { 
  1089. $pay_url = str_replace( 'http:', 'https:', $pay_url ); 
  1090.  
  1091. if ( $on_checkout ) { 
  1092. $pay_url = add_query_arg( 'key', $this->get_order_key(), $pay_url ); 
  1093. } else { 
  1094. $pay_url = add_query_arg( array( 'pay_for_order' => 'true', 'key' => $this->get_order_key() ), $pay_url ); 
  1095.  
  1096. return apply_filters( 'woocommerce_get_checkout_payment_url', $pay_url, $this ); 
  1097.  
  1098. /** 
  1099. * Generates a URL for the thanks page (order received). 
  1100. * @return string 
  1101. */ 
  1102. public function get_checkout_order_received_url() { 
  1103. $order_received_url = wc_get_endpoint_url( 'order-received', $this->get_id(), wc_get_page_permalink( 'checkout' ) ); 
  1104.  
  1105. if ( 'yes' === get_option( 'woocommerce_force_ssl_checkout' ) || is_ssl() ) { 
  1106. $order_received_url = str_replace( 'http:', 'https:', $order_received_url ); 
  1107.  
  1108. $order_received_url = add_query_arg( 'key', $this->get_order_key(), $order_received_url ); 
  1109.  
  1110. return apply_filters( 'woocommerce_get_checkout_order_received_url', $order_received_url, $this ); 
  1111.  
  1112. /** 
  1113. * Generates a URL so that a customer can cancel their (unpaid - pending) order. 
  1114. * @param string $redirect 
  1115. * @return string 
  1116. */ 
  1117. public function get_cancel_order_url( $redirect = '' ) { 
  1118. return apply_filters( 'woocommerce_get_cancel_order_url', wp_nonce_url( add_query_arg( array( 
  1119. 'cancel_order' => 'true',  
  1120. 'order' => $this->get_order_key(),  
  1121. 'order_id' => $this->get_id(),  
  1122. 'redirect' => $redirect,  
  1123. ), $this->get_cancel_endpoint() ), 'woocommerce-cancel_order' ) ); 
  1124.  
  1125. /** 
  1126. * Generates a raw (unescaped) cancel-order URL for use by payment gateways. 
  1127. * @param string $redirect 
  1128. * @return string The unescaped cancel-order URL. 
  1129. */ 
  1130. public function get_cancel_order_url_raw( $redirect = '' ) { 
  1131. return apply_filters( 'woocommerce_get_cancel_order_url_raw', add_query_arg( array( 
  1132. 'cancel_order' => 'true',  
  1133. 'order' => $this->get_order_key(),  
  1134. 'order_id' => $this->get_id(),  
  1135. 'redirect' => $redirect,  
  1136. '_wpnonce' => wp_create_nonce( 'woocommerce-cancel_order' ),  
  1137. ), $this->get_cancel_endpoint() ) ); 
  1138.  
  1139. /** 
  1140. * Helper method to return the cancel endpoint. 
  1141. * @return string the cancel endpoint; either the cart page or the home page. 
  1142. */ 
  1143. public function get_cancel_endpoint() { 
  1144. $cancel_endpoint = wc_get_page_permalink( 'cart' ); 
  1145. if ( ! $cancel_endpoint ) { 
  1146. $cancel_endpoint = home_url(); 
  1147.  
  1148. if ( false === strpos( $cancel_endpoint, '?' ) ) { 
  1149. $cancel_endpoint = trailingslashit( $cancel_endpoint ); 
  1150.  
  1151. return $cancel_endpoint; 
  1152.  
  1153. /** 
  1154. * Generates a URL to view an order from the my account page. 
  1155. * @return string 
  1156. */ 
  1157. public function get_view_order_url() { 
  1158. return apply_filters( 'woocommerce_get_view_order_url', wc_get_endpoint_url( 'view-order', $this->get_id(), wc_get_page_permalink( 'myaccount' ) ), $this ); 
  1159.  
  1160. /** 
  1161. |-------------------------------------------------------------------------- 
  1162. | Order notes. 
  1163. |-------------------------------------------------------------------------- 
  1164. */ 
  1165.  
  1166. /** 
  1167. * Adds a note (comment) to the order. Order must exist. 
  1168. * @param string $note Note to add. 
  1169. * @param int $is_customer_note (default: 0) Is this a note for the customer? 
  1170. * @param bool added_by_user Was the note added by a user? 
  1171. * @return int Comment ID. 
  1172. */ 
  1173. public function add_order_note( $note, $is_customer_note = 0, $added_by_user = false ) { 
  1174. if ( ! $this->get_id() ) { 
  1175. return 0; 
  1176.  
  1177. if ( is_user_logged_in() && current_user_can( 'edit_shop_order', $this->get_id() ) && $added_by_user ) { 
  1178. $user = get_user_by( 'id', get_current_user_id() ); 
  1179. $comment_author = $user->display_name; 
  1180. $comment_author_email = $user->user_email; 
  1181. } else { 
  1182. $comment_author = __( 'WooCommerce', 'woocommerce' ); 
  1183. $comment_author_email = strtolower( __( 'WooCommerce', 'woocommerce' ) ) . '@'; 
  1184. $comment_author_email .= isset( $_SERVER['HTTP_HOST'] ) ? str_replace( 'www.', '', $_SERVER['HTTP_HOST'] ) : 'noreply.com'; 
  1185. $comment_author_email = sanitize_email( $comment_author_email ); 
  1186. $commentdata = apply_filters( 'woocommerce_new_order_note_data', array( 
  1187. 'comment_post_ID' => $this->get_id(),  
  1188. 'comment_author' => $comment_author,  
  1189. 'comment_author_email' => $comment_author_email,  
  1190. 'comment_author_url' => '',  
  1191. 'comment_content' => $note,  
  1192. 'comment_agent' => 'WooCommerce',  
  1193. 'comment_type' => 'order_note',  
  1194. 'comment_parent' => 0,  
  1195. 'comment_approved' => 1,  
  1196. ), array( 'order_id' => $this->get_id(), 'is_customer_note' => $is_customer_note ) ); 
  1197.  
  1198. $comment_id = wp_insert_comment( $commentdata ); 
  1199.  
  1200. if ( $is_customer_note ) { 
  1201. add_comment_meta( $comment_id, 'is_customer_note', 1 ); 
  1202.  
  1203. do_action( 'woocommerce_new_customer_note', array( 'order_id' => $this->get_id(), 'customer_note' => $commentdata['comment_content'] ) ); 
  1204.  
  1205. return $comment_id; 
  1206.  
  1207. /** 
  1208. * List order notes (public) for the customer. 
  1209. * @return array 
  1210. */ 
  1211. public function get_customer_order_notes() { 
  1212. $notes = array(); 
  1213. $args = array( 
  1214. 'post_id' => $this->get_id(),  
  1215. 'approve' => 'approve',  
  1216. 'type' => '',  
  1217. ); 
  1218.  
  1219. remove_filter( 'comments_clauses', array( 'WC_Comments', 'exclude_order_comments' ) ); 
  1220.  
  1221. $comments = get_comments( $args ); 
  1222.  
  1223. foreach ( $comments as $comment ) { 
  1224. if ( ! get_comment_meta( $comment->comment_ID, 'is_customer_note', true ) ) { 
  1225. continue; 
  1226. $comment->comment_content = make_clickable( $comment->comment_content ); 
  1227. $notes[] = $comment; 
  1228.  
  1229. add_filter( 'comments_clauses', array( 'WC_Comments', 'exclude_order_comments' ) ); 
  1230.  
  1231. return $notes; 
  1232.  
  1233. /** 
  1234. |-------------------------------------------------------------------------- 
  1235. | Refunds 
  1236. |-------------------------------------------------------------------------- 
  1237. */ 
  1238.  
  1239. /** 
  1240. * Get order refunds. 
  1241. * @since 2.2 
  1242. * @return array of WC_Order_Refund objects 
  1243. */ 
  1244. public function get_refunds() { 
  1245. $cache_key = WC_Cache_Helper::get_cache_prefix( 'orders' ) . 'refunds' . $this->get_id(); 
  1246. $cached_data = wp_cache_get( $cache_key, $this->cache_group ); 
  1247.  
  1248. if ( false !== $cached_data ) { 
  1249. return $cached_data; 
  1250.  
  1251. $this->refunds = wc_get_orders( array( 
  1252. 'type' => 'shop_order_refund',  
  1253. 'parent' => $this->get_id(),  
  1254. 'limit' => -1,  
  1255. ) ); 
  1256.  
  1257. wp_cache_set( $cache_key, $this->refunds, $this->cache_group ); 
  1258.  
  1259. return $this->refunds; 
  1260.  
  1261. /** 
  1262. * Get amount already refunded. 
  1263. * @since 2.2 
  1264. * @return string 
  1265. */ 
  1266. public function get_total_refunded() { 
  1267. $cache_key = WC_Cache_Helper::get_cache_prefix( 'orders' ) . 'total_refunded' . $this->get_id(); 
  1268. $cached_data = wp_cache_get( $cache_key, $this->cache_group ); 
  1269.  
  1270. if ( false !== $cached_data ) { 
  1271. return $cached_data; 
  1272.  
  1273. $total_refunded = $this->data_store->get_total_refunded( $this ); 
  1274.  
  1275. wp_cache_set( $cache_key, $total_refunded, $this->cache_group ); 
  1276.  
  1277. return $total_refunded; 
  1278.  
  1279. /** 
  1280. * Get the total tax refunded. 
  1281. * @since 2.3 
  1282. * @return float 
  1283. */ 
  1284. public function get_total_tax_refunded() { 
  1285. $cache_key = WC_Cache_Helper::get_cache_prefix( 'orders' ) . 'total_tax_refunded' . $this->get_id(); 
  1286. $cached_data = wp_cache_get( $cache_key, $this->cache_group ); 
  1287.  
  1288. if ( false !== $cached_data ) { 
  1289. return $cached_data; 
  1290.  
  1291. $total_refunded = $this->data_store->get_total_tax_refunded( $this ); 
  1292.  
  1293. wp_cache_set( $cache_key, $total_refunded, $this->cache_group ); 
  1294.  
  1295. return $total_refunded; 
  1296.  
  1297. /** 
  1298. * Get the total shipping refunded. 
  1299. * @since 2.4 
  1300. * @return float 
  1301. */ 
  1302. public function get_total_shipping_refunded() { 
  1303. $cache_key = WC_Cache_Helper::get_cache_prefix( 'orders' ) . 'total_shipping_refunded' . $this->get_id(); 
  1304. $cached_data = wp_cache_get( $cache_key, $this->cache_group ); 
  1305.  
  1306. if ( false !== $cached_data ) { 
  1307. return $cached_data; 
  1308.  
  1309. $total_refunded = $this->data_store->get_total_shipping_refunded( $this ); 
  1310.  
  1311. wp_cache_set( $cache_key, $total_refunded, $this->cache_group ); 
  1312.  
  1313. return $total_refunded; 
  1314.  
  1315. /** 
  1316. * Gets the count of order items of a certain type that have been refunded. 
  1317. * @since 2.4.0 
  1318. * @param string $item_type 
  1319. * @return string 
  1320. */ 
  1321. public function get_item_count_refunded( $item_type = '' ) { 
  1322. if ( empty( $item_type ) ) { 
  1323. $item_type = array( 'line_item' ); 
  1324. if ( ! is_array( $item_type ) ) { 
  1325. $item_type = array( $item_type ); 
  1326. $count = 0; 
  1327.  
  1328. foreach ( $this->get_refunds() as $refund ) { 
  1329. foreach ( $refund->get_items( $item_type ) as $refunded_item ) { 
  1330. $count += abs( $refunded_item->get_quantity() ); 
  1331.  
  1332. return apply_filters( 'woocommerce_get_item_count_refunded', $count, $item_type, $this ); 
  1333.  
  1334. /** 
  1335. * Get the total number of items refunded. 
  1336. * @since 2.4.0 
  1337. * @param string $item_type type of the item we're checking, if not a line_item 
  1338. * @return integer 
  1339. */ 
  1340. public function get_total_qty_refunded( $item_type = 'line_item' ) { 
  1341. $qty = 0; 
  1342. foreach ( $this->get_refunds() as $refund ) { 
  1343. foreach ( $refund->get_items( $item_type ) as $refunded_item ) { 
  1344. $qty += $refunded_item->get_quantity(); 
  1345. return $qty; 
  1346.  
  1347. /** 
  1348. * Get the refunded amount for a line item. 
  1349. * @param int $item_id ID of the item we're checking 
  1350. * @param string $item_type type of the item we're checking, if not a line_item 
  1351. * @return integer 
  1352. */ 
  1353. public function get_qty_refunded_for_item( $item_id, $item_type = 'line_item' ) { 
  1354. $qty = 0; 
  1355. foreach ( $this->get_refunds() as $refund ) { 
  1356. foreach ( $refund->get_items( $item_type ) as $refunded_item ) { 
  1357. if ( absint( $refunded_item->get_meta( '_refunded_item_id' ) ) === $item_id ) { 
  1358. $qty += $refunded_item->get_quantity(); 
  1359. return $qty; 
  1360.  
  1361. /** 
  1362. * Get the refunded amount for a line item. 
  1363. * @param int $item_id ID of the item we're checking 
  1364. * @param string $item_type type of the item we're checking, if not a line_item 
  1365. * @return integer 
  1366. */ 
  1367. public function get_total_refunded_for_item( $item_id, $item_type = 'line_item' ) { 
  1368. $total = 0; 
  1369. foreach ( $this->get_refunds() as $refund ) { 
  1370. foreach ( $refund->get_items( $item_type ) as $refunded_item ) { 
  1371. if ( absint( $refunded_item->get_meta( '_refunded_item_id' ) ) === $item_id ) { 
  1372. $total += $refunded_item->get_total(); 
  1373. return $total * -1; 
  1374.  
  1375. /** 
  1376. * Get the refunded tax amount for a line item. 
  1377. * @param int $item_id ID of the item we're checking 
  1378. * @param int $tax_id ID of the tax we're checking 
  1379. * @param string $item_type type of the item we're checking, if not a line_item 
  1380. * @return double 
  1381. */ 
  1382. public function get_tax_refunded_for_item( $item_id, $tax_id, $item_type = 'line_item' ) { 
  1383. $total = 0; 
  1384. foreach ( $this->get_refunds() as $refund ) { 
  1385. foreach ( $refund->get_items( $item_type ) as $refunded_item ) { 
  1386. $refunded_item_id = (int) $refunded_item->get_meta( '_refunded_item_id' ); 
  1387. if ( $refunded_item_id === $item_id ) { 
  1388. $taxes = $refunded_item->get_taxes(); 
  1389. $total += isset( $taxes['total'][ $tax_id ] ) ? $taxes['total'][ $tax_id ] : 0; 
  1390. break; 
  1391. return wc_round_tax_total( $total ) * -1; 
  1392.  
  1393. /** 
  1394. * Get total tax refunded by rate ID. 
  1395. * @param int $rate_id 
  1396. * @return float 
  1397. */ 
  1398. public function get_total_tax_refunded_by_rate_id( $rate_id ) { 
  1399. $total = 0; 
  1400. foreach ( $this->get_refunds() as $refund ) { 
  1401. foreach ( $refund->get_items( 'tax' ) as $refunded_item ) { 
  1402. if ( absint( $refunded_item->get_rate_id() ) === $rate_id ) { 
  1403. $total += abs( $refunded_item->get_tax_total() ) + abs( $refunded_item->get_shipping_tax_total() ); 
  1404.  
  1405. return $total; 
  1406.  
  1407. /** 
  1408. * How much money is left to refund? 
  1409. * @return string 
  1410. */ 
  1411. public function get_remaining_refund_amount() { 
  1412. return wc_format_decimal( $this->get_total() - $this->get_total_refunded(), wc_get_price_decimals() ); 
  1413.  
  1414. /** 
  1415. * How many items are left to refund? 
  1416. * @return int 
  1417. */ 
  1418. public function get_remaining_refund_items() { 
  1419. return absint( $this->get_item_count() - $this->get_item_count_refunded() ); 
  1420.  
  1421. /** 
  1422. * Add total row for the payment method. 
  1423. * @param array $total_rows 
  1424. * @param string $tax_display 
  1425. */ 
  1426. protected function add_order_item_totals_payment_method_row( &$total_rows, $tax_display ) { 
  1427. if ( $this->get_total() > 0 && $this->get_payment_method_title() ) { 
  1428. $total_rows['payment_method'] = array( 
  1429. 'label' => __( 'Payment method:', 'woocommerce' ),  
  1430. 'value' => $this->get_payment_method_title(),  
  1431. ); 
  1432.  
  1433. /** 
  1434. * Add total row for refunds. 
  1435. * @param array $total_rows 
  1436. * @param string $tax_display 
  1437. */ 
  1438. protected function add_order_item_totals_refund_rows( &$total_rows, $tax_display ) { 
  1439. if ( $refunds = $this->get_refunds() ) { 
  1440. foreach ( $refunds as $id => $refund ) { 
  1441. $total_rows[ 'refund_' . $id ] = array( 
  1442. 'label' => $refund->get_reason() ? $refund->get_reason() : __( 'Refund', 'woocommerce' ) . ':',  
  1443. 'value' => wc_price( '-' . $refund->get_amount(), array( 'currency' => $this->get_currency() ) ),  
  1444. ); 
  1445.  
  1446. /** 
  1447. * Get totals for display on pages and in emails. 
  1448. * @param mixed $tax_display 
  1449. * @return array 
  1450. */ 
  1451. public function get_order_item_totals( $tax_display = '' ) { 
  1452. $tax_display = $tax_display ? $tax_display : get_option( 'woocommerce_tax_display_cart' ); 
  1453. $total_rows = array(); 
  1454.  
  1455. $this->add_order_item_totals_subtotal_row( $total_rows, $tax_display ); 
  1456. $this->add_order_item_totals_discount_row( $total_rows, $tax_display ); 
  1457. $this->add_order_item_totals_shipping_row( $total_rows, $tax_display ); 
  1458. $this->add_order_item_totals_fee_rows( $total_rows, $tax_display ); 
  1459. $this->add_order_item_totals_tax_rows( $total_rows, $tax_display ); 
  1460. $this->add_order_item_totals_payment_method_row( $total_rows, $tax_display ); 
  1461. $this->add_order_item_totals_refund_rows( $total_rows, $tax_display ); 
  1462. $this->add_order_item_totals_total_row( $total_rows, $tax_display ); 
  1463.  
  1464. return apply_filters( 'woocommerce_get_order_item_totals', $total_rows, $this, $tax_display );