2014-06-13 13:35:53 +00:00
< ? php
2016-06-21 19:03:56 +00:00
if ( ! defined ( 'ABSPATH' ) ) {
exit ;
}
2017-02-16 16:39:56 +00:00
include_once ( WC_ABSPATH . 'includes/legacy/abstract-wc-legacy-order.php' );
2016-06-21 19:03:56 +00:00
2014-06-13 13:35:53 +00:00
/**
2015-11-03 13:53:50 +00:00
* Abstract Order
2014-06-13 13:35:53 +00:00
*
2016-06-21 19:03:56 +00:00
* Handles generic order data and database interaction which is extended by both
* WC_Order ( regular orders ) and WC_Order_Refund ( refunds are negative orders ) .
2014-06-13 13:35:53 +00:00
*
2016-06-21 19:03:56 +00:00
* @ class WC_Abstract_Order
2017-03-15 16:36:53 +00:00
* @ version 3.0 . 0
2014-08-31 05:49:58 +00:00
* @ package WooCommerce / Classes
* @ category Class
* @ author WooThemes
2014-06-13 13:35:53 +00:00
*/
2016-06-21 19:03:56 +00:00
abstract class WC_Abstract_Order extends WC_Abstract_Legacy_Order {
2015-01-20 12:07:33 +00:00
2016-06-21 19:03:56 +00:00
/**
2017-03-15 16:36:53 +00:00
* Order Data array . This is the core order data exposed in APIs since 3.0 . 0.
2016-06-21 19:03:56 +00:00
*
2016-08-24 11:34:19 +00:00
* Notes : cart_tax = cart_tax is the new name for the legacy 'order_tax'
* which is the tax for items only , not shipping .
2016-11-17 11:22:24 +00:00
*
2017-03-15 16:36:53 +00:00
* @ since 3.0 . 0
2016-06-21 19:03:56 +00:00
* @ var array
*/
2016-09-09 12:34:49 +00:00
protected $data = array (
2016-06-21 19:03:56 +00:00
'parent_id' => 0 ,
2016-08-08 16:03:43 +00:00
'status' => '' ,
2016-06-21 19:03:56 +00:00
'currency' => '' ,
'version' => '' ,
'prices_include_tax' => false ,
2017-03-08 16:51:10 +00:00
'date_created' => null ,
'date_modified' => null ,
2016-06-21 19:03:56 +00:00
'discount_total' => 0 ,
'discount_tax' => 0 ,
'shipping_total' => 0 ,
'shipping_tax' => 0 ,
'cart_tax' => 0 ,
'total' => 0 ,
'total_tax' => 0 ,
);
2014-10-07 10:00:10 +00:00
2016-08-09 13:02:40 +00:00
/**
* Order items will be stored here , sometimes before they persist in the DB .
2016-11-17 11:22:24 +00:00
*
2017-03-15 16:36:53 +00:00
* @ since 3.0 . 0
2016-08-09 13:02:40 +00:00
* @ var array
*/
2017-02-01 13:54:18 +00:00
protected $items = array ();
2016-08-09 13:02:40 +00:00
2016-08-17 15:53:01 +00:00
/**
* Order items that need deleting are stored here .
2016-11-17 11:22:24 +00:00
*
2017-03-15 16:36:53 +00:00
* @ since 3.0 . 0
2016-08-17 15:53:01 +00:00
* @ var array
*/
2016-09-09 12:34:49 +00:00
protected $items_to_delete = array ();
2016-08-17 15:53:01 +00:00
2016-06-21 19:03:56 +00:00
/**
* Stores meta in cache for future reads .
2016-11-17 11:22:24 +00:00
*
2016-06-21 19:03:56 +00:00
* A group must be set to to enable caching .
* @ var string
*/
2017-03-02 17:15:39 +00:00
protected $cache_group = 'orders' ;
2015-01-20 12:07:33 +00:00
2016-11-17 16:02:09 +00:00
/**
* Which data store to load .
*
* @ var string
*/
protected $data_store_name = 'order' ;
2016-12-19 17:09:52 +00:00
/**
* This is the name of this object type .
* @ var string
*/
protected $object_type = 'order' ;
2014-06-13 13:35:53 +00:00
/**
* Get the order if ID is passed , otherwise the order is new and empty .
2015-11-03 12:28:01 +00:00
* This class should NOT be instantiated , but the get_order function or new WC_Order_Factory .
* should be used . It is possible , but the aforementioned are preferred and are the only .
2014-06-14 21:36:20 +00:00
* methods that will be maintained going forward .
2015-01-20 13:20:22 +00:00
*
2016-11-17 10:53:22 +00:00
* @ param int | object | WC_Order $order Order to read .
2014-06-13 13:35:53 +00:00
*/
2016-11-17 10:53:22 +00:00
public function __construct ( $order = 0 ) {
parent :: __construct ( $order );
if ( is_numeric ( $order ) && $order > 0 ) {
$this -> set_id ( $order );
} elseif ( $order instanceof self ) {
2016-11-21 16:46:32 +00:00
$this -> set_id ( $order -> get_id () );
2016-11-17 10:53:22 +00:00
} elseif ( ! empty ( $order -> ID ) ) {
2016-11-21 16:55:36 +00:00
$this -> set_id ( $order -> ID );
2016-11-17 10:53:22 +00:00
} else {
$this -> set_object_read ( true );
2016-06-21 19:03:56 +00:00
}
2016-11-17 10:53:22 +00:00
2016-11-17 16:02:09 +00:00
$this -> data_store = WC_Data_Store :: load ( $this -> data_store_name );
2016-11-17 10:53:22 +00:00
if ( $this -> get_id () > 0 ) {
$this -> data_store -> read ( $this );
}
}
2016-06-21 19:03:56 +00:00
/**
2016-11-17 11:22:24 +00:00
* Get internal type .
*
2016-06-21 19:03:56 +00:00
* @ return string
*/
public function get_type () {
return 'shop_order' ;
2014-10-14 13:25:48 +00:00
}
2014-08-31 05:49:58 +00:00
2014-07-03 11:38:55 +00:00
/**
2016-11-17 10:53:22 +00:00
* Get all class data in array format .
2016-11-17 11:22:24 +00:00
*
2017-03-15 16:36:53 +00:00
* @ since 3.0 . 0
2016-11-17 10:53:22 +00:00
* @ return array
2014-07-03 11:38:55 +00:00
*/
2016-11-17 10:53:22 +00:00
public function get_data () {
return array_merge (
2016-12-22 14:52:37 +00:00
array (
'id' => $this -> get_id (),
),
2016-11-17 10:53:22 +00:00
$this -> data ,
2016-06-21 19:03:56 +00:00
array (
2016-11-17 10:53:22 +00:00
'meta_data' => $this -> get_meta_data (),
'line_items' => $this -> get_items ( 'line_item' ),
'tax_lines' => $this -> get_items ( 'tax' ),
'shipping_lines' => $this -> get_items ( 'shipping' ),
'fee_lines' => $this -> get_items ( 'fee' ),
'coupon_lines' => $this -> get_items ( 'coupon' ),
2016-06-21 19:03:56 +00:00
)
);
2014-07-28 03:23:59 +00:00
}
2014-07-03 11:38:55 +00:00
2016-11-17 10:53:22 +00:00
/*
|--------------------------------------------------------------------------
| CRUD methods
|--------------------------------------------------------------------------
|
| Methods which create , read , update and delete orders from the database .
| Written in abstract fashion so that the way orders are stored can be
| changed more easily in the future .
|
| A save method is included for convenience ( chooses update or create based
| on if the order exists yet ) .
|
*/
2015-06-19 00:43:31 +00:00
2014-07-03 11:38:55 +00:00
/**
2016-06-21 19:03:56 +00:00
* Save data to the database .
2016-11-17 11:22:24 +00:00
*
2017-03-15 16:36:53 +00:00
* @ since 3.0 . 0
2016-06-21 19:03:56 +00:00
* @ return int order ID
2014-07-03 11:38:55 +00:00
*/
2016-06-21 19:03:56 +00:00
public function save () {
2016-11-17 10:53:22 +00:00
if ( $this -> data_store ) {
2016-12-22 17:41:23 +00:00
// Trigger action before saving to the DB. Allows you to adjust object props before save.
2016-12-19 17:09:52 +00:00
do_action ( 'woocommerce_before_' . $this -> object_type . '_object_save' , $this , $this -> data_store );
2016-11-17 10:53:22 +00:00
if ( $this -> get_id () ) {
$this -> data_store -> update ( $this );
} else {
$this -> data_store -> create ( $this );
2016-08-09 13:02:40 +00:00
}
2016-11-17 13:18:24 +00:00
}
$this -> save_items ();
return $this -> get_id ();
}
/**
* Save all order items which are part of this order .
*/
protected function save_items () {
foreach ( $this -> items_to_delete as $item ) {
$item -> delete ();
}
$this -> items_to_delete = array ();
2017-02-01 09:53:53 +00:00
// Add/save items.
2016-11-17 13:18:24 +00:00
foreach ( $this -> items as $item_group => $items ) {
if ( is_array ( $items ) ) {
2017-08-10 14:57:34 +00:00
$items = array_filter ( $items );
foreach ( $items as $item_key => $item ) {
2016-11-17 13:18:24 +00:00
$item -> set_order_id ( $this -> get_id () );
2017-08-11 15:16:09 +00:00
2016-11-17 13:18:24 +00:00
$item_id = $item -> save ();
// If ID changed (new item saved to DB)...
if ( $item_id !== $item_key ) {
$this -> items [ $item_group ][ $item_id ] = $item ;
2016-12-19 11:27:32 +00:00
2017-02-14 19:23:57 +00:00
unset ( $this -> items [ $item_group ][ $item_key ] );
2016-11-17 13:18:24 +00:00
}
}
}
2016-08-09 13:02:40 +00:00
}
}
2016-06-21 19:03:56 +00:00
/*
|--------------------------------------------------------------------------
| Getters
|--------------------------------------------------------------------------
*/
2014-07-03 11:38:55 +00:00
2016-06-21 19:03:56 +00:00
/**
* Get parent order ID .
2016-11-17 11:22:24 +00:00
*
2017-03-15 16:36:53 +00:00
* @ since 3.0 . 0
2016-11-17 11:22:24 +00:00
* @ param string $context
2016-06-21 19:03:56 +00:00
* @ return integer
*/
2016-11-17 11:22:24 +00:00
public function get_parent_id ( $context = 'view' ) {
return $this -> get_prop ( 'parent_id' , $context );
2016-06-21 19:03:56 +00:00
}
2014-07-28 03:28:25 +00:00
2016-06-21 19:03:56 +00:00
/**
* Gets order currency .
2016-11-17 11:22:24 +00:00
*
* @ param string $context
2016-06-21 19:03:56 +00:00
* @ return string
*/
2016-11-17 11:22:24 +00:00
public function get_currency ( $context = 'view' ) {
return $this -> get_prop ( 'currency' , $context );
2016-06-21 19:03:56 +00:00
}
2014-07-28 03:28:25 +00:00
2016-06-21 19:03:56 +00:00
/**
2016-11-17 11:22:24 +00:00
* Get order_version .
*
* @ param string $context
2016-06-21 19:03:56 +00:00
* @ return string
*/
2016-11-17 11:22:24 +00:00
public function get_version ( $context = 'view' ) {
return $this -> get_prop ( 'version' , $context );
2016-06-21 19:03:56 +00:00
}
2014-07-28 03:28:25 +00:00
2016-06-21 19:03:56 +00:00
/**
2016-11-17 11:22:24 +00:00
* Get prices_include_tax .
*
* @ param string $context
2016-06-21 19:03:56 +00:00
* @ return bool
*/
2016-11-17 11:22:24 +00:00
public function get_prices_include_tax ( $context = 'view' ) {
return $this -> get_prop ( 'prices_include_tax' , $context );
2016-06-21 19:03:56 +00:00
}
2014-07-28 03:28:25 +00:00
2016-06-21 19:03:56 +00:00
/**
2016-11-17 11:22:24 +00:00
* Get date_created .
*
* @ param string $context
2017-03-08 16:51:10 +00:00
* @ return WC_DateTime | NULL object if the date is set or null if there is no date .
2016-06-21 19:03:56 +00:00
*/
2016-11-17 11:22:24 +00:00
public function get_date_created ( $context = 'view' ) {
return $this -> get_prop ( 'date_created' , $context );
2016-06-21 19:03:56 +00:00
}
2014-07-28 03:28:25 +00:00
2016-06-21 19:03:56 +00:00
/**
2016-11-17 11:22:24 +00:00
* Get date_modified .
*
* @ param string $context
2017-03-08 16:51:10 +00:00
* @ return WC_DateTime | NULL object if the date is set or null if there is no date .
2016-06-21 19:03:56 +00:00
*/
2016-11-17 11:22:24 +00:00
public function get_date_modified ( $context = 'view' ) {
return $this -> get_prop ( 'date_modified' , $context );
2016-06-21 19:03:56 +00:00
}
2014-07-28 03:28:25 +00:00
2016-06-21 19:03:56 +00:00
/**
* Return the order statuses without wc - internal prefix .
2016-11-17 11:22:24 +00:00
*
* @ param string $context
2016-06-21 19:03:56 +00:00
* @ return string
*/
2016-11-17 11:22:24 +00:00
public function get_status ( $context = 'view' ) {
2017-03-09 13:45:33 +00:00
$status = $this -> get_prop ( 'status' , $context );
if ( empty ( $status ) && 'view' === $context ) {
// In view context, return the default status if no status has been set.
$status = apply_filters ( 'woocommerce_default_order_status' , 'pending' );
}
return $status ;
2014-07-28 03:28:25 +00:00
}
2016-06-21 19:03:56 +00:00
/**
2016-11-17 11:22:24 +00:00
* Get discount_total .
*
* @ param string $context
2016-06-21 19:03:56 +00:00
* @ return string
*/
2016-11-17 11:22:24 +00:00
public function get_discount_total ( $context = 'view' ) {
return $this -> get_prop ( 'discount_total' , $context );
2014-07-03 11:38:55 +00:00
}
2014-07-28 03:28:25 +00:00
/**
2016-11-17 11:22:24 +00:00
* Get discount_tax .
*
* @ param string $context
2016-06-21 19:03:56 +00:00
* @ return string
2014-07-28 03:28:25 +00:00
*/
2016-11-17 11:22:24 +00:00
public function get_discount_tax ( $context = 'view' ) {
return $this -> get_prop ( 'discount_tax' , $context );
2016-06-21 19:03:56 +00:00
}
2014-07-28 03:28:25 +00:00
2016-06-21 19:03:56 +00:00
/**
2016-11-17 11:22:24 +00:00
* Get shipping_total .
*
* @ param string $context
2016-06-21 19:03:56 +00:00
* @ return string
*/
2016-11-17 11:22:24 +00:00
public function get_shipping_total ( $context = 'view' ) {
return $this -> get_prop ( 'shipping_total' , $context );
2016-06-21 19:03:56 +00:00
}
2014-07-28 03:28:25 +00:00
2016-06-21 19:03:56 +00:00
/**
* Get shipping_tax .
2016-11-17 11:22:24 +00:00
*
* @ param string $context
2016-06-21 19:03:56 +00:00
* @ return string
*/
2016-11-17 11:22:24 +00:00
public function get_shipping_tax ( $context = 'view' ) {
return $this -> get_prop ( 'shipping_tax' , $context );
2016-06-21 19:03:56 +00:00
}
2014-07-28 03:28:25 +00:00
2016-06-21 19:03:56 +00:00
/**
* Gets cart tax amount .
2016-11-17 11:22:24 +00:00
*
* @ param string $context
2016-06-21 19:03:56 +00:00
* @ return float
*/
2016-11-17 11:22:24 +00:00
public function get_cart_tax ( $context = 'view' ) {
return $this -> get_prop ( 'cart_tax' , $context );
2016-06-21 19:03:56 +00:00
}
2014-07-28 03:28:25 +00:00
2016-06-21 19:03:56 +00:00
/**
2016-11-17 11:22:24 +00:00
* Gets order grand total . incl . taxes . Used in gateways .
*
* @ param string $context
2016-06-21 19:03:56 +00:00
* @ return float
*/
2016-11-17 11:22:24 +00:00
public function get_total ( $context = 'view' ) {
return $this -> get_prop ( 'total' , $context );
2014-07-28 03:28:25 +00:00
}
2014-07-03 11:38:55 +00:00
/**
2016-06-21 19:03:56 +00:00
* Get total tax amount . Alias for get_order_tax () .
2014-07-28 03:23:59 +00:00
*
2016-11-17 11:22:24 +00:00
* @ param string $context
2016-06-21 19:03:56 +00:00
* @ return float
2014-07-03 11:38:55 +00:00
*/
2016-11-17 11:22:24 +00:00
public function get_total_tax ( $context = 'view' ) {
return $this -> get_prop ( 'total_tax' , $context );
2016-06-21 19:03:56 +00:00
}
2014-07-03 11:38:55 +00:00
2016-11-17 11:22:24 +00:00
/*
|--------------------------------------------------------------------------
| Non - CRUD Getters
|--------------------------------------------------------------------------
*/
2016-06-21 19:03:56 +00:00
/**
* Gets the total discount amount .
2016-11-17 11:22:24 +00:00
*
2016-11-17 11:26:24 +00:00
* @ param bool $ex_tax Show discount excl any tax .
2016-06-21 19:03:56 +00:00
* @ return float
*/
public function get_total_discount ( $ex_tax = true ) {
if ( $ex_tax ) {
$total_discount = $this -> get_discount_total ();
} else {
$total_discount = $this -> get_discount_total () + $this -> get_discount_tax ();
2014-07-03 11:38:55 +00:00
}
2016-11-17 11:22:24 +00:00
return apply_filters ( 'woocommerce_order_get_total_discount' , round ( $total_discount , WC_ROUNDING_PRECISION ), $this );
2016-06-21 19:03:56 +00:00
}
2014-07-28 03:23:59 +00:00
2016-06-21 19:03:56 +00:00
/**
* Gets order subtotal .
* @ return float
*/
public function get_subtotal () {
$subtotal = 0 ;
2014-07-03 11:38:55 +00:00
2016-06-21 19:03:56 +00:00
foreach ( $this -> get_items () as $item ) {
$subtotal += $item -> get_subtotal ();
2014-07-19 03:15:41 +00:00
}
2014-07-03 11:38:55 +00:00
2016-11-17 11:22:24 +00:00
return apply_filters ( 'woocommerce_order_get_subtotal' , ( double ) $subtotal , $this );
2014-07-03 11:38:55 +00:00
}
/**
2016-06-21 19:03:56 +00:00
* Get taxes , merged by code , formatted ready for output .
2014-08-31 05:49:58 +00:00
*
2016-06-21 19:03:56 +00:00
* @ return array
2014-07-03 11:38:55 +00:00
*/
2016-06-21 19:03:56 +00:00
public function get_tax_totals () {
$tax_totals = array ();
2014-07-03 11:38:55 +00:00
2016-06-21 19:03:56 +00:00
foreach ( $this -> get_items ( 'tax' ) as $key => $tax ) {
$code = $tax -> get_rate_code ();
2014-07-03 11:38:55 +00:00
2016-06-21 19:03:56 +00:00
if ( ! isset ( $tax_totals [ $code ] ) ) {
$tax_totals [ $code ] = new stdClass ();
$tax_totals [ $code ] -> amount = 0 ;
2016-01-08 11:42:32 +00:00
}
2016-06-21 19:03:56 +00:00
$tax_totals [ $code ] -> id = $key ;
$tax_totals [ $code ] -> rate_id = $tax -> get_rate_id ();
$tax_totals [ $code ] -> is_compound = $tax -> is_compound ();
$tax_totals [ $code ] -> label = $tax -> get_label ();
2017-03-24 12:05:28 +00:00
$tax_totals [ $code ] -> amount += ( float ) $tax -> get_tax_total () + ( float ) $tax -> get_shipping_tax_total ();
2016-06-21 19:03:56 +00:00
$tax_totals [ $code ] -> formatted_amount = wc_price ( wc_round_tax_total ( $tax_totals [ $code ] -> amount ), array ( 'currency' => $this -> get_currency () ) );
2016-01-08 11:42:32 +00:00
}
2016-06-21 19:03:56 +00:00
if ( apply_filters ( 'woocommerce_order_hide_zero_taxes' , true ) ) {
$amounts = array_filter ( wp_list_pluck ( $tax_totals , 'amount' ) );
$tax_totals = array_intersect_key ( $tax_totals , $amounts );
2014-07-28 03:28:25 +00:00
}
2016-11-17 11:22:24 +00:00
return apply_filters ( 'woocommerce_order_get_tax_totals' , $tax_totals , $this );
2014-07-28 03:28:25 +00:00
}
2017-01-31 22:55:35 +00:00
/**
* Get all valid statuses for this order
*
2017-03-15 16:36:53 +00:00
* @ since 3.0 . 0
2017-01-31 22:55:35 +00:00
* @ return array Internal status keys e . g . 'wc-processing'
*/
protected function get_valid_statuses () {
return array_keys ( wc_get_order_statuses () );
}
2017-04-20 15:02:10 +00:00
/**
* Get user ID . Used by orders , not other order types like refunds .
*
* @ param string $context
* @ return int
*/
public function get_user_id ( $context = 'view' ) {
return 0 ;
}
/**
* Get user . Used by orders , not other order types like refunds .
*
2017-04-20 15:03:40 +00:00
* @ return WP_User | false
2017-04-20 15:02:10 +00:00
*/
public function get_user () {
return false ;
}
2016-06-21 19:03:56 +00:00
/*
|--------------------------------------------------------------------------
| Setters
|--------------------------------------------------------------------------
|
| Functions for setting order data . These should not update anything in the
| database itself and should only change what is stored in the class
2017-03-15 16:36:53 +00:00
| object . However , for backwards compatibility pre 3.0 . 0 some of these
2016-06-21 19:03:56 +00:00
| setters may handle both .
*/
2014-07-03 11:38:55 +00:00
/**
2016-06-21 19:03:56 +00:00
* Set parent order ID .
2016-11-17 11:26:24 +00:00
*
2017-03-15 16:36:53 +00:00
* @ since 3.0 . 0
2016-06-21 19:03:56 +00:00
* @ param int $value
2016-08-24 09:46:29 +00:00
* @ throws WC_Data_Exception
2014-07-03 11:38:55 +00:00
*/
2016-06-21 19:03:56 +00:00
public function set_parent_id ( $value ) {
2017-04-25 13:18:27 +00:00
if ( $value && ( $value === $this -> get_id () || ! wc_get_order ( $value ) ) ) {
2016-08-25 12:05:27 +00:00
$this -> error ( 'order_invalid_parent_id' , __ ( 'Invalid parent ID' , 'woocommerce' ) );
2016-08-23 14:25:50 +00:00
}
2016-11-17 11:26:24 +00:00
$this -> set_prop ( 'parent_id' , absint ( $value ) );
2014-07-03 11:38:55 +00:00
}
/**
2016-06-21 19:03:56 +00:00
* Set order status .
2016-11-17 11:26:24 +00:00
*
2017-03-15 16:36:53 +00:00
* @ since 3.0 . 0
2016-06-21 19:03:56 +00:00
* @ param string $new_status Status to change the order to . No internal wc - prefix is required .
2016-08-23 14:25:50 +00:00
* @ return array details of change
2014-07-03 11:38:55 +00:00
*/
2017-02-15 12:10:31 +00:00
public function set_status ( $new_status ) {
2016-08-08 16:03:43 +00:00
$old_status = $this -> get_status ();
$new_status = 'wc-' === substr ( $new_status , 0 , 3 ) ? substr ( $new_status , 3 ) : $new_status ;
2016-05-11 15:32:51 +00:00
2017-04-04 11:39:35 +00:00
// If setting the status, ensure it's set to a valid status.
if ( true === $this -> object_read ) {
// Only allow valid new status
if ( ! in_array ( 'wc-' . $new_status , $this -> get_valid_statuses () ) && 'trash' !== $new_status ) {
$new_status = 'pending' ;
}
// If the old status is set but unknown (e.g. draft) assume its pending for action usage.
if ( $old_status && ! in_array ( 'wc-' . $old_status , $this -> get_valid_statuses () ) && 'trash' !== $old_status ) {
$old_status = 'pending' ;
}
2015-12-23 12:50:28 +00:00
}
2014-07-03 11:38:55 +00:00
2016-11-17 12:34:39 +00:00
$this -> set_prop ( 'status' , $new_status );
2016-08-08 16:03:43 +00:00
2016-06-21 19:03:56 +00:00
return array (
'from' => $old_status ,
2016-08-27 01:46:45 +00:00
'to' => $new_status ,
2016-06-21 19:03:56 +00:00
);
2017-02-15 12:10:31 +00:00
}
2014-07-28 03:29:40 +00:00
2014-07-03 11:38:55 +00:00
/**
2016-11-17 11:26:24 +00:00
* Set order_version .
*
2016-06-21 19:03:56 +00:00
* @ param string $value
2016-08-24 09:46:29 +00:00
* @ throws WC_Data_Exception
2014-07-03 11:38:55 +00:00
*/
2016-06-21 19:03:56 +00:00
public function set_version ( $value ) {
2016-11-17 11:26:24 +00:00
$this -> set_prop ( 'version' , $value );
2014-07-03 11:38:55 +00:00
}
2014-06-13 13:35:53 +00:00
/**
2016-11-17 11:26:24 +00:00
* Set order_currency .
*
2016-06-21 19:03:56 +00:00
* @ param string $value
2016-08-24 09:46:29 +00:00
* @ throws WC_Data_Exception
2014-06-13 13:35:53 +00:00
*/
2016-06-21 19:03:56 +00:00
public function set_currency ( $value ) {
2016-08-17 10:44:56 +00:00
if ( $value && ! in_array ( $value , array_keys ( get_woocommerce_currencies () ) ) ) {
2016-08-25 12:05:27 +00:00
$this -> error ( 'order_invalid_currency' , __ ( 'Invalid currency code' , 'woocommerce' ) );
2016-08-17 10:44:56 +00:00
}
2016-11-17 11:26:24 +00:00
$this -> set_prop ( 'currency' , $value ? $value : get_woocommerce_currency () );
2014-06-13 13:35:53 +00:00
}
/**
2016-11-17 11:26:24 +00:00
* Set prices_include_tax .
*
2016-06-21 19:03:56 +00:00
* @ param bool $value
2016-08-24 09:46:29 +00:00
* @ throws WC_Data_Exception
2014-06-13 13:35:53 +00:00
*/
2016-06-21 19:03:56 +00:00
public function set_prices_include_tax ( $value ) {
2016-11-17 11:26:24 +00:00
$this -> set_prop ( 'prices_include_tax' , ( bool ) $value );
2014-06-13 13:35:53 +00:00
}
/**
2016-11-17 11:26:24 +00:00
* Set date_created .
*
2017-06-06 21:30:20 +00:00
* @ 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 there is no date .
2016-08-24 09:46:29 +00:00
* @ throws WC_Data_Exception
2014-06-13 13:35:53 +00:00
*/
2017-03-08 16:51:10 +00:00
public function set_date_created ( $date = null ) {
$this -> set_date_prop ( 'date_created' , $date );
2014-06-13 13:35:53 +00:00
}
/**
2016-11-17 11:26:24 +00:00
* Set date_modified .
*
2017-06-06 21:30:20 +00:00
* @ 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 there is no date .
2016-08-24 09:46:29 +00:00
* @ throws WC_Data_Exception
2014-06-13 13:35:53 +00:00
*/
2017-03-08 16:51:10 +00:00
public function set_date_modified ( $date = null ) {
$this -> set_date_prop ( 'date_modified' , $date );
2014-06-13 13:35:53 +00:00
}
/**
2016-11-17 11:26:24 +00:00
* Set discount_total .
*
2016-06-21 19:03:56 +00:00
* @ param string $value
2016-08-24 09:46:29 +00:00
* @ throws WC_Data_Exception
2014-06-13 13:35:53 +00:00
*/
2016-06-21 19:03:56 +00:00
public function set_discount_total ( $value ) {
2016-11-17 11:26:24 +00:00
$this -> set_prop ( 'discount_total' , wc_format_decimal ( $value ) );
2014-06-13 13:35:53 +00:00
}
/**
2016-11-17 11:26:24 +00:00
* Set discount_tax .
*
2016-06-21 19:03:56 +00:00
* @ param string $value
2016-08-24 09:46:29 +00:00
* @ throws WC_Data_Exception
2014-06-13 13:35:53 +00:00
*/
2016-06-21 19:03:56 +00:00
public function set_discount_tax ( $value ) {
2016-11-17 11:26:24 +00:00
$this -> set_prop ( 'discount_tax' , wc_format_decimal ( $value ) );
2014-06-13 13:35:53 +00:00
}
2016-06-21 19:03:56 +00:00
/**
2016-11-17 11:26:24 +00:00
* Set shipping_total .
*
2016-06-21 19:03:56 +00:00
* @ param string $value
2016-08-24 09:46:29 +00:00
* @ throws WC_Data_Exception
2016-06-21 19:03:56 +00:00
*/
public function set_shipping_total ( $value ) {
2016-11-17 11:26:24 +00:00
$this -> set_prop ( 'shipping_total' , wc_format_decimal ( $value ) );
2014-06-13 13:35:53 +00:00
}
2016-06-21 19:03:56 +00:00
/**
2016-11-17 11:26:24 +00:00
* Set shipping_tax .
*
2016-06-21 19:03:56 +00:00
* @ param string $value
2016-08-24 09:46:29 +00:00
* @ throws WC_Data_Exception
2016-06-21 19:03:56 +00:00
*/
public function set_shipping_tax ( $value ) {
2016-11-17 11:26:24 +00:00
$this -> set_prop ( 'shipping_tax' , wc_format_decimal ( $value ) );
2017-01-04 18:45:45 +00:00
$this -> set_total_tax ( ( float ) $this -> get_cart_tax () + ( float ) $this -> get_shipping_tax () );
2016-06-21 19:03:56 +00:00
}
2014-06-13 13:35:53 +00:00
/**
2016-11-17 11:26:24 +00:00
* Set cart tax .
*
2016-06-21 19:03:56 +00:00
* @ param string $value
2016-08-24 09:46:29 +00:00
* @ throws WC_Data_Exception
2014-06-13 13:35:53 +00:00
*/
2016-06-21 19:03:56 +00:00
public function set_cart_tax ( $value ) {
2016-11-17 11:26:24 +00:00
$this -> set_prop ( 'cart_tax' , wc_format_decimal ( $value ) );
2017-01-04 18:45:45 +00:00
$this -> set_total_tax ( ( float ) $this -> get_cart_tax () + ( float ) $this -> get_shipping_tax () );
2016-06-21 19:03:56 +00:00
}
/**
2017-07-17 10:10:52 +00:00
* Sets order tax ( sum of cart and shipping tax ) . Used internally only .
2016-11-17 11:26:24 +00:00
*
2016-06-21 19:03:56 +00:00
* @ param string $value
2016-08-24 09:46:29 +00:00
* @ throws WC_Data_Exception
2016-06-21 19:03:56 +00:00
*/
protected function set_total_tax ( $value ) {
2016-11-17 11:26:24 +00:00
$this -> set_prop ( 'total_tax' , wc_format_decimal ( $value ) );
2016-06-21 19:03:56 +00:00
}
2014-06-13 13:35:53 +00:00
2016-06-21 19:03:56 +00:00
/**
2016-11-17 11:26:24 +00:00
* Set total .
*
2016-06-21 19:03:56 +00:00
* @ param string $value
* @ param string $deprecated Function used to set different totals based on this .
2017-05-12 08:48:46 +00:00
*
* @ return bool | void
2016-08-24 09:46:29 +00:00
* @ throws WC_Data_Exception
2016-06-21 19:03:56 +00:00
*/
public function set_total ( $value , $deprecated = '' ) {
if ( $deprecated ) {
2017-03-15 16:36:53 +00:00
wc_deprecated_argument ( 'total_type' , '3.0' , 'Use dedicated total setter methods instead.' );
2016-06-21 19:03:56 +00:00
return $this -> legacy_set_total ( $value , $deprecated );
2015-11-30 15:16:23 +00:00
}
2016-11-17 11:26:24 +00:00
$this -> set_prop ( 'total' , wc_format_decimal ( $value , wc_get_price_decimals () ) );
2016-06-21 19:03:56 +00:00
}
2015-11-30 15:16:23 +00:00
2016-06-21 19:03:56 +00:00
/*
|--------------------------------------------------------------------------
| Order Item Handling
|--------------------------------------------------------------------------
|
| Order items are used for products , taxes , shipping , and fees within
| each order .
*/
2015-11-30 15:16:23 +00:00
2016-06-21 19:03:56 +00:00
/**
* Remove all line items ( products , coupons , shipping , taxes ) from the order .
2017-02-01 13:54:18 +00:00
*
2016-06-21 19:03:56 +00:00
* @ param string $type Order item type . Default null .
*/
public function remove_order_items ( $type = null ) {
if ( ! empty ( $type ) ) {
2016-11-17 12:34:39 +00:00
$this -> data_store -> delete_items ( $this , $type );
2016-08-12 15:48:48 +00:00
if ( $group = $this -> type_to_group ( $type ) ) {
2017-02-01 13:54:18 +00:00
unset ( $this -> items [ $group ] );
2016-08-12 15:48:48 +00:00
}
2016-06-21 19:03:56 +00:00
} else {
2016-11-17 12:34:39 +00:00
$this -> data_store -> delete_items ( $this );
2017-02-01 13:54:18 +00:00
$this -> items = array ();
2016-06-21 19:03:56 +00:00
}
}
2014-06-13 13:35:53 +00:00
2016-06-21 19:03:56 +00:00
/**
2016-08-12 15:48:48 +00:00
* Convert a type to a types group .
2017-02-01 13:54:18 +00:00
*
2016-08-12 15:48:48 +00:00
* @ param string $type
* @ return string group
2016-06-21 19:03:56 +00:00
*/
2016-08-12 15:48:48 +00:00
protected function type_to_group ( $type ) {
2017-03-20 09:37:06 +00:00
$type_to_group = apply_filters ( 'woocommerce_order_type_to_group' , array (
2016-08-09 13:15:04 +00:00
'line_item' => 'line_items' ,
'tax' => 'tax_lines' ,
'shipping' => 'shipping_lines' ,
'fee' => 'fee_lines' ,
'coupon' => 'coupon_lines' ,
2017-03-20 09:37:06 +00:00
) );
2016-08-12 15:48:48 +00:00
return isset ( $type_to_group [ $type ] ) ? $type_to_group [ $type ] : '' ;
}
2016-08-09 13:15:04 +00:00
2016-08-12 15:48:48 +00:00
/**
* Return an array of items / products within this order .
2017-02-01 13:54:18 +00:00
*
2016-08-12 15:48:48 +00:00
* @ param string | array $types Types of line items to get ( array or string ) .
* @ return Array of WC_Order_item
*/
public function get_items ( $types = 'line_item' ) {
2016-08-09 13:02:40 +00:00
$items = array ();
2016-08-09 13:21:54 +00:00
$types = array_filter ( ( array ) $types );
2016-08-09 13:02:40 +00:00
foreach ( $types as $type ) {
2016-08-12 15:48:48 +00:00
if ( $group = $this -> type_to_group ( $type ) ) {
2017-02-01 13:54:18 +00:00
if ( ! isset ( $this -> items [ $group ] ) ) {
2017-08-10 14:33:01 +00:00
$this -> items [ $group ] = array_filter ( $this -> data_store -> read_items ( $this , $type ) );
2016-08-09 13:21:54 +00:00
}
2016-08-19 12:43:33 +00:00
// Don't use array_merge here because keys are numeric
2017-08-10 14:33:01 +00:00
$items = $items + $this -> items [ $group ];
2016-08-09 13:15:04 +00:00
}
2016-08-09 13:02:40 +00:00
}
return apply_filters ( 'woocommerce_order_get_items' , $items , $this );
}
2015-11-30 15:16:23 +00:00
/**
2016-06-21 19:03:56 +00:00
* Return an array of fees within this order .
2017-02-01 13:54:18 +00:00
*
2016-06-21 19:03:56 +00:00
* @ return array
2015-11-30 15:16:23 +00:00
*/
2016-06-21 19:03:56 +00:00
public function get_fees () {
return $this -> get_items ( 'fee' );
2015-11-30 15:16:23 +00:00
}
2014-06-13 13:35:53 +00:00
/**
2016-06-21 19:03:56 +00:00
* Return an array of taxes within this order .
2017-02-01 13:54:18 +00:00
*
2016-06-21 19:03:56 +00:00
* @ return array
2014-06-13 13:35:53 +00:00
*/
2016-06-21 19:03:56 +00:00
public function get_taxes () {
return $this -> get_items ( 'tax' );
2014-06-13 13:35:53 +00:00
}
/**
2016-06-21 19:03:56 +00:00
* Return an array of shipping costs within this order .
2017-02-01 13:54:18 +00:00
*
2016-06-21 19:03:56 +00:00
* @ return array
2014-06-13 13:35:53 +00:00
*/
2016-06-21 19:03:56 +00:00
public function get_shipping_methods () {
return $this -> get_items ( 'shipping' );
}
2014-06-13 13:35:53 +00:00
2016-06-21 19:03:56 +00:00
/**
* Gets formatted shipping method title .
2017-02-01 13:54:18 +00:00
*
2016-06-21 19:03:56 +00:00
* @ return string
*/
public function get_shipping_method () {
$names = array ();
foreach ( $this -> get_shipping_methods () as $shipping_method ) {
$names [] = $shipping_method -> get_name ();
2014-06-13 13:35:53 +00:00
}
2016-06-21 19:03:56 +00:00
return apply_filters ( 'woocommerce_order_shipping_method' , implode ( ', ' , $names ), $this );
2015-10-29 15:34:33 +00:00
}
2014-06-13 13:35:53 +00:00
2015-10-29 15:34:33 +00:00
/**
2016-06-21 19:03:56 +00:00
* Get coupon codes only .
2017-02-01 13:54:18 +00:00
*
2016-06-21 19:03:56 +00:00
* @ return array
2015-10-29 15:34:33 +00:00
*/
2016-06-21 19:03:56 +00:00
public function get_used_coupons () {
2016-06-23 14:52:12 +00:00
$coupon_codes = array ();
if ( $coupons = $this -> get_items ( 'coupon' ) ) {
foreach ( $coupons as $coupon ) {
$coupon_codes [] = $coupon -> get_code ();
}
}
return $coupon_codes ;
2014-06-13 13:35:53 +00:00
}
/**
2016-06-21 19:03:56 +00:00
* Gets the count of order items of a certain type .
2014-06-13 13:35:53 +00:00
*
2016-06-21 19:03:56 +00:00
* @ param string $item_type
2014-06-13 13:35:53 +00:00
* @ return string
*/
2016-06-21 19:03:56 +00:00
public function get_item_count ( $item_type = '' ) {
$items = $this -> get_items ( empty ( $item_type ) ? 'line_item' : $item_type );
$count = 0 ;
2014-06-13 13:35:53 +00:00
2016-06-21 19:03:56 +00:00
foreach ( $items as $item ) {
2016-08-16 11:36:38 +00:00
$count += $item -> get_quantity ();
2014-06-13 13:35:53 +00:00
}
2016-06-21 19:03:56 +00:00
return apply_filters ( 'woocommerce_get_item_count' , $count , $item_type , $this );
}
2014-06-13 13:35:53 +00:00
2016-06-21 19:03:56 +00:00
/**
2017-06-28 05:28:23 +00:00
* Get an order item object , based on it ' s type .
2017-02-01 13:54:18 +00:00
*
2017-03-15 16:36:53 +00:00
* @ since 3.0 . 0
2017-08-10 13:38:02 +00:00
* @ param int $item_id ID of item to get .
* @ param bool $load_from_db Prior to 3.2 this item was loaded direct from WC_Order_Factory , not this object . This param is here for backwards compatility with that . If false , uses the local items variable instead .
* @ return WC_Order_Item | false
2016-06-21 19:03:56 +00:00
*/
2017-08-10 13:38:02 +00:00
public function get_item ( $item_id , $load_from_db = true ) {
if ( $load_from_db ) {
return WC_Order_Factory :: get_order_item ( $item_id );
}
2017-08-10 14:33:01 +00:00
// Search for item id.
if ( $this -> items ) {
foreach ( $this -> items as $group => $items ) {
if ( isset ( $items [ $item_id ] ) ) {
return $items [ $item_id ];
}
}
}
// Load all items of type and cache.
2017-08-10 13:38:02 +00:00
$type = $this -> data_store -> get_order_item_type ( $this , $item_id );
if ( ! $type ) {
return false ;
}
$items = $this -> get_items ( $type );
return ! empty ( $items [ $item_id ] ) ? $items [ $item_id ] : false ;
2014-06-13 13:35:53 +00:00
}
2016-08-09 13:02:40 +00:00
/**
2016-08-17 15:53:01 +00:00
* Get key for where a certain item type is stored in _items .
2017-02-01 13:54:18 +00:00
*
2017-03-15 16:36:53 +00:00
* @ since 3.0 . 0
2016-08-17 15:53:01 +00:00
* @ param $item object Order item ( product , shipping , fee , coupon , tax )
* @ return string
2016-08-09 13:02:40 +00:00
*/
2016-08-17 15:53:01 +00:00
protected function get_items_key ( $item ) {
2016-08-09 13:02:40 +00:00
if ( is_a ( $item , 'WC_Order_Item_Product' ) ) {
2016-08-17 15:53:01 +00:00
return 'line_items' ;
2016-08-09 13:02:40 +00:00
} elseif ( is_a ( $item , 'WC_Order_Item_Fee' ) ) {
2016-08-17 15:53:01 +00:00
return 'fee_lines' ;
2016-08-09 13:02:40 +00:00
} elseif ( is_a ( $item , 'WC_Order_Item_Shipping' ) ) {
2016-08-17 15:53:01 +00:00
return 'shipping_lines' ;
2016-08-09 13:02:40 +00:00
} elseif ( is_a ( $item , 'WC_Order_Item_Tax' ) ) {
2016-08-17 15:53:01 +00:00
return 'tax_lines' ;
2016-08-09 13:02:40 +00:00
} elseif ( is_a ( $item , 'WC_Order_Item_Coupon' ) ) {
2016-08-17 15:53:01 +00:00
return 'coupon_lines' ;
}
2017-05-23 18:16:30 +00:00
return apply_filters ( 'woocommerce_get_items_key' , '' , $item );
2016-08-17 15:53:01 +00:00
}
/**
* Remove item from the order .
2017-02-01 13:54:18 +00:00
*
2016-08-17 15:53:01 +00:00
* @ param int $item_id
2017-05-12 08:48:46 +00:00
* @ return false | void
2016-08-17 15:53:01 +00:00
*/
public function remove_item ( $item_id ) {
$item = $this -> get_item ( $item_id );
if ( ! $item || ! ( $items_key = $this -> get_items_key ( $item ) ) ) {
return false ;
}
// Unset and remove later
2016-09-09 12:34:49 +00:00
$this -> items_to_delete [] = $item ;
unset ( $this -> items [ $items_key ][ $item -> get_id () ] );
2016-08-17 15:53:01 +00:00
}
/**
* Adds an order item to this order . The order item will not persist until save .
2017-02-01 13:54:18 +00:00
*
2017-03-15 16:36:53 +00:00
* @ since 3.0 . 0
2016-08-22 13:51:53 +00:00
* @ param WC_Order_Item Order item object ( product , shipping , fee , coupon , tax )
2017-05-12 08:48:46 +00:00
*
2017-08-10 14:33:01 +00:00
* @ return false | void
2016-08-17 15:53:01 +00:00
*/
public function add_item ( $item ) {
if ( ! $items_key = $this -> get_items_key ( $item ) ) {
2016-08-09 13:02:40 +00:00
return false ;
}
// Make sure existing items are loaded so we can append this new one.
2017-02-01 13:54:18 +00:00
if ( ! isset ( $this -> items [ $items_key ] ) ) {
2016-09-09 12:34:49 +00:00
$this -> items [ $items_key ] = $this -> get_items ( $item -> get_type () );
2016-08-09 13:02:40 +00:00
}
2016-11-23 13:11:51 +00:00
// Set parent.
$item -> set_order_id ( $this -> get_id () );
2017-08-10 14:33:01 +00:00
// Append new row with generated temporary ID.
2017-02-01 09:53:53 +00:00
if ( $item_id = $item -> get_id () ) {
$this -> items [ $items_key ][ $item_id ] = $item ;
2016-08-15 10:02:25 +00:00
} else {
2017-05-08 16:44:10 +00:00
$this -> items [ $items_key ][ 'new:' . $items_key . sizeof ( $this -> items [ $items_key ] ) ] = $item ;
2016-08-15 10:02:25 +00:00
}
2016-08-09 13:02:40 +00:00
}
2017-08-10 13:22:27 +00:00
/**
* Apply a coupon to the order and recalculate totals .
*
* @ since 3.2 . 0
2017-08-23 13:25:41 +00:00
* @ param string | WC_Coupon $raw_coupon Coupon code or object .
2017-08-10 13:22:27 +00:00
* @ return true | WP_Error True if applied , error if not .
*/
2017-08-23 13:25:41 +00:00
public function apply_coupon ( $raw_coupon ) {
if ( is_a ( $raw_coupon , 'WC_Coupon' ) ) {
$coupon = $raw_coupon ;
} elseif ( is_string ( $raw_coupon ) ) {
$code = wc_format_coupon_code ( $raw_coupon );
2017-08-10 14:33:01 +00:00
$coupon = new WC_Coupon ( $code );
2017-08-10 13:22:27 +00:00
if ( $coupon -> get_code () !== $code || ! $coupon -> is_valid () ) {
return new WP_Error ( 'invalid_coupon' , __ ( 'Invalid coupon code' , 'woocommerce' ) );
}
2017-08-23 13:25:41 +00:00
} else {
return new WP_Error ( 'invalid_coupon' , __ ( 'Invalid coupon' , 'woocommerce' ) );
2017-08-10 13:22:27 +00:00
}
2017-08-10 18:14:01 +00:00
// Check to make sure coupon is not already applied.
$applied_coupons = $this -> get_items ( 'coupon' );
foreach ( $applied_coupons as $applied_coupon ) {
if ( $applied_coupon -> get_code () === $coupon -> get_code () ) {
return new WP_Error ( 'invalid_coupon' , __ ( 'Coupon code already applied!' , 'woocommerce' ) );
}
}
2017-08-10 13:22:27 +00:00
$discounts = new WC_Discounts ( $this );
2017-08-18 09:36:10 +00:00
$applied = $discounts -> apply_coupon ( $coupon );
2017-08-10 13:22:27 +00:00
if ( is_wp_error ( $applied ) ) {
return $applied ;
}
2017-08-14 14:57:51 +00:00
$this -> set_coupon_discount_amounts ( $discounts );
2017-08-25 17:21:27 +00:00
$this -> set_item_discount_amounts ( $discounts );
2017-08-10 13:22:27 +00:00
2017-08-14 14:57:51 +00:00
// Recalculate totals and taxes.
$this -> calculate_totals ( true );
// Record usage so counts and validation is correct.
if ( ! $used_by = $this -> get_user_id () ) {
$used_by = $this -> get_billing_email ();
2017-08-09 15:19:10 +00:00
}
2017-08-09 17:53:06 +00:00
2017-08-14 14:57:51 +00:00
$coupon -> increase_usage_count ( $used_by );
2017-08-10 13:22:27 +00:00
return true ;
2017-08-09 15:19:10 +00:00
}
2017-08-09 21:55:35 +00:00
/**
* Remove a coupon from the order and recalculate totals .
*
2017-08-10 10:38:09 +00:00
* Coupons affect line item totals , but there is no relationship between
* coupon and line total , so to remove a coupon we need to work from the
* line subtotal ( price before discount ) and re - apply all coupons in this
* order .
*
* Manual discounts are not affected ; those are separate and do not affect
* stored line totals .
*
2017-08-10 13:38:02 +00:00
* @ since 3.2 . 0
* @ param string $code Coupon code .
2017-08-09 21:55:35 +00:00
* @ return void
*/
public function remove_coupon ( $code ) {
2017-08-10 10:38:09 +00:00
$coupons = $this -> get_items ( 'coupon' );
// Remove the coupon line.
foreach ( $coupons as $item_id => $coupon ) {
if ( $coupon -> get_code () === $code ) {
$this -> remove_item ( $item_id );
2017-08-10 18:27:13 +00:00
$coupon_object = new WC_Coupon ( $code );
$coupon_object -> decrease_usage_count ( $this -> get_user_id () );
2017-08-25 15:05:01 +00:00
$this -> recalculate_coupons ();
2017-08-10 10:38:09 +00:00
break ;
}
}
}
/**
* Apply all coupons in this order again to all line items .
*
* @ since 3.2 . 0
*/
protected function recalculate_coupons () {
2017-08-14 14:57:51 +00:00
// Reset line item totals.
foreach ( $this -> get_items () as $item ) {
$item -> set_total ( $item -> get_subtotal () );
$item -> set_total_tax ( $item -> get_subtotal_tax () );
}
2017-08-10 10:38:09 +00:00
2017-08-24 16:08:45 +00:00
$discounts = new WC_Discounts ( $this );
foreach ( $this -> get_items ( 'coupon' ) as $coupon_item ) {
$coupon_code = $coupon_item -> get_code ();
$coupon_id = wc_get_coupon_id_by_code ( $coupon_code );
$coupon_object = false ;
2017-08-25 13:42:56 +00:00
// If we have a coupon ID (loaded via wc_get_coupon_id_by_code) we can simply load the new coupon object using the ID.
2017-08-24 16:08:45 +00:00
if ( $coupon_id ) {
$coupon_object = new WC_Coupon ( $coupon_id );
2017-08-25 13:42:56 +00:00
2017-08-25 17:21:27 +00:00
} else {
2017-08-25 15:05:01 +00:00
// If we do not have a coupon ID (was it virtual? has it been deleted?) we must create a temporary coupon using what data we have stored during checkout.
2017-08-24 16:08:45 +00:00
$coupon_object = new WC_Coupon ();
2017-08-25 17:21:27 +00:00
$coupon_object -> set_props ( ( array ) $coupon_item -> get_meta ( 'coupon_data' , true ) );
2017-08-24 16:08:45 +00:00
$coupon_object -> set_code ( $coupon_code );
2017-08-25 15:07:07 +00:00
$coupon_object -> set_virtual ( true );
2017-08-24 16:08:45 +00:00
2017-08-25 13:42:56 +00:00
// If there is no coupon amount (maybe dynamic?), set it to the given **discount** amount so the coupon's same value is applied.
2017-08-24 16:08:45 +00:00
if ( ! $coupon_object -> get_amount () ) {
2017-08-25 17:21:27 +00:00
// If the order originally had prices including tax, remove the discount + discount tax.
if ( $this -> get_prices_include_tax () ) {
$coupon_object -> set_amount ( $coupon_item -> get_discount () + $coupon_item -> get_discount_tax () );
} else {
$coupon_object -> set_amount ( $coupon_item -> get_discount () );
}
2017-08-24 16:08:45 +00:00
$coupon_object -> set_discount_type ( 'fixed_cart' );
}
}
/**
* Allow developers to filter this coupon before it get ' s re - applied to the order .
*
* @ since 3.2 . 0
*/
$coupon_object = apply_filters ( 'woocommerce_order_recalculate_coupons_coupon_object' , $coupon_object , $coupon_code , $coupon_item , $this );
if ( $coupon_object ) {
$discounts -> apply_coupon ( $coupon_object );
}
}
$this -> set_coupon_discount_amounts ( $discounts );
2017-08-25 17:21:27 +00:00
$this -> set_item_discount_amounts ( $discounts );
// Recalculate totals and taxes.
$this -> calculate_totals ( true );
}
2017-08-24 16:08:45 +00:00
2017-08-25 17:21:27 +00:00
/**
* After applying coupons via the WC_Disounts class , update line items .
*
* @ since 3.2 . 0
* @ param WC_Discounts $discounts Discounts class .
*/
protected function set_item_discount_amounts ( $discounts ) {
2017-08-14 14:57:51 +00:00
if ( $item_discounts = $discounts -> get_discounts_by_item () ) {
2017-08-10 11:06:03 +00:00
foreach ( $item_discounts as $item_id => $amount ) {
2017-08-10 13:38:02 +00:00
$item = $this -> get_item ( $item_id , false );
2017-08-25 17:21:27 +00:00
// If the prices include tax, discounts should be taken off the tax inclusive prices like in the cart.
2017-08-29 11:38:35 +00:00
if ( $this -> get_prices_include_tax () && wc_tax_enabled () ) {
2017-08-25 17:21:27 +00:00
$amount_tax = WC_Tax :: get_tax_total ( WC_Tax :: calc_tax ( $amount , WC_Tax :: get_rates ( $item -> get_tax_class () ), true ) );
$amount -= $amount_tax ;
$item -> set_total ( max ( 0 , $item -> get_total () - $amount ) );
} else {
$item -> set_total ( max ( 0 , $item -> get_total () - $amount ) );
}
2017-08-10 11:06:03 +00:00
}
}
2017-08-14 14:57:51 +00:00
}
/**
* After applying coupons via the WC_Disounts class , update or create coupon items .
*
* @ since 3.2 . 0
* @ param WC_Discounts $discounts Discounts class .
*/
protected function set_coupon_discount_amounts ( $discounts ) {
$coupons = $this -> get_items ( 'coupon' );
$coupon_code_to_id = wc_list_pluck ( $coupons , 'get_id' , 'get_code' );
$all_discounts = $discounts -> get_discounts ();
$coupon_discounts = $discounts -> get_discounts_by_coupon ();
2017-08-10 11:06:03 +00:00
if ( $coupon_discounts ) {
foreach ( $coupon_discounts as $coupon_code => $amount ) {
2017-08-14 14:57:51 +00:00
$item_id = isset ( $coupon_code_to_id [ $coupon_code ] ) ? $coupon_code_to_id [ $coupon_code ] : 0 ;
if ( ! $item_id ) {
$coupon_item = new WC_Order_Item_Coupon ();
$coupon_item -> set_code ( $coupon_code );
} else {
$coupon_item = $this -> get_item ( $item_id , false );
}
2017-08-25 17:21:27 +00:00
$discount_tax = 0 ;
2017-08-14 14:57:51 +00:00
// Work out how much tax has been removed as a result of the discount from this coupon.
2017-08-25 17:21:27 +00:00
foreach ( $all_discounts [ $coupon_code ] as $item_id => $item_discount_amount ) {
$item = $this -> get_item ( $item_id , false );
2017-08-29 11:38:35 +00:00
if ( $this -> get_prices_include_tax () && wc_tax_enabled () ) {
2017-08-25 17:21:27 +00:00
$amount_tax = array_sum ( WC_Tax :: calc_tax ( $item_discount_amount , WC_Tax :: get_rates ( $item -> get_tax_class () ), true ) );
$discount_tax += $amount_tax ;
$amount = $amount - $amount_tax ;
} else {
2017-08-14 14:57:51 +00:00
$discount_tax += array_sum ( WC_Tax :: calc_tax ( $item_discount_amount , WC_Tax :: get_rates ( $item -> get_tax_class () ) ) );
}
}
2017-08-25 17:21:27 +00:00
$coupon_item -> set_discount ( $amount );
$coupon_item -> set_discount_tax ( $discount_tax );
2017-08-14 14:57:51 +00:00
$this -> add_item ( $coupon_item );
2017-08-09 21:55:35 +00:00
}
}
}
2016-08-22 17:00:52 +00:00
/**
* Add a product line item to the order . This is the only line item type with
* it ' s own method because it saves looking up order amounts ( costs are added up for you ) .
2017-02-01 13:54:18 +00:00
*
2016-08-22 17:00:52 +00:00
* @ param \WC_Product $product
* @ param int $qty
* @ param array $args
* @ return int order item ID
2016-08-24 15:02:19 +00:00
* @ throws WC_Data_Exception
2016-08-22 17:00:52 +00:00
*/
public function add_product ( $product , $qty = 1 , $args = array () ) {
if ( $product ) {
$default_args = array (
2016-11-16 12:17:00 +00:00
'name' => $product -> get_name (),
2016-08-22 17:00:52 +00:00
'tax_class' => $product -> get_tax_class (),
2016-11-09 12:26:46 +00:00
'product_id' => $product -> is_type ( 'variation' ) ? $product -> get_parent_id () : $product -> get_id (),
'variation_id' => $product -> is_type ( 'variation' ) ? $product -> get_id () : 0 ,
'variation' => $product -> is_type ( 'variation' ) ? $product -> get_attributes () : array (),
2016-11-11 18:30:18 +00:00
'subtotal' => wc_get_price_excluding_tax ( $product , array ( 'qty' => $qty ) ),
'total' => wc_get_price_excluding_tax ( $product , array ( 'qty' => $qty ) ),
2016-08-22 17:00:52 +00:00
'quantity' => $qty ,
);
} else {
$default_args = array (
'quantity' => $qty ,
);
}
$args = wp_parse_args ( $args , $default_args );
// BW compatibility with old args
if ( isset ( $args [ 'totals' ] ) ) {
foreach ( $args [ 'totals' ] as $key => $value ) {
if ( 'tax' === $key ) {
$args [ 'total_tax' ] = $value ;
} elseif ( 'tax_data' === $key ) {
$args [ 'taxes' ] = $value ;
} else {
$args [ $key ] = $value ;
}
}
}
2016-11-17 21:30:34 +00:00
$item = new WC_Order_Item_Product ();
$item -> set_props ( $args );
2016-08-22 17:00:52 +00:00
$item -> set_backorder_meta ();
$item -> set_order_id ( $this -> get_id () );
$item -> save ();
$this -> add_item ( $item );
2017-03-15 16:36:53 +00:00
wc_do_deprecated_action ( 'woocommerce_order_add_product' , array ( $this -> get_id (), $item -> get_id (), $product , $qty , $args ), '3.0' , 'woocommerce_new_order_item action instead' );
2016-08-22 17:00:52 +00:00
return $item -> get_id ();
}
2016-08-15 10:02:25 +00:00
/*
|--------------------------------------------------------------------------
| Payment Token Handling
|--------------------------------------------------------------------------
|
| Payment tokens are hashes used to take payments by certain gateways .
|
*/
2015-05-01 11:42:29 +00:00
/**
2016-06-21 19:03:56 +00:00
* Add a payment token to an order
*
* @ since 2.6
* @ param WC_Payment_Token $token Payment token object
* @ return boolean | int The new token ID or false if it failed .
2015-05-01 11:42:29 +00:00
*/
2016-06-21 19:03:56 +00:00
public function add_payment_token ( $token ) {
if ( empty ( $token ) || ! ( $token instanceof WC_Payment_Token ) ) {
return false ;
}
2015-05-01 11:42:29 +00:00
2016-11-17 12:34:39 +00:00
$token_ids = $this -> data_store -> get_payment_token_ids ( $this );
2016-06-21 19:03:56 +00:00
$token_ids [] = $token -> get_id ();
2016-11-17 12:34:39 +00:00
$this -> data_store -> update_payment_token_ids ( $this , $token_ids );
2016-06-21 19:03:56 +00:00
do_action ( 'woocommerce_payment_token_added_to_order' , $this -> get_id (), $token -> get_id (), $token , $token_ids );
return $token -> get_id ();
2015-05-01 11:42:29 +00:00
}
2014-06-13 13:35:53 +00:00
/**
2016-06-21 19:03:56 +00:00
* Returns a list of all payment tokens associated with the current order
2014-08-31 05:49:58 +00:00
*
2016-06-21 19:03:56 +00:00
* @ since 2.6
* @ return array An array of payment token objects
2014-06-13 13:35:53 +00:00
*/
2016-06-21 19:03:56 +00:00
public function get_payment_tokens () {
2016-11-18 20:27:59 +00:00
return $this -> data_store -> get_payment_token_ids ( $this );
2014-06-13 13:35:53 +00:00
}
2016-06-21 19:03:56 +00:00
/*
|--------------------------------------------------------------------------
| Calculations .
|--------------------------------------------------------------------------
|
| These methods calculate order totals and taxes based on the current data .
|
*/
2014-06-13 13:35:53 +00:00
/**
2016-06-21 19:03:56 +00:00
* Calculate shipping total .
2014-06-13 13:35:53 +00:00
*
2016-06-21 19:03:56 +00:00
* @ since 2.2
* @ return float
*/
public function calculate_shipping () {
$shipping_total = 0 ;
2015-04-23 10:50:09 +00:00
2016-06-21 19:03:56 +00:00
foreach ( $this -> get_shipping_methods () as $shipping ) {
$shipping_total += $shipping -> get_total ();
2014-06-13 13:35:53 +00:00
}
2016-06-21 19:03:56 +00:00
$this -> set_shipping_total ( $shipping_total );
$this -> save ();
return $this -> get_shipping_total ();
2014-06-13 13:35:53 +00:00
}
2016-08-03 11:32:27 +00:00
/**
* Get all tax classes for items in the order .
*
* @ since 2.6 . 3
* @ return array
*/
public function get_items_tax_classes () {
$found_tax_classes = array ();
2015-04-23 10:50:09 +00:00
2016-08-03 11:32:27 +00:00
foreach ( $this -> get_items () as $item ) {
2017-08-03 06:44:02 +00:00
if ( ( $product = $item -> get_product () ) && ( $product -> is_taxable () || $product -> is_shipping_taxable () ) ) {
$found_tax_classes [] = $product -> get_tax_class ();
2016-08-03 11:32:27 +00:00
}
2014-06-13 13:35:53 +00:00
}
2017-08-10 13:22:27 +00:00
return array_unique ( $found_tax_classes );
}
2014-06-13 13:35:53 +00:00
/**
2017-07-27 09:49:47 +00:00
* Get tax location for this order .
2014-06-13 13:35:53 +00:00
*
2017-07-27 09:49:47 +00:00
* @ since 3.2 . 0
* @ param $args array Override the location .
* @ return array
2016-06-21 19:03:56 +00:00
*/
2017-07-27 09:49:47 +00:00
protected function get_tax_location ( $args = array () ) {
2016-11-17 12:34:39 +00:00
$tax_based_on = get_option ( 'woocommerce_tax_based_on' );
2017-06-01 19:51:55 +00:00
if ( 'shipping' === $tax_based_on && ! $this -> get_shipping_country () ) {
$tax_based_on = 'billing' ;
}
2017-07-27 09:49:47 +00:00
$args = wp_parse_args ( $args , array (
2016-06-21 19:03:56 +00:00
'country' => 'billing' === $tax_based_on ? $this -> get_billing_country () : $this -> get_shipping_country (),
'state' => 'billing' === $tax_based_on ? $this -> get_billing_state () : $this -> get_shipping_state (),
'postcode' => 'billing' === $tax_based_on ? $this -> get_billing_postcode () : $this -> get_shipping_postcode (),
'city' => 'billing' === $tax_based_on ? $this -> get_billing_city () : $this -> get_shipping_city (),
) );
// Default to base
if ( 'base' === $tax_based_on || empty ( $args [ 'country' ] ) ) {
$default = wc_get_base_location ();
$args [ 'country' ] = $default [ 'country' ];
$args [ 'state' ] = $default [ 'state' ];
$args [ 'postcode' ] = '' ;
$args [ 'city' ] = '' ;
2014-09-17 11:24:05 +00:00
}
2017-07-27 09:49:47 +00:00
return $args ;
}
/**
* Calculate taxes for all line items and shipping , and store the totals and tax rows .
*
* If by default the taxes are based on the shipping address and the current order doesn ' t
* have any , it would use the billing address rather than using the Shopping base location .
*
* Will use the base country unless customer addresses are set .
*
* @ param array $args Added in 3.0 . 0 to pass things like location .
*/
public function calculate_taxes ( $args = array () ) {
$calculate_tax_for = $this -> get_tax_location ( $args );
$shipping_tax_class = get_option ( 'woocommerce_shipping_tax_class' );
if ( 'inherit' === $shipping_tax_class ) {
2017-08-10 13:22:27 +00:00
$shipping_tax_class = current ( array_intersect ( array_merge ( array ( '' ), WC_Tax :: get_tax_class_slugs () ), $this -> get_items_tax_classes () ) );
2017-07-27 09:49:47 +00:00
}
// Trigger tax recalculation for all items.
2017-08-18 09:36:10 +00:00
foreach ( $this -> get_items ( array ( 'line_item' , 'fee' ) ) as $item_id => $item ) {
2017-07-27 09:49:47 +00:00
$item -> calculate_taxes ( $calculate_tax_for );
2015-12-07 10:12:17 +00:00
}
2014-07-28 03:23:59 +00:00
2017-08-10 15:33:21 +00:00
foreach ( $this -> get_shipping_methods () as $item_id => $item ) {
2017-07-27 09:49:47 +00:00
$item -> calculate_taxes ( array_merge ( $calculate_tax_for , array ( 'tax_class' => $shipping_tax_class ) ) );
2016-02-29 12:33:09 +00:00
}
2017-07-27 09:49:47 +00:00
2016-06-21 19:03:56 +00:00
$this -> update_taxes ();
}
2014-09-09 17:00:37 +00:00
2016-06-21 19:03:56 +00:00
/**
* Update tax lines for the order based on the line item taxes themselves .
*/
public function update_taxes () {
$cart_taxes = array ();
$shipping_taxes = array ();
2017-02-23 14:14:50 +00:00
$existing_taxes = $this -> get_taxes ();
$saved_rate_ids = array ();
2014-06-13 13:35:53 +00:00
2017-08-18 09:36:10 +00:00
foreach ( $this -> get_items ( array ( 'line_item' , 'fee' ) ) as $item_id => $item ) {
2016-06-21 19:03:56 +00:00
$taxes = $item -> get_taxes ();
foreach ( $taxes [ 'total' ] as $tax_rate_id => $tax ) {
2017-04-15 16:01:37 +00:00
$cart_taxes [ $tax_rate_id ] = isset ( $cart_taxes [ $tax_rate_id ] ) ? $cart_taxes [ $tax_rate_id ] + ( float ) $tax : ( float ) $tax ;
2016-06-21 19:03:56 +00:00
}
2016-03-03 17:04:20 +00:00
}
2014-06-13 13:35:53 +00:00
2016-06-21 19:03:56 +00:00
foreach ( $this -> get_shipping_methods () as $item_id => $item ) {
$taxes = $item -> get_taxes ();
foreach ( $taxes [ 'total' ] as $tax_rate_id => $tax ) {
2017-04-15 16:01:37 +00:00
$shipping_taxes [ $tax_rate_id ] = isset ( $shipping_taxes [ $tax_rate_id ] ) ? $shipping_taxes [ $tax_rate_id ] + ( float ) $tax : ( float ) $tax ;
2016-06-21 19:03:56 +00:00
}
}
2014-06-13 13:35:53 +00:00
2017-02-23 14:14:50 +00:00
foreach ( $existing_taxes as $tax ) {
// Remove taxes which no longer exist for cart/shipping.
2017-02-23 15:25:49 +00:00
if ( ( ! array_key_exists ( $tax -> get_rate_id (), $cart_taxes ) && ! array_key_exists ( $tax -> get_rate_id (), $shipping_taxes ) ) || in_array ( $tax -> get_rate_id (), $saved_rate_ids ) ) {
2017-02-23 14:14:50 +00:00
$this -> remove_item ( $tax -> get_id () );
continue ;
}
2017-02-23 15:25:49 +00:00
$saved_rate_ids [] = $tax -> get_rate_id ();
$tax -> set_tax_total ( isset ( $cart_taxes [ $tax -> get_rate_id () ] ) ? $cart_taxes [ $tax -> get_rate_id () ] : 0 );
$tax -> set_shipping_tax_total ( ! empty ( $shipping_taxes [ $tax -> get_rate_id () ] ) ? $shipping_taxes [ $tax -> get_rate_id () ] : 0 );
2017-02-23 14:14:50 +00:00
$tax -> save ();
}
$new_rate_ids = wp_parse_id_list ( array_diff ( array_keys ( $cart_taxes + $shipping_taxes ), $saved_rate_ids ) );
2014-06-13 13:35:53 +00:00
2017-02-23 14:14:50 +00:00
// New taxes.
foreach ( $new_rate_ids as $tax_rate_id ) {
2016-08-22 15:48:19 +00:00
$item = new WC_Order_Item_Tax ();
$item -> set_rate ( $tax_rate_id );
$item -> set_tax_total ( isset ( $cart_taxes [ $tax_rate_id ] ) ? $cart_taxes [ $tax_rate_id ] : 0 );
2017-02-15 12:10:31 +00:00
$item -> set_shipping_tax_total ( ! empty ( $shipping_taxes [ $tax_rate_id ] ) ? $shipping_taxes [ $tax_rate_id ] : 0 );
2016-08-22 15:48:19 +00:00
$this -> add_item ( $item );
2016-06-21 19:03:56 +00:00
}
2014-07-03 11:38:55 +00:00
2017-07-27 09:49:47 +00:00
// Save tax totals.
2016-06-21 19:03:56 +00:00
$this -> set_shipping_tax ( WC_Tax :: round ( array_sum ( $shipping_taxes ) ) );
$this -> set_cart_tax ( WC_Tax :: round ( array_sum ( $cart_taxes ) ) );
$this -> save ();
}
2014-08-31 05:49:58 +00:00
2016-06-21 19:03:56 +00:00
/**
* Calculate totals by looking at the contents of the order . Stores the totals and returns the orders final total .
*
* @ since 2.2
* @ param bool $and_taxes Calc taxes if true .
* @ return float calculated grand total .
*/
public function calculate_totals ( $and_taxes = true ) {
2017-08-09 17:53:06 +00:00
$cart_subtotal = 0 ;
$cart_total = 0 ;
$fee_total = 0 ;
2017-08-11 15:16:09 +00:00
$shipping_total = 0 ;
2017-08-09 17:53:06 +00:00
$cart_subtotal_tax = 0 ;
$cart_total_tax = 0 ;
2017-08-11 15:16:09 +00:00
// Sum line item costs.
foreach ( $this -> get_items () as $item ) {
$cart_subtotal += $item -> get_subtotal ();
$cart_total += $item -> get_total ();
}
// Sum shipping costs.
foreach ( $this -> get_shipping_methods () as $shipping ) {
$shipping_total += $shipping -> get_total ();
}
$this -> set_shipping_total ( $shipping_total );
2017-08-23 11:15:06 +00:00
// Sum fee costs.
foreach ( $this -> get_fees () as $item ) {
$amount = $item -> get_amount ();
if ( 0 > $amount ) {
2017-08-23 11:24:33 +00:00
$item -> set_total ( $amount );
2017-08-23 11:15:06 +00:00
$max_discount = round ( $cart_total + $fee_total + $shipping_total , wc_get_price_decimals () ) * - 1 ;
if ( $item -> get_total () < $max_discount ) {
$item -> set_total ( $max_discount );
}
}
$fee_total += $item -> get_total ();
}
2017-08-09 17:53:06 +00:00
// Calculate taxes for items, shipping, discounts.
2017-05-15 13:55:39 +00:00
if ( $and_taxes ) {
2016-06-21 19:03:56 +00:00
$this -> calculate_taxes ();
}
2014-07-03 11:38:55 +00:00
2017-08-11 15:16:09 +00:00
// Sum taxes.
2016-06-21 19:03:56 +00:00
foreach ( $this -> get_items () as $item ) {
2016-08-19 12:43:33 +00:00
$cart_subtotal_tax += $item -> get_subtotal_tax ();
$cart_total_tax += $item -> get_total_tax ();
2016-06-21 19:03:56 +00:00
}
2014-08-31 05:49:58 +00:00
2017-08-18 09:36:10 +00:00
$this -> set_discount_total ( $cart_subtotal - $cart_total );
$this -> set_discount_tax ( $cart_subtotal_tax - $cart_total_tax );
$this -> set_total ( round ( $cart_total + $fee_total + $this -> get_shipping_total () + $this -> get_cart_tax () + $this -> get_shipping_tax (), wc_get_price_decimals () ) );
2016-06-21 19:03:56 +00:00
$this -> save ();
2014-06-13 13:35:53 +00:00
2017-08-11 15:16:09 +00:00
return $this -> get_total ();
2014-06-13 13:35:53 +00:00
}
/**
2016-06-21 19:03:56 +00:00
* Get item subtotal - this is the cost before discount .
2014-06-13 13:35:53 +00:00
*
2016-06-21 19:03:56 +00:00
* @ param object $item
* @ param bool $inc_tax ( default : false ) .
* @ param bool $round ( default : true ) .
* @ return float
2014-06-13 13:35:53 +00:00
*/
2016-06-21 19:03:56 +00:00
public function get_item_subtotal ( $item , $inc_tax = false , $round = true ) {
$subtotal = 0 ;
2014-06-13 13:35:53 +00:00
2016-06-21 19:03:56 +00:00
if ( is_callable ( array ( $item , 'get_subtotal' ) ) ) {
if ( $inc_tax ) {
2016-08-16 11:36:38 +00:00
$subtotal = ( $item -> get_subtotal () + $item -> get_subtotal_tax () ) / max ( 1 , $item -> get_quantity () );
2016-06-21 19:03:56 +00:00
} else {
2017-05-04 08:09:16 +00:00
$subtotal = ( floatval ( $item -> get_subtotal () ) / max ( 1 , $item -> get_quantity () ) );
2016-06-21 19:03:56 +00:00
}
2014-06-13 13:35:53 +00:00
2016-06-21 19:03:56 +00:00
$subtotal = $round ? number_format ( ( float ) $subtotal , wc_get_price_decimals (), '.' , '' ) : $subtotal ;
}
2014-06-13 13:35:53 +00:00
2016-06-21 19:03:56 +00:00
return apply_filters ( 'woocommerce_order_amount_item_subtotal' , $subtotal , $this , $item , $inc_tax , $round );
}
2014-06-13 13:35:53 +00:00
2016-06-21 19:03:56 +00:00
/**
* Get line subtotal - this is the cost before discount .
*
* @ param object $item
* @ param bool $inc_tax ( default : false ) .
* @ param bool $round ( default : true ) .
* @ return float
*/
public function get_line_subtotal ( $item , $inc_tax = false , $round = true ) {
$subtotal = 0 ;
2014-06-13 13:35:53 +00:00
2016-06-21 19:03:56 +00:00
if ( is_callable ( array ( $item , 'get_subtotal' ) ) ) {
if ( $inc_tax ) {
$subtotal = $item -> get_subtotal () + $item -> get_subtotal_tax ();
} else {
$subtotal = $item -> get_subtotal ();
2014-06-13 13:35:53 +00:00
}
2016-06-21 19:03:56 +00:00
$subtotal = $round ? round ( $subtotal , wc_get_price_decimals () ) : $subtotal ;
}
2014-06-13 13:35:53 +00:00
2016-06-21 19:03:56 +00:00
return apply_filters ( 'woocommerce_order_amount_line_subtotal' , $subtotal , $this , $item , $inc_tax , $round );
}
2014-06-13 13:35:53 +00:00
2016-06-21 19:03:56 +00:00
/**
* Calculate item cost - useful for gateways .
*
* @ param object $item
* @ param bool $inc_tax ( default : false ) .
* @ param bool $round ( default : true ) .
* @ return float
*/
public function get_item_total ( $item , $inc_tax = false , $round = true ) {
$total = 0 ;
2014-06-13 13:35:53 +00:00
2016-06-21 19:03:56 +00:00
if ( is_callable ( array ( $item , 'get_total' ) ) ) {
if ( $inc_tax ) {
2016-08-16 11:36:38 +00:00
$total = ( $item -> get_total () + $item -> get_total_tax () ) / max ( 1 , $item -> get_quantity () );
2016-06-21 19:03:56 +00:00
} else {
2017-05-04 08:09:16 +00:00
$total = floatval ( $item -> get_total () ) / max ( 1 , $item -> get_quantity () );
2014-06-13 13:35:53 +00:00
}
2016-06-21 19:03:56 +00:00
$total = $round ? round ( $total , wc_get_price_decimals () ) : $total ;
2014-06-13 13:35:53 +00:00
}
2016-06-21 19:03:56 +00:00
return apply_filters ( 'woocommerce_order_amount_item_total' , $total , $this , $item , $inc_tax , $round );
}
2014-06-13 13:35:53 +00:00
/**
2016-06-21 19:03:56 +00:00
* Calculate line total - useful for gateways .
*
* @ param object $item
* @ param bool $inc_tax ( default : false ) .
* @ param bool $round ( default : true ) .
* @ return float
2014-06-13 13:35:53 +00:00
*/
2016-06-21 19:03:56 +00:00
public function get_line_total ( $item , $inc_tax = false , $round = true ) {
$total = 0 ;
2014-06-13 13:35:53 +00:00
2016-06-21 19:03:56 +00:00
if ( is_callable ( array ( $item , 'get_total' ) ) ) {
// Check if we need to add line tax to the line total.
$total = $inc_tax ? $item -> get_total () + $item -> get_total_tax () : $item -> get_total ();
2014-08-31 05:49:58 +00:00
2016-06-21 19:03:56 +00:00
// Check if we need to round.
$total = $round ? round ( $total , wc_get_price_decimals () ) : $total ;
}
2014-08-31 05:49:58 +00:00
2016-06-21 19:03:56 +00:00
return apply_filters ( 'woocommerce_order_amount_line_total' , $total , $this , $item , $inc_tax , $round );
}
2014-08-31 05:49:58 +00:00
2016-06-21 19:03:56 +00:00
/**
* Get item tax - useful for gateways .
*
* @ param mixed $item
* @ param bool $round ( default : true ) .
* @ return float
*/
public function get_item_tax ( $item , $round = true ) {
$tax = 0 ;
2014-06-13 13:35:53 +00:00
2016-06-21 19:03:56 +00:00
if ( is_callable ( array ( $item , 'get_total_tax' ) ) ) {
2016-08-16 11:36:38 +00:00
$tax = $item -> get_total_tax () / max ( 1 , $item -> get_quantity () );
2016-06-21 19:03:56 +00:00
$tax = $round ? wc_round_tax_total ( $tax ) : $tax ;
}
2015-11-19 16:07:04 +00:00
2016-06-21 19:03:56 +00:00
return apply_filters ( 'woocommerce_order_amount_item_tax' , $tax , $item , $round , $this );
2014-06-13 13:35:53 +00:00
}
2016-06-21 19:03:56 +00:00
/**
* Get line tax - useful for gateways .
*
* @ param mixed $item
* @ return float
*/
public function get_line_tax ( $item ) {
return apply_filters ( 'woocommerce_order_amount_line_tax' , is_callable ( array ( $item , 'get_total_tax' ) ) ? wc_round_tax_total ( $item -> get_total_tax () ) : 0 , $item , $this );
}
2014-06-13 13:35:53 +00:00
/**
2016-06-21 19:03:56 +00:00
* Gets line subtotal - formatted for display .
2014-06-13 13:35:53 +00:00
*
2016-06-21 19:03:56 +00:00
* @ param array $item
* @ param string $tax_display
* @ return string
2014-06-13 13:35:53 +00:00
*/
2016-06-21 19:03:56 +00:00
public function get_formatted_line_subtotal ( $item , $tax_display = '' ) {
$tax_display = $tax_display ? $tax_display : get_option ( 'woocommerce_tax_display_cart' );
2014-06-13 13:35:53 +00:00
2016-06-21 19:03:56 +00:00
if ( 'excl' == $tax_display ) {
$ex_tax_label = $this -> get_prices_include_tax () ? 1 : 0 ;
2014-06-13 13:35:53 +00:00
2016-06-21 19:03:56 +00:00
$subtotal = wc_price ( $this -> get_line_subtotal ( $item ), array ( 'ex_tax_label' => $ex_tax_label , 'currency' => $this -> get_currency () ) );
} else {
2016-08-27 02:23:54 +00:00
$subtotal = wc_price ( $this -> get_line_subtotal ( $item , true ), array ( 'currency' => $this -> get_currency () ) );
2014-06-13 13:35:53 +00:00
}
2016-06-21 19:03:56 +00:00
return apply_filters ( 'woocommerce_order_formatted_line_subtotal' , $subtotal , $item , $this );
2014-06-13 13:35:53 +00:00
}
2016-06-21 19:03:56 +00:00
/**
* Gets order total - formatted for display .
* @ return string
*/
public function get_formatted_order_total () {
$formatted_total = wc_price ( $this -> get_total (), array ( 'currency' => $this -> get_currency () ) );
return apply_filters ( 'woocommerce_get_formatted_order_total' , $formatted_total , $this );
}
2014-06-13 13:35:53 +00:00
/**
2016-06-21 19:03:56 +00:00
* Gets subtotal - subtotal is shown before discounts , but with localised taxes .
*
* @ param bool $compound ( default : false ) .
* @ param string $tax_display ( default : the tax_display_cart value ) .
* @ return string
2014-06-13 13:35:53 +00:00
*/
2016-06-21 19:03:56 +00:00
public function get_subtotal_to_display ( $compound = false , $tax_display = '' ) {
$tax_display = $tax_display ? $tax_display : get_option ( 'woocommerce_tax_display_cart' );
$subtotal = 0 ;
2014-06-13 13:35:53 +00:00
2016-06-21 19:03:56 +00:00
if ( ! $compound ) {
foreach ( $this -> get_items () as $item ) {
$subtotal += $item -> get_subtotal ();
2014-08-31 05:49:58 +00:00
2016-06-21 19:03:56 +00:00
if ( 'incl' === $tax_display ) {
$subtotal += $item -> get_subtotal_tax ();
2014-06-13 13:35:53 +00:00
}
2016-06-21 19:03:56 +00:00
}
2014-06-13 13:35:53 +00:00
2016-06-21 19:03:56 +00:00
$subtotal = wc_price ( $subtotal , array ( 'currency' => $this -> get_currency () ) );
2014-06-13 13:35:53 +00:00
2016-06-21 19:03:56 +00:00
if ( 'excl' === $tax_display && $this -> get_prices_include_tax () ) {
$subtotal .= ' <small class="tax_label">' . WC () -> countries -> ex_tax_or_vat () . '</small>' ;
}
} else {
if ( 'incl' === $tax_display ) {
return '' ;
}
foreach ( $this -> get_items () as $item ) {
$subtotal += $item -> get_subtotal ();
}
// Add Shipping Costs.
$subtotal += $this -> get_shipping_total ();
2014-06-13 13:35:53 +00:00
2016-06-21 19:03:56 +00:00
// Remove non-compound taxes.
foreach ( $this -> get_taxes () as $tax ) {
2017-04-18 11:00:21 +00:00
if ( $tax -> is_compound () ) {
2016-06-21 19:03:56 +00:00
continue ;
}
$subtotal = $subtotal + $tax -> get_tax_total () + $tax -> get_shipping_tax_total ();
2014-06-13 13:35:53 +00:00
}
2016-06-21 19:03:56 +00:00
// Remove discounts.
$subtotal = $subtotal - $this -> get_total_discount ();
$subtotal = wc_price ( $subtotal , array ( 'currency' => $this -> get_currency () ) );
2015-01-30 14:14:34 +00:00
}
2014-06-13 13:35:53 +00:00
2016-06-21 19:03:56 +00:00
return apply_filters ( 'woocommerce_order_subtotal_to_display' , $subtotal , $compound , $this );
}
2014-06-13 13:35:53 +00:00
/**
2016-06-21 19:03:56 +00:00
* Gets shipping ( formatted ) .
*
2017-05-15 11:50:52 +00:00
* @ param string $tax_display
*
2016-06-21 19:03:56 +00:00
* @ return string
2014-06-13 13:35:53 +00:00
*/
2016-06-21 19:03:56 +00:00
public function get_shipping_to_display ( $tax_display = '' ) {
$tax_display = $tax_display ? $tax_display : get_option ( 'woocommerce_tax_display_cart' );
2014-06-13 13:35:53 +00:00
2016-06-21 19:03:56 +00:00
if ( $this -> get_shipping_total () != 0 ) {
2014-06-13 13:35:53 +00:00
2016-09-07 22:32:24 +00:00
if ( 'excl' === $tax_display ) {
2014-08-31 05:49:58 +00:00
2016-06-21 19:03:56 +00:00
// Show shipping excluding tax.
2016-08-27 02:23:54 +00:00
$shipping = wc_price ( $this -> get_shipping_total (), array ( 'currency' => $this -> get_currency () ) );
2014-08-31 05:49:58 +00:00
2016-06-21 19:03:56 +00:00
if ( $this -> get_shipping_tax () != 0 && $this -> get_prices_include_tax () ) {
$shipping .= apply_filters ( 'woocommerce_order_shipping_to_display_tax_label' , ' <small class="tax_label">' . WC () -> countries -> ex_tax_or_vat () . '</small>' , $this , $tax_display );
2014-06-13 13:35:53 +00:00
}
2016-06-21 19:03:56 +00:00
} else {
// Show shipping including tax.
2016-08-27 02:23:54 +00:00
$shipping = wc_price ( $this -> get_shipping_total () + $this -> get_shipping_tax (), array ( 'currency' => $this -> get_currency () ) );
2014-06-13 13:35:53 +00:00
2016-06-21 19:03:56 +00:00
if ( $this -> get_shipping_tax () != 0 && ! $this -> get_prices_include_tax () ) {
$shipping .= apply_filters ( 'woocommerce_order_shipping_to_display_tax_label' , ' <small class="tax_label">' . WC () -> countries -> inc_tax_or_vat () . '</small>' , $this , $tax_display );
2014-06-13 13:35:53 +00:00
}
}
2017-09-04 16:42:31 +00:00
/* translators: %s: method */
2016-06-21 19:03:56 +00:00
$shipping .= apply_filters ( 'woocommerce_order_shipping_to_display_shipped_via' , ' <small class="shipped_via">' . sprintf ( __ ( 'via %s' , 'woocommerce' ), $this -> get_shipping_method () ) . '</small>' , $this );
} elseif ( $this -> get_shipping_method () ) {
$shipping = $this -> get_shipping_method ();
} else {
$shipping = __ ( 'Free!' , 'woocommerce' );
2015-01-30 14:14:34 +00:00
}
2016-06-21 19:03:56 +00:00
return apply_filters ( 'woocommerce_order_shipping_to_display' , $shipping , $this );
2014-06-13 13:35:53 +00:00
}
/**
2016-06-21 19:03:56 +00:00
* Get the discount amount ( formatted ) .
* @ since 2.3 . 0
2017-05-15 11:50:52 +00:00
*
* @ param string $tax_display
*
2016-06-21 19:03:56 +00:00
* @ return string
2014-06-13 13:35:53 +00:00
*/
2016-06-21 19:03:56 +00:00
public function get_discount_to_display ( $tax_display = '' ) {
$tax_display = $tax_display ? $tax_display : get_option ( 'woocommerce_tax_display_cart' );
return apply_filters ( 'woocommerce_order_discount_to_display' , wc_price ( $this -> get_total_discount ( 'excl' === $tax_display && 'excl' === get_option ( 'woocommerce_tax_display_cart' ) ), array ( 'currency' => $this -> get_currency () ) ), $this );
2014-06-13 13:35:53 +00:00
}
/**
2017-03-06 13:44:52 +00:00
* Add total row for subtotal .
2014-06-13 13:35:53 +00:00
*
2017-03-06 13:44:52 +00:00
* @ param array $total_rows
* @ param string $tax_display
2014-06-13 13:35:53 +00:00
*/
2017-03-06 13:44:52 +00:00
protected function add_order_item_totals_subtotal_row ( & $total_rows , $tax_display ) {
2016-06-21 19:03:56 +00:00
if ( $subtotal = $this -> get_subtotal_to_display ( false , $tax_display ) ) {
$total_rows [ 'cart_subtotal' ] = array (
'label' => __ ( 'Subtotal:' , 'woocommerce' ),
'value' => $subtotal ,
);
2014-06-13 13:35:53 +00:00
}
2017-03-06 13:44:52 +00:00
}
2014-06-13 13:35:53 +00:00
2017-03-06 13:44:52 +00:00
/**
* Add total row for discounts .
*
* @ param array $total_rows
* @ param string $tax_display
*/
protected function add_order_item_totals_discount_row ( & $total_rows , $tax_display ) {
2016-06-21 19:03:56 +00:00
if ( $this -> get_total_discount () > 0 ) {
$total_rows [ 'discount' ] = array (
'label' => __ ( 'Discount:' , 'woocommerce' ),
'value' => '-' . $this -> get_discount_to_display ( $tax_display ),
);
}
2017-03-06 13:44:52 +00:00
}
2014-06-13 13:35:53 +00:00
2017-03-06 13:44:52 +00:00
/**
* Add total row for shipping .
*
* @ param array $total_rows
* @ param string $tax_display
*/
protected function add_order_item_totals_shipping_row ( & $total_rows , $tax_display ) {
2016-06-21 19:03:56 +00:00
if ( $this -> get_shipping_method () ) {
$total_rows [ 'shipping' ] = array (
'label' => __ ( 'Shipping:' , 'woocommerce' ),
'value' => $this -> get_shipping_to_display ( $tax_display ),
);
2014-06-13 13:35:53 +00:00
}
2017-03-06 13:44:52 +00:00
}
2014-08-31 05:49:58 +00:00
2017-03-06 13:44:52 +00:00
/**
* Add total row for fees .
*
* @ param array $total_rows
* @ param string $tax_display
*/
protected function add_order_item_totals_fee_rows ( & $total_rows , $tax_display ) {
2016-06-21 19:03:56 +00:00
if ( $fees = $this -> get_fees () ) {
foreach ( $fees as $id => $fee ) {
if ( apply_filters ( 'woocommerce_get_order_item_totals_excl_free_fees' , empty ( $fee [ 'line_total' ] ) && empty ( $fee [ 'line_tax' ] ), $id ) ) {
continue ;
}
2016-08-03 11:57:32 +00:00
$total_rows [ 'fee_' . $fee -> get_id () ] = array (
2016-06-21 19:03:56 +00:00
'label' => $fee -> get_name () . ':' ,
2016-08-27 02:23:54 +00:00
'value' => wc_price ( 'excl' === $tax_display ? $fee -> get_total () : $fee -> get_total () + $fee -> get_total_tax (), array ( 'currency' => $this -> get_currency () ) ),
2016-06-21 19:03:56 +00:00
);
}
2014-06-13 13:35:53 +00:00
}
2017-03-06 13:44:52 +00:00
}
2015-09-21 21:28:03 +00:00
2017-03-06 13:44:52 +00:00
/**
* Add total row for taxes .
*
* @ param array $total_rows
* @ param string $tax_display
*/
protected function add_order_item_totals_tax_rows ( & $total_rows , $tax_display ) {
2016-06-21 19:03:56 +00:00
// Tax for tax exclusive prices.
if ( 'excl' === $tax_display ) {
2017-03-06 13:44:52 +00:00
if ( 'itemized' === get_option ( 'woocommerce_tax_total_display' ) ) {
2016-06-21 19:03:56 +00:00
foreach ( $this -> get_tax_totals () as $code => $tax ) {
$total_rows [ sanitize_title ( $code ) ] = array (
'label' => $tax -> label . ':' ,
'value' => $tax -> formatted_amount ,
);
}
} else {
$total_rows [ 'tax' ] = array (
'label' => WC () -> countries -> tax_or_vat () . ':' ,
'value' => wc_price ( $this -> get_total_tax (), array ( 'currency' => $this -> get_currency () ) ),
);
}
}
2017-03-06 13:44:52 +00:00
}
2014-06-13 13:35:53 +00:00
2017-03-06 13:44:52 +00:00
/**
* Add total row for grand total .
*
* @ param array $total_rows
* @ param string $tax_display
*/
protected function add_order_item_totals_total_row ( & $total_rows , $tax_display ) {
2016-06-21 19:03:56 +00:00
$total_rows [ 'order_total' ] = array (
'label' => __ ( 'Total:' , 'woocommerce' ),
'value' => $this -> get_formatted_order_total ( $tax_display ),
);
2017-03-06 13:44:52 +00:00
}
/**
* Get totals for display on pages and in emails .
*
* @ param mixed $tax_display
* @ return array
*/
public function get_order_item_totals ( $tax_display = '' ) {
$tax_display = $tax_display ? $tax_display : get_option ( 'woocommerce_tax_display_cart' );
$total_rows = array ();
$this -> add_order_item_totals_subtotal_row ( $total_rows , $tax_display );
$this -> add_order_item_totals_discount_row ( $total_rows , $tax_display );
$this -> add_order_item_totals_shipping_row ( $total_rows , $tax_display );
$this -> add_order_item_totals_fee_rows ( $total_rows , $tax_display );
$this -> add_order_item_totals_tax_rows ( $total_rows , $tax_display );
$this -> add_order_item_totals_total_row ( $total_rows , $tax_display );
2014-06-13 13:35:53 +00:00
2017-03-06 13:44:52 +00:00
return apply_filters ( 'woocommerce_get_order_item_totals' , $total_rows , $this , $tax_display );
2014-06-13 13:35:53 +00:00
}
2016-06-21 19:03:56 +00:00
/*
|--------------------------------------------------------------------------
| Conditionals
|--------------------------------------------------------------------------
|
| Checks if a condition is true or false .
|
*/
2014-06-13 13:35:53 +00:00
/**
2016-06-21 19:03:56 +00:00
* Checks the order status against a passed in status .
2014-06-13 13:35:53 +00:00
*
2017-05-15 11:50:52 +00:00
* @ param array | string $status
*
2014-06-13 13:35:53 +00:00
* @ return bool
*/
2016-06-21 19:03:56 +00:00
public function has_status ( $status ) {
return apply_filters ( 'woocommerce_order_has_status' , ( is_array ( $status ) && in_array ( $this -> get_status (), $status ) ) || $this -> get_status () === $status ? true : false , $this , $status );
2014-06-13 13:35:53 +00:00
}
/**
2016-06-21 19:03:56 +00:00
* Check whether this order has a specific shipping method or not .
2014-06-13 13:35:53 +00:00
*
2016-06-21 19:03:56 +00:00
* @ param string $method_id
* @ return bool
2014-06-13 13:35:53 +00:00
*/
2016-06-21 19:03:56 +00:00
public function has_shipping_method ( $method_id ) {
2014-06-13 13:35:53 +00:00
foreach ( $this -> get_shipping_methods () as $shipping_method ) {
2016-08-25 09:58:04 +00:00
if ( strpos ( $shipping_method -> get_method_id (), $method_id ) === 0 ) {
2016-06-21 19:03:56 +00:00
return true ;
2014-06-13 13:35:53 +00:00
}
}
2016-06-21 19:03:56 +00:00
return false ;
2014-06-13 13:35:53 +00:00
}
2014-09-02 18:47:56 +00:00
2016-06-21 19:03:56 +00:00
/**
* Returns true if the order contains a free product .
* @ since 2.5 . 0
2014-09-02 18:47:56 +00:00
* @ return bool
*/
2016-06-21 19:03:56 +00:00
public function has_free_item () {
foreach ( $this -> get_items () as $item ) {
if ( ! $item -> get_total () ) {
return true ;
}
}
return false ;
2014-09-02 18:47:56 +00:00
}
2014-07-28 03:31:26 +00:00
}