1
|
|
|
<?php |
2
|
|
|
/** |
3
|
|
|
* Abstract Order |
4
|
|
|
* |
5
|
|
|
* The WooCommerce order class handles order data. |
6
|
|
|
* |
7
|
|
|
* @class WC_Order |
8
|
|
|
* @version 2.2.0 |
9
|
|
|
* @package WooCommerce/Classes |
10
|
|
|
* @category Class |
11
|
|
|
* @author WooThemes |
12
|
|
|
* |
13
|
|
|
* @property string $billing_first_name The billing address first name. |
14
|
|
|
* @property string $billing_last_name The billing address last name. |
15
|
|
|
* @property string $billing_company The billing address company. |
16
|
|
|
* @property string $billing_address_1 The first line of the billing address. |
17
|
|
|
* @property string $billing_address_2 The second line of the billing address. |
18
|
|
|
* @property string $billing_city The city of the billing address. |
19
|
|
|
* @property string $billing_state The state of the billing address. |
20
|
|
|
* @property string $billing_postcode The postcode of the billing address. |
21
|
|
|
* @property string $billing_country The country of the billing address. |
22
|
|
|
* @property string $billing_phone The billing phone number. |
23
|
|
|
* @property string $billing_email The billing email. |
24
|
|
|
* @property string $shipping_first_name The shipping address first name. |
25
|
|
|
* @property string $shipping_last_name The shipping address last name. |
26
|
|
|
* @property string $shipping_company The shipping address company. |
27
|
|
|
* @property string $shipping_address_1 The first line of the shipping address. |
28
|
|
|
* @property string $shipping_address_2 The second line of the shipping address. |
29
|
|
|
* @property string $shipping_city The city of the shipping address. |
30
|
|
|
* @property string $shipping_state The state of the shipping address. |
31
|
|
|
* @property string $shipping_postcode The postcode of the shipping address. |
32
|
|
|
* @property string $shipping_country The country of the shipping address. |
33
|
|
|
* @property string $cart_discount Total amount of discount. |
34
|
|
|
* @property string $cart_discount_tax Total amount of discount applied to taxes. |
35
|
|
|
* @property string $shipping_method_title < 2.1 was used for shipping method title. Now @deprecated. |
36
|
|
|
* @property int $customer_user User ID who the order belongs to. 0 for guests. |
37
|
|
|
* @property string $order_key Random key/password unqique to each order. |
38
|
|
|
* @property string $order_discount Stored after tax discounts pre-2.3. Now @deprecated. |
39
|
|
|
* @property string $order_tax Stores order tax total. |
40
|
|
|
* @property string $order_shipping_tax Stores shipping tax total. |
41
|
|
|
* @property string $order_shipping Stores shipping total. |
42
|
|
|
* @property string $order_total Stores order total. |
43
|
|
|
* @property string $order_currency Stores currency code used for the order. |
44
|
|
|
* @property string $payment_method method ID. |
45
|
|
|
* @property string $payment_method_title Name of the payment method used. |
46
|
|
|
* @property string $customer_ip_address Customer IP Address. |
47
|
|
|
* @property string $customer_user_agent Customer User agent. |
48
|
|
|
*/ |
49
|
|
|
abstract class WC_Abstract_Order { |
50
|
|
|
|
51
|
|
|
/** @public int Order (post) ID. */ |
52
|
|
|
public $id = 0; |
53
|
|
|
|
54
|
|
|
/** @var $post WP_Post. */ |
55
|
|
|
public $post = null; |
56
|
|
|
|
57
|
|
|
/** @public string Order type. */ |
58
|
|
|
public $order_type = false; |
59
|
|
|
|
60
|
|
|
/** @public string Order Date. */ |
61
|
|
|
public $order_date = ''; |
62
|
|
|
|
63
|
|
|
/** @public string Order Modified Date. */ |
64
|
|
|
public $modified_date = ''; |
65
|
|
|
|
66
|
|
|
/** @public string Customer Message (excerpt). */ |
67
|
|
|
public $customer_message = ''; |
68
|
|
|
|
69
|
|
|
/** @public string Customer Note */ |
70
|
|
|
public $customer_note = ''; |
71
|
|
|
|
72
|
|
|
/** @public string Order Status. */ |
73
|
|
|
public $post_status = ''; |
74
|
|
|
|
75
|
|
|
/** @public bool Do prices include tax? */ |
76
|
|
|
public $prices_include_tax = false; |
77
|
|
|
|
78
|
|
|
/** @public string Display mode for taxes in cart. */ |
79
|
|
|
public $tax_display_cart = ''; |
80
|
|
|
|
81
|
|
|
/** @public bool Do totals display ex tax? */ |
82
|
|
|
public $display_totals_ex_tax = false; |
83
|
|
|
|
84
|
|
|
/** @public bool Do cart prices display ex tax? */ |
85
|
|
|
public $display_cart_ex_tax = false; |
86
|
|
|
|
87
|
|
|
/** @protected string Formatted address. Accessed via get_formatted_billing_address(). */ |
88
|
|
|
protected $formatted_billing_address = ''; |
89
|
|
|
|
90
|
|
|
/** @protected string Formatted address. Accessed via get_formatted_shipping_address(). */ |
91
|
|
|
protected $formatted_shipping_address = ''; |
92
|
|
|
|
93
|
|
|
/** |
94
|
|
|
* Get the order if ID is passed, otherwise the order is new and empty. |
95
|
|
|
* This class should NOT be instantiated, but the get_order function or new WC_Order_Factory. |
96
|
|
|
* should be used. It is possible, but the aforementioned are preferred and are the only. |
97
|
|
|
* methods that will be maintained going forward. |
98
|
|
|
* |
99
|
|
|
* @param int|object|WC_Order $order Order to init. |
100
|
|
|
*/ |
101
|
|
|
public function __construct( $order = 0 ) { |
102
|
|
|
$this->prices_include_tax = get_option('woocommerce_prices_include_tax') == 'yes' ? true : false; |
103
|
|
|
$this->tax_display_cart = get_option( 'woocommerce_tax_display_cart' ); |
104
|
|
|
$this->display_totals_ex_tax = $this->tax_display_cart == 'excl' ? true : false; |
105
|
|
|
$this->display_cart_ex_tax = $this->tax_display_cart == 'excl' ? true : false; |
106
|
|
|
$this->init( $order ); |
107
|
|
|
} |
108
|
|
|
|
109
|
|
|
/** |
110
|
|
|
* Init/load the order object. Called from the constructor. |
111
|
|
|
* |
112
|
|
|
* @param int|object|WC_Order $order Order to init. |
113
|
|
|
*/ |
114
|
|
View Code Duplication |
protected function init( $order ) { |
115
|
|
|
if ( is_numeric( $order ) ) { |
116
|
|
|
$this->id = absint( $order ); |
117
|
|
|
$this->post = get_post( $order ); |
118
|
|
|
$this->get_order( $this->id ); |
119
|
|
|
} elseif ( $order instanceof WC_Order ) { |
120
|
|
|
$this->id = absint( $order->id ); |
121
|
|
|
$this->post = $order->post; |
122
|
|
|
$this->get_order( $this->id ); |
123
|
|
|
} elseif ( isset( $order->ID ) ) { |
124
|
|
|
$this->id = absint( $order->ID ); |
125
|
|
|
$this->post = $order; |
126
|
|
|
$this->get_order( $this->id ); |
127
|
|
|
} |
128
|
|
|
} |
129
|
|
|
|
130
|
|
|
/** |
131
|
|
|
* Remove all line items (products, coupons, shipping, taxes) from the order. |
132
|
|
|
* |
133
|
|
|
* @param string $type Order item type. Default null. |
134
|
|
|
*/ |
135
|
|
|
public function remove_order_items( $type = null ) { |
136
|
|
|
global $wpdb; |
137
|
|
|
|
138
|
|
|
if ( ! empty( $type ) ) { |
139
|
|
|
$wpdb->query( $wpdb->prepare( "DELETE FROM itemmeta USING {$wpdb->prefix}woocommerce_order_itemmeta itemmeta INNER JOIN {$wpdb->prefix}woocommerce_order_items items WHERE itemmeta.order_item_id = items.order_item_id AND items.order_id = %d AND items.order_item_type = %s", $this->id, $type ) ); |
140
|
|
|
$wpdb->query( $wpdb->prepare( "DELETE FROM {$wpdb->prefix}woocommerce_order_items WHERE order_id = %d AND order_item_type = %s", $this->id, $type ) ); |
141
|
|
|
} else { |
142
|
|
|
$wpdb->query( $wpdb->prepare( "DELETE FROM itemmeta USING {$wpdb->prefix}woocommerce_order_itemmeta itemmeta INNER JOIN {$wpdb->prefix}woocommerce_order_items items WHERE itemmeta.order_item_id = items.order_item_id and items.order_id = %d", $this->id ) ); |
143
|
|
|
$wpdb->query( $wpdb->prepare( "DELETE FROM {$wpdb->prefix}woocommerce_order_items WHERE order_id = %d", $this->id ) ); |
144
|
|
|
} |
145
|
|
|
} |
146
|
|
|
|
147
|
|
|
/** |
148
|
|
|
* Returns a list of all payment tokens associated with the current order |
149
|
|
|
* |
150
|
|
|
* @since 2.6 |
151
|
|
|
* @return array An array of payment token objects |
152
|
|
|
*/ |
153
|
|
|
public function get_payment_tokens() { |
154
|
|
|
return WC_Payment_Tokens::get_order_tokens( $this->id ); |
155
|
|
|
} |
156
|
|
|
|
157
|
|
|
/** |
158
|
|
|
* Add a payment token to an order |
159
|
|
|
* |
160
|
|
|
* @since 2.6 |
161
|
|
|
* @param WC_Payment_Token $token Payment token object |
162
|
|
|
* @return boolean True if the token was added, false if not |
163
|
|
|
*/ |
164
|
|
|
public function add_payment_token( $token ) { |
165
|
|
|
if ( empty( $token ) || ! ( $token instanceof WC_Payment_Token ) ) { |
166
|
|
|
return false; |
167
|
|
|
} |
168
|
|
|
|
169
|
|
|
$token_ids = get_post_meta( $this->id, '_payment_tokens', true ); |
170
|
|
|
if ( empty ( $token_ids ) ) { |
171
|
|
|
$token_ids = array(); |
172
|
|
|
} |
173
|
|
|
$token_ids[] = $token->get_id(); |
174
|
|
|
|
175
|
|
|
update_post_meta( $this->id, '_payment_tokens', $token_ids ); |
176
|
|
|
do_action( 'woocommerce_payment_token_added_to_order', $this->id, $token->get_id(), $token, $token_ids ); |
177
|
|
|
return true; |
178
|
|
|
} |
179
|
|
|
|
180
|
|
|
/** |
181
|
|
|
* Set the payment method for the order. |
182
|
|
|
* |
183
|
|
|
* @param WC_Payment_Gateway $payment_method |
184
|
|
|
*/ |
185
|
|
|
public function set_payment_method( $payment_method ) { |
186
|
|
|
|
187
|
|
|
if ( is_object( $payment_method ) ) { |
188
|
|
|
update_post_meta( $this->id, '_payment_method', $payment_method->id ); |
189
|
|
|
update_post_meta( $this->id, '_payment_method_title', $payment_method->get_title() ); |
190
|
|
|
} |
191
|
|
|
} |
192
|
|
|
|
193
|
|
|
/** |
194
|
|
|
* Set the customer address. |
195
|
|
|
* |
196
|
|
|
* @param array $address Address data. |
197
|
|
|
* @param string $type billing or shipping. |
198
|
|
|
*/ |
199
|
|
|
public function set_address( $address, $type = 'billing' ) { |
200
|
|
|
|
201
|
|
|
foreach ( $address as $key => $value ) { |
202
|
|
|
update_post_meta( $this->id, "_{$type}_" . $key, $value ); |
203
|
|
|
} |
204
|
|
|
} |
205
|
|
|
|
206
|
|
|
/** |
207
|
|
|
* Returns the requested address in raw, non-formatted way. |
208
|
|
|
* @since 2.4.0 |
209
|
|
|
* @param string $type Billing or shipping. Anything else besides 'billing' will return shipping address. |
210
|
|
|
* @return array The stored address after filter. |
211
|
|
|
*/ |
212
|
|
|
public function get_address( $type = 'billing' ) { |
213
|
|
|
|
214
|
|
|
if ( 'billing' === $type ) { |
215
|
|
|
$address = array( |
216
|
|
|
'first_name' => $this->billing_first_name, |
217
|
|
|
'last_name' => $this->billing_last_name, |
218
|
|
|
'company' => $this->billing_company, |
219
|
|
|
'address_1' => $this->billing_address_1, |
220
|
|
|
'address_2' => $this->billing_address_2, |
221
|
|
|
'city' => $this->billing_city, |
222
|
|
|
'state' => $this->billing_state, |
223
|
|
|
'postcode' => $this->billing_postcode, |
224
|
|
|
'country' => $this->billing_country, |
225
|
|
|
'email' => $this->billing_email, |
226
|
|
|
'phone' => $this->billing_phone, |
227
|
|
|
); |
228
|
|
|
} else { |
229
|
|
|
$address = array( |
230
|
|
|
'first_name' => $this->shipping_first_name, |
231
|
|
|
'last_name' => $this->shipping_last_name, |
232
|
|
|
'company' => $this->shipping_company, |
233
|
|
|
'address_1' => $this->shipping_address_1, |
234
|
|
|
'address_2' => $this->shipping_address_2, |
235
|
|
|
'city' => $this->shipping_city, |
236
|
|
|
'state' => $this->shipping_state, |
237
|
|
|
'postcode' => $this->shipping_postcode, |
238
|
|
|
'country' => $this->shipping_country, |
239
|
|
|
); |
240
|
|
|
} |
241
|
|
|
|
242
|
|
|
return apply_filters( 'woocommerce_get_order_address', $address, $type, $this ); |
243
|
|
|
} |
244
|
|
|
|
245
|
|
|
/** |
246
|
|
|
* Add a product line item to the order. |
247
|
|
|
* |
248
|
|
|
* @since 2.2 |
249
|
|
|
* @param \WC_Product $product |
250
|
|
|
* @param int $qty Line item quantity. |
251
|
|
|
* @param array $args |
252
|
|
|
* @return int|bool Item ID or false. |
253
|
|
|
*/ |
254
|
|
|
public function add_product( $product, $qty = 1, $args = array() ) { |
255
|
|
|
$args = wp_parse_args( $args, array( |
256
|
|
|
'variation' => array(), |
257
|
|
|
'totals' => array() |
258
|
|
|
) ); |
259
|
|
|
|
260
|
|
|
if ( ! $product ) { |
261
|
|
|
return false; |
262
|
|
|
} |
263
|
|
|
|
264
|
|
|
$item_id = wc_add_order_item( $this->id, array( |
265
|
|
|
'order_item_name' => $product->get_title(), |
266
|
|
|
'order_item_type' => 'line_item' |
267
|
|
|
) ); |
268
|
|
|
|
269
|
|
|
if ( ! $item_id ) { |
270
|
|
|
return false; |
271
|
|
|
} |
272
|
|
|
|
273
|
|
|
wc_add_order_item_meta( $item_id, '_qty', wc_stock_amount( $qty ) ); |
274
|
|
|
wc_add_order_item_meta( $item_id, '_tax_class', $product->get_tax_class() ); |
275
|
|
|
wc_add_order_item_meta( $item_id, '_product_id', $product->id ); |
276
|
|
|
wc_add_order_item_meta( $item_id, '_variation_id', isset( $product->variation_id ) ? $product->variation_id : 0 ); |
277
|
|
|
|
278
|
|
|
// Set line item totals, either passed in or from the product |
279
|
|
|
wc_add_order_item_meta( $item_id, '_line_subtotal', wc_format_decimal( isset( $args['totals']['subtotal'] ) ? $args['totals']['subtotal'] : $product->get_price_excluding_tax( $qty ) ) ); |
280
|
|
|
wc_add_order_item_meta( $item_id, '_line_total', wc_format_decimal( isset( $args['totals']['total'] ) ? $args['totals']['total'] : $product->get_price_excluding_tax( $qty ) ) ); |
281
|
|
|
wc_add_order_item_meta( $item_id, '_line_subtotal_tax', wc_format_decimal( isset( $args['totals']['subtotal_tax'] ) ? $args['totals']['subtotal_tax'] : 0 ) ); |
282
|
|
|
wc_add_order_item_meta( $item_id, '_line_tax', wc_format_decimal( isset( $args['totals']['tax'] ) ? $args['totals']['tax'] : 0 ) ); |
283
|
|
|
|
284
|
|
|
// Save tax data - Since 2.2 |
285
|
|
|
if ( isset( $args['totals']['tax_data'] ) ) { |
286
|
|
|
|
287
|
|
|
$tax_data = array(); |
288
|
|
|
$tax_data['total'] = array_map( 'wc_format_decimal', $args['totals']['tax_data']['total'] ); |
289
|
|
|
$tax_data['subtotal'] = array_map( 'wc_format_decimal', $args['totals']['tax_data']['subtotal'] ); |
290
|
|
|
|
291
|
|
|
wc_add_order_item_meta( $item_id, '_line_tax_data', $tax_data ); |
292
|
|
|
} else { |
293
|
|
|
wc_add_order_item_meta( $item_id, '_line_tax_data', array( 'total' => array(), 'subtotal' => array() ) ); |
294
|
|
|
} |
295
|
|
|
|
296
|
|
|
// Add variation meta |
297
|
|
View Code Duplication |
if ( ! empty( $args['variation'] ) ) { |
|
|
|
|
298
|
|
|
foreach ( $args['variation'] as $key => $value ) { |
299
|
|
|
wc_add_order_item_meta( $item_id, str_replace( 'attribute_', '', $key ), $value ); |
300
|
|
|
} |
301
|
|
|
} |
302
|
|
|
|
303
|
|
|
// Backorders |
304
|
|
|
if ( $product->backorders_require_notification() && $product->is_on_backorder( $qty ) ) { |
305
|
|
|
wc_add_order_item_meta( $item_id, apply_filters( 'woocommerce_backordered_item_meta_name', __( 'Backordered', 'woocommerce' ) ), $qty - max( 0, $product->get_total_stock() ) ); |
306
|
|
|
} |
307
|
|
|
|
308
|
|
|
do_action( 'woocommerce_order_add_product', $this->id, $item_id, $product, $qty, $args ); |
309
|
|
|
|
310
|
|
|
return $item_id; |
311
|
|
|
} |
312
|
|
|
|
313
|
|
|
|
314
|
|
|
/** |
315
|
|
|
* Update a line item for the order. |
316
|
|
|
* |
317
|
|
|
* Note this does not update order totals. |
318
|
|
|
* |
319
|
|
|
* @since 2.2 |
320
|
|
|
* @param int $item_id order item ID. |
321
|
|
|
* @param array $args data to update. |
322
|
|
|
* @param WC_Product $product |
323
|
|
|
* @return bool |
324
|
|
|
*/ |
325
|
|
|
public function update_product( $item_id, $product, $args ) { |
326
|
|
|
|
327
|
|
|
if ( ! $item_id || ! is_object( $product ) ) { |
328
|
|
|
return false; |
329
|
|
|
} |
330
|
|
|
|
331
|
|
|
// quantity |
332
|
|
|
if ( isset( $args['qty'] ) ) { |
333
|
|
|
wc_update_order_item_meta( $item_id, '_qty', wc_stock_amount( $args['qty'] ) ); |
334
|
|
|
} |
335
|
|
|
|
336
|
|
|
// tax class |
337
|
|
|
if ( isset( $args['tax_class'] ) ) { |
338
|
|
|
wc_update_order_item_meta( $item_id, '_tax_class', $args['tax_class'] ); |
339
|
|
|
} |
340
|
|
|
|
341
|
|
|
// set item totals, either provided or from product |
342
|
|
|
if ( isset( $args['qty'] ) ) { |
343
|
|
|
wc_update_order_item_meta( $item_id, '_line_subtotal', wc_format_decimal( isset( $args['totals']['subtotal'] ) ? $args['totals']['subtotal'] : $product->get_price_excluding_tax( $args['qty'] ) ) ); |
344
|
|
|
wc_update_order_item_meta( $item_id, '_line_total', wc_format_decimal( isset( $args['totals']['total'] ) ? $args['totals']['total'] : $product->get_price_excluding_tax( $args['qty'] ) ) ); |
345
|
|
|
} |
346
|
|
|
|
347
|
|
|
// set item tax totals |
348
|
|
|
wc_update_order_item_meta( $item_id, '_line_subtotal_tax', wc_format_decimal( isset( $args['totals']['subtotal_tax'] ) ? $args['totals']['subtotal_tax'] : 0 ) ); |
349
|
|
|
wc_update_order_item_meta( $item_id, '_line_tax', wc_format_decimal( isset( $args['totals']['tax'] ) ? $args['totals']['tax'] : 0 ) ); |
350
|
|
|
|
351
|
|
|
// variation meta |
352
|
|
|
if ( isset( $args['variation'] ) && is_array( $args['variation'] ) ) { |
353
|
|
|
|
354
|
|
|
foreach ( $args['variation'] as $key => $value ) { |
355
|
|
|
wc_update_order_item_meta( $item_id, str_replace( 'attribute_', '', $key ), $value ); |
356
|
|
|
} |
357
|
|
|
} |
358
|
|
|
|
359
|
|
|
// backorders |
360
|
|
|
if ( isset( $args['qty'] ) && $product->backorders_require_notification() && $product->is_on_backorder( $args['qty'] ) ) { |
361
|
|
|
wc_update_order_item_meta( $item_id, apply_filters( 'woocommerce_backordered_item_meta_name', __( 'Backordered', 'woocommerce' ) ), $args['qty'] - max( 0, $product->get_total_stock() ) ); |
362
|
|
|
} |
363
|
|
|
|
364
|
|
|
do_action( 'woocommerce_order_edit_product', $this->id, $item_id, $args, $product ); |
365
|
|
|
|
366
|
|
|
return true; |
367
|
|
|
} |
368
|
|
|
|
369
|
|
|
|
370
|
|
|
/** |
371
|
|
|
* Add coupon code to the order. |
372
|
|
|
* |
373
|
|
|
* @param string $code |
374
|
|
|
* @param int $discount_amount |
375
|
|
|
* @param int $discount_amount_tax "Discounted" tax - used for tax inclusive prices. |
376
|
|
|
* @return int|bool Item ID or false. |
377
|
|
|
*/ |
378
|
|
|
public function add_coupon( $code, $discount_amount = 0, $discount_amount_tax = 0 ) { |
379
|
|
|
$item_id = wc_add_order_item( $this->id, array( |
380
|
|
|
'order_item_name' => $code, |
381
|
|
|
'order_item_type' => 'coupon' |
382
|
|
|
) ); |
383
|
|
|
|
384
|
|
|
if ( ! $item_id ) { |
385
|
|
|
return false; |
386
|
|
|
} |
387
|
|
|
|
388
|
|
|
wc_add_order_item_meta( $item_id, 'discount_amount', $discount_amount ); |
389
|
|
|
wc_add_order_item_meta( $item_id, 'discount_amount_tax', $discount_amount_tax ); |
390
|
|
|
|
391
|
|
|
do_action( 'woocommerce_order_add_coupon', $this->id, $item_id, $code, $discount_amount, $discount_amount_tax ); |
392
|
|
|
|
393
|
|
|
return $item_id; |
394
|
|
|
} |
395
|
|
|
|
396
|
|
|
/** |
397
|
|
|
* Update coupon for order. |
398
|
|
|
* |
399
|
|
|
* Note this does not update order totals. |
400
|
|
|
* |
401
|
|
|
* @since 2.2 |
402
|
|
|
* @param int $item_id |
403
|
|
|
* @param array $args |
404
|
|
|
* @return bool |
405
|
|
|
*/ |
406
|
|
|
public function update_coupon( $item_id, $args ) { |
407
|
|
|
if ( ! $item_id ) { |
408
|
|
|
return false; |
409
|
|
|
} |
410
|
|
|
|
411
|
|
|
// code |
412
|
|
|
if ( isset( $args['code'] ) ) { |
413
|
|
|
wc_update_order_item( $item_id, array( 'order_item_name' => $args['code'] ) ); |
414
|
|
|
} |
415
|
|
|
|
416
|
|
|
// amount |
417
|
|
|
if ( isset( $args['discount_amount'] ) ) { |
418
|
|
|
wc_update_order_item_meta( $item_id, 'discount_amount', wc_format_decimal( $args['discount_amount'] ) ); |
419
|
|
|
} |
420
|
|
|
if ( isset( $args['discount_amount_tax'] ) ) { |
421
|
|
|
wc_add_order_item_meta( $item_id, 'discount_amount_tax', wc_format_decimal( $args['discount_amount_tax'] ) ); |
422
|
|
|
} |
423
|
|
|
|
424
|
|
|
do_action( 'woocommerce_order_update_coupon', $this->id, $item_id, $args ); |
425
|
|
|
|
426
|
|
|
return true; |
427
|
|
|
} |
428
|
|
|
|
429
|
|
|
/** |
430
|
|
|
* Add a tax row to the order. |
431
|
|
|
* |
432
|
|
|
* @since 2.2 |
433
|
|
|
* @param int tax_rate_id |
434
|
|
|
* @return int|bool Item ID or false. |
435
|
|
|
*/ |
436
|
|
|
public function add_tax( $tax_rate_id, $tax_amount = 0, $shipping_tax_amount = 0 ) { |
437
|
|
|
|
438
|
|
|
$code = WC_Tax::get_rate_code( $tax_rate_id ); |
439
|
|
|
|
440
|
|
|
if ( ! $code ) { |
441
|
|
|
return false; |
442
|
|
|
} |
443
|
|
|
|
444
|
|
|
$item_id = wc_add_order_item( $this->id, array( |
445
|
|
|
'order_item_name' => $code, |
446
|
|
|
'order_item_type' => 'tax' |
447
|
|
|
) ); |
448
|
|
|
|
449
|
|
|
if ( ! $item_id ) { |
450
|
|
|
return false; |
451
|
|
|
} |
452
|
|
|
|
453
|
|
|
wc_add_order_item_meta( $item_id, 'rate_id', $tax_rate_id ); |
454
|
|
|
wc_add_order_item_meta( $item_id, 'label', WC_Tax::get_rate_label( $tax_rate_id ) ); |
455
|
|
|
wc_add_order_item_meta( $item_id, 'compound', WC_Tax::is_compound( $tax_rate_id ) ? 1 : 0 ); |
456
|
|
|
wc_add_order_item_meta( $item_id, 'tax_amount', wc_format_decimal( $tax_amount ) ); |
457
|
|
|
wc_add_order_item_meta( $item_id, 'shipping_tax_amount', wc_format_decimal( $shipping_tax_amount ) ); |
458
|
|
|
|
459
|
|
|
do_action( 'woocommerce_order_add_tax', $this->id, $item_id, $tax_rate_id, $tax_amount, $shipping_tax_amount ); |
460
|
|
|
|
461
|
|
|
return $item_id; |
462
|
|
|
} |
463
|
|
|
|
464
|
|
|
/** |
465
|
|
|
* Add a shipping row to the order. |
466
|
|
|
* |
467
|
|
|
* @param WC_Shipping_Rate shipping_rate |
468
|
|
|
* @return int|bool Item ID or false. |
469
|
|
|
*/ |
470
|
|
|
public function add_shipping( $shipping_rate ) { |
471
|
|
|
|
472
|
|
|
$item_id = wc_add_order_item( $this->id, array( |
473
|
|
|
'order_item_name' => $shipping_rate->label, |
474
|
|
|
'order_item_type' => 'shipping' |
475
|
|
|
) ); |
476
|
|
|
|
477
|
|
|
if ( ! $item_id ) { |
478
|
|
|
return false; |
479
|
|
|
} |
480
|
|
|
|
481
|
|
|
wc_add_order_item_meta( $item_id, 'method_id', $shipping_rate->id ); |
482
|
|
|
wc_add_order_item_meta( $item_id, 'cost', wc_format_decimal( $shipping_rate->cost ) ); |
483
|
|
|
|
484
|
|
|
// Save shipping taxes - Since 2.2 |
485
|
|
|
$taxes = array_map( 'wc_format_decimal', $shipping_rate->taxes ); |
486
|
|
|
wc_add_order_item_meta( $item_id, 'taxes', $taxes ); |
487
|
|
|
|
488
|
|
|
// Store meta |
489
|
|
|
$shipping_meta = $shipping_rate->get_meta_data(); |
490
|
|
|
if ( ! empty( $shipping_meta ) ) { |
491
|
|
|
foreach ( $shipping_rate->get_meta_data() as $key => $value ) { |
492
|
|
|
wc_add_order_item_meta( $item_id, $key, $value ); |
493
|
|
|
} |
494
|
|
|
} |
495
|
|
|
|
496
|
|
|
do_action( 'woocommerce_order_add_shipping', $this->id, $item_id, $shipping_rate ); |
497
|
|
|
|
498
|
|
|
// Update total |
499
|
|
|
$this->set_total( $this->order_shipping + wc_format_decimal( $shipping_rate->cost ), 'shipping' ); |
500
|
|
|
|
501
|
|
|
return $item_id; |
502
|
|
|
} |
503
|
|
|
|
504
|
|
|
/** |
505
|
|
|
* Update shipping method for order. |
506
|
|
|
* |
507
|
|
|
* Note this does not update the order total. |
508
|
|
|
* |
509
|
|
|
* @since 2.2 |
510
|
|
|
* @param int $item_id |
511
|
|
|
* @param array $args |
512
|
|
|
* @return bool |
513
|
|
|
*/ |
514
|
|
|
public function update_shipping( $item_id, $args ) { |
515
|
|
|
|
516
|
|
|
if ( ! $item_id ) { |
517
|
|
|
return false; |
518
|
|
|
} |
519
|
|
|
|
520
|
|
|
// method title |
521
|
|
|
if ( isset( $args['method_title'] ) ) { |
522
|
|
|
wc_update_order_item( $item_id, array( 'order_item_name' => $args['method_title'] ) ); |
523
|
|
|
} |
524
|
|
|
|
525
|
|
|
// method ID |
526
|
|
|
if ( isset( $args['method_id'] ) ) { |
527
|
|
|
wc_update_order_item_meta( $item_id, 'method_id', $args['method_id'] ); |
528
|
|
|
} |
529
|
|
|
|
530
|
|
|
// method cost |
531
|
|
|
if ( isset( $args['cost'] ) ) { |
532
|
|
|
// Get old cost before updating |
533
|
|
|
$old_cost = wc_get_order_item_meta( $item_id, 'cost' ); |
534
|
|
|
|
535
|
|
|
// Update |
536
|
|
|
wc_update_order_item_meta( $item_id, 'cost', wc_format_decimal( $args['cost'] ) ); |
537
|
|
|
|
538
|
|
|
// Update total |
539
|
|
|
$this->set_total( $this->order_shipping - wc_format_decimal( $old_cost ) + wc_format_decimal( $args['cost'] ), 'shipping' ); |
540
|
|
|
} |
541
|
|
|
|
542
|
|
|
do_action( 'woocommerce_order_update_shipping', $this->id, $item_id, $args ); |
543
|
|
|
|
544
|
|
|
return true; |
545
|
|
|
} |
546
|
|
|
|
547
|
|
|
/** |
548
|
|
|
* Add a fee to the order. |
549
|
|
|
* |
550
|
|
|
* @param object $fee |
551
|
|
|
* @return int|bool Item ID or false. |
552
|
|
|
*/ |
553
|
|
|
public function add_fee( $fee ) { |
554
|
|
|
|
555
|
|
|
$item_id = wc_add_order_item( $this->id, array( |
556
|
|
|
'order_item_name' => $fee->name, |
557
|
|
|
'order_item_type' => 'fee' |
558
|
|
|
) ); |
559
|
|
|
|
560
|
|
|
if ( ! $item_id ) { |
561
|
|
|
return false; |
562
|
|
|
} |
563
|
|
|
|
564
|
|
|
if ( $fee->taxable ) { |
565
|
|
|
wc_add_order_item_meta( $item_id, '_tax_class', $fee->tax_class ); |
566
|
|
|
} else { |
567
|
|
|
wc_add_order_item_meta( $item_id, '_tax_class', '0' ); |
568
|
|
|
} |
569
|
|
|
|
570
|
|
|
wc_add_order_item_meta( $item_id, '_line_total', wc_format_decimal( $fee->amount ) ); |
571
|
|
|
wc_add_order_item_meta( $item_id, '_line_tax', wc_format_decimal( $fee->tax ) ); |
572
|
|
|
|
573
|
|
|
// Save tax data - Since 2.2 |
574
|
|
|
$tax_data = array_map( 'wc_format_decimal', $fee->tax_data ); |
575
|
|
|
wc_add_order_item_meta( $item_id, '_line_tax_data', array( 'total' => $tax_data ) ); |
576
|
|
|
|
577
|
|
|
do_action( 'woocommerce_order_add_fee', $this->id, $item_id, $fee ); |
578
|
|
|
|
579
|
|
|
return $item_id; |
580
|
|
|
} |
581
|
|
|
|
582
|
|
|
/** |
583
|
|
|
* Update fee for order. |
584
|
|
|
* |
585
|
|
|
* Note this does not update order totals. |
586
|
|
|
* |
587
|
|
|
* @since 2.2 |
588
|
|
|
* @param int $item_id |
589
|
|
|
* @param array $args |
590
|
|
|
* @return bool |
591
|
|
|
*/ |
592
|
|
|
public function update_fee( $item_id, $args ) { |
593
|
|
|
|
594
|
|
|
if ( ! $item_id ) { |
595
|
|
|
return false; |
596
|
|
|
} |
597
|
|
|
|
598
|
|
|
// name |
599
|
|
|
if ( isset( $args['name'] ) ) { |
600
|
|
|
wc_update_order_item( $item_id, array( 'order_item_name' => $args['name'] ) ); |
601
|
|
|
} |
602
|
|
|
|
603
|
|
|
// tax class |
604
|
|
|
if ( isset( $args['tax_class'] ) ) { |
605
|
|
|
wc_update_order_item_meta( $item_id, '_tax_class', $args['tax_class'] ); |
606
|
|
|
} |
607
|
|
|
|
608
|
|
|
// total |
609
|
|
|
if ( isset( $args['line_total'] ) ) { |
610
|
|
|
wc_update_order_item_meta( $item_id, '_line_total', wc_format_decimal( $args['line_total'] ) ); |
611
|
|
|
} |
612
|
|
|
|
613
|
|
|
// total tax |
614
|
|
|
if ( isset( $args['line_tax'] ) ) { |
615
|
|
|
wc_update_order_item_meta( $item_id, '_line_tax', wc_format_decimal( $args['line_tax'] ) ); |
616
|
|
|
} |
617
|
|
|
|
618
|
|
|
do_action( 'woocommerce_order_update_fee', $this->id, $item_id, $args ); |
619
|
|
|
|
620
|
|
|
return true; |
621
|
|
|
} |
622
|
|
|
|
623
|
|
|
/** |
624
|
|
|
* Set an order total. |
625
|
|
|
* |
626
|
|
|
* @param float $amount |
627
|
|
|
* @param string $total_type |
628
|
|
|
* |
629
|
|
|
* @return bool |
630
|
|
|
*/ |
631
|
|
|
public function set_total( $amount, $total_type = 'total' ) { |
632
|
|
|
|
633
|
|
|
if ( ! in_array( $total_type, array( 'shipping', 'tax', 'shipping_tax', 'total', 'cart_discount', 'cart_discount_tax' ) ) ) { |
634
|
|
|
return false; |
635
|
|
|
} |
636
|
|
|
|
637
|
|
|
switch ( $total_type ) { |
638
|
|
|
case 'total' : |
639
|
|
|
$key = '_order_total'; |
640
|
|
|
$amount = wc_format_decimal( $amount, wc_get_price_decimals() ); |
641
|
|
|
break; |
642
|
|
|
case 'cart_discount' : |
643
|
|
|
case 'cart_discount_tax' : |
644
|
|
|
$key = '_' . $total_type; |
645
|
|
|
$amount = wc_format_decimal( $amount ); |
646
|
|
|
break; |
647
|
|
|
default : |
648
|
|
|
$key = '_order_' . $total_type; |
649
|
|
|
$amount = wc_format_decimal( $amount ); |
650
|
|
|
break; |
651
|
|
|
} |
652
|
|
|
|
653
|
|
|
update_post_meta( $this->id, $key, $amount ); |
654
|
|
|
|
655
|
|
|
return true; |
656
|
|
|
} |
657
|
|
|
|
658
|
|
|
/** |
659
|
|
|
* Calculate taxes for all line items and shipping, and store the totals and tax rows. |
660
|
|
|
* |
661
|
|
|
* Will use the base country unless customer addresses are set. |
662
|
|
|
* |
663
|
|
|
* @return bool success or fail. |
664
|
|
|
*/ |
665
|
|
|
public function calculate_taxes() { |
666
|
|
|
$tax_total = 0; |
667
|
|
|
$shipping_tax_total = 0; |
668
|
|
|
$taxes = array(); |
669
|
|
|
$shipping_taxes = array(); |
670
|
|
|
$tax_based_on = get_option( 'woocommerce_tax_based_on' ); |
671
|
|
|
|
672
|
|
|
// If is_vat_exempt is 'yes', or wc_tax_enabled is false, return and do nothing. |
673
|
|
|
if ( 'yes' === $this->is_vat_exempt || ! wc_tax_enabled() ) { |
674
|
|
|
return false; |
675
|
|
|
} |
676
|
|
|
|
677
|
|
|
if ( 'billing' === $tax_based_on ) { |
678
|
|
|
$country = $this->billing_country; |
679
|
|
|
$state = $this->billing_state; |
680
|
|
|
$postcode = $this->billing_postcode; |
681
|
|
|
$city = $this->billing_city; |
682
|
|
|
} elseif ( 'shipping' === $tax_based_on ) { |
683
|
|
|
$country = $this->shipping_country; |
684
|
|
|
$state = $this->shipping_state; |
685
|
|
|
$postcode = $this->shipping_postcode; |
686
|
|
|
$city = $this->shipping_city; |
687
|
|
|
} |
688
|
|
|
|
689
|
|
|
// Default to base |
690
|
|
View Code Duplication |
if ( 'base' === $tax_based_on || empty( $country ) ) { |
|
|
|
|
691
|
|
|
$default = wc_get_base_location(); |
692
|
|
|
$country = $default['country']; |
693
|
|
|
$state = $default['state']; |
694
|
|
|
$postcode = ''; |
695
|
|
|
$city = ''; |
696
|
|
|
} |
697
|
|
|
|
698
|
|
|
// Get items |
699
|
|
|
foreach ( $this->get_items( array( 'line_item', 'fee' ) ) as $item_id => $item ) { |
700
|
|
|
|
701
|
|
|
$product = $this->get_product_from_item( $item ); |
702
|
|
|
$line_total = isset( $item['line_total'] ) ? $item['line_total'] : 0; |
703
|
|
|
$line_subtotal = isset( $item['line_subtotal'] ) ? $item['line_subtotal'] : 0; |
704
|
|
|
$tax_class = $item['tax_class']; |
705
|
|
|
$item_tax_status = $product ? $product->get_tax_status() : 'taxable'; |
706
|
|
|
|
707
|
|
|
if ( '0' !== $tax_class && 'taxable' === $item_tax_status ) { |
708
|
|
|
|
709
|
|
|
$tax_rates = WC_Tax::find_rates( array( |
710
|
|
|
'country' => $country, |
711
|
|
|
'state' => $state, |
712
|
|
|
'postcode' => $postcode, |
713
|
|
|
'city' => $city, |
714
|
|
|
'tax_class' => $tax_class |
715
|
|
|
) ); |
716
|
|
|
|
717
|
|
|
$line_subtotal_taxes = WC_Tax::calc_tax( $line_subtotal, $tax_rates, false ); |
718
|
|
|
$line_taxes = WC_Tax::calc_tax( $line_total, $tax_rates, false ); |
719
|
|
|
$line_subtotal_tax = max( 0, array_sum( $line_subtotal_taxes ) ); |
720
|
|
|
$line_tax = max( 0, array_sum( $line_taxes ) ); |
721
|
|
|
$tax_total += $line_tax; |
722
|
|
|
|
723
|
|
|
wc_update_order_item_meta( $item_id, '_line_subtotal_tax', wc_format_decimal( $line_subtotal_tax ) ); |
724
|
|
|
wc_update_order_item_meta( $item_id, '_line_tax', wc_format_decimal( $line_tax ) ); |
725
|
|
|
wc_update_order_item_meta( $item_id, '_line_tax_data', array( 'total' => $line_taxes, 'subtotal' => $line_subtotal_taxes ) ); |
726
|
|
|
|
727
|
|
|
// Sum the item taxes |
728
|
|
View Code Duplication |
foreach ( array_keys( $taxes + $line_taxes ) as $key ) { |
|
|
|
|
729
|
|
|
$taxes[ $key ] = ( isset( $line_taxes[ $key ] ) ? $line_taxes[ $key ] : 0 ) + ( isset( $taxes[ $key ] ) ? $taxes[ $key ] : 0 ); |
730
|
|
|
} |
731
|
|
|
} |
732
|
|
|
} |
733
|
|
|
|
734
|
|
|
// Calc taxes for shipping |
735
|
|
|
foreach ( $this->get_shipping_methods() as $item_id => $item ) { |
736
|
|
|
$shipping_tax_class = get_option( 'woocommerce_shipping_tax_class' ); |
737
|
|
|
|
738
|
|
|
// Inherit tax class from items |
739
|
|
|
if ( '' === $shipping_tax_class ) { |
740
|
|
|
$tax_classes = WC_Tax::get_tax_classes(); |
741
|
|
|
|
742
|
|
|
foreach ( $tax_classes as $tax_class ) { |
743
|
|
|
$tax_class = sanitize_title( $tax_class ); |
744
|
|
|
if ( in_array( $tax_class, $found_tax_classes ) ) { |
745
|
|
|
$tax_rates = WC_Tax::find_shipping_rates( array( |
746
|
|
|
'country' => $country, |
747
|
|
|
'state' => $state, |
748
|
|
|
'postcode' => $postcode, |
749
|
|
|
'city' => $city, |
750
|
|
|
'tax_class' => $tax_class, |
751
|
|
|
) ); |
752
|
|
|
break; |
753
|
|
|
} |
754
|
|
|
} |
755
|
|
|
} else { |
756
|
|
|
$tax_rates = WC_Tax::find_shipping_rates( array( |
757
|
|
|
'country' => $country, |
758
|
|
|
'state' => $state, |
759
|
|
|
'postcode' => $postcode, |
760
|
|
|
'city' => $city, |
761
|
|
|
'tax_class' => 'standard' === $shipping_tax_class ? '' : $shipping_tax_class, |
762
|
|
|
) ); |
763
|
|
|
} |
764
|
|
|
|
765
|
|
|
$line_taxes = WC_Tax::calc_tax( $item['cost'], $tax_rates, false ); |
766
|
|
|
$line_tax = max( 0, array_sum( $line_taxes ) ); |
767
|
|
|
$shipping_tax_total += $line_tax; |
768
|
|
|
|
769
|
|
|
wc_update_order_item_meta( $item_id, '_line_tax', wc_format_decimal( $line_tax ) ); |
770
|
|
|
wc_update_order_item_meta( $item_id, '_line_tax_data', array( 'total' => $line_taxes ) ); |
771
|
|
|
|
772
|
|
|
// Sum the item taxes |
773
|
|
View Code Duplication |
foreach ( array_keys( $shipping_taxes + $line_taxes ) as $key ) { |
|
|
|
|
774
|
|
|
$shipping_taxes[ $key ] = ( isset( $line_taxes[ $key ] ) ? $line_taxes[ $key ] : 0 ) + ( isset( $shipping_taxes[ $key ] ) ? $shipping_taxes[ $key ] : 0 ); |
775
|
|
|
} |
776
|
|
|
} |
777
|
|
|
|
778
|
|
|
// Save tax totals |
779
|
|
|
$this->set_total( $shipping_tax_total, 'shipping_tax' ); |
780
|
|
|
$this->set_total( $tax_total, 'tax' ); |
781
|
|
|
|
782
|
|
|
// Tax rows |
783
|
|
|
$this->remove_order_items( 'tax' ); |
784
|
|
|
|
785
|
|
|
// Now merge to keep tax rows |
786
|
|
View Code Duplication |
foreach ( array_keys( $taxes + $shipping_taxes ) as $tax_rate_id ) { |
|
|
|
|
787
|
|
|
$this->add_tax( $tax_rate_id, isset( $taxes[ $tax_rate_id ] ) ? $taxes[ $tax_rate_id ] : 0, isset( $shipping_taxes[ $tax_rate_id ] ) ? $shipping_taxes[ $tax_rate_id ] : 0 ); |
788
|
|
|
} |
789
|
|
|
|
790
|
|
|
return true; |
791
|
|
|
} |
792
|
|
|
|
793
|
|
|
|
794
|
|
|
/** |
795
|
|
|
* Calculate shipping total. |
796
|
|
|
* |
797
|
|
|
* @since 2.2 |
798
|
|
|
* @return float |
799
|
|
|
*/ |
800
|
|
|
public function calculate_shipping() { |
801
|
|
|
|
802
|
|
|
$shipping_total = 0; |
803
|
|
|
|
804
|
|
|
foreach ( $this->get_shipping_methods() as $shipping ) { |
805
|
|
|
$shipping_total += $shipping['cost']; |
806
|
|
|
} |
807
|
|
|
|
808
|
|
|
$this->set_total( $shipping_total, 'shipping' ); |
809
|
|
|
|
810
|
|
|
return $this->get_total_shipping(); |
811
|
|
|
} |
812
|
|
|
|
813
|
|
|
/** |
814
|
|
|
* Update tax lines at order level by looking at the line item taxes themselves. |
815
|
|
|
* |
816
|
|
|
* @return bool success or fail. |
817
|
|
|
*/ |
818
|
|
|
public function update_taxes() { |
819
|
|
|
$order_taxes = array(); |
820
|
|
|
$order_shipping_taxes = array(); |
821
|
|
|
|
822
|
|
|
foreach ( $this->get_items( array( 'line_item', 'fee' ) ) as $item_id => $item ) { |
823
|
|
|
|
824
|
|
|
$line_tax_data = maybe_unserialize( $item['line_tax_data'] ); |
825
|
|
|
|
826
|
|
View Code Duplication |
if ( isset( $line_tax_data['total'] ) ) { |
|
|
|
|
827
|
|
|
|
828
|
|
|
foreach ( $line_tax_data['total'] as $tax_rate_id => $tax ) { |
829
|
|
|
|
830
|
|
|
if ( ! isset( $order_taxes[ $tax_rate_id ] ) ) { |
831
|
|
|
$order_taxes[ $tax_rate_id ] = 0; |
832
|
|
|
} |
833
|
|
|
|
834
|
|
|
$order_taxes[ $tax_rate_id ] += $tax; |
835
|
|
|
} |
836
|
|
|
} |
837
|
|
|
} |
838
|
|
|
|
839
|
|
|
foreach ( $this->get_items( array( 'shipping' ) ) as $item_id => $item ) { |
840
|
|
|
|
841
|
|
|
$line_tax_data = maybe_unserialize( $item['taxes'] ); |
842
|
|
|
|
843
|
|
View Code Duplication |
if ( isset( $line_tax_data ) ) { |
|
|
|
|
844
|
|
|
foreach ( $line_tax_data as $tax_rate_id => $tax ) { |
845
|
|
|
if ( ! isset( $order_shipping_taxes[ $tax_rate_id ] ) ) { |
846
|
|
|
$order_shipping_taxes[ $tax_rate_id ] = 0; |
847
|
|
|
} |
848
|
|
|
|
849
|
|
|
$order_shipping_taxes[ $tax_rate_id ] += $tax; |
850
|
|
|
} |
851
|
|
|
} |
852
|
|
|
} |
853
|
|
|
|
854
|
|
|
// Remove old existing tax rows. |
855
|
|
|
$this->remove_order_items( 'tax' ); |
856
|
|
|
|
857
|
|
|
// Now merge to keep tax rows. |
858
|
|
|
foreach ( array_keys( $order_taxes + $order_shipping_taxes ) as $tax_rate_id ) { |
859
|
|
|
$this->add_tax( $tax_rate_id, isset( $order_taxes[ $tax_rate_id ] ) ? $order_taxes[ $tax_rate_id ] : 0, isset( $order_shipping_taxes[ $tax_rate_id ] ) ? $order_shipping_taxes[ $tax_rate_id ] : 0 ); |
860
|
|
|
} |
861
|
|
|
|
862
|
|
|
// Save tax totals |
863
|
|
|
$this->set_total( WC_Tax::round( array_sum( $order_shipping_taxes ) ), 'shipping_tax' ); |
864
|
|
|
$this->set_total( WC_Tax::round( array_sum( $order_taxes ) ), 'tax' ); |
865
|
|
|
|
866
|
|
|
return true; |
867
|
|
|
} |
868
|
|
|
|
869
|
|
|
/** |
870
|
|
|
* Calculate totals by looking at the contents of the order. Stores the totals and returns the orders final total. |
871
|
|
|
* |
872
|
|
|
* @since 2.2 |
873
|
|
|
* @param bool $and_taxes Calc taxes if true. |
874
|
|
|
* @return float calculated grand total. |
875
|
|
|
*/ |
876
|
|
|
public function calculate_totals( $and_taxes = true ) { |
877
|
|
|
$cart_subtotal = 0; |
878
|
|
|
$cart_total = 0; |
879
|
|
|
$fee_total = 0; |
880
|
|
|
$cart_subtotal_tax = 0; |
881
|
|
|
$cart_total_tax = 0; |
882
|
|
|
|
883
|
|
|
if ( $and_taxes && wc_tax_enabled() ) { |
884
|
|
|
$this->calculate_taxes(); |
885
|
|
|
} |
886
|
|
|
|
887
|
|
|
// line items |
888
|
|
|
foreach ( $this->get_items() as $item ) { |
889
|
|
|
$cart_subtotal += wc_format_decimal( isset( $item['line_subtotal'] ) ? $item['line_subtotal'] : 0 ); |
890
|
|
|
$cart_total += wc_format_decimal( isset( $item['line_total'] ) ? $item['line_total'] : 0 ); |
891
|
|
|
$cart_subtotal_tax += wc_format_decimal( isset( $item['line_subtotal_tax'] ) ? $item['line_subtotal_tax'] : 0 ); |
892
|
|
|
$cart_total_tax += wc_format_decimal( isset( $item['line_tax'] ) ? $item['line_tax'] : 0 ); |
893
|
|
|
} |
894
|
|
|
|
895
|
|
|
$this->calculate_shipping(); |
896
|
|
|
|
897
|
|
|
foreach ( $this->get_fees() as $item ) { |
898
|
|
|
$fee_total += $item['line_total']; |
899
|
|
|
} |
900
|
|
|
|
901
|
|
|
$this->set_total( $cart_subtotal - $cart_total, 'cart_discount' ); |
902
|
|
|
$this->set_total( $cart_subtotal_tax - $cart_total_tax, 'cart_discount_tax' ); |
903
|
|
|
|
904
|
|
|
$grand_total = round( $cart_total + $fee_total + $this->get_total_shipping() + $this->get_cart_tax() + $this->get_shipping_tax(), wc_get_price_decimals() ); |
905
|
|
|
|
906
|
|
|
$this->set_total( $grand_total, 'total' ); |
907
|
|
|
|
908
|
|
|
return $grand_total; |
909
|
|
|
} |
910
|
|
|
|
911
|
|
|
/** |
912
|
|
|
* Gets an order from the database. |
913
|
|
|
* |
914
|
|
|
* @param int $id (default: 0). |
915
|
|
|
* @return bool |
916
|
|
|
*/ |
917
|
|
View Code Duplication |
public function get_order( $id = 0 ) { |
|
|
|
|
918
|
|
|
|
919
|
|
|
if ( ! $id ) { |
920
|
|
|
return false; |
921
|
|
|
} |
922
|
|
|
|
923
|
|
|
if ( $result = get_post( $id ) ) { |
924
|
|
|
$this->populate( $result ); |
925
|
|
|
return true; |
926
|
|
|
} |
927
|
|
|
|
928
|
|
|
return false; |
929
|
|
|
} |
930
|
|
|
|
931
|
|
|
/** |
932
|
|
|
* Populates an order from the loaded post data. |
933
|
|
|
* |
934
|
|
|
* @param mixed $result |
935
|
|
|
*/ |
936
|
|
|
public function populate( $result ) { |
937
|
|
|
|
938
|
|
|
// Standard post data |
939
|
|
|
$this->id = $result->ID; |
940
|
|
|
$this->order_date = $result->post_date; |
941
|
|
|
$this->modified_date = $result->post_modified; |
942
|
|
|
$this->customer_message = $result->post_excerpt; |
943
|
|
|
$this->customer_note = $result->post_excerpt; |
944
|
|
|
$this->post_status = $result->post_status; |
945
|
|
|
|
946
|
|
|
// Billing email can default to user if set. |
947
|
|
|
if ( empty( $this->billing_email ) && ! empty( $this->customer_user ) && ( $user = get_user_by( 'id', $this->customer_user ) ) ) { |
948
|
|
|
$this->billing_email = $user->user_email; |
949
|
|
|
} |
950
|
|
|
|
951
|
|
|
// Orders store the state of prices including tax when created. |
952
|
|
|
$this->prices_include_tax = metadata_exists( 'post', $this->id, '_prices_include_tax' ) ? get_post_meta( $this->id, '_prices_include_tax', true ) === 'yes' : $this->prices_include_tax; |
953
|
|
|
} |
954
|
|
|
|
955
|
|
|
/** |
956
|
|
|
* __isset function. |
957
|
|
|
* |
958
|
|
|
* @param mixed $key |
959
|
|
|
* @return bool |
960
|
|
|
*/ |
961
|
|
|
public function __isset( $key ) { |
962
|
|
|
|
963
|
|
|
if ( ! $this->id ) { |
964
|
|
|
return false; |
965
|
|
|
} |
966
|
|
|
|
967
|
|
|
return metadata_exists( 'post', $this->id, '_' . $key ); |
968
|
|
|
} |
969
|
|
|
|
970
|
|
|
/** |
971
|
|
|
* __get function. |
972
|
|
|
* |
973
|
|
|
* @param mixed $key |
974
|
|
|
* @return mixed |
975
|
|
|
*/ |
976
|
|
|
public function __get( $key ) { |
977
|
|
|
// Get values or default if not set. |
978
|
|
|
if ( 'completed_date' === $key ) { |
979
|
|
|
$value = ( $value = get_post_meta( $this->id, '_completed_date', true ) ) ? $value : $this->modified_date; |
980
|
|
|
} elseif ( 'user_id' === $key ) { |
981
|
|
|
$value = ( $value = get_post_meta( $this->id, '_customer_user', true ) ) ? absint( $value ) : ''; |
982
|
|
|
} elseif ( 'status' === $key ) { |
983
|
|
|
$value = $this->get_status(); |
984
|
|
|
} else { |
985
|
|
|
$value = get_post_meta( $this->id, '_' . $key, true ); |
986
|
|
|
} |
987
|
|
|
|
988
|
|
|
return $value; |
989
|
|
|
} |
990
|
|
|
|
991
|
|
|
/** |
992
|
|
|
* Return the order statuses without wc- internal prefix. |
993
|
|
|
* |
994
|
|
|
* Queries get_post_status() directly to avoid having out of date statuses, if updated elsewhere. |
995
|
|
|
* |
996
|
|
|
* @return string |
997
|
|
|
*/ |
998
|
|
|
public function get_status() { |
999
|
|
|
$this->post_status = get_post_status( $this->id ); |
1000
|
|
|
return apply_filters( 'woocommerce_order_get_status', 'wc-' === substr( $this->post_status, 0, 3 ) ? substr( $this->post_status, 3 ) : $this->post_status, $this ); |
1001
|
|
|
} |
1002
|
|
|
|
1003
|
|
|
/** |
1004
|
|
|
* Checks the order status against a passed in status. |
1005
|
|
|
* |
1006
|
|
|
* @return bool |
1007
|
|
|
*/ |
1008
|
|
|
public function has_status( $status ) { |
1009
|
|
|
return apply_filters( 'woocommerce_order_has_status', ( is_array( $status ) && in_array( $this->get_status(), $status ) ) || $this->get_status() === $status ? true : false, $this, $status ); |
1010
|
|
|
} |
1011
|
|
|
|
1012
|
|
|
/** |
1013
|
|
|
* Gets the user ID associated with the order. Guests are 0. |
1014
|
|
|
* |
1015
|
|
|
* @since 2.2 |
1016
|
|
|
* @return int |
1017
|
|
|
*/ |
1018
|
|
|
public function get_user_id() { |
1019
|
|
|
return $this->customer_user ? intval( $this->customer_user ) : 0; |
1020
|
|
|
} |
1021
|
|
|
|
1022
|
|
|
/** |
1023
|
|
|
* Get the user associated with the order. False for guests. |
1024
|
|
|
* |
1025
|
|
|
* @since 2.2 |
1026
|
|
|
* @return WP_User|false |
1027
|
|
|
*/ |
1028
|
|
|
public function get_user() { |
1029
|
|
|
return $this->get_user_id() ? get_user_by( 'id', $this->get_user_id() ) : false; |
1030
|
|
|
} |
1031
|
|
|
|
1032
|
|
|
/** |
1033
|
|
|
* Get transaction id for the order. |
1034
|
|
|
* |
1035
|
|
|
* @return string |
1036
|
|
|
*/ |
1037
|
|
|
public function get_transaction_id() { |
1038
|
|
|
return get_post_meta( $this->id, '_transaction_id', true ); |
1039
|
|
|
} |
1040
|
|
|
|
1041
|
|
|
/** |
1042
|
|
|
* Check if an order key is valid. |
1043
|
|
|
* |
1044
|
|
|
* @param mixed $key |
1045
|
|
|
* @return bool |
1046
|
|
|
*/ |
1047
|
|
|
public function key_is_valid( $key ) { |
1048
|
|
|
|
1049
|
|
|
if ( $key == $this->order_key ) { |
1050
|
|
|
return true; |
1051
|
|
|
} |
1052
|
|
|
|
1053
|
|
|
return false; |
1054
|
|
|
} |
1055
|
|
|
|
1056
|
|
|
/** |
1057
|
|
|
* get_order_number function. |
1058
|
|
|
* |
1059
|
|
|
* Gets the order number for display (by default, order ID). |
1060
|
|
|
* |
1061
|
|
|
* @return string |
1062
|
|
|
*/ |
1063
|
|
|
public function get_order_number() { |
1064
|
|
|
return apply_filters( 'woocommerce_order_number', $this->id, $this ); |
1065
|
|
|
} |
1066
|
|
|
|
1067
|
|
|
/** |
1068
|
|
|
* Get a formatted billing address for the order. |
1069
|
|
|
* |
1070
|
|
|
* @return string |
1071
|
|
|
*/ |
1072
|
|
|
public function get_formatted_billing_address() { |
1073
|
|
|
if ( ! $this->formatted_billing_address ) { |
1074
|
|
|
|
1075
|
|
|
// Formatted Addresses. |
1076
|
|
|
$address = apply_filters( 'woocommerce_order_formatted_billing_address', array( |
1077
|
|
|
'first_name' => $this->billing_first_name, |
1078
|
|
|
'last_name' => $this->billing_last_name, |
1079
|
|
|
'company' => $this->billing_company, |
1080
|
|
|
'address_1' => $this->billing_address_1, |
1081
|
|
|
'address_2' => $this->billing_address_2, |
1082
|
|
|
'city' => $this->billing_city, |
1083
|
|
|
'state' => $this->billing_state, |
1084
|
|
|
'postcode' => $this->billing_postcode, |
1085
|
|
|
'country' => $this->billing_country |
1086
|
|
|
), $this ); |
1087
|
|
|
|
1088
|
|
|
$this->formatted_billing_address = WC()->countries->get_formatted_address( $address ); |
1089
|
|
|
} |
1090
|
|
|
|
1091
|
|
|
return $this->formatted_billing_address; |
1092
|
|
|
} |
1093
|
|
|
|
1094
|
|
|
/** |
1095
|
|
|
* Get a formatted shipping address for the order. |
1096
|
|
|
* |
1097
|
|
|
* @return string |
1098
|
|
|
*/ |
1099
|
|
|
public function get_formatted_shipping_address() { |
1100
|
|
|
if ( ! $this->formatted_shipping_address ) { |
1101
|
|
|
|
1102
|
|
|
if ( $this->shipping_address_1 || $this->shipping_address_2 ) { |
1103
|
|
|
|
1104
|
|
|
// Formatted Addresses |
1105
|
|
|
$address = apply_filters( 'woocommerce_order_formatted_shipping_address', array( |
1106
|
|
|
'first_name' => $this->shipping_first_name, |
1107
|
|
|
'last_name' => $this->shipping_last_name, |
1108
|
|
|
'company' => $this->shipping_company, |
1109
|
|
|
'address_1' => $this->shipping_address_1, |
1110
|
|
|
'address_2' => $this->shipping_address_2, |
1111
|
|
|
'city' => $this->shipping_city, |
1112
|
|
|
'state' => $this->shipping_state, |
1113
|
|
|
'postcode' => $this->shipping_postcode, |
1114
|
|
|
'country' => $this->shipping_country |
1115
|
|
|
), $this ); |
1116
|
|
|
|
1117
|
|
|
$this->formatted_shipping_address = WC()->countries->get_formatted_address( $address ); |
1118
|
|
|
} |
1119
|
|
|
} |
1120
|
|
|
|
1121
|
|
|
return $this->formatted_shipping_address; |
1122
|
|
|
} |
1123
|
|
|
|
1124
|
|
|
/** |
1125
|
|
|
* Get a formatted shipping address for the order. |
1126
|
|
|
* |
1127
|
|
|
* @return string |
1128
|
|
|
*/ |
1129
|
|
|
public function get_shipping_address_map_url() { |
1130
|
|
|
$address = apply_filters( 'woocommerce_shipping_address_map_url_parts', array( |
1131
|
|
|
'address_1' => $this->shipping_address_1, |
1132
|
|
|
'address_2' => $this->shipping_address_2, |
1133
|
|
|
'city' => $this->shipping_city, |
1134
|
|
|
'state' => $this->shipping_state, |
1135
|
|
|
'postcode' => $this->shipping_postcode, |
1136
|
|
|
'country' => $this->shipping_country |
1137
|
|
|
), $this ); |
1138
|
|
|
|
1139
|
|
|
return apply_filters( 'woocommerce_shipping_address_map_url', 'https://maps.google.com/maps?&q=' . urlencode( implode( ', ', $address ) ) . '&z=16', $this ); |
1140
|
|
|
} |
1141
|
|
|
|
1142
|
|
|
/** |
1143
|
|
|
* Get the billing address in an array. |
1144
|
|
|
* @deprecated 2.3 |
1145
|
|
|
* @return string |
1146
|
|
|
*/ |
1147
|
|
|
public function get_billing_address() { |
1148
|
|
|
_deprecated_function( 'get_billing_address', '2.3', 'get_formatted_billing_address' ); |
1149
|
|
|
return $this->get_formatted_billing_address(); |
1150
|
|
|
} |
1151
|
|
|
|
1152
|
|
|
/** |
1153
|
|
|
* Get the shipping address in an array. |
1154
|
|
|
* @deprecated 2.3 |
1155
|
|
|
* @return string |
1156
|
|
|
*/ |
1157
|
|
|
public function get_shipping_address() { |
1158
|
|
|
_deprecated_function( 'get_shipping_address', '2.3', 'get_formatted_shipping_address' ); |
1159
|
|
|
return $this->get_formatted_shipping_address(); |
1160
|
|
|
} |
1161
|
|
|
|
1162
|
|
|
/** |
1163
|
|
|
* Get a formatted billing full name. |
1164
|
|
|
* |
1165
|
|
|
* @since 2.4.0 |
1166
|
|
|
* |
1167
|
|
|
* @return string |
1168
|
|
|
*/ |
1169
|
|
|
public function get_formatted_billing_full_name() { |
1170
|
|
|
return sprintf( _x( '%1$s %2$s', 'full name', 'woocommerce' ), $this->billing_first_name, $this->billing_last_name ); |
1171
|
|
|
} |
1172
|
|
|
|
1173
|
|
|
/** |
1174
|
|
|
* Get a formatted shipping full name. |
1175
|
|
|
* |
1176
|
|
|
* @since 2.4.0 |
1177
|
|
|
* |
1178
|
|
|
* @return string |
1179
|
|
|
*/ |
1180
|
|
|
public function get_formatted_shipping_full_name() { |
1181
|
|
|
return sprintf( _x( '%1$s %2$s', 'full name', 'woocommerce' ), $this->shipping_first_name, $this->shipping_last_name ); |
1182
|
|
|
} |
1183
|
|
|
|
1184
|
|
|
/** |
1185
|
|
|
* Return an array of items/products within this order. |
1186
|
|
|
* |
1187
|
|
|
* @param string|array $type Types of line items to get (array or string). |
1188
|
|
|
* @return array |
1189
|
|
|
*/ |
1190
|
|
|
public function get_items( $type = '' ) { |
1191
|
|
|
global $wpdb; |
1192
|
|
|
|
1193
|
|
|
if ( empty( $type ) ) { |
1194
|
|
|
$type = array( 'line_item' ); |
1195
|
|
|
} |
1196
|
|
|
|
1197
|
|
|
if ( ! is_array( $type ) ) { |
1198
|
|
|
$type = array( $type ); |
1199
|
|
|
} |
1200
|
|
|
|
1201
|
|
|
$items = array(); |
1202
|
|
|
$get_items_sql = $wpdb->prepare( "SELECT order_item_id, order_item_name, order_item_type FROM {$wpdb->prefix}woocommerce_order_items WHERE order_id = %d ", $this->id ); |
1203
|
|
|
$get_items_sql .= "AND order_item_type IN ( '" . implode( "','", array_map( 'esc_sql', $type ) ) . "' ) ORDER BY order_item_id;"; |
1204
|
|
|
$line_items = $wpdb->get_results( $get_items_sql ); |
1205
|
|
|
|
1206
|
|
|
// Loop items |
1207
|
|
|
foreach ( $line_items as $item ) { |
1208
|
|
|
$items[ $item->order_item_id ]['name'] = $item->order_item_name; |
1209
|
|
|
$items[ $item->order_item_id ]['type'] = $item->order_item_type; |
1210
|
|
|
$items[ $item->order_item_id ]['item_meta'] = $this->get_item_meta( $item->order_item_id ); |
1211
|
|
|
$items[ $item->order_item_id ]['item_meta_array'] = $this->get_item_meta_array( $item->order_item_id ); |
1212
|
|
|
$items[ $item->order_item_id ] = $this->expand_item_meta( $items[ $item->order_item_id ] ); |
1213
|
|
|
} |
1214
|
|
|
|
1215
|
|
|
return apply_filters( 'woocommerce_order_get_items', $items, $this ); |
1216
|
|
|
} |
1217
|
|
|
|
1218
|
|
|
/** |
1219
|
|
|
* Expand item meta into the $item array. |
1220
|
|
|
* @since 2.4.0 |
1221
|
|
|
* @param array $item before expansion. |
1222
|
|
|
* @return array |
1223
|
|
|
*/ |
1224
|
|
|
public function expand_item_meta( $item ) { |
1225
|
|
|
// Reserved meta keys |
1226
|
|
|
$reserved_item_meta_keys = array( |
1227
|
|
|
'name', |
1228
|
|
|
'type', |
1229
|
|
|
'item_meta', |
1230
|
|
|
'item_meta_array', |
1231
|
|
|
'qty', |
1232
|
|
|
'tax_class', |
1233
|
|
|
'product_id', |
1234
|
|
|
'variation_id', |
1235
|
|
|
'line_subtotal', |
1236
|
|
|
'line_total', |
1237
|
|
|
'line_tax', |
1238
|
|
|
'line_subtotal_tax' |
1239
|
|
|
); |
1240
|
|
|
|
1241
|
|
|
// Expand item meta if set. |
1242
|
|
|
if ( ! empty( $item['item_meta'] ) ) { |
1243
|
|
|
foreach ( $item['item_meta'] as $name => $value ) { |
1244
|
|
|
if ( in_array( $name, $reserved_item_meta_keys ) ) { |
1245
|
|
|
continue; |
1246
|
|
|
} |
1247
|
|
|
if ( '_' === substr( $name, 0, 1 ) ) { |
1248
|
|
|
$item[ substr( $name, 1 ) ] = $value[0]; |
1249
|
|
|
} elseif ( ! in_array( $name, $reserved_item_meta_keys ) ) { |
1250
|
|
|
$item[ $name ] = make_clickable( $value[0] ); |
1251
|
|
|
} |
1252
|
|
|
} |
1253
|
|
|
} |
1254
|
|
|
return $item; |
1255
|
|
|
} |
1256
|
|
|
|
1257
|
|
|
/** |
1258
|
|
|
* Gets the count of order items of a certain type. |
1259
|
|
|
* |
1260
|
|
|
* @param string $item_type |
1261
|
|
|
* @return string |
1262
|
|
|
*/ |
1263
|
|
View Code Duplication |
public function get_item_count( $item_type = '' ) { |
|
|
|
|
1264
|
|
|
if ( empty( $item_type ) ) { |
1265
|
|
|
$item_type = array( 'line_item' ); |
1266
|
|
|
} |
1267
|
|
|
if ( ! is_array( $item_type ) ) { |
1268
|
|
|
$item_type = array( $item_type ); |
1269
|
|
|
} |
1270
|
|
|
|
1271
|
|
|
$items = $this->get_items( $item_type ); |
1272
|
|
|
$count = 0; |
1273
|
|
|
|
1274
|
|
|
foreach ( $items as $item ) { |
1275
|
|
|
$count += empty( $item['qty'] ) ? 1 : $item['qty']; |
1276
|
|
|
} |
1277
|
|
|
|
1278
|
|
|
return apply_filters( 'woocommerce_get_item_count', $count, $item_type, $this ); |
1279
|
|
|
} |
1280
|
|
|
|
1281
|
|
|
/** |
1282
|
|
|
* Get refunds |
1283
|
|
|
* @return array |
1284
|
|
|
*/ |
1285
|
|
|
public function get_refunds() { return array(); } |
1286
|
|
|
|
1287
|
|
|
/** |
1288
|
|
|
* Return an array of fees within this order. |
1289
|
|
|
* |
1290
|
|
|
* @return array |
1291
|
|
|
*/ |
1292
|
|
|
public function get_fees() { |
1293
|
|
|
return $this->get_items( 'fee' ); |
1294
|
|
|
} |
1295
|
|
|
|
1296
|
|
|
/** |
1297
|
|
|
* Return an array of taxes within this order. |
1298
|
|
|
* |
1299
|
|
|
* @return array |
1300
|
|
|
*/ |
1301
|
|
|
public function get_taxes() { |
1302
|
|
|
return $this->get_items( 'tax' ); |
1303
|
|
|
} |
1304
|
|
|
|
1305
|
|
|
/** |
1306
|
|
|
* Return an array of shipping costs within this order. |
1307
|
|
|
* |
1308
|
|
|
* @return array |
1309
|
|
|
*/ |
1310
|
|
|
public function get_shipping_methods() { |
1311
|
|
|
return $this->get_items( 'shipping' ); |
1312
|
|
|
} |
1313
|
|
|
|
1314
|
|
|
/** |
1315
|
|
|
* Check whether this order has a specific shipping method or not. |
1316
|
|
|
* |
1317
|
|
|
* @param string $method_id |
1318
|
|
|
* |
1319
|
|
|
* @return bool |
1320
|
|
|
*/ |
1321
|
|
|
public function has_shipping_method( $method_id ) { |
1322
|
|
|
|
1323
|
|
|
$shipping_methods = $this->get_shipping_methods(); |
1324
|
|
|
$has_method = false; |
1325
|
|
|
|
1326
|
|
|
if ( empty( $shipping_methods ) ) { |
1327
|
|
|
return false; |
1328
|
|
|
} |
1329
|
|
|
|
1330
|
|
|
foreach ( $shipping_methods as $shipping_method ) { |
1331
|
|
|
if ( $shipping_method['method_id'] == $method_id ) { |
1332
|
|
|
$has_method = true; |
1333
|
|
|
} |
1334
|
|
|
} |
1335
|
|
|
|
1336
|
|
|
return $has_method; |
1337
|
|
|
} |
1338
|
|
|
|
1339
|
|
|
/** |
1340
|
|
|
* Get taxes, merged by code, formatted ready for output. |
1341
|
|
|
* |
1342
|
|
|
* @return array |
1343
|
|
|
*/ |
1344
|
|
|
public function get_tax_totals() { |
1345
|
|
|
|
1346
|
|
|
$taxes = $this->get_items( 'tax' ); |
1347
|
|
|
$tax_totals = array(); |
1348
|
|
|
|
1349
|
|
|
foreach ( $taxes as $key => $tax ) { |
1350
|
|
|
|
1351
|
|
|
$code = $tax[ 'name' ]; |
1352
|
|
|
|
1353
|
|
View Code Duplication |
if ( ! isset( $tax_totals[ $code ] ) ) { |
|
|
|
|
1354
|
|
|
$tax_totals[ $code ] = new stdClass(); |
1355
|
|
|
$tax_totals[ $code ]->amount = 0; |
1356
|
|
|
} |
1357
|
|
|
|
1358
|
|
|
$tax_totals[ $code ]->id = $key; |
1359
|
|
|
$tax_totals[ $code ]->rate_id = $tax['rate_id']; |
1360
|
|
|
$tax_totals[ $code ]->is_compound = $tax[ 'compound' ]; |
1361
|
|
|
$tax_totals[ $code ]->label = isset( $tax[ 'label' ] ) ? $tax[ 'label' ] : $tax[ 'name' ]; |
1362
|
|
|
$tax_totals[ $code ]->amount += $tax[ 'tax_amount' ] + $tax[ 'shipping_tax_amount' ]; |
1363
|
|
|
$tax_totals[ $code ]->formatted_amount = wc_price( wc_round_tax_total( $tax_totals[ $code ]->amount ), array('currency' => $this->get_order_currency()) ); |
1364
|
|
|
} |
1365
|
|
|
|
1366
|
|
View Code Duplication |
if ( apply_filters( 'woocommerce_order_hide_zero_taxes', true ) ) { |
|
|
|
|
1367
|
|
|
$amounts = array_filter( wp_list_pluck( $tax_totals, 'amount' ) ); |
1368
|
|
|
$tax_totals = array_intersect_key( $tax_totals, $amounts ); |
1369
|
|
|
} |
1370
|
|
|
|
1371
|
|
|
return apply_filters( 'woocommerce_order_tax_totals', $tax_totals, $this ); |
1372
|
|
|
} |
1373
|
|
|
|
1374
|
|
|
/** |
1375
|
|
|
* has_meta function for order items. |
1376
|
|
|
* |
1377
|
|
|
* @param string $order_item_id |
1378
|
|
|
* @return array of meta data. |
1379
|
|
|
*/ |
1380
|
|
|
public function has_meta( $order_item_id ) { |
1381
|
|
|
global $wpdb; |
1382
|
|
|
|
1383
|
|
|
return $wpdb->get_results( $wpdb->prepare( "SELECT meta_key, meta_value, meta_id, order_item_id |
1384
|
|
|
FROM {$wpdb->prefix}woocommerce_order_itemmeta WHERE order_item_id = %d |
1385
|
|
|
ORDER BY meta_id", absint( $order_item_id ) ), ARRAY_A ); |
1386
|
|
|
} |
1387
|
|
|
|
1388
|
|
|
/** |
1389
|
|
|
* Get all item meta data in array format in the order it was saved. Does not group meta by key like get_item_meta(). |
1390
|
|
|
* |
1391
|
|
|
* @param mixed $order_item_id |
1392
|
|
|
* @return array of objects |
1393
|
|
|
*/ |
1394
|
|
|
public function get_item_meta_array( $order_item_id ) { |
1395
|
|
|
global $wpdb; |
1396
|
|
|
|
1397
|
|
|
// Get cache key - uses get_cache_prefix to invalidate when needed |
1398
|
|
|
$cache_key = WC_Cache_Helper::get_cache_prefix( 'orders' ) . 'item_meta_array_' . $order_item_id; |
1399
|
|
|
$item_meta_array = wp_cache_get( $cache_key, 'orders' ); |
1400
|
|
|
|
1401
|
|
|
if ( false === $item_meta_array ) { |
1402
|
|
|
$item_meta_array = array(); |
1403
|
|
|
$metadata = $wpdb->get_results( $wpdb->prepare( "SELECT meta_key, meta_value, meta_id FROM {$wpdb->prefix}woocommerce_order_itemmeta WHERE order_item_id = %d ORDER BY meta_id", absint( $order_item_id ) ) ); |
1404
|
|
|
foreach ( $metadata as $metadata_row ) { |
1405
|
|
|
$item_meta_array[ $metadata_row->meta_id ] = (object) array( 'key' => $metadata_row->meta_key, 'value' => $metadata_row->meta_value ); |
1406
|
|
|
} |
1407
|
|
|
wp_cache_set( $cache_key, $item_meta_array, 'orders' ); |
1408
|
|
|
} |
1409
|
|
|
|
1410
|
|
|
return $item_meta_array ; |
1411
|
|
|
} |
1412
|
|
|
|
1413
|
|
|
/** |
1414
|
|
|
* Display meta data belonging to an item. |
1415
|
|
|
* @param array $item |
1416
|
|
|
*/ |
1417
|
|
|
public function display_item_meta( $item ) { |
1418
|
|
|
$product = $this->get_product_from_item( $item ); |
1419
|
|
|
$item_meta = new WC_Order_Item_Meta( $item, $product ); |
1420
|
|
|
$item_meta->display(); |
1421
|
|
|
} |
1422
|
|
|
|
1423
|
|
|
/** |
1424
|
|
|
* Get order item meta. |
1425
|
|
|
* |
1426
|
|
|
* @param mixed $order_item_id |
1427
|
|
|
* @param string $key (default: '') |
1428
|
|
|
* @param bool $single (default: false) |
1429
|
|
|
* @return array|string |
1430
|
|
|
*/ |
1431
|
|
|
public function get_item_meta( $order_item_id, $key = '', $single = false ) { |
1432
|
|
|
return get_metadata( 'order_item', $order_item_id, $key, $single ); |
1433
|
|
|
} |
1434
|
|
|
|
1435
|
|
|
/** Total Getters *******************************************************/ |
1436
|
|
|
|
1437
|
|
|
/** |
1438
|
|
|
* Gets the total discount amount. |
1439
|
|
|
* @param bool $ex_tax Show discount excl any tax. |
1440
|
|
|
* @return float |
1441
|
|
|
*/ |
1442
|
|
|
public function get_total_discount( $ex_tax = true ) { |
1443
|
|
|
if ( ! $this->order_version || version_compare( $this->order_version, '2.3.7', '<' ) ) { |
1444
|
|
|
// Backwards compatible total calculation - totals were not stored consistently in old versions. |
1445
|
|
|
if ( $ex_tax ) { |
1446
|
|
View Code Duplication |
if ( $this->prices_include_tax ) { |
|
|
|
|
1447
|
|
|
$total_discount = (double) $this->cart_discount - (double) $this->cart_discount_tax; |
1448
|
|
|
} else { |
1449
|
|
|
$total_discount = (double) $this->cart_discount; |
1450
|
|
|
} |
1451
|
|
View Code Duplication |
} else { |
|
|
|
|
1452
|
|
|
if ( $this->prices_include_tax ) { |
1453
|
|
|
$total_discount = (double) $this->cart_discount; |
1454
|
|
|
} else { |
1455
|
|
|
$total_discount = (double) $this->cart_discount + (double) $this->cart_discount_tax; |
1456
|
|
|
} |
1457
|
|
|
} |
1458
|
|
|
// New logic - totals are always stored exclusive of tax, tax total is stored in cart_discount_tax |
1459
|
|
|
} else { |
1460
|
|
|
if ( $ex_tax ) { |
1461
|
|
|
$total_discount = (double) $this->cart_discount; |
1462
|
|
|
} else { |
1463
|
|
|
$total_discount = (double) $this->cart_discount + (double) $this->cart_discount_tax; |
1464
|
|
|
} |
1465
|
|
|
} |
1466
|
|
|
return apply_filters( 'woocommerce_order_amount_total_discount', round( $total_discount, WC_ROUNDING_PRECISION ), $this ); |
1467
|
|
|
} |
1468
|
|
|
|
1469
|
|
|
/** |
1470
|
|
|
* Gets the discount amount. |
1471
|
|
|
* @deprecated in favour of get_total_discount() since we now only have one discount type. |
1472
|
|
|
* @return float |
1473
|
|
|
*/ |
1474
|
|
|
public function get_cart_discount() { |
1475
|
|
|
_deprecated_function( 'get_cart_discount', '2.3', 'get_total_discount' ); |
1476
|
|
|
return apply_filters( 'woocommerce_order_amount_cart_discount', $this->get_total_discount(), $this ); |
1477
|
|
|
} |
1478
|
|
|
|
1479
|
|
|
/** |
1480
|
|
|
* Get cart discount (formatted). |
1481
|
|
|
* |
1482
|
|
|
* @deprecated order (after tax) discounts removed in 2.3.0. |
1483
|
|
|
* @return string |
1484
|
|
|
*/ |
1485
|
|
|
public function get_order_discount_to_display() { |
1486
|
|
|
_deprecated_function( 'get_order_discount_to_display', '2.3' ); |
1487
|
|
|
} |
1488
|
|
|
|
1489
|
|
|
/** |
1490
|
|
|
* Gets the total (order) discount amount - these are applied after tax. |
1491
|
|
|
* |
1492
|
|
|
* @deprecated order (after tax) discounts removed in 2.3.0. |
1493
|
|
|
* @return float |
1494
|
|
|
*/ |
1495
|
|
|
public function get_order_discount() { |
1496
|
|
|
_deprecated_function( 'get_order_discount', '2.3' ); |
1497
|
|
|
return apply_filters( 'woocommerce_order_amount_order_discount', (double) $this->order_discount, $this ); |
1498
|
|
|
} |
1499
|
|
|
|
1500
|
|
|
/** |
1501
|
|
|
* Gets cart tax amount. |
1502
|
|
|
* |
1503
|
|
|
* @return float |
1504
|
|
|
*/ |
1505
|
|
|
public function get_cart_tax() { |
1506
|
|
|
return apply_filters( 'woocommerce_order_amount_cart_tax', (double) $this->order_tax, $this ); |
1507
|
|
|
} |
1508
|
|
|
|
1509
|
|
|
/** |
1510
|
|
|
* Gets shipping tax amount. |
1511
|
|
|
* |
1512
|
|
|
* @return float |
1513
|
|
|
*/ |
1514
|
|
|
public function get_shipping_tax() { |
1515
|
|
|
return apply_filters( 'woocommerce_order_amount_shipping_tax', (double) $this->order_shipping_tax, $this ); |
1516
|
|
|
} |
1517
|
|
|
|
1518
|
|
|
/** |
1519
|
|
|
* Gets shipping and product tax. |
1520
|
|
|
* |
1521
|
|
|
* @return float |
1522
|
|
|
*/ |
1523
|
|
|
public function get_total_tax() { |
1524
|
|
|
return apply_filters( 'woocommerce_order_amount_total_tax', wc_round_tax_total( $this->get_cart_tax() + $this->get_shipping_tax() ), $this ); |
1525
|
|
|
} |
1526
|
|
|
|
1527
|
|
|
/** |
1528
|
|
|
* Gets shipping total. |
1529
|
|
|
* |
1530
|
|
|
* @return float |
1531
|
|
|
*/ |
1532
|
|
|
public function get_total_shipping() { |
1533
|
|
|
return apply_filters( 'woocommerce_order_amount_total_shipping', (double) $this->order_shipping, $this ); |
1534
|
|
|
} |
1535
|
|
|
|
1536
|
|
|
/** |
1537
|
|
|
* Gets order total. |
1538
|
|
|
* |
1539
|
|
|
* @return float |
1540
|
|
|
*/ |
1541
|
|
|
public function get_total() { |
1542
|
|
|
return apply_filters( 'woocommerce_order_amount_total', (double) $this->order_total, $this ); |
1543
|
|
|
} |
1544
|
|
|
|
1545
|
|
|
/** |
1546
|
|
|
* Gets order subtotal. |
1547
|
|
|
* |
1548
|
|
|
* @return mixed|void |
1549
|
|
|
*/ |
1550
|
|
|
public function get_subtotal() { |
1551
|
|
|
$subtotal = 0; |
1552
|
|
|
|
1553
|
|
|
foreach ( $this->get_items() as $item ) { |
1554
|
|
|
$subtotal += ( isset( $item['line_subtotal'] ) ) ? $item['line_subtotal'] : 0; |
1555
|
|
|
} |
1556
|
|
|
|
1557
|
|
|
return apply_filters( 'woocommerce_order_amount_subtotal', (double) $subtotal, $this ); |
1558
|
|
|
} |
1559
|
|
|
|
1560
|
|
|
/** |
1561
|
|
|
* Get item subtotal - this is the cost before discount. |
1562
|
|
|
* |
1563
|
|
|
* @param mixed $item |
1564
|
|
|
* @param bool $inc_tax (default: false). |
1565
|
|
|
* @param bool $round (default: true). |
1566
|
|
|
* @return float |
1567
|
|
|
*/ |
1568
|
|
|
public function get_item_subtotal( $item, $inc_tax = false, $round = true ) { |
1569
|
|
|
if ( $inc_tax ) { |
1570
|
|
|
$price = ( $item['line_subtotal'] + $item['line_subtotal_tax'] ) / max( 1, $item['qty'] ); |
1571
|
|
|
} else { |
1572
|
|
|
$price = ( $item['line_subtotal'] / max( 1, $item['qty'] ) ); |
1573
|
|
|
} |
1574
|
|
|
|
1575
|
|
|
$price = $round ? number_format( (float) $price, wc_get_price_decimals(), '.', '' ) : $price; |
1576
|
|
|
|
1577
|
|
|
return apply_filters( 'woocommerce_order_amount_item_subtotal', $price, $this, $item, $inc_tax, $round ); |
1578
|
|
|
} |
1579
|
|
|
|
1580
|
|
|
/** |
1581
|
|
|
* Get line subtotal - this is the cost before discount. |
1582
|
|
|
* |
1583
|
|
|
* @param mixed $item |
1584
|
|
|
* @param bool $inc_tax (default: false). |
1585
|
|
|
* @param bool $round (default: true). |
1586
|
|
|
* @return float |
1587
|
|
|
*/ |
1588
|
|
View Code Duplication |
public function get_line_subtotal( $item, $inc_tax = false, $round = true ) { |
|
|
|
|
1589
|
|
|
if ( $inc_tax ) { |
1590
|
|
|
$price = $item['line_subtotal'] + $item['line_subtotal_tax']; |
1591
|
|
|
} else { |
1592
|
|
|
$price = $item['line_subtotal']; |
1593
|
|
|
} |
1594
|
|
|
|
1595
|
|
|
$price = $round ? round( $price, wc_get_price_decimals() ) : $price; |
1596
|
|
|
|
1597
|
|
|
return apply_filters( 'woocommerce_order_amount_line_subtotal', $price, $this, $item, $inc_tax, $round ); |
1598
|
|
|
} |
1599
|
|
|
|
1600
|
|
|
/** |
1601
|
|
|
* Calculate item cost - useful for gateways. |
1602
|
|
|
* |
1603
|
|
|
* @param mixed $item |
1604
|
|
|
* @param bool $inc_tax (default: false). |
1605
|
|
|
* @param bool $round (default: true). |
1606
|
|
|
* @return float |
1607
|
|
|
*/ |
1608
|
|
|
public function get_item_total( $item, $inc_tax = false, $round = true ) { |
1609
|
|
|
|
1610
|
|
|
$qty = ( ! empty( $item['qty'] ) ) ? $item['qty'] : 1; |
1611
|
|
|
|
1612
|
|
|
if ( $inc_tax ) { |
1613
|
|
|
$price = ( $item['line_total'] + $item['line_tax'] ) / max( 1, $qty ); |
1614
|
|
|
} else { |
1615
|
|
|
$price = $item['line_total'] / max( 1, $qty ); |
1616
|
|
|
} |
1617
|
|
|
|
1618
|
|
|
$price = $round ? round( $price, wc_get_price_decimals() ) : $price; |
1619
|
|
|
|
1620
|
|
|
return apply_filters( 'woocommerce_order_amount_item_total', $price, $this, $item, $inc_tax, $round ); |
1621
|
|
|
} |
1622
|
|
|
|
1623
|
|
|
/** |
1624
|
|
|
* Calculate line total - useful for gateways. |
1625
|
|
|
* |
1626
|
|
|
* @param mixed $item |
1627
|
|
|
* @param bool $inc_tax (default: false). |
1628
|
|
|
* @param bool $round (default: true). |
1629
|
|
|
* @return float |
1630
|
|
|
*/ |
1631
|
|
View Code Duplication |
public function get_line_total( $item, $inc_tax = false, $round = true ) { |
|
|
|
|
1632
|
|
|
|
1633
|
|
|
// Check if we need to add line tax to the line total. |
1634
|
|
|
$line_total = $inc_tax ? $item['line_total'] + $item['line_tax'] : $item['line_total']; |
1635
|
|
|
|
1636
|
|
|
// Check if we need to round. |
1637
|
|
|
$line_total = $round ? round( $line_total, wc_get_price_decimals() ) : $line_total; |
1638
|
|
|
|
1639
|
|
|
return apply_filters( 'woocommerce_order_amount_line_total', $line_total, $this, $item, $inc_tax, $round ); |
1640
|
|
|
} |
1641
|
|
|
|
1642
|
|
|
/** |
1643
|
|
|
* Calculate item tax - useful for gateways. |
1644
|
|
|
* |
1645
|
|
|
* @param mixed $item |
1646
|
|
|
* @param bool $round (default: true). |
1647
|
|
|
* @return float |
1648
|
|
|
*/ |
1649
|
|
|
public function get_item_tax( $item, $round = true ) { |
1650
|
|
|
|
1651
|
|
|
$price = $item['line_tax'] / max( 1, $item['qty'] ); |
1652
|
|
|
$price = $round ? wc_round_tax_total( $price ) : $price; |
1653
|
|
|
|
1654
|
|
|
return apply_filters( 'woocommerce_order_amount_item_tax', $price, $item, $round, $this ); |
1655
|
|
|
} |
1656
|
|
|
|
1657
|
|
|
/** |
1658
|
|
|
* Calculate line tax - useful for gateways. |
1659
|
|
|
* |
1660
|
|
|
* @param mixed $item |
1661
|
|
|
* @return float |
1662
|
|
|
*/ |
1663
|
|
|
public function get_line_tax( $item ) { |
1664
|
|
|
return apply_filters( 'woocommerce_order_amount_line_tax', wc_round_tax_total( $item['line_tax'] ), $item, $this ); |
1665
|
|
|
} |
1666
|
|
|
|
1667
|
|
|
/** End Total Getters *******************************************************/ |
1668
|
|
|
|
1669
|
|
|
/** |
1670
|
|
|
* Gets formatted shipping method title. |
1671
|
|
|
* |
1672
|
|
|
* @return string |
1673
|
|
|
*/ |
1674
|
|
|
public function get_shipping_method() { |
1675
|
|
|
|
1676
|
|
|
$labels = array(); |
1677
|
|
|
|
1678
|
|
|
// Backwards compat < 2.1 - get shipping title stored in meta. |
1679
|
|
|
if ( $this->shipping_method_title ) { |
1680
|
|
|
$labels[] = $this->shipping_method_title; |
1681
|
|
|
} else { |
1682
|
|
|
|
1683
|
|
|
// 2.1+ get line items for shipping. |
1684
|
|
|
$shipping_methods = $this->get_shipping_methods(); |
1685
|
|
|
|
1686
|
|
|
foreach ( $shipping_methods as $shipping ) { |
1687
|
|
|
$labels[] = $shipping['name'] ? $shipping['name'] : __( 'Shipping', 'woocommerce' ); |
1688
|
|
|
} |
1689
|
|
|
} |
1690
|
|
|
|
1691
|
|
|
return apply_filters( 'woocommerce_order_shipping_method', implode( ', ', $labels ), $this ); |
1692
|
|
|
} |
1693
|
|
|
|
1694
|
|
|
/** |
1695
|
|
|
* Gets line subtotal - formatted for display. |
1696
|
|
|
* |
1697
|
|
|
* @param array $item |
1698
|
|
|
* @param string $tax_display |
1699
|
|
|
* @return string |
1700
|
|
|
*/ |
1701
|
|
|
public function get_formatted_line_subtotal( $item, $tax_display = '' ) { |
1702
|
|
|
|
1703
|
|
|
if ( ! $tax_display ) { |
1704
|
|
|
$tax_display = $this->tax_display_cart; |
1705
|
|
|
} |
1706
|
|
|
|
1707
|
|
|
if ( ! isset( $item['line_subtotal'] ) || ! isset( $item['line_subtotal_tax'] ) ) { |
1708
|
|
|
return ''; |
1709
|
|
|
} |
1710
|
|
|
|
1711
|
|
|
if ( 'excl' == $tax_display ) { |
1712
|
|
|
$ex_tax_label = $this->prices_include_tax ? 1 : 0; |
1713
|
|
|
|
1714
|
|
|
$subtotal = wc_price( $this->get_line_subtotal( $item ), array( 'ex_tax_label' => $ex_tax_label, 'currency' => $this->get_order_currency() ) ); |
1715
|
|
|
} else { |
1716
|
|
|
$subtotal = wc_price( $this->get_line_subtotal( $item, true ), array('currency' => $this->get_order_currency()) ); |
1717
|
|
|
} |
1718
|
|
|
|
1719
|
|
|
return apply_filters( 'woocommerce_order_formatted_line_subtotal', $subtotal, $item, $this ); |
1720
|
|
|
} |
1721
|
|
|
|
1722
|
|
|
/** |
1723
|
|
|
* Gets order currency. |
1724
|
|
|
* |
1725
|
|
|
* @return string |
1726
|
|
|
*/ |
1727
|
|
|
public function get_order_currency() { |
1728
|
|
|
return apply_filters( 'woocommerce_get_order_currency', $this->order_currency, $this ); |
1729
|
|
|
} |
1730
|
|
|
|
1731
|
|
|
/** |
1732
|
|
|
* Gets order total - formatted for display. |
1733
|
|
|
* |
1734
|
|
|
* @return string |
1735
|
|
|
*/ |
1736
|
|
|
public function get_formatted_order_total() { |
1737
|
|
|
$formatted_total = wc_price( $this->get_total(), array( 'currency' => $this->get_order_currency() ) ); |
1738
|
|
|
return apply_filters( 'woocommerce_get_formatted_order_total', $formatted_total, $this ); |
1739
|
|
|
} |
1740
|
|
|
|
1741
|
|
|
/** |
1742
|
|
|
* Gets subtotal - subtotal is shown before discounts, but with localised taxes. |
1743
|
|
|
* |
1744
|
|
|
* @param bool $compound (default: false). |
1745
|
|
|
* @param string $tax_display (default: the tax_display_cart value). |
1746
|
|
|
* @return string |
1747
|
|
|
*/ |
1748
|
|
|
public function get_subtotal_to_display( $compound = false, $tax_display = '' ) { |
1749
|
|
|
|
1750
|
|
|
if ( ! $tax_display ) { |
1751
|
|
|
$tax_display = $this->tax_display_cart; |
1752
|
|
|
} |
1753
|
|
|
|
1754
|
|
|
$subtotal = 0; |
1755
|
|
|
|
1756
|
|
|
if ( ! $compound ) { |
1757
|
|
|
foreach ( $this->get_items() as $item ) { |
1758
|
|
|
|
1759
|
|
|
if ( ! isset( $item['line_subtotal'] ) || ! isset( $item['line_subtotal_tax'] ) ) { |
1760
|
|
|
return ''; |
1761
|
|
|
} |
1762
|
|
|
|
1763
|
|
|
$subtotal += $item['line_subtotal']; |
1764
|
|
|
|
1765
|
|
|
if ( 'incl' == $tax_display ) { |
1766
|
|
|
$subtotal += $item['line_subtotal_tax']; |
1767
|
|
|
} |
1768
|
|
|
} |
1769
|
|
|
|
1770
|
|
|
$subtotal = wc_price( $subtotal, array('currency' => $this->get_order_currency()) ); |
1771
|
|
|
|
1772
|
|
|
if ( $tax_display == 'excl' && $this->prices_include_tax ) { |
1773
|
|
|
$subtotal .= ' <small class="tax_label">' . WC()->countries->ex_tax_or_vat() . '</small>'; |
1774
|
|
|
} |
1775
|
|
|
|
1776
|
|
|
} else { |
1777
|
|
|
|
1778
|
|
|
if ( 'incl' == $tax_display ) { |
1779
|
|
|
return ''; |
1780
|
|
|
} |
1781
|
|
|
|
1782
|
|
|
foreach ( $this->get_items() as $item ) { |
1783
|
|
|
|
1784
|
|
|
$subtotal += $item['line_subtotal']; |
1785
|
|
|
|
1786
|
|
|
} |
1787
|
|
|
|
1788
|
|
|
// Add Shipping Costs. |
1789
|
|
|
$subtotal += $this->get_total_shipping(); |
1790
|
|
|
|
1791
|
|
|
// Remove non-compound taxes. |
1792
|
|
|
foreach ( $this->get_taxes() as $tax ) { |
1793
|
|
|
|
1794
|
|
|
if ( ! empty( $tax['compound'] ) ) { |
1795
|
|
|
continue; |
1796
|
|
|
} |
1797
|
|
|
|
1798
|
|
|
$subtotal = $subtotal + $tax['tax_amount'] + $tax['shipping_tax_amount']; |
1799
|
|
|
|
1800
|
|
|
} |
1801
|
|
|
|
1802
|
|
|
// Remove discounts. |
1803
|
|
|
$subtotal = $subtotal - $this->get_total_discount(); |
1804
|
|
|
|
1805
|
|
|
$subtotal = wc_price( $subtotal, array('currency' => $this->get_order_currency()) ); |
1806
|
|
|
} |
1807
|
|
|
|
1808
|
|
|
return apply_filters( 'woocommerce_order_subtotal_to_display', $subtotal, $compound, $this ); |
1809
|
|
|
} |
1810
|
|
|
|
1811
|
|
|
|
1812
|
|
|
/** |
1813
|
|
|
* Gets shipping (formatted). |
1814
|
|
|
* |
1815
|
|
|
* @return string |
1816
|
|
|
*/ |
1817
|
|
|
public function get_shipping_to_display( $tax_display = '' ) { |
1818
|
|
|
if ( ! $tax_display ) { |
1819
|
|
|
$tax_display = $this->tax_display_cart; |
1820
|
|
|
} |
1821
|
|
|
|
1822
|
|
|
if ( $this->order_shipping != 0 ) { |
1823
|
|
|
|
1824
|
|
|
if ( $tax_display == 'excl' ) { |
1825
|
|
|
|
1826
|
|
|
// Show shipping excluding tax. |
1827
|
|
|
$shipping = wc_price( $this->order_shipping, array('currency' => $this->get_order_currency()) ); |
1828
|
|
|
|
1829
|
|
View Code Duplication |
if ( $this->order_shipping_tax != 0 && $this->prices_include_tax ) { |
|
|
|
|
1830
|
|
|
$shipping .= apply_filters( 'woocommerce_order_shipping_to_display_tax_label', ' <small class="tax_label">' . WC()->countries->ex_tax_or_vat() . '</small>', $this, $tax_display ); |
1831
|
|
|
} |
1832
|
|
|
|
1833
|
|
|
} else { |
1834
|
|
|
|
1835
|
|
|
// Show shipping including tax. |
1836
|
|
|
$shipping = wc_price( $this->order_shipping + $this->order_shipping_tax, array('currency' => $this->get_order_currency()) ); |
1837
|
|
|
|
1838
|
|
View Code Duplication |
if ( $this->order_shipping_tax != 0 && ! $this->prices_include_tax ) { |
|
|
|
|
1839
|
|
|
$shipping .= apply_filters( 'woocommerce_order_shipping_to_display_tax_label', ' <small class="tax_label">' . WC()->countries->inc_tax_or_vat() . '</small>', $this, $tax_display ); |
1840
|
|
|
} |
1841
|
|
|
|
1842
|
|
|
} |
1843
|
|
|
|
1844
|
|
|
$shipping .= apply_filters( 'woocommerce_order_shipping_to_display_shipped_via', ' <small class="shipped_via">' . sprintf( __( 'via %s', 'woocommerce' ), $this->get_shipping_method() ) . '</small>', $this ); |
1845
|
|
|
|
1846
|
|
|
} elseif ( $this->get_shipping_method() ) { |
1847
|
|
|
$shipping = $this->get_shipping_method(); |
1848
|
|
|
} else { |
1849
|
|
|
$shipping = __( 'Free!', 'woocommerce' ); |
1850
|
|
|
} |
1851
|
|
|
|
1852
|
|
|
return apply_filters( 'woocommerce_order_shipping_to_display', $shipping, $this ); |
1853
|
|
|
} |
1854
|
|
|
|
1855
|
|
|
/** |
1856
|
|
|
* Get the discount amount (formatted). |
1857
|
|
|
* @since 2.3.0 |
1858
|
|
|
* @return string |
1859
|
|
|
*/ |
1860
|
|
|
public function get_discount_to_display( $tax_display = '' ) { |
1861
|
|
|
if ( ! $tax_display ) { |
1862
|
|
|
$tax_display = $this->tax_display_cart; |
1863
|
|
|
} |
1864
|
|
|
return apply_filters( 'woocommerce_order_discount_to_display', wc_price( $this->get_total_discount( $tax_display === 'excl' && $this->display_totals_ex_tax ), array( 'currency' => $this->get_order_currency() ) ), $this ); |
1865
|
|
|
} |
1866
|
|
|
|
1867
|
|
|
/** |
1868
|
|
|
* Get cart discount (formatted). |
1869
|
|
|
* @deprecated |
1870
|
|
|
* @return string |
1871
|
|
|
*/ |
1872
|
|
|
public function get_cart_discount_to_display( $tax_display = '' ) { |
1873
|
|
|
_deprecated_function( 'get_cart_discount_to_display', '2.3', 'get_discount_to_display' ); |
1874
|
|
|
return apply_filters( 'woocommerce_order_cart_discount_to_display', $this->get_discount_to_display( $tax_display ), $this ); |
1875
|
|
|
} |
1876
|
|
|
|
1877
|
|
|
/** |
1878
|
|
|
* Get a product (either product or variation). |
1879
|
|
|
* |
1880
|
|
|
* @param mixed $item |
1881
|
|
|
* @return WC_Product |
1882
|
|
|
*/ |
1883
|
|
|
public function get_product_from_item( $item ) { |
1884
|
|
|
|
1885
|
|
|
if ( ! empty( $item['variation_id'] ) && 'product_variation' === get_post_type( $item['variation_id'] ) ) { |
1886
|
|
|
$_product = wc_get_product( $item['variation_id'] ); |
1887
|
|
|
} elseif ( ! empty( $item['product_id'] ) ) { |
1888
|
|
|
$_product = wc_get_product( $item['product_id'] ); |
1889
|
|
|
} else { |
1890
|
|
|
$_product = false; |
1891
|
|
|
} |
1892
|
|
|
|
1893
|
|
|
return apply_filters( 'woocommerce_get_product_from_item', $_product, $item, $this ); |
1894
|
|
|
} |
1895
|
|
|
|
1896
|
|
|
|
1897
|
|
|
/** |
1898
|
|
|
* Get totals for display on pages and in emails. |
1899
|
|
|
* |
1900
|
|
|
* @param mixed $tax_display |
1901
|
|
|
* @return array |
1902
|
|
|
*/ |
1903
|
|
|
public function get_order_item_totals( $tax_display = '' ) { |
1904
|
|
|
|
1905
|
|
|
if ( ! $tax_display ) { |
1906
|
|
|
$tax_display = $this->tax_display_cart; |
1907
|
|
|
} |
1908
|
|
|
|
1909
|
|
|
$total_rows = array(); |
1910
|
|
|
|
1911
|
|
|
if ( $subtotal = $this->get_subtotal_to_display( false, $tax_display ) ) { |
1912
|
|
|
$total_rows['cart_subtotal'] = array( |
1913
|
|
|
'label' => __( 'Subtotal:', 'woocommerce' ), |
1914
|
|
|
'value' => $subtotal |
1915
|
|
|
); |
1916
|
|
|
} |
1917
|
|
|
|
1918
|
|
|
if ( $this->get_total_discount() > 0 ) { |
1919
|
|
|
$total_rows['discount'] = array( |
1920
|
|
|
'label' => __( 'Discount:', 'woocommerce' ), |
1921
|
|
|
'value' => '-' . $this->get_discount_to_display( $tax_display ) |
1922
|
|
|
); |
1923
|
|
|
} |
1924
|
|
|
|
1925
|
|
|
if ( $this->get_shipping_method() ) { |
1926
|
|
|
$total_rows['shipping'] = array( |
1927
|
|
|
'label' => __( 'Shipping:', 'woocommerce' ), |
1928
|
|
|
'value' => $this->get_shipping_to_display( $tax_display ) |
1929
|
|
|
); |
1930
|
|
|
} |
1931
|
|
|
|
1932
|
|
|
if ( $fees = $this->get_fees() ) { |
1933
|
|
|
foreach ( $fees as $id => $fee ) { |
1934
|
|
|
|
1935
|
|
|
if ( apply_filters( 'woocommerce_get_order_item_totals_excl_free_fees', $fee['line_total'] + $fee['line_tax'] == 0, $id ) ) { |
1936
|
|
|
continue; |
1937
|
|
|
} |
1938
|
|
|
|
1939
|
|
|
if ( 'excl' == $tax_display ) { |
1940
|
|
|
|
1941
|
|
|
$total_rows[ 'fee_' . $id ] = array( |
1942
|
|
|
'label' => ( $fee['name'] ? $fee['name'] : __( 'Fee', 'woocommerce' ) ) . ':', |
1943
|
|
|
'value' => wc_price( $fee['line_total'], array('currency' => $this->get_order_currency()) ) |
1944
|
|
|
); |
1945
|
|
|
|
1946
|
|
|
} else { |
1947
|
|
|
|
1948
|
|
|
$total_rows[ 'fee_' . $id ] = array( |
1949
|
|
|
'label' => $fee['name'] . ':', |
1950
|
|
|
'value' => wc_price( $fee['line_total'] + $fee['line_tax'], array('currency' => $this->get_order_currency()) ) |
1951
|
|
|
); |
1952
|
|
|
} |
1953
|
|
|
} |
1954
|
|
|
} |
1955
|
|
|
|
1956
|
|
|
// Tax for tax exclusive prices. |
1957
|
|
|
if ( 'excl' === $tax_display ) { |
1958
|
|
|
|
1959
|
|
|
if ( get_option( 'woocommerce_tax_total_display' ) == 'itemized' ) { |
1960
|
|
|
|
1961
|
|
|
foreach ( $this->get_tax_totals() as $code => $tax ) { |
1962
|
|
|
|
1963
|
|
|
$total_rows[ sanitize_title( $code ) ] = array( |
1964
|
|
|
'label' => $tax->label . ':', |
1965
|
|
|
'value' => $tax->formatted_amount |
1966
|
|
|
); |
1967
|
|
|
} |
1968
|
|
|
|
1969
|
|
|
} else { |
1970
|
|
|
|
1971
|
|
|
$total_rows['tax'] = array( |
1972
|
|
|
'label' => WC()->countries->tax_or_vat() . ':', |
1973
|
|
|
'value' => wc_price( $this->get_total_tax(), array( 'currency' => $this->get_order_currency() ) ) |
1974
|
|
|
); |
1975
|
|
|
} |
1976
|
|
|
} |
1977
|
|
|
|
1978
|
|
|
if ( $this->get_total() > 0 && $this->payment_method_title ) { |
1979
|
|
|
$total_rows['payment_method'] = array( |
1980
|
|
|
'label' => __( 'Payment Method:', 'woocommerce' ), |
1981
|
|
|
'value' => $this->payment_method_title |
1982
|
|
|
); |
1983
|
|
|
} |
1984
|
|
|
|
1985
|
|
|
if ( $refunds = $this->get_refunds() ) { |
1986
|
|
|
foreach ( $refunds as $id => $refund ) { |
1987
|
|
|
$total_rows[ 'refund_' . $id ] = array( |
1988
|
|
|
'label' => $refund->get_refund_reason() ? $refund->get_refund_reason() : __( 'Refund', 'woocommerce' ) . ':', |
1989
|
|
|
'value' => wc_price( '-' . $refund->get_refund_amount(), array( 'currency' => $this->get_order_currency() ) ) |
1990
|
|
|
); |
1991
|
|
|
} |
1992
|
|
|
} |
1993
|
|
|
|
1994
|
|
|
$total_rows['order_total'] = array( |
1995
|
|
|
'label' => __( 'Total:', 'woocommerce' ), |
1996
|
|
|
'value' => $this->get_formatted_order_total( $tax_display ) |
|
|
|
|
1997
|
|
|
); |
1998
|
|
|
|
1999
|
|
|
return apply_filters( 'woocommerce_get_order_item_totals', $total_rows, $this ); |
2000
|
|
|
} |
2001
|
|
|
|
2002
|
|
|
|
2003
|
|
|
/** |
2004
|
|
|
* Output items for display in html emails. |
2005
|
|
|
* |
2006
|
|
|
* @param array $args Items args. |
2007
|
|
|
* @param null $deprecated1 Deprecated arg. |
2008
|
|
|
* @param null $deprecated2 Deprecated arg. |
2009
|
|
|
* @param null $deprecated3 Deprecated arg. |
2010
|
|
|
* @param null $deprecated4 Deprecated arg. |
2011
|
|
|
* @param null $deprecated5 Deprecated arg. |
2012
|
|
|
* @return string |
2013
|
|
|
*/ |
2014
|
|
|
public function email_order_items_table( $args = array(), $deprecated1 = null, $deprecated2 = null, $deprecated3 = null, $deprecated4 = null, $deprecated5 = null ) { |
2015
|
|
|
ob_start(); |
2016
|
|
|
|
2017
|
|
|
if ( ! is_null( $deprecated1 ) || ! is_null( $deprecated2 ) || ! is_null( $deprecated3 ) || ! is_null( $deprecated4 ) || ! is_null( $deprecated5 ) ) { |
2018
|
|
|
_deprecated_argument( __FUNCTION__, '2.5.0' ); |
2019
|
|
|
} |
2020
|
|
|
|
2021
|
|
|
$defaults = array( |
2022
|
|
|
'show_sku' => false, |
2023
|
|
|
'show_image' => false, |
2024
|
|
|
'image_size' => array( 32, 32 ), |
2025
|
|
|
'plain_text' => false, |
2026
|
|
|
'sent_to_admin' => false |
2027
|
|
|
); |
2028
|
|
|
|
2029
|
|
|
$args = wp_parse_args( $args, $defaults ); |
2030
|
|
|
$template = $args['plain_text'] ? 'emails/plain/email-order-items.php' : 'emails/email-order-items.php'; |
2031
|
|
|
|
2032
|
|
|
wc_get_template( $template, apply_filters( 'woocommerce_email_order_items_args', array( |
2033
|
|
|
'order' => $this, |
2034
|
|
|
'items' => $this->get_items(), |
2035
|
|
|
'show_download_links' => $this->is_download_permitted() && ! $args['sent_to_admin'], |
2036
|
|
|
'show_sku' => $args['show_sku'], |
2037
|
|
|
'show_purchase_note' => $this->is_paid() && ! $args['sent_to_admin'], |
2038
|
|
|
'show_image' => $args['show_image'], |
2039
|
|
|
'image_size' => $args['image_size'], |
2040
|
|
|
'plain_text' => $args['plain_text'], |
2041
|
|
|
'sent_to_admin' => $args['sent_to_admin'] |
2042
|
|
|
) ) ); |
2043
|
|
|
|
2044
|
|
|
return apply_filters( 'woocommerce_email_order_items_table', ob_get_clean(), $this ); |
2045
|
|
|
} |
2046
|
|
|
|
2047
|
|
|
/** |
2048
|
|
|
* Returns if an order has been paid for based on the order status. |
2049
|
|
|
* @since 2.5.0 |
2050
|
|
|
* @return bool |
2051
|
|
|
*/ |
2052
|
|
|
public function is_paid() { |
2053
|
|
|
return apply_filters( 'woocommerce_order_is_paid', $this->has_status( apply_filters( 'woocommerce_order_is_paid_statuses', array( 'processing', 'completed' ) ) ), $this ); |
2054
|
|
|
} |
2055
|
|
|
|
2056
|
|
|
/** |
2057
|
|
|
* Checks if product download is permitted. |
2058
|
|
|
* |
2059
|
|
|
* @return bool |
2060
|
|
|
*/ |
2061
|
|
|
public function is_download_permitted() { |
2062
|
|
|
return apply_filters( 'woocommerce_order_is_download_permitted', $this->has_status( 'completed' ) || ( get_option( 'woocommerce_downloads_grant_access_after_payment' ) == 'yes' && $this->has_status( 'processing' ) ), $this ); |
2063
|
|
|
} |
2064
|
|
|
|
2065
|
|
|
/** |
2066
|
|
|
* Returns true if the order contains a downloadable product. |
2067
|
|
|
* @return bool |
2068
|
|
|
*/ |
2069
|
|
|
public function has_downloadable_item() { |
2070
|
|
|
foreach ( $this->get_items() as $item ) { |
2071
|
|
|
$_product = $this->get_product_from_item( $item ); |
2072
|
|
|
|
2073
|
|
|
if ( $_product && $_product->exists() && $_product->is_downloadable() && $_product->has_file() ) { |
2074
|
|
|
return true; |
2075
|
|
|
} |
2076
|
|
|
} |
2077
|
|
|
return false; |
2078
|
|
|
} |
2079
|
|
|
|
2080
|
|
|
/** |
2081
|
|
|
* Returns true if the order contains a free product. |
2082
|
|
|
* @since 2.5.0 |
2083
|
|
|
* @return bool |
2084
|
|
|
*/ |
2085
|
|
|
public function has_free_item() { |
2086
|
|
|
foreach ( $this->get_items() as $item ) { |
2087
|
|
|
if ( ! $item['line_total'] ) { |
2088
|
|
|
return true; |
2089
|
|
|
} |
2090
|
|
|
} |
2091
|
|
|
return false; |
2092
|
|
|
} |
2093
|
|
|
|
2094
|
|
|
/** |
2095
|
|
|
* Generates a URL so that a customer can pay for their (unpaid - pending) order. Pass 'true' for the checkout version which doesn't offer gateway choices. |
2096
|
|
|
* |
2097
|
|
|
* @param bool $on_checkout |
2098
|
|
|
* @return string |
2099
|
|
|
*/ |
2100
|
|
|
public function get_checkout_payment_url( $on_checkout = false ) { |
2101
|
|
|
|
2102
|
|
|
$pay_url = wc_get_endpoint_url( 'order-pay', $this->id, wc_get_page_permalink( 'checkout' ) ); |
2103
|
|
|
|
2104
|
|
View Code Duplication |
if ( 'yes' == get_option( 'woocommerce_force_ssl_checkout' ) || is_ssl() ) { |
|
|
|
|
2105
|
|
|
$pay_url = str_replace( 'http:', 'https:', $pay_url ); |
2106
|
|
|
} |
2107
|
|
|
|
2108
|
|
|
if ( $on_checkout ) { |
2109
|
|
|
$pay_url = add_query_arg( 'key', $this->order_key, $pay_url ); |
2110
|
|
|
} else { |
2111
|
|
|
$pay_url = add_query_arg( array( 'pay_for_order' => 'true', 'key' => $this->order_key ), $pay_url ); |
2112
|
|
|
} |
2113
|
|
|
|
2114
|
|
|
return apply_filters( 'woocommerce_get_checkout_payment_url', $pay_url, $this ); |
2115
|
|
|
} |
2116
|
|
|
|
2117
|
|
|
/** |
2118
|
|
|
* Generates a URL for the thanks page (order received). |
2119
|
|
|
* |
2120
|
|
|
* @return string |
2121
|
|
|
*/ |
2122
|
|
|
public function get_checkout_order_received_url() { |
2123
|
|
|
|
2124
|
|
|
$order_received_url = wc_get_endpoint_url( 'order-received', $this->id, wc_get_page_permalink( 'checkout' ) ); |
2125
|
|
|
|
2126
|
|
|
if ( 'yes' == get_option( 'woocommerce_force_ssl_checkout' ) || is_ssl() ) { |
2127
|
|
|
$order_received_url = str_replace( 'http:', 'https:', $order_received_url ); |
2128
|
|
|
} |
2129
|
|
|
|
2130
|
|
|
$order_received_url = add_query_arg( 'key', $this->order_key, $order_received_url ); |
2131
|
|
|
|
2132
|
|
|
return apply_filters( 'woocommerce_get_checkout_order_received_url', $order_received_url, $this ); |
2133
|
|
|
} |
2134
|
|
|
|
2135
|
|
|
/** |
2136
|
|
|
* Generates a URL so that a customer can cancel their (unpaid - pending) order. |
2137
|
|
|
* |
2138
|
|
|
* @param string $redirect |
2139
|
|
|
* |
2140
|
|
|
* @return string |
2141
|
|
|
*/ |
2142
|
|
View Code Duplication |
public function get_cancel_order_url( $redirect = '' ) { |
|
|
|
|
2143
|
|
|
|
2144
|
|
|
// Get cancel endpoint |
2145
|
|
|
$cancel_endpoint = $this->get_cancel_endpoint(); |
2146
|
|
|
|
2147
|
|
|
return apply_filters( 'woocommerce_get_cancel_order_url', esc_url( add_query_arg( array( |
2148
|
|
|
'cancel_order' => 'true', |
2149
|
|
|
'order' => $this->order_key, |
2150
|
|
|
'order_id' => $this->id, |
2151
|
|
|
'redirect' => $redirect, |
2152
|
|
|
), $cancel_endpoint ) ) ); |
2153
|
|
|
} |
2154
|
|
|
|
2155
|
|
|
/** |
2156
|
|
|
* Generates a raw (unescaped) cancel-order URL for use by payment gateways. |
2157
|
|
|
* |
2158
|
|
|
* @param string $redirect |
2159
|
|
|
* @return string The unescaped cancel-order URL. |
2160
|
|
|
*/ |
2161
|
|
View Code Duplication |
public function get_cancel_order_url_raw( $redirect = '' ) { |
|
|
|
|
2162
|
|
|
|
2163
|
|
|
// Get cancel endpoint |
2164
|
|
|
$cancel_endpoint = $this->get_cancel_endpoint(); |
2165
|
|
|
|
2166
|
|
|
return apply_filters( 'woocommerce_get_cancel_order_url_raw', add_query_arg( array( |
2167
|
|
|
'cancel_order' => 'true', |
2168
|
|
|
'order' => $this->order_key, |
2169
|
|
|
'order_id' => $this->id, |
2170
|
|
|
'redirect' => $redirect, |
2171
|
|
|
), $cancel_endpoint ) ); |
2172
|
|
|
} |
2173
|
|
|
|
2174
|
|
|
|
2175
|
|
|
/** |
2176
|
|
|
* Helper method to return the cancel endpoint. |
2177
|
|
|
* |
2178
|
|
|
* @return string the cancel endpoint; either the cart page or the home page. |
2179
|
|
|
*/ |
2180
|
|
|
public function get_cancel_endpoint() { |
2181
|
|
|
|
2182
|
|
|
$cancel_endpoint = wc_get_page_permalink( 'cart' ); |
2183
|
|
|
if ( ! $cancel_endpoint ) { |
2184
|
|
|
$cancel_endpoint = home_url(); |
2185
|
|
|
} |
2186
|
|
|
|
2187
|
|
|
if ( false === strpos( $cancel_endpoint, '?' ) ) { |
2188
|
|
|
$cancel_endpoint = trailingslashit( $cancel_endpoint ); |
2189
|
|
|
} |
2190
|
|
|
|
2191
|
|
|
return $cancel_endpoint; |
2192
|
|
|
} |
2193
|
|
|
|
2194
|
|
|
|
2195
|
|
|
/** |
2196
|
|
|
* Generates a URL to view an order from the my account page. |
2197
|
|
|
* |
2198
|
|
|
* @return string |
2199
|
|
|
*/ |
2200
|
|
|
public function get_view_order_url() { |
2201
|
|
|
|
2202
|
|
|
$view_order_url = wc_get_endpoint_url( 'view-order', $this->id, wc_get_page_permalink( 'myaccount' ) ); |
2203
|
|
|
|
2204
|
|
|
return apply_filters( 'woocommerce_get_view_order_url', $view_order_url, $this ); |
2205
|
|
|
} |
2206
|
|
|
|
2207
|
|
|
/** |
2208
|
|
|
* Get the downloadable files for an item in this order. |
2209
|
|
|
* |
2210
|
|
|
* @param array $item |
2211
|
|
|
* @return array |
2212
|
|
|
*/ |
2213
|
|
|
public function get_item_downloads( $item ) { |
2214
|
|
|
global $wpdb; |
2215
|
|
|
|
2216
|
|
|
$product_id = $item['variation_id'] > 0 ? $item['variation_id'] : $item['product_id']; |
2217
|
|
|
$product = wc_get_product( $product_id ); |
2218
|
|
|
if ( ! $product ) { |
2219
|
|
|
/** |
2220
|
|
|
* $product can be `false`. Example: checking an old order, when a product or variation has been deleted. |
2221
|
|
|
* @see \WC_Product_Factory::get_product |
2222
|
|
|
*/ |
2223
|
|
|
return array(); |
2224
|
|
|
} |
2225
|
|
|
$download_ids = $wpdb->get_col( $wpdb->prepare(" |
2226
|
|
|
SELECT download_id |
2227
|
|
|
FROM {$wpdb->prefix}woocommerce_downloadable_product_permissions |
2228
|
|
|
WHERE user_email = %s |
2229
|
|
|
AND order_key = %s |
2230
|
|
|
AND product_id = %s |
2231
|
|
|
ORDER BY permission_id |
2232
|
|
|
", $this->billing_email, $this->order_key, $product_id ) ); |
2233
|
|
|
|
2234
|
|
|
$files = array(); |
2235
|
|
|
|
2236
|
|
|
foreach ( $download_ids as $download_id ) { |
2237
|
|
|
|
2238
|
|
|
if ( $product->has_file( $download_id ) ) { |
2239
|
|
|
$files[ $download_id ] = $product->get_file( $download_id ); |
2240
|
|
|
$files[ $download_id ]['download_url'] = $this->get_download_url( $product_id, $download_id ); |
2241
|
|
|
} |
2242
|
|
|
} |
2243
|
|
|
|
2244
|
|
|
return apply_filters( 'woocommerce_get_item_downloads', $files, $item, $this ); |
2245
|
|
|
} |
2246
|
|
|
|
2247
|
|
|
/** |
2248
|
|
|
* Display download links for an order item. |
2249
|
|
|
* @param array $item |
2250
|
|
|
*/ |
2251
|
|
|
public function display_item_downloads( $item ) { |
2252
|
|
|
$product = $this->get_product_from_item( $item ); |
2253
|
|
|
|
2254
|
|
|
if ( $product && $product->exists() && $product->is_downloadable() && $this->is_download_permitted() ) { |
2255
|
|
|
$download_files = $this->get_item_downloads( $item ); |
2256
|
|
|
$i = 0; |
2257
|
|
|
$links = array(); |
2258
|
|
|
|
2259
|
|
|
foreach ( $download_files as $download_id => $file ) { |
2260
|
|
|
$i++; |
2261
|
|
|
$prefix = count( $download_files ) > 1 ? sprintf( __( 'Download %d', 'woocommerce' ), $i ) : __( 'Download', 'woocommerce' ); |
2262
|
|
|
$links[] = '<small class="download-url">' . $prefix . ': <a href="' . esc_url( $file['download_url'] ) . '" target="_blank">' . esc_html( $file['name'] ) . '</a></small>' . "\n"; |
2263
|
|
|
} |
2264
|
|
|
|
2265
|
|
|
echo '<br/>' . implode( '<br/>', $links ); |
2266
|
|
|
} |
2267
|
|
|
} |
2268
|
|
|
|
2269
|
|
|
/** |
2270
|
|
|
* Get the Download URL. |
2271
|
|
|
* |
2272
|
|
|
* @param int $product_id |
2273
|
|
|
* @param int $download_id |
2274
|
|
|
* @return string |
2275
|
|
|
*/ |
2276
|
|
|
public function get_download_url( $product_id, $download_id ) { |
2277
|
|
|
return add_query_arg( array( |
2278
|
|
|
'download_file' => $product_id, |
2279
|
|
|
'order' => $this->order_key, |
2280
|
|
|
'email' => urlencode( $this->billing_email ), |
2281
|
|
|
'key' => $download_id |
2282
|
|
|
), trailingslashit( home_url() ) ); |
2283
|
|
|
} |
2284
|
|
|
|
2285
|
|
|
/** |
2286
|
|
|
* Adds a note (comment) to the order. |
2287
|
|
|
* |
2288
|
|
|
* @param string $note Note to add. |
2289
|
|
|
* @param int $is_customer_note (default: 0) Is this a note for the customer? |
2290
|
|
|
* @param bool added_by_user Was the note added by a user? |
2291
|
|
|
* @return int Comment ID. |
2292
|
|
|
*/ |
2293
|
|
|
public function add_order_note( $note, $is_customer_note = 0, $added_by_user = false ) { |
2294
|
|
|
if ( is_user_logged_in() && current_user_can( 'edit_shop_order', $this->id ) && $added_by_user ) { |
2295
|
|
|
$user = get_user_by( 'id', get_current_user_id() ); |
2296
|
|
|
$comment_author = $user->display_name; |
2297
|
|
|
$comment_author_email = $user->user_email; |
2298
|
|
|
} else { |
2299
|
|
|
$comment_author = __( 'WooCommerce', 'woocommerce' ); |
2300
|
|
|
$comment_author_email = strtolower( __( 'WooCommerce', 'woocommerce' ) ) . '@'; |
2301
|
|
|
$comment_author_email .= isset( $_SERVER['HTTP_HOST'] ) ? str_replace( 'www.', '', $_SERVER['HTTP_HOST'] ) : 'noreply.com'; |
2302
|
|
|
$comment_author_email = sanitize_email( $comment_author_email ); |
2303
|
|
|
} |
2304
|
|
|
|
2305
|
|
|
$comment_post_ID = $this->id; |
2306
|
|
|
$comment_author_url = ''; |
2307
|
|
|
$comment_content = $note; |
2308
|
|
|
$comment_agent = 'WooCommerce'; |
2309
|
|
|
$comment_type = 'order_note'; |
2310
|
|
|
$comment_parent = 0; |
2311
|
|
|
$comment_approved = 1; |
2312
|
|
|
$commentdata = apply_filters( 'woocommerce_new_order_note_data', compact( 'comment_post_ID', 'comment_author', 'comment_author_email', 'comment_author_url', 'comment_content', 'comment_agent', 'comment_type', 'comment_parent', 'comment_approved' ), array( 'order_id' => $this->id, 'is_customer_note' => $is_customer_note ) ); |
2313
|
|
|
|
2314
|
|
|
$comment_id = wp_insert_comment( $commentdata ); |
2315
|
|
|
|
2316
|
|
|
if ( $is_customer_note ) { |
2317
|
|
|
add_comment_meta( $comment_id, 'is_customer_note', 1 ); |
2318
|
|
|
|
2319
|
|
|
do_action( 'woocommerce_new_customer_note', array( 'order_id' => $this->id, 'customer_note' => $commentdata['comment_content'] ) ); |
2320
|
|
|
} |
2321
|
|
|
|
2322
|
|
|
return $comment_id; |
2323
|
|
|
} |
2324
|
|
|
|
2325
|
|
|
/** |
2326
|
|
|
* Updates status of order. |
2327
|
|
|
* |
2328
|
|
|
* @param string $new_status Status to change the order to. No internal wc- prefix is required. |
2329
|
|
|
* @param string $note (default: '') Optional note to add. |
2330
|
|
|
* @param bool $manual is this a manual order status change? |
2331
|
|
|
* @return bool Successful change or not |
2332
|
|
|
*/ |
2333
|
|
|
public function update_status( $new_status, $note = '', $manual = false ) { |
2334
|
|
|
if ( ! $this->id ) { |
2335
|
|
|
return false; |
2336
|
|
|
} |
2337
|
|
|
|
2338
|
|
|
// Standardise status names. |
2339
|
|
|
$new_status = 'wc-' === substr( $new_status, 0, 3 ) ? substr( $new_status, 3 ) : $new_status; |
2340
|
|
|
$old_status = $this->get_status(); |
2341
|
|
|
|
2342
|
|
|
// If the old status is unknown (e.g. draft) assume its pending for action usage. |
2343
|
|
|
if ( ! in_array( 'wc-' . $old_status, array_keys( wc_get_order_statuses() ) ) ) { |
2344
|
|
|
$old_status = 'pending'; |
2345
|
|
|
} |
2346
|
|
|
|
2347
|
|
|
// If the statuses are the same there is no need to update, unless the post status is not a valid 'wc' status. |
2348
|
|
|
if ( $new_status === $old_status && in_array( $this->post_status, array_keys( wc_get_order_statuses() ) ) ) { |
2349
|
|
|
return false; |
2350
|
|
|
} |
2351
|
|
|
|
2352
|
|
|
$this->post_status = 'wc-' . $new_status; |
2353
|
|
|
$update_post_data = array( |
2354
|
|
|
'ID' => $this->id, |
2355
|
|
|
'post_status' => $this->post_status, |
2356
|
|
|
); |
2357
|
|
|
|
2358
|
|
|
if ( 'pending' === $old_status && ! $manual ) { |
2359
|
|
|
$update_post_data[ 'post_date' ] = current_time( 'mysql', 0 ); |
2360
|
|
|
$update_post_data[ 'post_date_gmt' ] = current_time( 'mysql', 1 ); |
2361
|
|
|
} |
2362
|
|
|
|
2363
|
|
|
if ( ! wp_update_post( $update_post_data ) ) { |
2364
|
|
|
$this->add_order_note( sprintf( __( 'Unable to update order from %1$s to %2$s.', 'woocommerce' ), wc_get_order_status_name( $old_status ), wc_get_order_status_name( $new_status ) ), 0, $manual ); |
2365
|
|
|
return false; |
2366
|
|
|
} |
2367
|
|
|
|
2368
|
|
|
// Status was set. |
2369
|
|
|
do_action( 'woocommerce_order_status_' . $new_status, $this->id ); |
2370
|
|
|
|
2371
|
|
|
// Status was changed. |
2372
|
|
|
if ( $new_status !== $old_status ) { |
2373
|
|
|
$this->add_order_note( trim( $note . ' ' . sprintf( __( 'Order status changed from %1$s to %2$s.', 'woocommerce' ), wc_get_order_status_name( $old_status ), wc_get_order_status_name( $new_status ) ) ), 0, $manual ); |
2374
|
|
|
do_action( 'woocommerce_order_status_' . $old_status . '_to_' . $new_status, $this->id ); |
2375
|
|
|
do_action( 'woocommerce_order_status_changed', $this->id, $old_status, $new_status ); |
2376
|
|
|
} else { |
2377
|
|
|
$this->add_order_note( trim( $note . ' ' . sprintf( __( 'Order status changed to %s.', 'woocommerce' ), wc_get_order_status_name( $new_status ) ) ), 0, $manual ); |
2378
|
|
|
} |
2379
|
|
|
|
2380
|
|
|
switch ( $new_status ) { |
2381
|
|
|
|
2382
|
|
|
case 'completed' : |
2383
|
|
|
// Record the sales. |
2384
|
|
|
$this->record_product_sales(); |
2385
|
|
|
|
2386
|
|
|
// Increase coupon usage counts. |
2387
|
|
|
$this->increase_coupon_usage_counts(); |
2388
|
|
|
|
2389
|
|
|
// Record the completed date of the order. |
2390
|
|
|
update_post_meta( $this->id, '_completed_date', current_time('mysql') ); |
2391
|
|
|
|
2392
|
|
|
// Update reports. |
2393
|
|
|
wc_delete_shop_order_transients( $this->id ); |
2394
|
|
|
break; |
2395
|
|
|
|
2396
|
|
|
case 'processing' : |
2397
|
|
|
case 'on-hold' : |
2398
|
|
|
// Record the sales. |
2399
|
|
|
$this->record_product_sales(); |
2400
|
|
|
|
2401
|
|
|
// Increase coupon usage counts. |
2402
|
|
|
$this->increase_coupon_usage_counts(); |
2403
|
|
|
|
2404
|
|
|
// Update reports. |
2405
|
|
|
wc_delete_shop_order_transients( $this->id ); |
2406
|
|
|
break; |
2407
|
|
|
|
2408
|
|
|
case 'cancelled' : |
2409
|
|
|
// If the order is cancelled, restore used coupons. |
2410
|
|
|
$this->decrease_coupon_usage_counts(); |
2411
|
|
|
|
2412
|
|
|
// Update reports. |
2413
|
|
|
wc_delete_shop_order_transients( $this->id ); |
2414
|
|
|
break; |
2415
|
|
|
} |
2416
|
|
|
|
2417
|
|
|
return true; |
2418
|
|
|
} |
2419
|
|
|
|
2420
|
|
|
|
2421
|
|
|
/** |
2422
|
|
|
* Cancel the order and restore the cart (before payment). |
2423
|
|
|
* |
2424
|
|
|
* @param string $note (default: '') Optional note to add. |
2425
|
|
|
*/ |
2426
|
|
|
public function cancel_order( $note = '' ) { |
2427
|
|
|
WC()->session->set( 'order_awaiting_payment', false ); |
2428
|
|
|
$this->update_status( 'cancelled', $note ); |
2429
|
|
|
} |
2430
|
|
|
|
2431
|
|
|
/** |
2432
|
|
|
* When a payment is complete this function is called. |
2433
|
|
|
* |
2434
|
|
|
* Most of the time this should mark an order as 'processing' so that admin can process/post the items. |
2435
|
|
|
* If the cart contains only downloadable items then the order is 'completed' since the admin needs to take no action. |
2436
|
|
|
* Stock levels are reduced at this point. |
2437
|
|
|
* Sales are also recorded for products. |
2438
|
|
|
* Finally, record the date of payment. |
2439
|
|
|
* |
2440
|
|
|
* @param string $transaction_id Optional transaction id to store in post meta. |
2441
|
|
|
*/ |
2442
|
|
|
public function payment_complete( $transaction_id = '' ) { |
2443
|
|
|
do_action( 'woocommerce_pre_payment_complete', $this->id ); |
2444
|
|
|
|
2445
|
|
|
if ( null !== WC()->session ) { |
2446
|
|
|
WC()->session->set( 'order_awaiting_payment', false ); |
2447
|
|
|
} |
2448
|
|
|
|
2449
|
|
|
$valid_order_statuses = apply_filters( 'woocommerce_valid_order_statuses_for_payment_complete', array( 'on-hold', 'pending', 'failed', 'cancelled' ), $this ); |
2450
|
|
|
|
2451
|
|
|
if ( $this->id && $this->has_status( $valid_order_statuses ) ) { |
2452
|
|
|
$order_needs_processing = false; |
2453
|
|
|
|
2454
|
|
|
if ( sizeof( $this->get_items() ) > 0 ) { |
2455
|
|
|
foreach ( $this->get_items() as $item ) { |
2456
|
|
|
if ( $_product = $this->get_product_from_item( $item ) ) { |
2457
|
|
|
$virtual_downloadable_item = $_product->is_downloadable() && $_product->is_virtual(); |
2458
|
|
|
|
2459
|
|
|
if ( apply_filters( 'woocommerce_order_item_needs_processing', ! $virtual_downloadable_item, $_product, $this->id ) ) { |
2460
|
|
|
$order_needs_processing = true; |
2461
|
|
|
break; |
2462
|
|
|
} |
2463
|
|
|
} else { |
2464
|
|
|
$order_needs_processing = true; |
2465
|
|
|
break; |
2466
|
|
|
} |
2467
|
|
|
} |
2468
|
|
|
} |
2469
|
|
|
|
2470
|
|
|
$this->update_status( apply_filters( 'woocommerce_payment_complete_order_status', $order_needs_processing ? 'processing' : 'completed', $this->id ) ); |
2471
|
|
|
|
2472
|
|
|
add_post_meta( $this->id, '_paid_date', current_time( 'mysql' ), true ); |
2473
|
|
|
|
2474
|
|
|
if ( ! empty( $transaction_id ) ) { |
2475
|
|
|
update_post_meta( $this->id, '_transaction_id', $transaction_id ); |
2476
|
|
|
} |
2477
|
|
|
|
2478
|
|
|
// Payment is complete so reduce stock levels |
2479
|
|
|
if ( apply_filters( 'woocommerce_payment_complete_reduce_order_stock', ! get_post_meta( $this->id, '_order_stock_reduced', true ), $this->id ) ) { |
2480
|
|
|
$this->reduce_order_stock(); |
2481
|
|
|
} |
2482
|
|
|
|
2483
|
|
|
do_action( 'woocommerce_payment_complete', $this->id ); |
2484
|
|
|
} else { |
2485
|
|
|
do_action( 'woocommerce_payment_complete_order_status_' . $this->get_status(), $this->id ); |
2486
|
|
|
} |
2487
|
|
|
} |
2488
|
|
|
|
2489
|
|
|
|
2490
|
|
|
/** |
2491
|
|
|
* Record sales. |
2492
|
|
|
*/ |
2493
|
|
|
public function record_product_sales() { |
2494
|
|
|
if ( 'yes' === get_post_meta( $this->id, '_recorded_sales', true ) ) { |
2495
|
|
|
return; |
2496
|
|
|
} |
2497
|
|
|
|
2498
|
|
|
if ( sizeof( $this->get_items() ) > 0 ) { |
2499
|
|
|
|
2500
|
|
|
foreach ( $this->get_items() as $item ) { |
2501
|
|
|
|
2502
|
|
|
if ( $item['product_id'] > 0 ) { |
2503
|
|
|
$sales = (int) get_post_meta( $item['product_id'], 'total_sales', true ); |
2504
|
|
|
$sales += (int) $item['qty']; |
2505
|
|
|
|
2506
|
|
|
if ( $sales ) { |
2507
|
|
|
update_post_meta( $item['product_id'], 'total_sales', $sales ); |
2508
|
|
|
} |
2509
|
|
|
} |
2510
|
|
|
} |
2511
|
|
|
} |
2512
|
|
|
|
2513
|
|
|
update_post_meta( $this->id, '_recorded_sales', 'yes' ); |
2514
|
|
|
|
2515
|
|
|
/** |
2516
|
|
|
* Called when sales for an order are recorded |
2517
|
|
|
* |
2518
|
|
|
* @param int $order_id order id |
2519
|
|
|
*/ |
2520
|
|
|
do_action( 'woocommerce_recorded_sales', $this->id ); |
2521
|
|
|
} |
2522
|
|
|
|
2523
|
|
|
|
2524
|
|
|
/** |
2525
|
|
|
* Get coupon codes only. |
2526
|
|
|
* |
2527
|
|
|
* @return array |
2528
|
|
|
*/ |
2529
|
|
|
public function get_used_coupons() { |
2530
|
|
|
|
2531
|
|
|
$codes = array(); |
2532
|
|
|
$coupons = $this->get_items( 'coupon' ); |
2533
|
|
|
|
2534
|
|
|
foreach ( $coupons as $item_id => $item ) { |
2535
|
|
|
$codes[] = trim( $item['name'] ); |
2536
|
|
|
} |
2537
|
|
|
|
2538
|
|
|
return $codes; |
2539
|
|
|
} |
2540
|
|
|
|
2541
|
|
|
|
2542
|
|
|
/** |
2543
|
|
|
* Increase applied coupon counts. |
2544
|
|
|
*/ |
2545
|
|
View Code Duplication |
public function increase_coupon_usage_counts() { |
|
|
|
|
2546
|
|
|
if ( 'yes' == get_post_meta( $this->id, '_recorded_coupon_usage_counts', true ) ) { |
2547
|
|
|
return; |
2548
|
|
|
} |
2549
|
|
|
|
2550
|
|
|
if ( sizeof( $this->get_used_coupons() ) > 0 ) { |
2551
|
|
|
|
2552
|
|
|
foreach ( $this->get_used_coupons() as $code ) { |
2553
|
|
|
if ( ! $code ) { |
2554
|
|
|
continue; |
2555
|
|
|
} |
2556
|
|
|
|
2557
|
|
|
$coupon = new WC_Coupon( $code ); |
2558
|
|
|
|
2559
|
|
|
$used_by = $this->get_user_id(); |
2560
|
|
|
|
2561
|
|
|
if ( ! $used_by ) { |
2562
|
|
|
$used_by = $this->billing_email; |
2563
|
|
|
} |
2564
|
|
|
|
2565
|
|
|
$coupon->inc_usage_count( $used_by ); |
2566
|
|
|
} |
2567
|
|
|
|
2568
|
|
|
update_post_meta( $this->id, '_recorded_coupon_usage_counts', 'yes' ); |
2569
|
|
|
} |
2570
|
|
|
} |
2571
|
|
|
|
2572
|
|
|
|
2573
|
|
|
/** |
2574
|
|
|
* Decrease applied coupon counts. |
2575
|
|
|
*/ |
2576
|
|
View Code Duplication |
public function decrease_coupon_usage_counts() { |
|
|
|
|
2577
|
|
|
|
2578
|
|
|
if ( 'yes' != get_post_meta( $this->id, '_recorded_coupon_usage_counts', true ) ) { |
2579
|
|
|
return; |
2580
|
|
|
} |
2581
|
|
|
|
2582
|
|
|
if ( sizeof( $this->get_used_coupons() ) > 0 ) { |
2583
|
|
|
|
2584
|
|
|
foreach ( $this->get_used_coupons() as $code ) { |
2585
|
|
|
|
2586
|
|
|
if ( ! $code ) { |
2587
|
|
|
continue; |
2588
|
|
|
} |
2589
|
|
|
|
2590
|
|
|
$coupon = new WC_Coupon( $code ); |
2591
|
|
|
|
2592
|
|
|
$used_by = $this->get_user_id(); |
2593
|
|
|
if ( ! $used_by ) { |
2594
|
|
|
$used_by = $this->billing_email; |
2595
|
|
|
} |
2596
|
|
|
|
2597
|
|
|
$coupon->dcr_usage_count( $used_by ); |
2598
|
|
|
} |
2599
|
|
|
|
2600
|
|
|
delete_post_meta( $this->id, '_recorded_coupon_usage_counts' ); |
2601
|
|
|
} |
2602
|
|
|
} |
2603
|
|
|
|
2604
|
|
|
/** |
2605
|
|
|
* Reduce stock levels for all line items in the order. |
2606
|
|
|
* Runs if stock management is enabled, but can be disabled on per-order basis by extensions @since 2.4.0 via woocommerce_can_reduce_order_stock hook. |
2607
|
|
|
*/ |
2608
|
|
|
public function reduce_order_stock() { |
2609
|
|
|
if ( 'yes' === get_option( 'woocommerce_manage_stock' ) && apply_filters( 'woocommerce_can_reduce_order_stock', true, $this ) && sizeof( $this->get_items() ) > 0 ) { |
2610
|
|
|
foreach ( $this->get_items() as $item ) { |
2611
|
|
|
if ( $item['product_id'] > 0 ) { |
2612
|
|
|
$_product = $this->get_product_from_item( $item ); |
2613
|
|
|
|
2614
|
|
|
if ( $_product && $_product->exists() && $_product->managing_stock() ) { |
2615
|
|
|
$qty = apply_filters( 'woocommerce_order_item_quantity', $item['qty'], $this, $item ); |
2616
|
|
|
$new_stock = $_product->reduce_stock( $qty ); |
2617
|
|
|
$item_name = $_product->get_sku() ? $_product->get_sku(): $item['product_id']; |
2618
|
|
|
|
2619
|
|
|
if ( isset( $item['variation_id'] ) && $item['variation_id'] ) { |
2620
|
|
|
$this->add_order_note( sprintf( __( 'Item %1$s variation #%2$s stock reduced from %3$s to %4$s.', 'woocommerce' ), $item_name, $item['variation_id'], $new_stock + $qty, $new_stock) ); |
2621
|
|
|
} else { |
2622
|
|
|
$this->add_order_note( sprintf( __( 'Item %1$s stock reduced from %2$s to %3$s.', 'woocommerce' ), $item_name, $new_stock + $qty, $new_stock) ); |
2623
|
|
|
} |
2624
|
|
|
$this->send_stock_notifications( $_product, $new_stock, $item['qty'] ); |
2625
|
|
|
} |
2626
|
|
|
} |
2627
|
|
|
} |
2628
|
|
|
|
2629
|
|
|
add_post_meta( $this->id, '_order_stock_reduced', '1', true ); |
2630
|
|
|
|
2631
|
|
|
do_action( 'woocommerce_reduce_order_stock', $this ); |
2632
|
|
|
} |
2633
|
|
|
} |
2634
|
|
|
|
2635
|
|
|
/** |
2636
|
|
|
* Send the stock notifications. |
2637
|
|
|
* |
2638
|
|
|
* @param WC_Product $product |
2639
|
|
|
* @param int $new_stock |
2640
|
|
|
* @param int $qty_ordered |
2641
|
|
|
*/ |
2642
|
|
|
public function send_stock_notifications( $product, $new_stock, $qty_ordered ) { |
2643
|
|
|
|
2644
|
|
|
// Backorders |
2645
|
|
|
if ( $new_stock < 0 ) { |
2646
|
|
|
do_action( 'woocommerce_product_on_backorder', array( 'product' => $product, 'order_id' => $this->id, 'quantity' => $qty_ordered ) ); |
2647
|
|
|
} |
2648
|
|
|
|
2649
|
|
|
// stock status notifications |
2650
|
|
|
$notification_sent = false; |
2651
|
|
|
|
2652
|
|
|
if ( 'yes' == get_option( 'woocommerce_notify_no_stock' ) && get_option( 'woocommerce_notify_no_stock_amount' ) >= $new_stock ) { |
2653
|
|
|
do_action( 'woocommerce_no_stock', $product ); |
2654
|
|
|
$notification_sent = true; |
2655
|
|
|
} |
2656
|
|
|
|
2657
|
|
|
if ( ! $notification_sent && 'yes' == get_option( 'woocommerce_notify_low_stock' ) && get_option( 'woocommerce_notify_low_stock_amount' ) >= $new_stock ) { |
2658
|
|
|
do_action( 'woocommerce_low_stock', $product ); |
2659
|
|
|
} |
2660
|
|
|
|
2661
|
|
|
do_action( 'woocommerce_after_send_stock_notifications', $product, $new_stock, $qty_ordered ); |
2662
|
|
|
} |
2663
|
|
|
|
2664
|
|
|
|
2665
|
|
|
/** |
2666
|
|
|
* List order notes (public) for the customer. |
2667
|
|
|
* |
2668
|
|
|
* @return array |
2669
|
|
|
*/ |
2670
|
|
|
public function get_customer_order_notes() { |
2671
|
|
|
$notes = array(); |
2672
|
|
|
$args = array( |
2673
|
|
|
'post_id' => $this->id, |
2674
|
|
|
'approve' => 'approve', |
2675
|
|
|
'type' => '' |
2676
|
|
|
); |
2677
|
|
|
|
2678
|
|
|
remove_filter( 'comments_clauses', array( 'WC_Comments', 'exclude_order_comments' ) ); |
2679
|
|
|
|
2680
|
|
|
$comments = get_comments( $args ); |
2681
|
|
|
|
2682
|
|
|
foreach ( $comments as $comment ) { |
2683
|
|
|
if ( ! get_comment_meta( $comment->comment_ID, 'is_customer_note', true ) ) { |
2684
|
|
|
continue; |
2685
|
|
|
} |
2686
|
|
|
$comment->comment_content = make_clickable( $comment->comment_content ); |
2687
|
|
|
$notes[] = $comment; |
2688
|
|
|
} |
2689
|
|
|
|
2690
|
|
|
add_filter( 'comments_clauses', array( 'WC_Comments', 'exclude_order_comments' ) ); |
2691
|
|
|
|
2692
|
|
|
return $notes; |
2693
|
|
|
} |
2694
|
|
|
|
2695
|
|
|
/** |
2696
|
|
|
* Checks if an order needs payment, based on status and order total. |
2697
|
|
|
* |
2698
|
|
|
* @return bool |
2699
|
|
|
*/ |
2700
|
|
|
public function needs_payment() { |
2701
|
|
|
|
2702
|
|
|
$valid_order_statuses = apply_filters( 'woocommerce_valid_order_statuses_for_payment', array( 'pending', 'failed' ), $this ); |
2703
|
|
|
|
2704
|
|
|
if ( $this->has_status( $valid_order_statuses ) && $this->get_total() > 0 ) { |
2705
|
|
|
$needs_payment = true; |
2706
|
|
|
} else { |
2707
|
|
|
$needs_payment = false; |
2708
|
|
|
} |
2709
|
|
|
|
2710
|
|
|
return apply_filters( 'woocommerce_order_needs_payment', $needs_payment, $this, $valid_order_statuses ); |
2711
|
|
|
} |
2712
|
|
|
|
2713
|
|
|
/** |
2714
|
|
|
* Checks if an order needs display the shipping address, based on shipping method. |
2715
|
|
|
* |
2716
|
|
|
* @return boolean |
2717
|
|
|
*/ |
2718
|
|
|
public function needs_shipping_address() { |
2719
|
|
|
if ( ! wc_shipping_enabled() ) { |
2720
|
|
|
return false; |
2721
|
|
|
} |
2722
|
|
|
|
2723
|
|
|
$hide = apply_filters( 'woocommerce_order_hide_shipping_address', array( 'local_pickup' ), $this ); |
2724
|
|
|
$needs_address = false; |
2725
|
|
|
|
2726
|
|
|
foreach ( $this->get_shipping_methods() as $shipping_method ) { |
2727
|
|
|
if ( ! in_array( $shipping_method['method_id'], $hide ) ) { |
2728
|
|
|
$needs_address = true; |
2729
|
|
|
break; |
2730
|
|
|
} |
2731
|
|
|
} |
2732
|
|
|
|
2733
|
|
|
return apply_filters( 'woocommerce_order_needs_shipping_address', $needs_address, $hide, $this ); |
2734
|
|
|
} |
2735
|
|
|
|
2736
|
|
|
/** |
2737
|
|
|
* Checks if an order can be edited, specifically for use on the Edit Order screen. |
2738
|
|
|
* |
2739
|
|
|
* @return bool |
2740
|
|
|
*/ |
2741
|
|
|
public function is_editable() { |
2742
|
|
|
return apply_filters( 'wc_order_is_editable', in_array( $this->get_status(), array( 'pending', 'on-hold', 'auto-draft', 'failed' ) ), $this ); |
2743
|
|
|
} |
2744
|
|
|
} |
2745
|
|
|
|
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.