2016-06-21 19:10:09 +00:00
< ? php
if ( ! defined ( 'ABSPATH' ) ) {
exit ;
}
/**
* Order Line Item ( product ) .
*
* @ version 2.7 . 0
* @ since 2.7 . 0
* @ package WooCommerce / Classes
* @ author WooThemes
*/
class WC_Order_Item_Product extends WC_Order_Item {
/**
2016-08-25 12:31:03 +00:00
* Order Data array . This is the core order data exposed in APIs since 2.7 . 0.
2016-06-21 19:10:09 +00:00
* @ since 2.7 . 0
* @ var array
*/
2016-08-25 12:31:03 +00:00
protected $_data = array (
2016-08-16 11:36:38 +00:00
'order_id' => 0 ,
'id' => 0 ,
'name' => '' ,
'product_id' => 0 ,
'variation_id' => 0 ,
2016-08-24 15:02:19 +00:00
'quantity' => 1 ,
2016-08-16 11:36:38 +00:00
'tax_class' => '' ,
'subtotal' => 0 ,
'subtotal_tax' => 0 ,
'total' => 0 ,
'total_tax' => 0 ,
'taxes' => array (
2016-06-21 19:10:09 +00:00
'subtotal' => array (),
'total' => array ()
),
);
/**
* offsetGet for ArrayAccess / Backwards compatibility .
* @ deprecated Add deprecation notices in future release .
* @ param string $offset
* @ return mixed
*/
public function offsetGet ( $offset ) {
if ( 'line_subtotal' === $offset ) {
$offset = 'subtotal' ;
} elseif ( 'line_subtotal_tax' === $offset ) {
$offset = 'subtotal_tax' ;
} elseif ( 'line_total' === $offset ) {
$offset = 'total' ;
} elseif ( 'line_tax' === $offset ) {
$offset = 'total_tax' ;
} elseif ( 'line_tax_data' === $offset ) {
$offset = 'taxes' ;
}
return parent :: offsetGet ( $offset );
}
/**
* offsetSet for ArrayAccess / Backwards compatibility .
* @ deprecated Add deprecation notices in future release .
* @ param string $offset
* @ param mixed $value
*/
public function offsetSet ( $offset , $value ) {
if ( 'line_subtotal' === $offset ) {
$offset = 'subtotal' ;
} elseif ( 'line_subtotal_tax' === $offset ) {
$offset = 'subtotal_tax' ;
} elseif ( 'line_total' === $offset ) {
$offset = 'total' ;
} elseif ( 'line_tax' === $offset ) {
$offset = 'total_tax' ;
} elseif ( 'line_tax_data' === $offset ) {
$offset = 'taxes' ;
}
parent :: offsetSet ( $offset , $value );
}
/**
* offsetExists for ArrayAccess
* @ param string $offset
* @ return bool
*/
public function offsetExists ( $offset ) {
if ( in_array ( $offset , array ( 'line_subtotal' , 'line_subtotal_tax' , 'line_total' , 'line_tax' , 'line_tax_data' , 'item_meta_array' , 'item_meta' ) ) ) {
return true ;
}
return parent :: offsetExists ( $offset );
}
/**
* Read / populate data properties specific to this order item .
*/
public function read ( $id ) {
parent :: read ( $id );
2016-08-25 12:05:27 +00:00
if ( ! $this -> get_id () ) {
return ;
2016-06-21 19:10:09 +00:00
}
2016-08-25 12:05:27 +00:00
$this -> set_props ( array (
'product_id' => get_metadata ( 'order_item' , $this -> get_id (), '_product_id' , true ),
'variation_id' => get_metadata ( 'order_item' , $this -> get_id (), '_variation_id' , true ),
'quantity' => get_metadata ( 'order_item' , $this -> get_id (), '_qty' , true ),
'tax_class' => get_metadata ( 'order_item' , $this -> get_id (), '_tax_class' , true ),
'subtotal' => get_metadata ( 'order_item' , $this -> get_id (), '_line_subtotal' , true ),
'total' => get_metadata ( 'order_item' , $this -> get_id (), '_line_total' , true ),
'taxes' => get_metadata ( 'order_item' , $this -> get_id (), '_line_tax_data' , true ),
) );
2016-06-21 19:10:09 +00:00
}
/**
* Save properties specific to this order item .
* @ return int Item ID
*/
public function save () {
parent :: save ();
if ( $this -> get_id () ) {
wc_update_order_item_meta ( $this -> get_id (), '_product_id' , $this -> get_product_id () );
wc_update_order_item_meta ( $this -> get_id (), '_variation_id' , $this -> get_variation_id () );
2016-08-16 11:36:38 +00:00
wc_update_order_item_meta ( $this -> get_id (), '_qty' , $this -> get_quantity () );
2016-06-21 19:10:09 +00:00
wc_update_order_item_meta ( $this -> get_id (), '_tax_class' , $this -> get_tax_class () );
wc_update_order_item_meta ( $this -> get_id (), '_line_subtotal' , $this -> get_subtotal () );
wc_update_order_item_meta ( $this -> get_id (), '_line_subtotal_tax' , $this -> get_subtotal_tax () );
wc_update_order_item_meta ( $this -> get_id (), '_line_total' , $this -> get_total () );
wc_update_order_item_meta ( $this -> get_id (), '_line_tax' , $this -> get_total_tax () );
wc_update_order_item_meta ( $this -> get_id (), '_line_tax_data' , $this -> get_taxes () );
}
return $this -> get_id ();
}
/**
* Internal meta keys we don ' t want exposed as part of meta_data .
* @ return array ()
*/
protected function get_internal_meta_keys () {
return array ( '_product_id' , '_variation_id' , '_qty' , '_tax_class' , '_line_subtotal' , '_line_subtotal_tax' , '_line_total' , '_line_tax' , '_line_tax_data' );
}
/**
* Get the associated product .
* @ return WC_Product | bool
*/
public function get_product () {
if ( $this -> get_variation_id () ) {
$product = wc_get_product ( $this -> get_variation_id () );
} else {
$product = wc_get_product ( $this -> get_product_id () );
}
// Backwards compatible filter from WC_Order::get_product_from_item()
if ( has_filter ( 'woocommerce_get_product_from_item' ) ) {
$product = apply_filters ( 'woocommerce_get_product_from_item' , $product , $this , wc_get_order ( $this -> get_order_id () ) );
}
return apply_filters ( 'woocommerce_order_item_product' , $product , $this );
}
2016-08-03 11:52:45 +00:00
/**
* Get the Download URL .
* @ param int $download_id
* @ return string
*/
public function get_item_download_url ( $download_id ) {
$order = $this -> get_order ();
return $order ? add_query_arg ( array (
'download_file' => $this -> get_variation_id () ? $this -> get_variation_id () : $this -> get_product_id (),
'order' => $order -> get_order_key (),
'email' => urlencode ( $order -> get_billing_email () ),
'key' => $download_id
), trailingslashit ( home_url () ) ) : '' ;
}
2016-06-21 19:10:09 +00:00
/**
* Get any associated downloadable files .
* @ return array
*/
public function get_item_downloads () {
global $wpdb ;
$files = array ();
$product = $this -> get_product ();
2016-08-03 11:52:45 +00:00
$order = $this -> get_order ();
2016-06-21 19:10:09 +00:00
if ( $product && $order && $product -> is_downloadable () && $order -> is_download_permitted () ) {
2016-08-03 11:52:45 +00:00
$download_ids = $wpdb -> get_col (
2016-06-21 19:10:09 +00:00
$wpdb -> prepare (
" SELECT download_id FROM { $wpdb -> prefix } woocommerce_downloadable_product_permissions WHERE user_email = %s AND order_key = %s AND product_id = %d ORDER BY permission_id " ,
$order -> get_billing_email (),
$order -> get_order_key (),
2016-08-03 11:52:45 +00:00
$this -> get_variation_id () ? $this -> get_variation_id () : $this -> get_product_id ()
2016-06-21 19:10:09 +00:00
)
);
foreach ( $download_ids as $download_id ) {
if ( $product -> has_file ( $download_id ) ) {
2016-08-03 11:52:45 +00:00
$files [ $download_id ] = $product -> get_file ( $download_id );
$files [ $download_id ][ 'download_url' ] = $this -> get_item_download_url ( $download_id );
2016-06-21 19:10:09 +00:00
}
}
}
return apply_filters ( 'woocommerce_get_item_downloads' , $files , $this , $order );
}
/**
* Get tax status .
* @ return string
*/
public function get_tax_status () {
$product = $this -> get_product ();
return $product ? $product -> get_tax_status () : 'taxable' ;
}
2016-08-15 10:02:38 +00:00
/**
* Set meta data for backordered products .
*/
public function set_backorder_meta () {
2016-08-16 11:36:38 +00:00
if ( $this -> get_product () -> backorders_require_notification () && $this -> get_product () -> is_on_backorder ( $this -> get_quantity () ) ) {
$this -> add_meta_data ( apply_filters ( 'woocommerce_backordered_item_meta_name' , __ ( 'Backordered' , 'woocommerce' ) ), $this -> get_quantity () - max ( 0 , $this -> get_product () -> get_total_stock () ), true );
2016-08-15 10:02:38 +00:00
}
}
2016-06-21 19:10:09 +00:00
/*
|--------------------------------------------------------------------------
| Setters
|--------------------------------------------------------------------------
*/
/**
2016-08-16 11:36:38 +00:00
* Set quantity .
2016-06-21 19:10:09 +00:00
* @ param int $value
2016-08-24 09:46:29 +00:00
* @ throws WC_Data_Exception
2016-06-21 19:10:09 +00:00
*/
2016-08-16 11:36:38 +00:00
public function set_quantity ( $value ) {
2016-08-17 15:53:01 +00:00
if ( 0 >= $value ) {
2016-08-25 12:05:27 +00:00
$this -> error ( 'order_item_product_invalid_quantity' , __ ( 'Quantity must be positive' , 'woocommerce' ) );
2016-08-17 15:53:01 +00:00
}
2016-08-26 09:48:17 +00:00
$this -> _data [ 'quantity' ] = wc_stock_amount ( $value );
2016-06-21 19:10:09 +00:00
}
/**
* Set tax class .
* @ param string $value
2016-08-24 09:46:29 +00:00
* @ throws WC_Data_Exception
2016-06-21 19:10:09 +00:00
*/
public function set_tax_class ( $value ) {
2016-08-17 15:53:01 +00:00
if ( $value && ! in_array ( $value , WC_Tax :: get_tax_classes () ) ) {
2016-08-25 12:05:27 +00:00
$this -> error ( 'order_item_product_invalid_tax_class' , __ ( 'Invalid tax class' , 'woocommerce' ) );
2016-08-17 15:53:01 +00:00
}
2016-08-26 09:48:17 +00:00
$this -> _data [ 'tax_class' ] = $value ;
2016-06-21 19:10:09 +00:00
}
/**
* Set Product ID
* @ param int $value
2016-08-24 09:46:29 +00:00
* @ throws WC_Data_Exception
2016-06-21 19:10:09 +00:00
*/
public function set_product_id ( $value ) {
2016-08-24 13:37:19 +00:00
if ( $value > 0 && 'product' !== get_post_type ( absint ( $value ) ) ) {
2016-08-25 12:05:27 +00:00
$this -> error ( 'order_item_product_invalid_product_id' , __ ( 'Invalid product ID' , 'woocommerce' ) );
2016-08-23 13:58:44 +00:00
}
2016-08-26 09:48:17 +00:00
$this -> _data [ 'product_id' ] = absint ( $value );
2016-06-21 19:10:09 +00:00
}
/**
* Set variation ID .
* @ param int $value
2016-08-24 09:46:29 +00:00
* @ throws WC_Data_Exception
2016-06-21 19:10:09 +00:00
*/
public function set_variation_id ( $value ) {
2016-08-24 13:37:19 +00:00
if ( $value > 0 && 'product_variation' !== get_post_type ( $value ) ) {
2016-08-25 12:05:27 +00:00
$this -> error ( 'order_item_product_invalid_variation_id' , __ ( 'Invalid variation ID' , 'woocommerce' ) );
2016-08-23 13:58:44 +00:00
}
2016-08-26 09:48:17 +00:00
$this -> _data [ 'variation_id' ] = absint ( $value );
2016-06-21 19:10:09 +00:00
}
/**
* Line subtotal ( before discounts ) .
* @ param string $value
2016-08-24 09:46:29 +00:00
* @ throws WC_Data_Exception
2016-06-21 19:10:09 +00:00
*/
public function set_subtotal ( $value ) {
2016-08-26 09:48:17 +00:00
$this -> _data [ 'subtotal' ] = wc_format_decimal ( $value );
2016-06-21 19:10:09 +00:00
}
/**
* Line total ( after discounts ) .
* @ param string $value
2016-08-24 09:46:29 +00:00
* @ throws WC_Data_Exception
2016-06-21 19:10:09 +00:00
*/
public function set_total ( $value ) {
2016-08-26 09:48:17 +00:00
$this -> _data [ 'total' ] = wc_format_decimal ( $value );
2016-08-25 12:05:27 +00:00
// Subtotal cannot be less than total
2016-08-25 13:32:28 +00:00
if ( ! $this -> get_subtotal () || $this -> get_subtotal () < $this -> get_total () ) {
2016-08-25 12:05:27 +00:00
$this -> set_subtotal ( $value );
}
2016-06-21 19:10:09 +00:00
}
/**
* Line subtotal tax ( before discounts ) .
* @ param string $value
2016-08-24 09:46:29 +00:00
* @ throws WC_Data_Exception
2016-06-21 19:10:09 +00:00
*/
2016-08-25 12:05:27 +00:00
protected function set_subtotal_tax ( $value ) {
2016-08-26 09:48:17 +00:00
$this -> _data [ 'subtotal_tax' ] = wc_format_decimal ( $value );
2016-06-21 19:10:09 +00:00
}
/**
* Line total tax ( after discounts ) .
* @ param string $value
2016-08-24 09:46:29 +00:00
* @ throws WC_Data_Exception
2016-06-21 19:10:09 +00:00
*/
2016-08-25 12:05:27 +00:00
protected function set_total_tax ( $value ) {
2016-08-26 09:48:17 +00:00
$this -> _data [ 'total_tax' ] = wc_format_decimal ( $value );
2016-06-21 19:10:09 +00:00
}
/**
2016-08-25 12:05:27 +00:00
* Set line taxes and totals for passed in taxes .
2016-06-21 19:10:09 +00:00
* @ param array $raw_tax_data
2016-08-24 09:46:29 +00:00
* @ throws WC_Data_Exception
2016-06-21 19:10:09 +00:00
*/
public function set_taxes ( $raw_tax_data ) {
$raw_tax_data = maybe_unserialize ( $raw_tax_data );
$tax_data = array (
'total' => array (),
'subtotal' => array ()
);
if ( ! empty ( $raw_tax_data [ 'total' ] ) && ! empty ( $raw_tax_data [ 'subtotal' ] ) ) {
$tax_data [ 'subtotal' ] = array_map ( 'wc_format_decimal' , $raw_tax_data [ 'subtotal' ] );
2016-08-25 12:05:27 +00:00
$tax_data [ 'total' ] = array_map ( 'wc_format_decimal' , $raw_tax_data [ 'total' ] );
// Subtotal cannot be less than total!
if ( array_sum ( $tax_data [ 'subtotal' ] ) < array_sum ( $tax_data [ 'total' ] ) ) {
$tax_data [ 'subtotal' ] = $tax_data [ 'total' ];
}
2016-06-21 19:10:09 +00:00
}
2016-08-26 09:48:17 +00:00
$this -> _data [ 'taxes' ] = $tax_data ;
2016-08-25 12:05:27 +00:00
$this -> set_total_tax ( array_sum ( $tax_data [ 'total' ] ) );
$this -> set_subtotal_tax ( array_sum ( $tax_data [ 'subtotal' ] ) );
2016-06-21 19:10:09 +00:00
}
/**
* Set variation data ( stored as meta data - write only ) .
* @ param array $data Key / Value pairs
*/
public function set_variation ( $data ) {
foreach ( $data as $key => $value ) {
2016-08-08 15:20:15 +00:00
$this -> add_meta_data ( str_replace ( 'attribute_' , '' , $key ), $value , true );
2016-06-21 19:10:09 +00:00
}
}
/**
* Set properties based on passed in product object .
* @ param WC_Product $product
2016-08-24 09:46:29 +00:00
* @ throws WC_Data_Exception
2016-06-21 19:10:09 +00:00
*/
public function set_product ( $product ) {
2016-08-17 15:53:01 +00:00
if ( ! is_a ( $product , 'WC_Product' ) ) {
2016-08-25 12:05:27 +00:00
$this -> error ( 'order_item_product_invalid_product' , __ ( 'Invalid product' , 'woocommerce' ) );
2016-06-21 19:10:09 +00:00
}
2016-08-17 15:53:01 +00:00
$this -> set_product_id ( $product -> get_id () );
$this -> set_name ( $product -> get_title () );
$this -> set_tax_class ( $product -> get_tax_class () );
$this -> set_variation_id ( is_callable ( array ( $product , 'get_variation_id' ) ) ? $product -> get_variation_id () : 0 );
$this -> set_variation ( is_callable ( array ( $product , 'get_variation_attributes' ) ) ? $product -> get_variation_attributes () : array () );
2016-06-21 19:10:09 +00:00
}
/*
|--------------------------------------------------------------------------
| Getters
|--------------------------------------------------------------------------
*/
/**
* Get order item type .
* @ return string
*/
public function get_type () {
return 'line_item' ;
}
/**
* Get product ID .
* @ return int
*/
public function get_product_id () {
2016-08-26 09:48:17 +00:00
return absint ( $this -> _data [ 'product_id' ] );
2016-06-21 19:10:09 +00:00
}
/**
* Get variation ID .
* @ return int
*/
public function get_variation_id () {
2016-08-26 09:48:17 +00:00
return absint ( $this -> _data [ 'variation_id' ] );
2016-06-21 19:10:09 +00:00
}
/**
2016-08-16 11:36:38 +00:00
* Get quantity .
2016-06-21 19:10:09 +00:00
* @ return int
*/
2016-08-16 11:36:38 +00:00
public function get_quantity () {
2016-08-26 09:48:17 +00:00
return wc_stock_amount ( $this -> _data [ 'quantity' ] );
2016-06-21 19:10:09 +00:00
}
/**
* Get tax class .
* @ return string
*/
public function get_tax_class () {
2016-08-26 09:48:17 +00:00
return $this -> _data [ 'tax_class' ];
2016-06-21 19:10:09 +00:00
}
/**
* Get subtotal .
* @ return string
*/
public function get_subtotal () {
2016-08-26 09:48:17 +00:00
return wc_format_decimal ( $this -> _data [ 'subtotal' ] );
2016-06-21 19:10:09 +00:00
}
/**
* Get subtotal tax .
* @ return string
*/
public function get_subtotal_tax () {
2016-08-26 09:48:17 +00:00
return wc_format_decimal ( $this -> _data [ 'subtotal_tax' ] );
2016-06-21 19:10:09 +00:00
}
/**
* Get total .
* @ return string
*/
public function get_total () {
2016-08-26 09:48:17 +00:00
return wc_format_decimal ( $this -> _data [ 'total' ] );
2016-06-21 19:10:09 +00:00
}
/**
* Get total tax .
* @ return string
*/
public function get_total_tax () {
2016-08-26 09:48:17 +00:00
return wc_format_decimal ( $this -> _data [ 'total_tax' ] );
2016-06-21 19:10:09 +00:00
}
/**
* Get fee taxes .
* @ return array
*/
public function get_taxes () {
2016-08-26 09:48:17 +00:00
return $this -> _data [ 'taxes' ];
2016-06-21 19:10:09 +00:00
}
}