WC_Order_Item_Product

Order Line Item (product).

Defined (1)

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

/includes/class-wc-order-item-product.php  
  1. class WC_Order_Item_Product extends WC_Order_Item { 
  2.  
  3. /** 
  4. * Order Data array. This is the core order data exposed in APIs since 3.0.0. 
  5. * @since 3.0.0 
  6. * @var array 
  7. */ 
  8. protected $extra_data = array( 
  9. 'product_id' => 0,  
  10. 'variation_id' => 0,  
  11. 'quantity' => 1,  
  12. 'tax_class' => '',  
  13. 'subtotal' => 0,  
  14. 'subtotal_tax' => 0,  
  15. 'total' => 0,  
  16. 'total_tax' => 0,  
  17. 'taxes' => array( 
  18. 'subtotal' => array(),  
  19. 'total' => array(),  
  20. ),  
  21. ); 
  22.  
  23. /** 
  24. |-------------------------------------------------------------------------- 
  25. | Setters 
  26. |-------------------------------------------------------------------------- 
  27. */ 
  28.  
  29. /** 
  30. * Set quantity. 
  31. * @param int $value 
  32. * @throws WC_Data_Exception 
  33. */ 
  34. public function set_quantity( $value ) { 
  35. $this->set_prop( 'quantity', wc_stock_amount( $value ) ); 
  36.  
  37. /** 
  38. * Set tax class. 
  39. * @param string $value 
  40. * @throws WC_Data_Exception 
  41. */ 
  42. public function set_tax_class( $value ) { 
  43. if ( $value && ! in_array( $value, WC_Tax::get_tax_class_slugs() ) ) { 
  44. $this->error( 'order_item_product_invalid_tax_class', __( 'Invalid tax class', 'woocommerce' ) ); 
  45. $this->set_prop( 'tax_class', $value ); 
  46.  
  47. /** 
  48. * Set Product ID 
  49. * @param int $value 
  50. * @throws WC_Data_Exception 
  51. */ 
  52. public function set_product_id( $value ) { 
  53. if ( $value > 0 && 'product' !== get_post_type( absint( $value ) ) ) { 
  54. $this->error( 'order_item_product_invalid_product_id', __( 'Invalid product ID', 'woocommerce' ) ); 
  55. $this->set_prop( 'product_id', absint( $value ) ); 
  56.  
  57. /** 
  58. * Set variation ID. 
  59. * @param int $value 
  60. * @throws WC_Data_Exception 
  61. */ 
  62. public function set_variation_id( $value ) { 
  63. if ( $value > 0 && 'product_variation' !== get_post_type( $value ) ) { 
  64. $this->error( 'order_item_product_invalid_variation_id', __( 'Invalid variation ID', 'woocommerce' ) ); 
  65. $this->set_prop( 'variation_id', absint( $value ) ); 
  66.  
  67. /** 
  68. * Line subtotal (before discounts). 
  69. * @param string $value 
  70. * @throws WC_Data_Exception 
  71. */ 
  72. public function set_subtotal( $value ) { 
  73. $this->set_prop( 'subtotal', floatval( wc_format_decimal( $value ) ) ); 
  74.  
  75. /** 
  76. * Line total (after discounts). 
  77. * @param string $value 
  78. * @throws WC_Data_Exception 
  79. */ 
  80. public function set_total( $value ) { 
  81. $this->set_prop( 'total', floatval( wc_format_decimal( $value ) ) ); 
  82.  
  83. // Subtotal cannot be less than total 
  84. if ( ! $this->get_subtotal() || $this->get_subtotal() < $this->get_total() ) { 
  85. $this->set_subtotal( $value ); 
  86.  
  87. /** 
  88. * Line subtotal tax (before discounts). 
  89. * @param string $value 
  90. * @throws WC_Data_Exception 
  91. */ 
  92. public function set_subtotal_tax( $value ) { 
  93. $this->set_prop( 'subtotal_tax', wc_format_decimal( $value ) ); 
  94.  
  95. /** 
  96. * Line total tax (after discounts). 
  97. * @param string $value 
  98. * @throws WC_Data_Exception 
  99. */ 
  100. public function set_total_tax( $value ) { 
  101. $this->set_prop( 'total_tax', wc_format_decimal( $value ) ); 
  102.  
  103. /** 
  104. * Set line taxes and totals for passed in taxes. 
  105. * @param array $raw_tax_data 
  106. * @throws WC_Data_Exception 
  107. */ 
  108. public function set_taxes( $raw_tax_data ) { 
  109. $raw_tax_data = maybe_unserialize( $raw_tax_data ); 
  110. $tax_data = array( 
  111. 'total' => array(),  
  112. 'subtotal' => array(),  
  113. ); 
  114. if ( ! empty( $raw_tax_data['total'] ) && ! empty( $raw_tax_data['subtotal'] ) ) { 
  115. $tax_data['subtotal'] = array_map( 'wc_format_decimal', $raw_tax_data['subtotal'] ); 
  116. $tax_data['total'] = array_map( 'wc_format_decimal', $raw_tax_data['total'] ); 
  117.  
  118. // Subtotal cannot be less than total! 
  119. if ( array_sum( $tax_data['subtotal'] ) < array_sum( $tax_data['total'] ) ) { 
  120. $tax_data['subtotal'] = $tax_data['total']; 
  121. $this->set_prop( 'taxes', $tax_data ); 
  122. $this->set_total_tax( array_sum( $tax_data['total'] ) ); 
  123. $this->set_subtotal_tax( array_sum( $tax_data['subtotal'] ) ); 
  124.  
  125. /** 
  126. * Set variation data (stored as meta data - write only). 
  127. * @param array $data Key/Value pairs 
  128. */ 
  129. public function set_variation( $data ) { 
  130. foreach ( $data as $key => $value ) { 
  131. $this->add_meta_data( str_replace( 'attribute_', '', $key ), $value, true ); 
  132.  
  133. /** 
  134. * Set properties based on passed in product object. 
  135. * @param WC_Product $product 
  136. * @throws WC_Data_Exception 
  137. */ 
  138. public function set_product( $product ) { 
  139. if ( ! is_a( $product, 'WC_Product' ) ) { 
  140. $this->error( 'order_item_product_invalid_product', __( 'Invalid product', 'woocommerce' ) ); 
  141. if ( $product->is_type( 'variation' ) ) { 
  142. $this->set_product_id( $product->get_parent_id() ); 
  143. $this->set_variation_id( $product->get_id() ); 
  144. $this->set_variation( is_callable( array( $product, 'get_variation_attributes' ) ) ? $product->get_variation_attributes() : array() ); 
  145. } else { 
  146. $this->set_product_id( $product->get_id() ); 
  147. $this->set_name( $product->get_name() ); 
  148. $this->set_tax_class( $product->get_tax_class() ); 
  149.  
  150. /** 
  151. * Set meta data for backordered products. 
  152. */ 
  153. public function set_backorder_meta() { 
  154. $product = $this->get_product(); 
  155. if ( $product && $product->backorders_require_notification() && $product->is_on_backorder( $this->get_quantity() ) ) { 
  156. $this->add_meta_data( apply_filters( 'woocommerce_backordered_item_meta_name', __( 'Backordered', 'woocommerce' ) ), $this->get_quantity() - max( 0, $product->get_stock_quantity() ), true ); 
  157.  
  158. /** 
  159. |-------------------------------------------------------------------------- 
  160. | Getters 
  161. |-------------------------------------------------------------------------- 
  162. */ 
  163.  
  164. /** 
  165. * Get order item type. 
  166. * @return string 
  167. */ 
  168. public function get_type() { 
  169. return 'line_item'; 
  170.  
  171. /** 
  172. * Get product ID. 
  173. * @param string $context 
  174. * @return int 
  175. */ 
  176. public function get_product_id( $context = 'view' ) { 
  177. return $this->get_prop( 'product_id', $context ); 
  178.  
  179. /** 
  180. * Get variation ID. 
  181. * @param string $context 
  182. * @return int 
  183. */ 
  184. public function get_variation_id( $context = 'view' ) { 
  185. return $this->get_prop( 'variation_id', $context ); 
  186.  
  187. /** 
  188. * Get quantity. 
  189. * @param string $context 
  190. * @return int 
  191. */ 
  192. public function get_quantity( $context = 'view' ) { 
  193. return $this->get_prop( 'quantity', $context ); 
  194.  
  195. /** 
  196. * Get tax class. 
  197. * @param string $context 
  198. * @return string 
  199. */ 
  200. public function get_tax_class( $context = 'view' ) { 
  201. return $this->get_prop( 'tax_class', $context ); 
  202.  
  203. /** 
  204. * Get subtotal. 
  205. * @param string $context 
  206. * @return string 
  207. */ 
  208. public function get_subtotal( $context = 'view' ) { 
  209. return $this->get_prop( 'subtotal', $context ); 
  210.  
  211. /** 
  212. * Get subtotal tax. 
  213. * @param string $context 
  214. * @return string 
  215. */ 
  216. public function get_subtotal_tax( $context = 'view' ) { 
  217. return $this->get_prop( 'subtotal_tax', $context ); 
  218.  
  219. /** 
  220. * Get total. 
  221. * @param string $context 
  222. * @return string 
  223. */ 
  224. public function get_total( $context = 'view' ) { 
  225. return $this->get_prop( 'total', $context ); 
  226.  
  227. /** 
  228. * Get total tax. 
  229. * @param string $context 
  230. * @return string 
  231. */ 
  232. public function get_total_tax( $context = 'view' ) { 
  233. return $this->get_prop( 'total_tax', $context ); 
  234.  
  235. /** 
  236. * Get taxes. 
  237. * @param string $context 
  238. * @return array 
  239. */ 
  240. public function get_taxes( $context = 'view' ) { 
  241. return $this->get_prop( 'taxes', $context ); 
  242.  
  243. /** 
  244. * Get the associated product. 
  245. * @return WC_Product|bool 
  246. */ 
  247. public function get_product() { 
  248. if ( $this->get_variation_id() ) { 
  249. $product = wc_get_product( $this->get_variation_id() ); 
  250. } else { 
  251. $product = wc_get_product( $this->get_product_id() ); 
  252.  
  253. // Backwards compatible filter from WC_Order::get_product_from_item() 
  254. if ( has_filter( 'woocommerce_get_product_from_item' ) ) { 
  255. $product = apply_filters( 'woocommerce_get_product_from_item', $product, $this, $this->get_order() ); 
  256.  
  257. return apply_filters( 'woocommerce_order_item_product', $product, $this ); 
  258.  
  259. /** 
  260. * Get the Download URL. 
  261. * @param int $download_id 
  262. * @return string 
  263. */ 
  264. public function get_item_download_url( $download_id ) { 
  265. $order = $this->get_order(); 
  266.  
  267. return $order ? add_query_arg( array( 
  268. 'download_file' => $this->get_variation_id() ? $this->get_variation_id() : $this->get_product_id(),  
  269. 'order' => $order->get_order_key(),  
  270. 'email' => urlencode( $order->get_billing_email() ),  
  271. 'key' => $download_id,  
  272. ), trailingslashit( home_url() ) ) : ''; 
  273.  
  274. /** 
  275. * Get any associated downloadable files. 
  276. * @return array 
  277. */ 
  278. public function get_item_downloads() { 
  279. $files = array(); 
  280. $product = $this->get_product(); 
  281. $order = $this->get_order(); 
  282. $product_id = $this->get_variation_id() ? $this->get_variation_id() : $this->get_product_id(); 
  283.  
  284. if ( $product && $order && $product->is_downloadable() && $order->is_download_permitted() ) { 
  285. $data_store = WC_Data_Store::load( 'customer-download' ); 
  286. $customer_downloads = $data_store->get_downloads( array( 
  287. 'user_email' => $order->get_billing_email(),  
  288. 'order_id' => $order->get_id(),  
  289. 'product_id' => $product_id,  
  290. ) ); 
  291. foreach ( $customer_downloads as $customer_download ) { 
  292. $download_id = $customer_download->get_download_id(); 
  293.  
  294. if ( $product->has_file( $download_id ) ) { 
  295. $file = $product->get_file( $download_id ); 
  296. $files[ $download_id ] = $file->get_data(); 
  297. $files[ $download_id ]['download_url'] = add_query_arg( array( 
  298. 'download_file' => $product_id,  
  299. 'order' => $order->get_order_key(),  
  300. 'email' => urlencode( $order->get_billing_email() ),  
  301. 'key' => $download_id,  
  302. ), trailingslashit( home_url() ) ); 
  303.  
  304. return apply_filters( 'woocommerce_get_item_downloads', $files, $this, $order ); 
  305.  
  306. /** 
  307. * Get tax status. 
  308. * @return string 
  309. */ 
  310. public function get_tax_status() { 
  311. $product = $this->get_product(); 
  312. return $product ? $product->get_tax_status() : 'taxable'; 
  313.  
  314. /** 
  315. |-------------------------------------------------------------------------- 
  316. | Array Access Methods 
  317. |-------------------------------------------------------------------------- 
  318. | For backwards compat with legacy arrays. 
  319. */ 
  320.  
  321. /** 
  322. * offsetGet for ArrayAccess/Backwards compatibility. 
  323. * @deprecated Add deprecation notices in future release. 
  324. * @param string $offset 
  325. * @return mixed 
  326. */ 
  327. public function offsetGet( $offset ) { 
  328. if ( 'line_subtotal' === $offset ) { 
  329. $offset = 'subtotal'; 
  330. } elseif ( 'line_subtotal_tax' === $offset ) { 
  331. $offset = 'subtotal_tax'; 
  332. } elseif ( 'line_total' === $offset ) { 
  333. $offset = 'total'; 
  334. } elseif ( 'line_tax' === $offset ) { 
  335. $offset = 'total_tax'; 
  336. } elseif ( 'line_tax_data' === $offset ) { 
  337. $offset = 'taxes'; 
  338. } elseif ( 'qty' === $offset ) { 
  339. $offset = 'quantity'; 
  340. return parent::offsetGet( $offset ); 
  341.  
  342. /** 
  343. * offsetSet for ArrayAccess/Backwards compatibility. 
  344. * @deprecated Add deprecation notices in future release. 
  345. * @param string $offset 
  346. * @param mixed $value 
  347. */ 
  348. public function offsetSet( $offset, $value ) { 
  349. if ( 'line_subtotal' === $offset ) { 
  350. $offset = 'subtotal'; 
  351. } elseif ( 'line_subtotal_tax' === $offset ) { 
  352. $offset = 'subtotal_tax'; 
  353. } elseif ( 'line_total' === $offset ) { 
  354. $offset = 'total'; 
  355. } elseif ( 'line_tax' === $offset ) { 
  356. $offset = 'total_tax'; 
  357. } elseif ( 'line_tax_data' === $offset ) { 
  358. $offset = 'taxes'; 
  359. } elseif ( 'qty' === $offset ) { 
  360. $offset = 'quantity'; 
  361. parent::offsetSet( $offset, $value ); 
  362.  
  363. /** 
  364. * offsetExists for ArrayAccess 
  365. * @param string $offset 
  366. * @return bool 
  367. */ 
  368. public function offsetExists( $offset ) { 
  369. if ( in_array( $offset, array( 'line_subtotal', 'line_subtotal_tax', 'line_total', 'line_tax', 'line_tax_data', 'item_meta_array', 'item_meta', 'qty' ) ) ) { 
  370. return true; 
  371. return parent::offsetExists( $offset );