diff --git a/includes/abstracts/abstract-wc-order.php b/includes/abstracts/abstract-wc-order.php
new file mode 100644
index 00000000000..1be2d3b0db0
--- /dev/null
+++ b/includes/abstracts/abstract-wc-order.php
@@ -0,0 +1,2094 @@
+prices_include_tax = get_option('woocommerce_prices_include_tax') == 'yes' ? true : false;
+ $this->tax_display_cart = get_option( 'woocommerce_tax_display_cart' );
+
+ $this->display_totals_ex_tax = $this->tax_display_cart == 'excl' ? true : false;
+ $this->display_cart_ex_tax = $this->tax_display_cart == 'excl' ? true : false;
+
+ $this->order_type = 'simple';
+
+ if ( is_numeric( $order ) ) {
+ $this->id = absint( $order );
+ $this->post = get_post( $order );
+ $this->get_order( $this->id );
+ } elseif ( $order instanceof WC_Order ) {
+ $this->id = absint( $order->id );
+ $this->post = $order->post;
+ $this->get_order( $this->id );
+ } elseif ( $order instanceof WP_Post || isset( $order->ID ) ) {
+ $this->id = absint( $order->ID );
+ $this->post = $order;
+ $this->get_order( $this->id );
+ }
+ }
+
+ /**
+ * Remove all line items (products, coupons, shipping, taxes) from the order.
+ */
+ public function remove_order_items( $type = null ) {
+ global $wpdb;
+
+ if ( $type ) {
+ $wpdb->query( $wpdb->prepare( "DELETE FROM {$wpdb->prefix}woocommerce_order_itemmeta WHERE order_item_id IN ( SELECT order_item_id FROM {$wpdb->prefix}woocommerce_order_items WHERE order_id = %d AND order_item_type = %s )", $this->id, $type ) );
+ $wpdb->query( $wpdb->prepare( "DELETE FROM {$wpdb->prefix}woocommerce_order_items WHERE order_id = %d AND order_item_type = %s", $this->id, $type ) );
+ } else {
+ $wpdb->query( $wpdb->prepare( "DELETE FROM {$wpdb->prefix}woocommerce_order_itemmeta WHERE order_item_id IN ( SELECT order_item_id FROM {$wpdb->prefix}woocommerce_order_items WHERE order_id = %d )", $this->id ) );
+ $wpdb->query( $wpdb->prepare( "DELETE FROM {$wpdb->prefix}woocommerce_order_items WHERE order_id = %d", $this->id ) );
+ }
+ }
+
+ /**
+ * Set the payment method for the order
+ * @param WC_Payment_Gateway
+ */
+ public function set_payment_method( $payment_method ) {
+ if ( is_object( $payment_method ) ) {
+ update_post_meta( $this->id, '_payment_method', $payment_method->id );
+ update_post_meta( $this->id, '_payment_method_title', $payment_method->get_title() );
+ }
+ }
+
+ /**
+ * Set the customer address
+ * @param array $address Address data
+ * @param string $type billing or shipping
+ */
+ public function set_address( $address, $type = 'billing' ) {
+ foreach( $address as $key => $value ) {
+ update_post_meta( $this->id, "_{$type}_" . $key, $value );
+ }
+ }
+
+ /**
+ * Add a product line item to the order
+ * @param WC_Product $item
+ * @param int $qty Line item quantity
+ * @param array args
+ * @return int|bool Item ID or false
+ */
+ public function add_product( $product, $qty = 1, $args = array() ) {
+ $default_args = array(
+ 'variation' => array(),
+ 'totals' => array()
+ );
+
+ $args = wp_parse_args( $args, $default_args );
+ $item_id = wc_add_order_item( $this->id, array(
+ 'order_item_name' => $product->get_title(),
+ 'order_item_type' => 'line_item'
+ ) );
+
+ if ( ! $item_id ) {
+ return false;
+ }
+
+ wc_add_order_item_meta( $item_id, '_qty', wc_stock_amount( $qty ) );
+ wc_add_order_item_meta( $item_id, '_tax_class', $product->get_tax_class() );
+ wc_add_order_item_meta( $item_id, '_product_id', $product->id );
+ wc_add_order_item_meta( $item_id, '_variation_id', isset( $product->variation_id ) ? $product->variation_id : 0 );
+
+ // Set line item totals, either passed in or from the product
+ 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 ) ) );
+ 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 ) ) );
+ wc_add_order_item_meta( $item_id, '_line_subtotal_tax', wc_format_decimal( isset( $args['totals']['subtotal_tax'] ) ? $args['totals']['subtotal_tax'] : 0 ) );
+ wc_add_order_item_meta( $item_id, '_line_tax', wc_format_decimal( isset( $args['totals']['tax'] ) ? $args['totals']['tax'] : 0 ) );
+
+ // Add variation meta
+ foreach ( $args['variation'] as $key => $value ) {
+ wc_add_order_item_meta( $item_id, str_replace( 'attribute_', '', $key ), $value );
+ }
+
+ // Backorders
+ if ( $product->backorders_require_notification() && $product->is_on_backorder( $qty ) ) {
+ wc_add_order_item_meta( $item_id, apply_filters( 'woocommerce_backordered_item_meta_name', __( 'Backordered', 'woocommerce' ) ), $qty - max( 0, $product->get_total_stock() ) );
+ }
+
+ do_action( 'woocommerce_order_add_product', $this->id, $item_id, $product, $qty, $args );
+
+ return $item_id;
+ }
+
+ /**
+ * Add coupon code to the order
+ * @param string $code
+ * @param float $discount_amount
+ * @return int|bool Item ID or false
+ */
+ public function add_coupon( $code, $discount_amount = 0 ) {
+ $item_id = wc_add_order_item( $this->id, array(
+ 'order_item_name' => $code,
+ 'order_item_type' => 'coupon'
+ ) );
+
+ if ( ! $item_id ) {
+ return false;
+ }
+
+ wc_add_order_item_meta( $item_id, 'discount_amount', $discount_amount );
+
+ do_action( 'woocommerce_order_add_coupon', $this->id, $item_id, $code, $discount_amount );
+
+ return $item_id;
+ }
+
+ /**
+ * Add a tax row to the order
+ * @param int tax_rate_id
+ * @return int|bool Item ID or false
+ */
+ public function add_tax( $tax_rate_id, $tax_amount = 0, $shipping_tax_amount = 0 ) {
+ $code = WC_Tax::get_rate_code( $tax_rate_id );
+
+ if ( ! $code ) {
+ return false;
+ }
+
+ $item_id = wc_add_order_item( $this->id, array(
+ 'order_item_name' => $code,
+ 'order_item_type' => 'tax'
+ ) );
+
+ if ( ! $item_id ) {
+ return false;
+ }
+
+ wc_add_order_item_meta( $item_id, 'rate_id', $tax_rate_id );
+ wc_add_order_item_meta( $item_id, 'label', WC_Tax::get_rate_label( $tax_rate_id ) );
+ wc_add_order_item_meta( $item_id, 'compound', WC_Tax::is_compound( $tax_rate_id ) ? 1 : 0 );
+ wc_add_order_item_meta( $item_id, 'tax_amount', wc_format_decimal( $tax_amount ) );
+ wc_add_order_item_meta( $item_id, 'shipping_tax_amount', wc_format_decimal( $shipping_tax_amount ) );
+
+ do_action( 'woocommerce_order_add_tax', $this->id, $item_id, $tax_rate_id, $tax_amount, $shipping_tax_amount );
+
+ return $item_id;
+ }
+
+ /**
+ * Add a shipping row to the order
+ * @param WC_Shipping_Rate shipping_rate
+ * @return int|bool Item ID or false
+ */
+ public function add_shipping( $shipping_rate ) {
+ $item_id = wc_add_order_item( $this->id, array(
+ 'order_item_name' => $shipping_rate->label,
+ 'order_item_type' => 'shipping'
+ ) );
+
+ if ( ! $item_id ) {
+ return false;
+ }
+
+ wc_add_order_item_meta( $item_id, 'method_id', $shipping_rate->id );
+ wc_add_order_item_meta( $item_id, 'cost', wc_format_decimal( $shipping_rate->cost ) );
+
+ do_action( 'woocommerce_order_add_shipping', $this->id, $item_id, $shipping_rate );
+
+ // Update total
+ $this->set_total( $this->order_shipping + wc_format_decimal( $shipping_rate->cost ), 'shipping' );
+
+ return $item_id;
+ }
+
+ /**
+ * Add a fee to the order
+ * @param object $fee
+ * @return int|bool Item ID or false
+ */
+ public function add_fee( $fee ) {
+ $item_id = wc_add_order_item( $this->id, array(
+ 'order_item_name' => $fee->name,
+ 'order_item_type' => 'fee'
+ ) );
+
+ if ( ! $item_id ) {
+ return false;
+ }
+
+ if ( $fee->taxable ) {
+ wc_add_order_item_meta( $item_id, '_tax_class', $fee->tax_class );
+ } else {
+ wc_add_order_item_meta( $item_id, '_tax_class', '0' );
+ }
+
+ wc_add_order_item_meta( $item_id, '_line_total', wc_format_decimal( $fee->amount ) );
+ wc_add_order_item_meta( $item_id, '_line_tax', wc_format_decimal( $fee->tax ) );
+
+ do_action( 'woocommerce_order_add_fee', $this->id, $item_id, $fee );
+
+ return $item_id;
+ }
+
+ /**
+ * Set an order total
+ * @param float $amount
+ * @param string $total_type
+ */
+ public function set_total( $amount, $total_type = 'total' ) {
+ if ( ! in_array( $total_type, array( 'shipping', 'order_discount', 'tax', 'shipping_tax', 'total', 'cart_discount' ) ) ) {
+ return false;
+ }
+ switch ( $total_type ) {
+ case 'total' :
+ $key = '_order_total';
+ $amount = wc_format_decimal( $amount, get_option( 'woocommerce_price_num_decimals' ) );
+ break;
+ case 'order_discount' :
+ case 'cart_discount' :
+ $key = '_' . $total_type;
+ $amount = wc_format_decimal( $amount );
+ break;
+ default :
+ $key = '_order_' . $total_type;
+ $amount = wc_format_decimal( $amount );
+ break;
+ }
+ update_post_meta( $this->id, $key, $amount );
+ }
+
+ /**
+ * Calculate taxes for all line items and shipping, and store the totals and tax rows.
+ *
+ * Will use the base country unless customer addresses are set.
+ *
+ * @return bool success or fail
+ */
+ public function calculate_taxes() {
+ $shipping_tax_total = 0;
+ $tax_total = 0;
+ $taxes = array();
+ $tax_based_on = get_option( 'woocommerce_tax_based_on' );
+
+ if ( 'base' === $tax_based_on ) {
+ $default = get_option( 'woocommerce_default_country' );
+ $postcode = '';
+ $city = '';
+ if ( strstr( $default, ':' ) ) {
+ list( $country, $state ) = explode( ':', $default );
+ } else {
+ $country = $default;
+ $state = '';
+ }
+ } elseif ( 'billing' === $tax_based_on ) {
+ $country = $this->billing_country;
+ $state = $this->billing_state;
+ $postcode = $this->billing_postcode;
+ $city = $this->billing_city;
+ } else {
+ $country = $this->shipping_country;
+ $state = $this->shipping_state;
+ $postcode = $this->shipping_postcode;
+ $city = $this->shipping_city;
+ }
+
+ // Get items
+ foreach ( $this->get_items( array( 'line_item', 'fee' ) ) as $item_id => $item ) {
+ $product = $this->get_product_from_item( $item );
+ $line_total = isset( $item['line_total'] ) ? $item['line_total'] : 0;
+ $line_subtotal = isset( $item['line_subtotal'] ) ? $item['line_subtotal'] : 0;
+ $tax_class = $item['tax_class'];
+ $item_tax_status = $product ? $product->get_tax_status() : 'taxable';
+
+ if ( '0' !== $tax_class && 'taxable' === $item_tax_status ) {
+ $tax_rates = WC_Tax::find_rates( array(
+ 'country' => $country,
+ 'state' => $state,
+ 'postcode' => $postcode,
+ 'city' => $city,
+ 'tax_class' => $tax_class
+ ) );
+ $line_subtotal_taxes = WC_Tax::calc_tax( $line_subtotal, $tax_rates, false );
+ $line_taxes = WC_Tax::calc_tax( $line_total, $tax_rates, false );
+ $line_subtotal_tax = max( 0, array_sum( $line_subtotal_taxes ) );
+ $line_tax = max( 0, array_sum( $line_taxes ) );
+ $tax_total += $line_tax;
+
+ wc_update_order_item_meta( $item_id, '_line_subtotal_tax', wc_format_decimal( $line_subtotal_tax ) );
+ wc_update_order_item_meta( $item_id, '_line_tax', wc_format_decimal( $line_tax ) );
+
+ // Sum the item taxes
+ foreach ( array_keys( $taxes + $line_taxes ) as $key ) {
+ $taxes[ $key ] = ( isset( $line_taxes[ $key ] ) ? $line_taxes[ $key ] : 0 ) + ( isset( $taxes[ $key ] ) ? $taxes[ $key ] : 0 );
+ }
+ }
+ }
+
+ // Now calculate shipping tax
+ $matched_tax_rates = array();
+ $tax_rates = WC_Tax::find_rates( array(
+ 'country' => $country,
+ 'state' => $state,
+ 'postcode' => $postcode,
+ 'city' => $city,
+ 'tax_class' => ''
+ ) );
+
+ if ( $tax_rates ) {
+ foreach ( $tax_rates as $key => $rate ) {
+ if ( isset( $rate['shipping'] ) && 'yes' === $rate['shipping'] ) {
+ $matched_tax_rates[ $key ] = $rate;
+ }
+ }
+ }
+
+ $shipping_taxes = WC_Tax::calc_shipping_tax( $this->order_shipping, $matched_tax_rates );
+ $shipping_tax_total = WC_Tax::round( array_sum( $shipping_taxes ) );
+
+ // Save tax totals
+ $this->set_total( $shipping_tax_total, 'shipping_tax' );
+ $this->set_total( $tax_total, 'tax' );
+
+ // Tax rows
+ $this->remove_order_items( 'tax' );
+
+ // Now merge to keep tax rows
+ foreach ( array_keys( $taxes + $shipping_taxes ) as $tax_rate_id ) {
+ $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 );
+ }
+
+ return true;
+ }
+
+ /**
+ * Calculate totals by looking at the contents of the order. Stores the totals and returns the orders final total.
+ *
+ * @return $total calculated grand total
+ */
+ public function calculate_totals() {
+ $cart_subtotal = 0;
+ $cart_total = 0;
+ $fee_total = 0;
+
+ $this->calculate_taxes();
+
+ foreach ( $this->get_items() as $item ) {
+ $cart_subtotal += wc_format_decimal( isset( $item['line_subtotal'] ) ? $item['line_subtotal'] : 0 );
+ $cart_total += wc_format_decimal( isset( $item['line_total'] ) ? $item['line_total'] : 0 );
+ }
+
+ foreach ( $this->get_fees() as $item ) {
+ $fee_total += $item['line_total'];
+ }
+
+ $grand_total = round( $cart_total + $fee_total + $this->get_total_shipping() - $this->get_order_discount() + $this->get_cart_tax() + $this->get_shipping_tax(), absint( get_option( 'woocommerce_price_num_decimals' ) ) );
+
+ $this->set_total( $cart_subtotal - $cart_total, 'cart_discount' );
+ $this->set_total( $grand_total, 'total' );
+
+ return $grand_total;
+ }
+
+ /**
+ * Gets an order from the database.
+ *
+ * @access public
+ * @param int $id (default: 0)
+ * @return bool
+ */
+ public function get_order( $id = 0 ) {
+ if ( ! $id ) {
+ return false;
+ }
+ if ( $result = get_post( $id ) ) {
+ $this->populate( $result );
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Populates an order from the loaded post data.
+ *
+ * @access public
+ * @param mixed $result
+ * @return void
+ */
+ public function populate( $result ) {
+ // Standard post data
+ $this->id = $result->ID;
+ $this->order_date = $result->post_date;
+ $this->modified_date = $result->post_modified;
+ $this->customer_message = $result->post_excerpt;
+ $this->customer_note = $result->post_excerpt;
+ $this->post_status = $result->post_status;
+
+ // Billing email cam default to user if set
+ if ( empty( $this->billing_email ) && ! empty( $this->customer_user ) ) {
+ $user = get_user_by( 'id', $this->customer_user );
+ $this->billing_email = $user->user_email;
+ }
+ }
+
+ /**
+ * __isset function.
+ *
+ * @access public
+ * @param mixed $key
+ * @return bool
+ */
+ public function __isset( $key ) {
+ if ( ! $this->id ) {
+ return false;
+ }
+ return metadata_exists( 'post', $this->id, '_' . $key );
+ }
+
+ /**
+ * __get function.
+ *
+ * @access public
+ * @param mixed $key
+ * @return mixed
+ */
+ public function __get( $key ) {
+ // Get values or default if not set
+ if ( 'completed_date' === $key ) {
+ $value = ( $value = get_post_meta( $this->id, '_completed_date', true ) ) ? $value : $this->modified_date;
+ } elseif ( 'user_id' === $key ) {
+ $value = ( $value = get_post_meta( $this->id, '_customer_user', true ) ) ? absint( $value ) : '';
+ } elseif ( 'status' === $key ) {
+ $value = $this->get_status();
+ } else {
+ $value = get_post_meta( $this->id, '_' . $key, true );
+ }
+ return $value;
+ }
+
+ /**
+ * Return the order statuses without wc- internal prefix
+ * @return string
+ */
+ public function get_status() {
+ return apply_filters( 'woocommerce_order_get_status', 'wc-' === substr( $this->post_status, 0, 3 ) ? substr( $this->post_status, 3 ) : $this->post_status, $this );
+ }
+
+ /**
+ * Checks the order status against a passed in status.
+ *
+ * @access public
+ * @param mixed $type Array or string of types
+ * @return bool
+ */
+ public function has_status( $status ) {
+ return apply_filters( 'woocommerce_order_has_status', ( is_array( $status ) && in_array( $this->get_status(), $status ) ) || $this->get_status() === $status ? true : false, $this, $status );
+ }
+
+ /**
+ * Gets the user ID associated with the order. Guests are 0.
+ * @since 2.2
+ * @return int|false
+ */
+ public function get_user_id() {
+ return $this->customer_user ? $this->customer_user : 0;
+ }
+
+ /**
+ * Get the user associated with the order. False for guests.
+ * @since 2.2
+ * @return WP_User|false
+ */
+ public function get_user() {
+ return $user_id = $this->get_user_id() ? get_user_by( 'id', $user_id ) : false;
+ }
+
+ /**
+ * Check if an order key is valid.
+ *
+ * @access public
+ * @param mixed $key
+ * @return bool
+ */
+ public function key_is_valid( $key ) {
+ if ( $key == $this->order_key ) {
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * get_order_number function.
+ *
+ * Gets the order number for display (by default, order ID)
+ *
+ * @access public
+ * @return string
+ */
+ public function get_order_number() {
+ return apply_filters( 'woocommerce_order_number', _x( '#', 'hash before order number', 'woocommerce' ) . $this->id, $this );
+ }
+
+ /**
+ * Get a formatted billing address for the order.
+ *
+ * @access public
+ * @return string
+ */
+ public function get_formatted_billing_address() {
+ if ( ! $this->formatted_billing_address ) {
+
+ // Formatted Addresses
+ $address = apply_filters( 'woocommerce_order_formatted_billing_address', array(
+ 'first_name' => $this->billing_first_name,
+ 'last_name' => $this->billing_last_name,
+ 'company' => $this->billing_company,
+ 'address_1' => $this->billing_address_1,
+ 'address_2' => $this->billing_address_2,
+ 'city' => $this->billing_city,
+ 'state' => $this->billing_state,
+ 'postcode' => $this->billing_postcode,
+ 'country' => $this->billing_country
+ ), $this );
+
+ $this->formatted_billing_address = WC()->countries->get_formatted_address( $address );
+ }
+ return $this->formatted_billing_address;
+ }
+
+ /**
+ * Get the billing address in an array.
+ *
+ * @access public
+ * @return string
+ */
+ public function get_billing_address() {
+ if ( ! $this->billing_address ) {
+ // Formatted Addresses
+ $address = array(
+ 'address_1' => $this->billing_address_1,
+ 'address_2' => $this->billing_address_2,
+ 'city' => $this->billing_city,
+ 'state' => $this->billing_state,
+ 'postcode' => $this->billing_postcode,
+ 'country' => $this->billing_country
+ );
+ $joined_address = array();
+ foreach ( $address as $part ) {
+ if ( ! empty( $part ) ) {
+ $joined_address[] = $part;
+ }
+ }
+ $this->billing_address = implode( ', ', $joined_address );
+ }
+ return $this->billing_address;
+ }
+
+ /**
+ * Get a formatted shipping address for the order.
+ *
+ * @access public
+ * @return string
+ */
+ public function get_formatted_shipping_address() {
+ if ( ! $this->formatted_shipping_address ) {
+ if ( $this->shipping_address_1 ) {
+
+ // Formatted Addresses
+ $address = apply_filters( 'woocommerce_order_formatted_shipping_address', array(
+ 'first_name' => $this->shipping_first_name,
+ 'last_name' => $this->shipping_last_name,
+ 'company' => $this->shipping_company,
+ 'address_1' => $this->shipping_address_1,
+ 'address_2' => $this->shipping_address_2,
+ 'city' => $this->shipping_city,
+ 'state' => $this->shipping_state,
+ 'postcode' => $this->shipping_postcode,
+ 'country' => $this->shipping_country
+ ), $this );
+
+ $this->formatted_shipping_address = WC()->countries->get_formatted_address( $address );
+ }
+ }
+ return $this->formatted_shipping_address;
+ }
+
+ /**
+ * Get the shipping address in an array.
+ *
+ * @access public
+ * @return array
+ */
+ public function get_shipping_address() {
+ if ( ! $this->shipping_address ) {
+ if ( $this->shipping_address_1 ) {
+ // Formatted Addresses
+ $address = array(
+ 'address_1' => $this->shipping_address_1,
+ 'address_2' => $this->shipping_address_2,
+ 'city' => $this->shipping_city,
+ 'state' => $this->shipping_state,
+ 'postcode' => $this->shipping_postcode,
+ 'country' => $this->shipping_country
+ );
+ $joined_address = array();
+ foreach ( $address as $part ) {
+ if ( ! empty( $part ) ) {
+ $joined_address[] = $part;
+ }
+ }
+ $this->shipping_address = implode( ', ', $joined_address );
+ }
+ }
+ return $this->shipping_address;
+ }
+
+ /**
+ * Return an array of items/products within this order.
+ *
+ * @access public
+ * @param string|array $type Types of line items to get (array or string)
+ * @return array
+ */
+ public function get_items( $type = '' ) {
+ global $wpdb;
+
+ if ( empty( $type ) ) {
+ $type = array( 'line_item' );
+ }
+
+ if ( ! is_array( $type ) ) {
+ $type = array( $type );
+ }
+
+ $type = array_map( 'esc_attr', $type );
+
+ $line_items = $wpdb->get_results( $wpdb->prepare( "
+ SELECT order_item_id, order_item_name, order_item_type
+ FROM {$wpdb->prefix}woocommerce_order_items
+ WHERE order_id = %d
+ AND order_item_type IN ( '" . implode( "','", $type ) . "' )
+ ORDER BY order_item_id
+ ", $this->id ) );
+
+ $items = array();
+
+ // Reserved meta keys
+ $reserved_item_meta_keys = array(
+ 'name',
+ 'type',
+ 'item_meta',
+ 'qty',
+ 'tax_class',
+ 'product_id',
+ 'variation_id',
+ 'line_subtotal',
+ 'line_total',
+ 'line_tax',
+ 'line_subtotal_tax'
+ );
+
+ // Loop items
+ foreach ( $line_items as $item ) {
+ // Place line item into array to return
+ $items[ $item->order_item_id ]['name'] = $item->order_item_name;
+ $items[ $item->order_item_id ]['type'] = $item->order_item_type;
+ $items[ $item->order_item_id ]['item_meta'] = $this->get_item_meta( $item->order_item_id );
+
+ // Expand meta data into the array
+ foreach ( $items[ $item->order_item_id ]['item_meta'] as $name => $value ) {
+ if ( in_array( $name, $reserved_item_meta_keys ) ) {
+ continue;
+ }
+ if ( '_' === substr( $name, 0, 1 ) ) {
+ $items[ $item->order_item_id ][ substr( $name, 1 ) ] = $value[0];
+ } elseif ( ! in_array( $name, $reserved_item_meta_keys ) ) {
+ $items[ $item->order_item_id ][ $name ] = $value[0];
+ }
+ }
+ }
+
+ return apply_filters( 'woocommerce_order_get_items', $items, $this );
+ }
+
+ /**
+ * Gets order total - formatted for display.
+ *
+ * @access public
+ * @return string
+ */
+ public function get_item_count( $type = '' ) {
+ if ( empty( $type ) ) {
+ $type = array( 'line_item' );
+ }
+
+ if ( ! is_array( $type ) ) {
+ $type = array( $type );
+ }
+
+ $items = $this->get_items( $type );
+
+ $count = 0;
+
+ foreach ( $items as $item ) {
+ if ( ! empty( $item['qty'] ) ) {
+ $count += $item['qty'];
+ } else {
+ $count ++;
+ }
+ }
+
+ return apply_filters( 'woocommerce_get_item_count', $count, $type, $this );
+ }
+
+ /**
+ * Return an array of fees within this order.
+ *
+ * @access public
+ * @return array
+ */
+ public function get_fees() {
+ return $this->get_items( 'fee' );
+ }
+
+ /**
+ * Return an array of taxes within this order.
+ *
+ * @access public
+ * @return array
+ */
+ public function get_taxes() {
+ return $this->get_items( 'tax' );
+ }
+
+ /**
+ * Return an array of shipping costs within this order.
+ *
+ * @return array
+ */
+ public function get_shipping_methods() {
+ return $this->get_items( 'shipping' );
+ }
+
+ /**
+ * Check whether this order has a specific shipping method or not
+ * @param string $method_id
+ * @return bool
+ */
+ public function has_shipping_method( $method_id ) {
+ $shipping_methods = $this->get_shipping_methods();
+ $has_method = false;
+
+ if ( ! $shipping_methods ) {
+ return false;
+ }
+
+ foreach ( $shipping_methods as $shipping_method ) {
+ if ( $shipping_method['method_id'] == $method_id ) {
+ $has_method = true;
+ }
+ }
+
+ return $has_method;
+ }
+
+ /**
+ * Get taxes, merged by code, formatted ready for output.
+ *
+ * @access public
+ * @return array
+ */
+ public function get_tax_totals() {
+ $taxes = $this->get_items( 'tax' );
+ $tax_totals = array();
+
+ foreach ( $taxes as $key => $tax ) {
+
+ $code = $tax[ 'name' ];
+
+ if ( ! isset( $tax_totals[ $code ] ) ) {
+ $tax_totals[ $code ] = new stdClass();
+ $tax_totals[ $code ]->amount = 0;
+ }
+
+ $tax_totals[ $code ]->is_compound = $tax[ 'compound' ];
+ $tax_totals[ $code ]->label = isset( $tax[ 'label' ] ) ? $tax[ 'label' ] : $tax[ 'name' ];
+ $tax_totals[ $code ]->amount += $tax[ 'tax_amount' ] + $tax[ 'shipping_tax_amount' ];
+ $tax_totals[ $code ]->formatted_amount = wc_price( wc_round_tax_total( $tax_totals[ $code ]->amount ), array('currency' => $this->get_order_currency()) );
+ }
+
+ return apply_filters( 'woocommerce_order_tax_totals', $tax_totals, $this );
+ }
+
+ /**
+ * has_meta function for order items.
+ * @access public
+ * @param string $order_item_id
+ * @return array of meta data
+ */
+ public function has_meta( $order_item_id ) {
+ global $wpdb;
+
+ return $wpdb->get_results( $wpdb->prepare( "SELECT meta_key, meta_value, meta_id, order_item_id
+ FROM {$wpdb->prefix}woocommerce_order_itemmeta WHERE order_item_id = %d
+ ORDER BY meta_id", absint( $order_item_id ) ), ARRAY_A );
+ }
+
+ /**
+ * Get order item meta.
+ *
+ * @access public
+ * @param mixed $order_item_id
+ * @param string $key (default: '')
+ * @param bool $single (default: false)
+ * @return array|string
+ */
+ public function get_item_meta( $order_item_id, $key = '', $single = false ) {
+ return get_metadata( 'order_item', $order_item_id, $key, $single );
+ }
+
+ /** Total Getters *******************************************************/
+
+ /**
+ * Gets the total (product) discount amount - these are applied before tax.
+ *
+ * @access public
+ * @return float
+ */
+ public function get_cart_discount() {
+ return apply_filters( 'woocommerce_order_amount_cart_discount', (double) $this->cart_discount, $this );
+ }
+
+ /**
+ * Gets the total (product) discount amount - these are applied before tax.
+ *
+ * @access public
+ * @return float
+ */
+ public function get_order_discount() {
+ return apply_filters( 'woocommerce_order_amount_order_discount', (double) $this->order_discount, $this );
+ }
+
+ /**
+ * Gets the total discount amount - both kinds
+ *
+ * @access public
+ * @return float
+ */
+ public function get_total_discount() {
+ return apply_filters( 'woocommerce_order_amount_total_discount', $this->get_cart_discount() + $this->get_order_discount(), $this );
+ }
+
+ /**
+ * Gets shipping tax amount.
+ *
+ * @access public
+ * @return float
+ */
+ public function get_cart_tax() {
+ return apply_filters( 'woocommerce_order_amount_cart_tax', (double) $this->order_tax, $this );
+ }
+
+ /**
+ * Gets shipping tax amount.
+ *
+ * @access public
+ * @return float
+ */
+ public function get_shipping_tax() {
+ return apply_filters( 'woocommerce_order_amount_shipping_tax', (double) $this->order_shipping_tax, $this );
+ }
+
+ /**
+ * Gets shipping and product tax.
+ *
+ * @access public
+ * @return float
+ */
+ public function get_total_tax() {
+ return apply_filters( 'woocommerce_order_amount_total_tax', wc_round_tax_total( $this->get_cart_tax() + $this->get_shipping_tax() ), $this );
+ }
+
+ /**
+ * Gets shipping total.
+ *
+ * @access public
+ * @return float
+ */
+ public function get_total_shipping() {
+ return apply_filters( 'woocommerce_order_amount_total_shipping', (double) $this->order_shipping, $this );
+ }
+
+ /**
+ * Gets order total.
+ *
+ * @access public
+ * @return float
+ */
+ public function get_total() {
+ return apply_filters( 'woocommerce_order_amount_total', (double) $this->order_total, $this );
+ }
+
+ /**
+ * Get item subtotal - this is the cost before discount.
+ *
+ * @access public
+ * @param mixed $item
+ * @param bool $inc_tax (default: false)
+ * @param bool $round (default: true)
+ * @return float
+ */
+ public function get_item_subtotal( $item, $inc_tax = false, $round = true ) {
+ if ( $inc_tax ) {
+ $price = ( $item['line_subtotal'] + $item['line_subtotal_tax'] ) / max( 1, $item['qty'] );
+ } else {
+ $price = ( $item['line_subtotal'] / $item['qty'] );
+ }
+
+ $price = $round ? round( $price, 2 ) : $price;
+
+ return apply_filters( 'woocommerce_order_amount_item_subtotal', $price, $this, $item );
+ }
+
+ /**
+ * Get line subtotal - this is the cost before discount.
+ *
+ * @access public
+ * @param mixed $item
+ * @param bool $inc_tax (default: false)
+ * @param bool $round (default: true)
+ * @return float
+ */
+ public function get_line_subtotal( $item, $inc_tax = false, $round = true ) {
+ if ( $inc_tax ) {
+ $price = $item['line_subtotal'] + $item['line_subtotal_tax'];
+ } else {
+ $price = $item['line_subtotal'];
+ }
+
+ $price = $round ? round( $price, 2 ) : $price;
+
+ return apply_filters( 'woocommerce_order_amount_line_subtotal', $price, $this, $item );
+ }
+
+ /**
+ * Calculate item cost - useful for gateways.
+ *
+ * @access public
+ * @param mixed $item
+ * @param bool $inc_tax (default: false)
+ * @param bool $round (default: true)
+ * @return float
+ */
+ public function get_item_total( $item, $inc_tax = false, $round = true ) {
+ if ( $inc_tax ) {
+ $price = ( $item['line_total'] + $item['line_tax'] ) / max( 1, $item['qty'] );
+ } else {
+ $price = $item['line_total'] / $item['qty'];
+ }
+
+ $price = $round ? round( $price, 2 ) : $price;
+
+ return apply_filters( 'woocommerce_order_amount_item_total', $price, $this );
+ }
+
+ /**
+ * Calculate line total - useful for gateways.
+ *
+ * @access public
+ * @param mixed $item
+ * @param bool $inc_tax (default: false)
+ * @return float
+ */
+ public function get_line_total( $item, $inc_tax = false ) {
+ $line_total = $inc_tax ? round( $item['line_total'] + $item['line_tax'], 2 ) : round( $item['line_total'], 2 );
+ return apply_filters( 'woocommerce_order_amount_line_total', $line_total, $this );
+ }
+
+ /**
+ * Calculate item tax - useful for gateways.
+ *
+ * @access public
+ * @param mixed $item
+ * @param bool $round (default: true)
+ * @return float
+ */
+ public function get_item_tax( $item, $round = true ) {
+ $price = $item['line_tax'] / max( 1, $item['qty'] );
+ $price = $round ? wc_round_tax_total( $price ) : $price;
+ return apply_filters( 'woocommerce_order_amount_item_tax', $price, $item, $round, $this );
+ }
+
+ /**
+ * Calculate line tax - useful for gateways.
+ *
+ * @access public
+ * @param mixed $item
+ * @return float
+ */
+ public function get_line_tax( $item ) {
+ return apply_filters( 'woocommerce_order_amount_line_tax', wc_round_tax_total( $item['line_tax'] ), $item, $this );
+ }
+
+ /**
+ * Gets shipping total.
+ *
+ * @deprecated As of 2.1, use of get_total_shipping() is preferred
+ * @access public
+ * @return float
+ */
+ public function get_shipping() {
+ _deprecated_function( 'get_shipping', '2.1', 'get_total_shipping' );
+ return $this->get_total_shipping();
+ }
+
+ /**
+ * get_order_total function. Alias for get_total()
+ *
+ * @deprecated As of 2.1, use of get_total() is preferred
+ * @access public
+ * @return float
+ */
+ public function get_order_total() {
+ _deprecated_function( 'get_order_total', '2.1', 'get_total' );
+ return $this->get_total();
+ }
+
+ /** End Total Getters *******************************************************/
+
+ /**
+ * Gets formatted shipping method title.
+ *
+ * @return string
+ */
+ public function get_shipping_method() {
+ $labels = array();
+
+ // Backwards compat < 2.1 - get shipping title stored in meta
+ if ( $this->shipping_method_title ) {
+ $labels[] = $this->shipping_method_title;
+ } else {
+ // 2.1+ get line items for shipping
+ $shipping_methods = $this->get_shipping_methods();
+
+ foreach ( $shipping_methods as $shipping ) {
+ $labels[] = $shipping['name'];
+ }
+ }
+
+ return apply_filters( 'woocommerce_order_shipping_method', implode( ', ', $labels ), $this );
+ }
+
+ /**
+ * Gets line subtotal - formatted for display.
+ *
+ * @access public
+ * @param array $item
+ * @param string $tax_display
+ * @return string
+ */
+ public function get_formatted_line_subtotal( $item, $tax_display = '' ) {
+ if ( ! $tax_display ) {
+ $tax_display = $this->tax_display_cart;
+ }
+
+ if ( ! isset( $item['line_subtotal'] ) || ! isset( $item['line_subtotal_tax'] ) ) {
+ return '';
+ }
+
+ if ( 'excl' == $tax_display ) {
+ $ex_tax_label = $this->prices_include_tax ? 1 : 0;
+
+ $subtotal = wc_price( $this->get_line_subtotal( $item ), array( 'ex_tax_label' => $ex_tax_label, 'currency' => $this->get_order_currency() ) );
+ } else {
+ $subtotal = wc_price( $this->get_line_subtotal( $item, true ), array('currency' => $this->get_order_currency()) );
+ }
+
+ return apply_filters( 'woocommerce_order_formatted_line_subtotal', $subtotal, $item, $this );
+ }
+
+ /**
+ * Gets order currency
+ *
+ * @access public
+ * @return string
+ */
+ public function get_order_currency() {
+
+ $currency = $this->order_currency;
+
+ return apply_filters( 'woocommerce_get_order_currency', $currency, $this );
+ }
+
+ /**
+ * Gets order total - formatted for display.
+ *
+ * @access public
+ * @return string
+ */
+ public function get_formatted_order_total() {
+
+ $formatted_total = wc_price( $this->order_total , array('currency' => $this->get_order_currency()));
+
+ return apply_filters( 'woocommerce_get_formatted_order_total', $formatted_total, $this );
+ }
+
+
+ /**
+ * Gets subtotal - subtotal is shown before discounts, but with localised taxes.
+ *
+ * @access public
+ * @param bool $compound (default: false)
+ * @param string $tax_display (default: the tax_display_cart value)
+ * @return string
+ */
+ public function get_subtotal_to_display( $compound = false, $tax_display = '' ) {
+ if ( ! $tax_display ) {
+ $tax_display = $this->tax_display_cart;
+ }
+
+ $subtotal = 0;
+
+ if ( ! $compound ) {
+ foreach ( $this->get_items() as $item ) {
+
+ if ( ! isset( $item['line_subtotal'] ) || ! isset( $item['line_subtotal_tax'] ) ) {
+ return '';
+ }
+
+ $subtotal += $item['line_subtotal'];
+
+ if ( 'incl' == $tax_display ) {
+ $subtotal += $item['line_subtotal_tax'];
+ }
+ }
+
+ $subtotal = wc_price( $subtotal, array('currency' => $this->get_order_currency()) );
+
+ if ( $tax_display == 'excl' && $this->prices_include_tax ) {
+ $subtotal .= ' ' . WC()->countries->ex_tax_or_vat() . '';
+ }
+
+ } else {
+
+ if ( 'incl' == $tax_display ) {
+ return '';
+ }
+
+ foreach ( $this->get_items() as $item ) {
+
+ $subtotal += $item['line_subtotal'];
+
+ }
+
+ // Add Shipping Costs
+ $subtotal += $this->get_total_shipping();
+
+ // Remove non-compound taxes
+ foreach ( $this->get_taxes() as $tax ) {
+
+ if ( ! empty( $tax['compound'] ) ) {
+ continue;
+ }
+
+ $subtotal = $subtotal + $tax['tax_amount'] + $tax['shipping_tax_amount'];
+
+ }
+
+ // Remove discounts
+ $subtotal = $subtotal - $this->get_cart_discount();
+
+ $subtotal = wc_price( $subtotal, array('currency' => $this->get_order_currency()) );
+ }
+
+ return apply_filters( 'woocommerce_order_subtotal_to_display', $subtotal, $compound, $this );
+ }
+
+
+ /**
+ * Gets shipping (formatted).
+ *
+ * @access public
+ * @return string
+ */
+ public function get_shipping_to_display( $tax_display = '' ) {
+ if ( ! $tax_display ) {
+ $tax_display = $this->tax_display_cart;
+ }
+
+ if ( $this->order_shipping > 0 ) {
+
+ $tax_text = '';
+
+ if ( $tax_display == 'excl' ) {
+
+ // Show shipping excluding tax
+ $shipping = wc_price( $this->order_shipping, array('currency' => $this->get_order_currency()) );
+
+ if ( $this->order_shipping_tax > 0 && $this->prices_include_tax ) {
+ $tax_text = WC()->countries->ex_tax_or_vat() . ' ';
+ }
+
+ } else {
+
+ // Show shipping including tax
+ $shipping = wc_price( $this->order_shipping + $this->order_shipping_tax, array('currency' => $this->get_order_currency()) );
+
+ if ( $this->order_shipping_tax > 0 && ! $this->prices_include_tax ) {
+ $tax_text = WC()->countries->inc_tax_or_vat() . ' ';
+ }
+
+ }
+
+ $shipping .= sprintf( __( ' %svia %s', 'woocommerce' ), $tax_text, $this->get_shipping_method() );
+
+ } elseif ( $this->get_shipping_method() ) {
+ $shipping = $this->get_shipping_method();
+ } else {
+ $shipping = __( 'Free!', 'woocommerce' );
+ }
+
+ return apply_filters( 'woocommerce_order_shipping_to_display', $shipping, $this );
+ }
+
+
+ /**
+ * Get cart discount (formatted).
+ *
+ * @access public
+ * @return string.
+ */
+ public function get_cart_discount_to_display() {
+ return apply_filters( 'woocommerce_order_cart_discount_to_display', wc_price( $this->get_cart_discount(), array( 'currency' => $this->get_order_currency() ) ), $this );
+ }
+
+
+ /**
+ * Get cart discount (formatted).
+ *
+ * @access public
+ * @return string
+ */
+ public function get_order_discount_to_display() {
+ return apply_filters( 'woocommerce_order_discount_to_display', wc_price( $this->get_order_discount(), array( 'currency' => $this->get_order_currency() ) ), $this );
+ }
+
+
+ /**
+ * Get a product (either product or variation).
+ *
+ * @access public
+ * @param mixed $item
+ * @return WC_Product
+ */
+ public function get_product_from_item( $item ) {
+ if ( ! empty( $item['variation_id'] ) && 'product_variation' === get_post_type( $item['variation_id'] ) ) {
+ $_product = get_product( $item['variation_id'] );
+ } else {
+ $_product = get_product( $item['product_id'] );
+ }
+ return apply_filters( 'woocommerce_get_product_from_item', $_product, $item, $this );
+ }
+
+
+ /**
+ * Get totals for display on pages and in emails.
+ *
+ * @access public
+ * @return array
+ */
+ public function get_order_item_totals( $tax_display = '' ) {
+ if ( ! $tax_display ) {
+ $tax_display = $this->tax_display_cart;
+ }
+
+ $total_rows = array();
+
+ if ( $subtotal = $this->get_subtotal_to_display() ) {
+ $total_rows['cart_subtotal'] = array(
+ 'label' => __( 'Cart Subtotal:', 'woocommerce' ),
+ 'value' => $subtotal
+ );
+ }
+
+ if ( $this->get_cart_discount() > 0 ) {
+ $total_rows['cart_discount'] = array(
+ 'label' => __( 'Cart Discount:', 'woocommerce' ),
+ 'value' => '-' . $this->get_cart_discount_to_display()
+ );
+ }
+
+ if ( $this->get_shipping_method() ) {
+ $total_rows['shipping'] = array(
+ 'label' => __( 'Shipping:', 'woocommerce' ),
+ 'value' => $this->get_shipping_to_display()
+ );
+ }
+
+ if ( $fees = $this->get_fees() )
+ foreach( $fees as $id => $fee ) {
+ if ( apply_filters( 'woocommerce_get_order_item_totals_excl_free_fees', $fee['line_total'] + $fee['line_tax'] == 0, $id ) ) {
+ continue;
+ }
+
+ if ( 'excl' == $tax_display ) {
+
+ $total_rows[ 'fee_' . $id ] = array(
+ 'label' => $fee['name'] . ':',
+ 'value' => wc_price( $fee['line_total'], array('currency' => $this->get_order_currency()) )
+ );
+
+ } else {
+
+ $total_rows[ 'fee_' . $id ] = array(
+ 'label' => $fee['name'] . ':',
+ 'value' => wc_price( $fee['line_total'] + $fee['line_tax'], array('currency' => $this->get_order_currency()) )
+ );
+
+ }
+ }
+
+ // Tax for tax exclusive prices
+ if ( 'excl' == $tax_display ) {
+ if ( get_option( 'woocommerce_tax_total_display' ) == 'itemized' ) {
+ foreach ( $this->get_tax_totals() as $code => $tax ) {
+ $total_rows[ sanitize_title( $code ) ] = array(
+ 'label' => $tax->label . ':',
+ 'value' => $tax->formatted_amount
+ );
+ }
+ } else {
+ $total_rows['tax'] = array(
+ 'label' => WC()->countries->tax_or_vat() . ':',
+ 'value' => wc_price( $this->get_total_tax(), array('currency' => $this->get_order_currency()) )
+ );
+ }
+ }
+
+ if ( $this->get_order_discount() > 0 ) {
+ $total_rows['order_discount'] = array(
+ 'label' => __( 'Order Discount:', 'woocommerce' ),
+ 'value' => '-' . $this->get_order_discount_to_display()
+ );
+ }
+
+ if ( $this->get_total() > 0 ) {
+ $total_rows['payment_method'] = array(
+ 'label' => __( 'Payment Method:', 'woocommerce' ),
+ 'value' => $this->payment_method_title
+ );
+ }
+
+ $total_rows['order_total'] = array(
+ 'label' => __( 'Order Total:', 'woocommerce' ),
+ 'value' => $this->get_formatted_order_total()
+ );
+
+ // Tax for inclusive prices
+ if ( 'yes' == get_option( 'woocommerce_calc_taxes' ) && 'incl' == $tax_display ) {
+
+ $tax_string_array = array();
+
+ if ( 'itemized' == get_option( 'woocommerce_tax_total_display' ) ) {
+ foreach ( $this->get_tax_totals() as $code => $tax ) {
+ $tax_string_array[] = sprintf( '%s %s', $tax->formatted_amount, $tax->label );
+ }
+ } else {
+ $tax_string_array[] = sprintf( '%s %s', wc_price( $this->get_total_tax(), array('currency' => $this->get_order_currency()) ), WC()->countries->tax_or_vat() );
+ }
+
+ if ( ! empty( $tax_string_array ) ) {
+ $total_rows['order_total']['value'] .= ' ' . sprintf( __( '(Includes %s)', 'woocommerce' ), implode( ', ', $tax_string_array ) );
+ }
+ }
+
+ return apply_filters( 'woocommerce_get_order_item_totals', $total_rows, $this );
+ }
+
+
+ /**
+ * Output items for display in html emails.
+ *
+ * @access public
+ * @param bool $show_download_links (default: false)
+ * @param bool $show_sku (default: false)
+ * @param bool $show_purchase_note (default: false)
+ * @param bool $show_image (default: false)
+ * @param array $image_size (default: array( 32, 32 )
+ * @param bool plain text
+ * @return string
+ */
+ public function email_order_items_table( $show_download_links = false, $show_sku = false, $show_purchase_note = false, $show_image = false, $image_size = array( 32, 32 ), $plain_text = false ) {
+
+ ob_start();
+
+ $template = $plain_text ? 'emails/plain/email-order-items.php' : 'emails/email-order-items.php';
+
+ wc_get_template( $template, array(
+ 'order' => $this,
+ 'items' => $this->get_items(),
+ 'show_download_links' => $show_download_links,
+ 'show_sku' => $show_sku,
+ 'show_purchase_note' => $show_purchase_note,
+ 'show_image' => $show_image,
+ 'image_size' => $image_size
+ ) );
+
+ $return = apply_filters( 'woocommerce_email_order_items_table', ob_get_clean(), $this );
+
+ return $return;
+ }
+
+ /**
+ * Checks if product download is permitted
+ *
+ * @access public
+ * @return bool
+ */
+ public function is_download_permitted() {
+ 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 );
+ }
+
+ /**
+ * Returns true if the order contains a downloadable product.
+ *
+ * @access public
+ * @return bool
+ */
+ public function has_downloadable_item() {
+ $has_downloadable_item = false;
+
+ foreach ( $this->get_items() as $item ) {
+
+ $_product = $this->get_product_from_item( $item );
+
+ if ( $_product && $_product->exists() && $_product->is_downloadable() && $_product->has_file() ) {
+ $has_downloadable_item = true;
+ }
+
+ }
+
+ return $has_downloadable_item;
+ }
+
+
+ /**
+ * 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.
+ *
+ * @access public
+ * @param boolean $on_checkout
+ * @return string
+ */
+ public function get_checkout_payment_url( $on_checkout = false ) {
+
+ $pay_url = wc_get_endpoint_url( 'order-pay', $this->id, get_permalink( wc_get_page_id( 'checkout' ) ) );
+
+ if ( 'yes' == get_option( 'woocommerce_force_ssl_checkout' ) || is_ssl() ) {
+ $pay_url = str_replace( 'http:', 'https:', $pay_url );
+ }
+
+ if ( $on_checkout ) {
+ $pay_url = add_query_arg( 'key', $this->order_key, $pay_url );
+ } else {
+ $pay_url = add_query_arg( array( 'pay_for_order' => 'true', 'key' => $this->order_key ), $pay_url );
+ }
+
+ return apply_filters( 'woocommerce_get_checkout_payment_url', $pay_url, $this );
+ }
+
+
+ /**
+ * Generates a URL for the thanks page (order received)
+ *
+ * @access public
+ * @return string
+ */
+ public function get_checkout_order_received_url() {
+
+ $order_received_url = wc_get_endpoint_url( 'order-received', $this->id, get_permalink( wc_get_page_id( 'checkout' ) ) );
+
+ if ( 'yes' == get_option( 'woocommerce_force_ssl_checkout' ) || is_ssl() ) {
+ $order_received_url = str_replace( 'http:', 'https:', $order_received_url );
+ }
+
+ $order_received_url = add_query_arg( 'key', $this->order_key, $order_received_url );
+
+ return apply_filters( 'woocommerce_get_checkout_order_received_url', $order_received_url, $this );
+ }
+
+
+ /**
+ * Generates a URL so that a customer can cancel their (unpaid - pending) order.
+ *
+ * @access public
+ * @return string
+ */
+ public function get_cancel_order_url( $redirect = '' ) {
+ $cancel_endpoint = get_permalink( wc_get_page_id( 'cart' ) );
+ if ( ! $cancel_endpoint ) {
+ $cancel_endpoint = home_url();
+ }
+
+ if ( false === strpos( $cancel_endpoint, '?' ) ) {
+ $cancel_endpoint = trailingslashit( $cancel_endpoint );
+ }
+
+ return apply_filters('woocommerce_get_cancel_order_url', wp_nonce_url( add_query_arg( array( 'cancel_order' => 'true', 'order' => $this->order_key, 'order_id' => $this->id, 'redirect' => $redirect ), $cancel_endpoint ), 'woocommerce-cancel_order' ) );
+ }
+
+ /**
+ * Generates a URL to view an order from the my account page
+ *
+ * @return string
+ */
+ public function get_view_order_url() {
+ $view_order_url = wc_get_endpoint_url( 'view-order', $this->id, get_permalink( wc_get_page_id( 'myaccount' ) ) );
+
+ return apply_filters( 'woocommerce_get_view_order_url', $view_order_url, $this );
+ }
+
+ /**
+ * Gets any downloadable product file urls.
+ *
+ * @deprecated as of 2.1 get_item_downloads is preferred as downloads are more than just file urls
+ * @param int $product_id product identifier
+ * @param int $variation_id variation identifier, or null
+ * @param array $item the item
+ * @return array available downloadable file urls
+ */
+ public function get_downloadable_file_urls( $product_id, $variation_id, $item ) {
+ global $wpdb;
+
+ _deprecated_function( 'get_downloadable_file_urls', '2.1', 'get_item_downloads' );
+
+ $download_file = $variation_id > 0 ? $variation_id : $product_id;
+ $_product = get_product( $download_file );
+
+ $user_email = $this->billing_email;
+
+ $results = $wpdb->get_results( $wpdb->prepare("
+ SELECT download_id
+ FROM {$wpdb->prefix}woocommerce_downloadable_product_permissions
+ WHERE user_email = %s
+ AND order_key = %s
+ AND product_id = %s
+ ", $user_email, $this->order_key, $download_file ) );
+
+ $file_urls = array();
+ foreach ( $results as $result ) {
+ if ( $_product->has_file( $result->download_id ) ) {
+ $file_urls[ $_product->get_file_download_path( $result->download_id ) ] = $this->get_download_url( $download_file, $result->download_id );
+ }
+ }
+
+ return apply_filters( 'woocommerce_get_downloadable_file_urls', $file_urls, $product_id, $variation_id, $item );
+ }
+
+ /**
+ * Get the downloadable files for an item in this order
+ * @param array $item
+ * @return array
+ */
+ public function get_item_downloads( $item ) {
+ global $wpdb;
+
+ $product_id = $item['variation_id'] > 0 ? $item['variation_id'] : $item['product_id'];
+ $product = get_product( $product_id );
+ $download_ids = $wpdb->get_col( $wpdb->prepare("
+ SELECT download_id
+ FROM {$wpdb->prefix}woocommerce_downloadable_product_permissions
+ WHERE user_email = %s
+ AND order_key = %s
+ AND product_id = %s
+ ORDER BY permission_id
+ ", $this->billing_email, $this->order_key, $product_id ) );
+
+ $files = array();
+
+ foreach ( $download_ids as $download_id ) {
+ if ( $product->has_file( $download_id ) ) {
+ $files[ $download_id ] = $product->get_file( $download_id );
+ $files[ $download_id ]['download_url'] = $this->get_download_url( $product_id, $download_id );
+ }
+ }
+
+ return apply_filters( 'woocommerce_get_item_downloads', $files, $item, $this );
+ }
+
+ /**
+ * Get the Download URL
+ * @param int $product_id
+ * @param int $download_id
+ * @return string
+ */
+ public function get_download_url( $product_id, $download_id ) {
+ return add_query_arg( array(
+ 'download_file' => $product_id,
+ 'order' => $this->order_key,
+ 'email' => urlencode( $this->billing_email ),
+ 'key' => $download_id
+ ), trailingslashit( home_url() ) );
+ }
+
+ /**
+ * Adds a note (comment) to the order
+ *
+ * @access public
+ * @param string $note Note to add
+ * @param int $is_customer_note (default: 0) Is this a note for the customer?
+ * @return id Comment ID
+ */
+ public function add_order_note( $note, $is_customer_note = 0 ) {
+
+ $is_customer_note = intval( $is_customer_note );
+
+ if ( is_user_logged_in() && current_user_can( 'edit_shop_order', $this->id ) ) {
+ $user = get_user_by( 'id', get_current_user_id() );
+ $comment_author = $user->display_name;
+ $comment_author_email = $user->user_email;
+ } else {
+ $comment_author = __( 'WooCommerce', 'woocommerce' );
+ $comment_author_email = strtolower( __( 'WooCommerce', 'woocommerce' ) ) . '@';
+ $comment_author_email .= isset( $_SERVER['HTTP_HOST'] ) ? str_replace( 'www.', '', $_SERVER['HTTP_HOST'] ) : 'noreply.com';
+ $comment_author_email = sanitize_email( $comment_author_email );
+ }
+
+ $comment_post_ID = $this->id;
+ $comment_author_url = '';
+ $comment_content = $note;
+ $comment_agent = 'WooCommerce';
+ $comment_type = 'order_note';
+ $comment_parent = 0;
+ $comment_approved = 1;
+ $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 ) );
+
+ $comment_id = wp_insert_comment( $commentdata );
+
+ add_comment_meta( $comment_id, 'is_customer_note', $is_customer_note );
+
+ if ( $is_customer_note ) {
+ do_action( 'woocommerce_new_customer_note', array( 'order_id' => $this->id, 'customer_note' => $note ) );
+ }
+
+ return $comment_id;
+ }
+
+ /**
+ * Updates status of order
+ *
+ * @access public
+ * @param string $new_status Status to change the order to. No internal wc- prefix is required.
+ * @param string $note (default: '') Optional note to add
+ */
+ public function update_status( $new_status, $note = '' ) {
+ $old_status = $this->get_status();
+ $new_status = 'wc-' === substr( $new_status, 0, 3 ) ? substr( $new_status, 3 ) : $new_status;
+
+ // Only update if they differ
+ if ( $this->id && $new_status !== $old_status ) {
+
+ // Update the order
+ wp_update_post( array( 'ID' => $this->id, 'post_status' => 'wc-' . $new_status ) );
+ $this->post_status = 'wc-' . $new_status;
+ $this->add_order_note( trim( $note . ' ' . sprintf( __( 'Order status changed from %s to %s.', 'woocommerce' ), $old_status, $new_status ) ) );
+
+ // Status was changed
+ do_action( 'woocommerce_order_status_' . $new_status, $this->id );
+ do_action( 'woocommerce_order_status_' . $old_status . '_to_' . $new_status, $this->id );
+ do_action( 'woocommerce_order_status_changed', $this->id, $old_status, $new_status );
+
+ switch ( $new_status ) {
+ case 'completed' :
+ // Record the sales
+ $this->record_product_sales();
+
+ // Increase coupon usage counts
+ $this->increase_coupon_usage_counts();
+
+ // Record the completed date of the order
+ update_post_meta( $this->id, '_completed_date', current_time('mysql') );
+
+ // Update reports
+ wc_delete_shop_order_transients( $this->id );
+ break;
+ case 'processing' :
+ case 'on-hold' :
+ // Record the sales
+ $this->record_product_sales();
+
+ // Increase coupon usage counts
+ $this->increase_coupon_usage_counts();
+
+ // Update reports
+ wc_delete_shop_order_transients( $this->id );
+ break;
+ case 'cancelled' :
+ // If the order is cancelled, restore used coupons
+ $this->decrease_coupon_usage_counts();
+
+ // Update reports
+ wc_delete_shop_order_transients( $this->id );
+ break;
+ }
+ }
+ }
+
+
+ /**
+ * Cancel the order and restore the cart (before payment)
+ *
+ * @access public
+ * @param string $note (default: '') Optional note to add
+ * @return void
+ */
+ public function cancel_order( $note = '' ) {
+ unset( WC()->session->order_awaiting_payment );
+
+ $this->update_status( 'cancelled', $note );
+
+ }
+
+ /**
+ * When a payment is complete this function is called
+ *
+ * Most of the time this should mark an order as 'processing' so that admin can process/post the items
+ * If the cart contains only downloadable items then the order is 'completed' since the admin needs to take no action
+ * Stock levels are reduced at this point
+ * Sales are also recorded for products
+ * Finally, record the date of payment
+ *
+ * @access public
+ * @param $transaction_id string Optional transaction id to store in post meta
+ * @return void
+ */
+ public function payment_complete( $transaction_id = '' ) {
+
+ do_action( 'woocommerce_pre_payment_complete', $this->id );
+
+ if ( ! empty( WC()->session->order_awaiting_payment ) ) {
+ unset( WC()->session->order_awaiting_payment );
+ }
+
+ $valid_order_statuses = apply_filters( 'woocommerce_valid_order_statuses_for_payment_complete', array( 'on-hold', 'pending', 'failed' ), $this );
+
+ if ( $this->id && $this->has_status( $valid_order_statuses ) ) {
+
+ $order_needs_processing = true;
+
+ if ( sizeof( $this->get_items() ) > 0 ) {
+
+ foreach( $this->get_items() as $item ) {
+
+ if ( $item['product_id'] > 0 ) {
+
+ $_product = $this->get_product_from_item( $item );
+
+ if ( false !== $_product && ( $_product->is_downloadable() && $_product->is_virtual() ) || ! apply_filters( 'woocommerce_order_item_needs_processing', true, $_product, $this->id ) ) {
+ $order_needs_processing = false;
+ continue;
+ }
+
+ }
+ $order_needs_processing = true;
+ break;
+ }
+ }
+
+ $new_order_status = $order_needs_processing ? 'processing' : 'completed';
+
+ $new_order_status = apply_filters( 'woocommerce_payment_complete_order_status', $new_order_status, $this->id );
+
+ $this->update_status( $new_order_status );
+
+ add_post_meta( $this->id, '_paid_date', current_time('mysql'), true );
+
+ if ( ! empty( $transaction_id ) ) {
+ add_post_meta( $this->id, '_transaction_id', $transaction_id );
+ }
+
+ $this_order = array(
+ 'ID' => $this->id,
+ 'post_date' => current_time( 'mysql', 0 ),
+ 'post_date_gmt' => current_time( 'mysql', 1 )
+ );
+ wp_update_post( $this_order );
+
+ if ( apply_filters( 'woocommerce_payment_complete_reduce_order_stock', true, $this->id ) ) {
+ $this->reduce_order_stock(); // Payment is complete so reduce stock levels
+ }
+
+ do_action( 'woocommerce_payment_complete', $this->id );
+
+ } else {
+
+ do_action( 'woocommerce_payment_complete_order_status_' . $this->get_status(), $this->id );
+
+ }
+ }
+
+
+ /**
+ * Record sales
+ *
+ * @access public
+ * @return void
+ */
+ public function record_product_sales() {
+
+ if ( 'yes' == get_post_meta( $this->id, '_recorded_sales', true ) ) {
+ return;
+ }
+
+ if ( sizeof( $this->get_items() ) > 0 ) {
+ foreach ( $this->get_items() as $item ) {
+ if ( $item['product_id'] > 0 ) {
+ $sales = (int) get_post_meta( $item['product_id'], 'total_sales', true );
+ $sales += (int) $item['qty'];
+ if ( $sales ) {
+ update_post_meta( $item['product_id'], 'total_sales', $sales );
+ }
+ }
+ }
+ }
+
+ update_post_meta( $this->id, '_recorded_sales', 'yes' );
+ }
+
+
+ /**
+ * Get coupon codes only.
+ *
+ * @access public
+ * @return array
+ */
+ public function get_used_coupons() {
+
+ $codes = array();
+ $coupons = $this->get_items( 'coupon' );
+
+ foreach ( $coupons as $item_id => $item ) {
+ $codes[] = trim( $item['name'] );
+ }
+
+ return $codes;
+ }
+
+
+ /**
+ * Increase applied coupon counts
+ *
+ * @access public
+ * @return void
+ */
+ public function increase_coupon_usage_counts() {
+
+ if ( 'yes' == get_post_meta( $this->id, '_recorded_coupon_usage_counts', true ) ) {
+ return;
+ }
+
+ if ( sizeof( $this->get_used_coupons() ) > 0 ) {
+ foreach ( $this->get_used_coupons() as $code ) {
+ if ( ! $code ) {
+ continue;
+ }
+
+ $coupon = new WC_Coupon( $code );
+
+ $used_by = $this->user_id;
+ if ( ! $used_by ) {
+ $used_by = $this->billing_email;
+ }
+
+ $coupon->inc_usage_count( $used_by );
+ }
+ }
+
+ update_post_meta( $this->id, '_recorded_coupon_usage_counts', 'yes' );
+ }
+
+
+ /**
+ * Decrease applied coupon counts
+ *
+ * @access public
+ * @return void
+ */
+ public function decrease_coupon_usage_counts() {
+
+ if ( 'yes' != get_post_meta( $this->id, '_recorded_coupon_usage_counts', true ) ) {
+ return;
+ }
+
+ if ( sizeof( $this->get_used_coupons() ) > 0 ) {
+ foreach ( $this->get_used_coupons() as $code ) {
+ if ( ! $code ) {
+ continue;
+ }
+
+ $coupon = new WC_Coupon( $code );
+
+ $used_by = $this->user_id;
+ if ( ! $used_by ) {
+ $used_by = $this->billing_email;
+ }
+
+ $coupon->dcr_usage_count( $used_by );
+ }
+ }
+
+ delete_post_meta( $this->id, '_recorded_coupon_usage_counts' );
+ }
+
+
+ /**
+ * Reduce stock levels
+ *
+ * @access public
+ * @return void
+ */
+ public function reduce_order_stock() {
+
+ if ( 'yes' == get_option('woocommerce_manage_stock') && sizeof( $this->get_items() ) > 0 ) {
+
+ // Reduce stock levels and do any other actions with products in the cart
+ foreach ( $this->get_items() as $item ) {
+
+ if ( $item['product_id'] > 0 ) {
+ $_product = $this->get_product_from_item( $item );
+
+ if ( $_product && $_product->exists() && $_product->managing_stock() ) {
+ $qty = apply_filters( 'woocommerce_order_item_quantity', $item['qty'], $this, $item );
+ $new_stock = $_product->reduce_stock( $qty );
+
+ $this->add_order_note( sprintf( __( 'Item #%s stock reduced from %s to %s.', 'woocommerce' ), $item['product_id'], $new_stock + $qty, $new_stock) );
+ $this->send_stock_notifications( $_product, $new_stock, $item['qty'] );
+ }
+
+ }
+
+ }
+
+ do_action( 'woocommerce_reduce_order_stock', $this );
+
+ $this->add_order_note( __( 'Order item stock reduced successfully.', 'woocommerce' ) );
+ }
+ }
+
+ /**
+ * send_stock_notifications function.
+ *
+ * @access public
+ * @param object $product
+ * @param int $new_stock
+ * @param int $qty_ordered
+ * @return void
+ */
+ public function send_stock_notifications( $product, $new_stock, $qty_ordered ) {
+
+ // Backorders
+ if ( $new_stock < 0 ) {
+ do_action( 'woocommerce_product_on_backorder', array( 'product' => $product, 'order_id' => $this->id, 'quantity' => $qty_ordered ) );
+ }
+
+ // stock status notifications
+ $notification_sent = false;
+
+ if ( 'yes' == get_option( 'woocommerce_notify_no_stock' ) && get_option('woocommerce_notify_no_stock_amount') >= $new_stock ) {
+ do_action( 'woocommerce_no_stock', $product );
+ $notification_sent = true;
+ }
+ if ( ! $notification_sent && 'yes' == get_option( 'woocommerce_notify_low_stock' ) && get_option('woocommerce_notify_low_stock_amount') >= $new_stock ) {
+ do_action( 'woocommerce_low_stock', $product );
+ $notification_sent = true;
+ }
+
+ }
+
+
+ /**
+ * List order notes (public) for the customer
+ *
+ * @access public
+ * @return array
+ */
+ public function get_customer_order_notes() {
+
+ $notes = array();
+
+ $args = array(
+ 'post_id' => $this->id,
+ 'approve' => 'approve',
+ 'type' => ''
+ );
+
+ remove_filter( 'comments_clauses', array( 'WC_Comments', 'exclude_order_comments' ) );
+
+ $comments = get_comments( $args );
+
+ foreach ( $comments as $comment ) {
+ $is_customer_note = get_comment_meta( $comment->comment_ID, 'is_customer_note', true );
+ $comment->comment_content = make_clickable( $comment->comment_content );
+ if ( $is_customer_note ) {
+ $notes[] = $comment;
+ }
+ }
+
+ add_filter( 'comments_clauses', array( 'WC_Comments', 'exclude_order_comments' ) );
+
+ return (array) $notes;
+
+ }
+
+ /**
+ * Checks if an order needs payment, based on status and order total
+ *
+ * @access public
+ * @return bool
+ */
+ public function needs_payment() {
+ $valid_order_statuses = apply_filters( 'woocommerce_valid_order_statuses_for_payment', array( 'pending', 'failed' ), $this );
+
+ if ( $this->has_status( $valid_order_statuses ) && $this->get_total() > 0 ) {
+ $needs_payment = true;
+ } else {
+ $needs_payment = false;
+ }
+
+ return apply_filters( 'woocommerce_order_needs_payment', $needs_payment, $this, $valid_order_statuses );
+ }
+
+ /**
+ * Checks if an order needs display the shipping address, based on shipping method
+ *
+ * @access public
+ * @return bool
+ */
+ public function needs_shipping_address() {
+ $hide = apply_filters( 'woocommerce_order_hide_shipping_address', array( 'local_pickup' ), $this );
+ $needs = false;
+
+ foreach ( $this->get_shipping_methods() as $shipping_method ) {
+ if ( ! in_array( $shipping_method['method_id'], $hide ) ) {
+ $needs = true;
+ break;
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/includes/abstracts/abstract-wc-payment-gateway.php b/includes/abstracts/abstract-wc-payment-gateway.php
index 2c5f66ac4a2..14528b697bc 100644
--- a/includes/abstracts/abstract-wc-payment-gateway.php
+++ b/includes/abstracts/abstract-wc-payment-gateway.php
@@ -100,7 +100,7 @@ abstract class WC_Payment_Gateway extends WC_Settings_API {
// Gets order total from "pay for order" page.
if ( 0 < $order_id ) {
- $order = new WC_Order( $order_id );
+ $order = get_order( $order_id );
$total = (float) $order->get_total();
// Gets order total from cart/checkout.
diff --git a/includes/admin/class-wc-admin-post-types.php b/includes/admin/class-wc-admin-post-types.php
index 7710ed29acc..16300f3a56d 100644
--- a/includes/admin/class-wc-admin-post-types.php
+++ b/includes/admin/class-wc-admin-post-types.php
@@ -439,7 +439,7 @@ class WC_Admin_Post_Types {
global $post, $woocommerce, $the_order;
if ( empty( $the_order ) || $the_order->id != $post->ID ) {
- $the_order = new WC_Order( $post->ID );
+ $the_order = get_order( $post->ID );
}
switch ( $column ) {
@@ -1180,7 +1180,7 @@ class WC_Admin_Post_Types {
$post_ids = array_map( 'absint', (array) $_REQUEST['post'] );
foreach ( $post_ids as $post_id ) {
- $order = new WC_Order( $post_id );
+ $order = get_order( $post_id );
$order->update_status( $new_status, __( 'Order status changed by bulk edit:', 'woocommerce' ) );
$changed++;
}
@@ -2015,7 +2015,7 @@ class WC_Admin_Post_Types {
$existing_permissions = $wpdb->get_results( $wpdb->prepare( "SELECT * from {$wpdb->prefix}woocommerce_downloadable_product_permissions WHERE product_id = %d GROUP BY order_id", $product_id ) );
foreach ( $existing_permissions as $existing_permission ) {
- $order = new WC_Order( $existing_permission->order_id );
+ $order = get_order( $existing_permission->order_id );
if ( $order->id ) {
// Remove permissions
diff --git a/includes/admin/meta-boxes/class-wc-meta-box-order-actions.php b/includes/admin/meta-boxes/class-wc-meta-box-order-actions.php
index 670944a9b01..28d60351479 100644
--- a/includes/admin/meta-boxes/class-wc-meta-box-order-actions.php
+++ b/includes/admin/meta-boxes/class-wc-meta-box-order-actions.php
@@ -21,7 +21,7 @@ class WC_Meta_Box_Order_Actions {
global $theorder;
if ( ! is_object( $theorder ) )
- $theorder = new WC_Order( $post->ID );
+ $theorder = get_order( $post->ID );
$order = $theorder;
?>
@@ -82,7 +82,7 @@ class WC_Meta_Box_Order_Actions {
*/
public static function save( $post_id, $post ) {
// Order data saved, now get it so we can manipulate status
- $order = new WC_Order( $post_id );
+ $order = get_order( $post_id );
// Handle button actions
if ( ! empty( $_POST['wc_order_action'] ) ) {
diff --git a/includes/admin/meta-boxes/class-wc-meta-box-order-data.php b/includes/admin/meta-boxes/class-wc-meta-box-order-data.php
index d10ba27e443..828722e391d 100644
--- a/includes/admin/meta-boxes/class-wc-meta-box-order-data.php
+++ b/includes/admin/meta-boxes/class-wc-meta-box-order-data.php
@@ -133,7 +133,7 @@ class WC_Meta_Box_Order_Data {
global $theorder;
if ( ! is_object( $theorder ) ) {
- $theorder = new WC_Order( $post->ID );
+ $theorder = get_order( $post->ID );
}
$order = $theorder;
@@ -441,7 +441,7 @@ class WC_Meta_Box_Order_Data {
$wpdb->query( $wpdb->prepare( "UPDATE $wpdb->posts SET post_date = %s, post_date_gmt = %s WHERE ID = %s", $date, get_gmt_from_date( $date ), $post_id ) );
// Order data saved, now get it so we can manipulate status
- $order = new WC_Order( $post_id );
+ $order = get_order( $post_id );
// Order status
$order->update_status( $_POST['order_status'] );
diff --git a/includes/admin/meta-boxes/class-wc-meta-box-order-items.php b/includes/admin/meta-boxes/class-wc-meta-box-order-items.php
index 254f9762072..cc250e0e87e 100644
--- a/includes/admin/meta-boxes/class-wc-meta-box-order-items.php
+++ b/includes/admin/meta-boxes/class-wc-meta-box-order-items.php
@@ -21,7 +21,7 @@ class WC_Meta_Box_Order_Items {
global $thepostid, $theorder;
if ( ! is_object( $theorder ) )
- $theorder = new WC_Order( $thepostid );
+ $theorder = get_order( $thepostid );
$order = $theorder;
?>
diff --git a/includes/admin/meta-boxes/class-wc-meta-box-order-totals.php b/includes/admin/meta-boxes/class-wc-meta-box-order-totals.php
index ac3f5a84de1..a5b2aacac1f 100644
--- a/includes/admin/meta-boxes/class-wc-meta-box-order-totals.php
+++ b/includes/admin/meta-boxes/class-wc-meta-box-order-totals.php
@@ -21,7 +21,7 @@ class WC_Meta_Box_Order_Totals {
global $theorder, $wpdb, $post;
if ( ! is_object( $theorder ) )
- $theorder = new WC_Order( $post->ID );
+ $theorder = get_order( $post->ID );
$order = $theorder;
diff --git a/includes/admin/reports/class-wc-report-customer-list.php b/includes/admin/reports/class-wc-report-customer-list.php
index 595d38115fc..7636fa8ea8e 100644
--- a/includes/admin/reports/class-wc-report-customer-list.php
+++ b/includes/admin/reports/class-wc-report-customer-list.php
@@ -163,7 +163,7 @@ class WC_Report_Customer_List extends WP_List_Table {
) );
if ( $order_ids ) {
- $order = new WC_Order( $order_ids[0] );
+ $order = get_order( $order_ids[0] );
echo '' . $order->get_order_number() . ' – ' . date_i18n( get_option( 'date_format' ), strtotime( $order->order_date ) );
} else echo '-';
diff --git a/includes/api/class-wc-api-orders.php b/includes/api/class-wc-api-orders.php
index 4f69648650a..d7860538a62 100644
--- a/includes/api/class-wc-api-orders.php
+++ b/includes/api/class-wc-api-orders.php
@@ -106,7 +106,7 @@ class WC_API_Orders extends WC_API_Resource {
if ( is_wp_error( $id ) )
return $id;
- $order = new WC_Order( $id );
+ $order = get_order( $id );
$order_post = get_post( $id );
@@ -275,7 +275,7 @@ class WC_API_Orders extends WC_API_Resource {
if ( is_wp_error( $id ) )
return $id;
- $order = new WC_Order( $id );
+ $order = get_order( $id );
if ( ! empty( $data['status'] ) ) {
diff --git a/includes/class-wc-ajax.php b/includes/class-wc-ajax.php
index bacc884e0c8..8fae68c7ad9 100644
--- a/includes/class-wc-ajax.php
+++ b/includes/class-wc-ajax.php
@@ -351,7 +351,7 @@ class WC_AJAX {
die();
}
- $order = new WC_Order( $order_id );
+ $order = get_order( $order_id );
$order->update_status( 'completed' );
wp_safe_redirect( wp_get_referer() );
@@ -376,7 +376,7 @@ class WC_AJAX {
die();
}
- $order = new WC_Order( $order_id );
+ $order = get_order( $order_id );
$order->update_status( 'processing' );
wp_safe_redirect( wp_get_referer() );
@@ -847,7 +847,7 @@ class WC_AJAX {
$product_ids = $_POST['product_ids'];
$loop = intval( $_POST['loop'] );
$file_counter = 0;
- $order = new WC_Order( $order_id );
+ $order = get_order( $order_id );
if ( ! is_array( $product_ids ) ) {
$product_ids = array( $product_ids );
@@ -936,7 +936,7 @@ class WC_AJAX {
}
$_product = get_product( $post->ID );
- $order = new WC_Order( $order_id );
+ $order = get_order( $order_id );
$class = 'new_row';
// Set values
@@ -996,7 +996,7 @@ class WC_AJAX {
check_ajax_referer( 'order-item', 'security' );
$order_id = absint( $_POST['order_id'] );
- $order = new WC_Order( $order_id );
+ $order = get_order( $order_id );
// Add line item
$item_id = wc_add_order_item( $order_id, array(
@@ -1043,7 +1043,7 @@ class WC_AJAX {
$order_id = absint( $_POST['order_id'] );
$order_item_ids = isset( $_POST['order_item_ids'] ) ? $_POST['order_item_ids'] : array();
$order_item_qty = isset( $_POST['order_item_qty'] ) ? $_POST['order_item_qty'] : array();
- $order = new WC_Order( $order_id );
+ $order = get_order( $order_id );
$order_items = $order->get_items();
$return = array();
@@ -1089,7 +1089,7 @@ class WC_AJAX {
$order_id = absint( $_POST['order_id'] );
$order_item_ids = isset( $_POST['order_item_ids'] ) ? $_POST['order_item_ids'] : array();
$order_item_qty = isset( $_POST['order_item_qty'] ) ? $_POST['order_item_qty'] : array();
- $order = new WC_Order( $order_id );
+ $order = get_order( $order_id );
$order_items = $order->get_items();
$return = array();
@@ -1169,7 +1169,7 @@ class WC_AJAX {
$taxes = $tax_rows = $item_taxes = $shipping_taxes = array();
$order_id = absint( $_POST['order_id'] );
- $order = new WC_Order( $order_id );
+ $order = get_order( $order_id );
$country = strtoupper( esc_attr( $_POST['country'] ) );
$state = strtoupper( esc_attr( $_POST['state'] ) );
$postcode = strtoupper( esc_attr( $_POST['postcode'] ) );
@@ -1285,7 +1285,7 @@ class WC_AJAX {
$is_customer_note = $note_type == 'customer' ? 1 : 0;
if ( $post_id > 0 ) {
- $order = new WC_Order( $post_id );
+ $order = get_order( $post_id );
$comment_id = $order->add_order_note( $note, $is_customer_note );
echo '
' . __( 'Go to homepage', 'woocommerce' ) . '', '', array( 'response' => 404 ) );
diff --git a/includes/class-wc-emails.php b/includes/class-wc-emails.php
index da8bce26d96..01d0ba5bfc5 100644
--- a/includes/class-wc-emails.php
+++ b/includes/class-wc-emails.php
@@ -412,7 +412,7 @@ class WC_Emails {
else
$title = sprintf(__( 'Product #%s - %s', 'woocommerce' ), $product->id, get_the_title($product->id)) . $sku;
- $order = new WC_Order( $order_id );
+ $order = get_order( $order_id );
$message = sprintf(__( '%s units of %s have been backordered in order %s.', 'woocommerce' ), $quantity, $title, $order->get_order_number() );
// CC, BCC, additional headers
diff --git a/includes/class-wc-form-handler.php b/includes/class-wc-form-handler.php
index bd8b3ced679..4216b28e172 100755
--- a/includes/class-wc-form-handler.php
+++ b/includes/class-wc-form-handler.php
@@ -264,7 +264,7 @@ class WC_Form_Handler {
// Pay for existing order
$order_key = $_GET['key'];
$order_id = absint( $wp->query_vars['order-pay'] );
- $order = new WC_Order( $order_id );
+ $order = get_order( $order_id );
$valid_order_statuses = apply_filters( 'woocommerce_valid_order_statuses_for_payment', array( 'pending', 'failed' ), $order );
@@ -462,7 +462,7 @@ class WC_Form_Handler {
WC()->cart->empty_cart();
// Load the previous order - Stop if the order does not exist
- $order = new WC_Order( absint( $_GET['order_again'] ) );
+ $order = get_order( absint( $_GET['order_again'] ) );
if ( empty( $order->id ) ) {
return;
@@ -519,7 +519,7 @@ class WC_Form_Handler {
$order_key = $_GET['order'];
$order_id = absint( $_GET['order_id'] );
- $order = new WC_Order( $order_id );
+ $order = get_order( $order_id );
$user_can_cancel = current_user_can( 'cancel_order', $order_id );
$order_can_cancel = $order->has_status( apply_filters( 'woocommerce_valid_order_statuses_for_cancel', array( 'pending', 'failed' ) ) );
$redirect = $_GET['redirect'];
diff --git a/includes/class-wc-order-factory.php b/includes/class-wc-order-factory.php
new file mode 100644
index 00000000000..c4d28f74e3b
--- /dev/null
+++ b/includes/class-wc-order-factory.php
@@ -0,0 +1,57 @@
+ID );
+ $post_type = $the_order->post_type;
+ }
+
+ if ( 'shop_order' == $post_type ) {
+ $classname = 'WC_Order';
+ $order_type = 'simple';
+ } else {
+ $classname = false;
+ $order_type = false;
+ }
+
+ // Filter classname so that the class can be overridden if extended.
+ $classname = apply_filters( 'woocommerce_order_class', $classname, $order_type, $post_type, $order_id );
+
+ if ( ! class_exists( $classname ) )
+ $classname = 'WC_Order';
+
+ return new $classname( $the_order, $args );
+ }
+}
\ No newline at end of file
diff --git a/includes/class-wc-order.php b/includes/class-wc-order.php
index 408a214ad38..07a114430c0 100644
--- a/includes/class-wc-order.php
+++ b/includes/class-wc-order.php
@@ -1,2078 +1,18 @@
prices_include_tax = get_option('woocommerce_prices_include_tax') == 'yes' ? true : false;
- $this->tax_display_cart = get_option( 'woocommerce_tax_display_cart' );
-
- $this->display_totals_ex_tax = $this->tax_display_cart == 'excl' ? true : false;
- $this->display_cart_ex_tax = $this->tax_display_cart == 'excl' ? true : false;
-
- if ( $id > 0 ) {
- $this->get_order( $id );
- }
- }
-
- /**
- * Remove all line items (products, coupons, shipping, taxes) from the order.
- */
- public function remove_order_items( $type = null ) {
- global $wpdb;
-
- if ( $type ) {
- $wpdb->query( $wpdb->prepare( "DELETE FROM {$wpdb->prefix}woocommerce_order_itemmeta WHERE order_item_id IN ( SELECT order_item_id FROM {$wpdb->prefix}woocommerce_order_items WHERE order_id = %d AND order_item_type = %s )", $this->id, $type ) );
- $wpdb->query( $wpdb->prepare( "DELETE FROM {$wpdb->prefix}woocommerce_order_items WHERE order_id = %d AND order_item_type = %s", $this->id, $type ) );
- } else {
- $wpdb->query( $wpdb->prepare( "DELETE FROM {$wpdb->prefix}woocommerce_order_itemmeta WHERE order_item_id IN ( SELECT order_item_id FROM {$wpdb->prefix}woocommerce_order_items WHERE order_id = %d )", $this->id ) );
- $wpdb->query( $wpdb->prepare( "DELETE FROM {$wpdb->prefix}woocommerce_order_items WHERE order_id = %d", $this->id ) );
- }
- }
-
- /**
- * Set the payment method for the order
- * @param WC_Payment_Gateway
- */
- public function set_payment_method( $payment_method ) {
- if ( is_object( $payment_method ) ) {
- update_post_meta( $this->id, '_payment_method', $payment_method->id );
- update_post_meta( $this->id, '_payment_method_title', $payment_method->get_title() );
- }
- }
-
- /**
- * Set the customer address
- * @param array $address Address data
- * @param string $type billing or shipping
- */
- public function set_address( $address, $type = 'billing' ) {
- foreach( $address as $key => $value ) {
- update_post_meta( $this->id, "_{$type}_" . $key, $value );
- }
- }
-
- /**
- * Add a product line item to the order
- * @param WC_Product $item
- * @param int $qty Line item quantity
- * @param array args
- * @return int|bool Item ID or false
- */
- public function add_product( $product, $qty = 1, $args = array() ) {
- $default_args = array(
- 'variation' => array(),
- 'totals' => array()
- );
-
- $args = wp_parse_args( $args, $default_args );
- $item_id = wc_add_order_item( $this->id, array(
- 'order_item_name' => $product->get_title(),
- 'order_item_type' => 'line_item'
- ) );
-
- if ( ! $item_id ) {
- return false;
- }
-
- wc_add_order_item_meta( $item_id, '_qty', wc_stock_amount( $qty ) );
- wc_add_order_item_meta( $item_id, '_tax_class', $product->get_tax_class() );
- wc_add_order_item_meta( $item_id, '_product_id', $product->id );
- wc_add_order_item_meta( $item_id, '_variation_id', isset( $product->variation_id ) ? $product->variation_id : 0 );
-
- // Set line item totals, either passed in or from the product
- 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 ) ) );
- 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 ) ) );
- wc_add_order_item_meta( $item_id, '_line_subtotal_tax', wc_format_decimal( isset( $args['totals']['subtotal_tax'] ) ? $args['totals']['subtotal_tax'] : 0 ) );
- wc_add_order_item_meta( $item_id, '_line_tax', wc_format_decimal( isset( $args['totals']['tax'] ) ? $args['totals']['tax'] : 0 ) );
-
- // Add variation meta
- foreach ( $args['variation'] as $key => $value ) {
- wc_add_order_item_meta( $item_id, str_replace( 'attribute_', '', $key ), $value );
- }
-
- // Backorders
- if ( $product->backorders_require_notification() && $product->is_on_backorder( $qty ) ) {
- wc_add_order_item_meta( $item_id, apply_filters( 'woocommerce_backordered_item_meta_name', __( 'Backordered', 'woocommerce' ) ), $qty - max( 0, $product->get_total_stock() ) );
- }
-
- do_action( 'woocommerce_order_add_product', $this->id, $item_id, $product, $qty, $args );
-
- return $item_id;
- }
-
- /**
- * Add coupon code to the order
- * @param string $code
- * @param float $discount_amount
- * @return int|bool Item ID or false
- */
- public function add_coupon( $code, $discount_amount = 0 ) {
- $item_id = wc_add_order_item( $this->id, array(
- 'order_item_name' => $code,
- 'order_item_type' => 'coupon'
- ) );
-
- if ( ! $item_id ) {
- return false;
- }
-
- wc_add_order_item_meta( $item_id, 'discount_amount', $discount_amount );
-
- do_action( 'woocommerce_order_add_coupon', $this->id, $item_id, $code, $discount_amount );
-
- return $item_id;
- }
-
- /**
- * Add a tax row to the order
- * @param int tax_rate_id
- * @return int|bool Item ID or false
- */
- public function add_tax( $tax_rate_id, $tax_amount = 0, $shipping_tax_amount = 0 ) {
- $code = WC_Tax::get_rate_code( $tax_rate_id );
-
- if ( ! $code ) {
- return false;
- }
-
- $item_id = wc_add_order_item( $this->id, array(
- 'order_item_name' => $code,
- 'order_item_type' => 'tax'
- ) );
-
- if ( ! $item_id ) {
- return false;
- }
-
- wc_add_order_item_meta( $item_id, 'rate_id', $tax_rate_id );
- wc_add_order_item_meta( $item_id, 'label', WC_Tax::get_rate_label( $tax_rate_id ) );
- wc_add_order_item_meta( $item_id, 'compound', WC_Tax::is_compound( $tax_rate_id ) ? 1 : 0 );
- wc_add_order_item_meta( $item_id, 'tax_amount', wc_format_decimal( $tax_amount ) );
- wc_add_order_item_meta( $item_id, 'shipping_tax_amount', wc_format_decimal( $shipping_tax_amount ) );
-
- do_action( 'woocommerce_order_add_tax', $this->id, $item_id, $tax_rate_id, $tax_amount, $shipping_tax_amount );
-
- return $item_id;
- }
-
- /**
- * Add a shipping row to the order
- * @param WC_Shipping_Rate shipping_rate
- * @return int|bool Item ID or false
- */
- public function add_shipping( $shipping_rate ) {
- $item_id = wc_add_order_item( $this->id, array(
- 'order_item_name' => $shipping_rate->label,
- 'order_item_type' => 'shipping'
- ) );
-
- if ( ! $item_id ) {
- return false;
- }
-
- wc_add_order_item_meta( $item_id, 'method_id', $shipping_rate->id );
- wc_add_order_item_meta( $item_id, 'cost', wc_format_decimal( $shipping_rate->cost ) );
-
- do_action( 'woocommerce_order_add_shipping', $this->id, $item_id, $shipping_rate );
-
- // Update total
- $this->set_total( $this->order_shipping + wc_format_decimal( $shipping_rate->cost ), 'shipping' );
-
- return $item_id;
- }
-
- /**
- * Add a fee to the order
- * @param object $fee
- * @return int|bool Item ID or false
- */
- public function add_fee( $fee ) {
- $item_id = wc_add_order_item( $this->id, array(
- 'order_item_name' => $fee->name,
- 'order_item_type' => 'fee'
- ) );
-
- if ( ! $item_id ) {
- return false;
- }
-
- if ( $fee->taxable ) {
- wc_add_order_item_meta( $item_id, '_tax_class', $fee->tax_class );
- } else {
- wc_add_order_item_meta( $item_id, '_tax_class', '0' );
- }
-
- wc_add_order_item_meta( $item_id, '_line_total', wc_format_decimal( $fee->amount ) );
- wc_add_order_item_meta( $item_id, '_line_tax', wc_format_decimal( $fee->tax ) );
-
- do_action( 'woocommerce_order_add_fee', $this->id, $item_id, $fee );
-
- return $item_id;
- }
-
- /**
- * Set an order total
- * @param float $amount
- * @param string $total_type
- */
- public function set_total( $amount, $total_type = 'total' ) {
- if ( ! in_array( $total_type, array( 'shipping', 'order_discount', 'tax', 'shipping_tax', 'total', 'cart_discount' ) ) ) {
- return false;
- }
- switch ( $total_type ) {
- case 'total' :
- $key = '_order_total';
- $amount = wc_format_decimal( $amount, get_option( 'woocommerce_price_num_decimals' ) );
- break;
- case 'order_discount' :
- case 'cart_discount' :
- $key = '_' . $total_type;
- $amount = wc_format_decimal( $amount );
- break;
- default :
- $key = '_order_' . $total_type;
- $amount = wc_format_decimal( $amount );
- break;
- }
- update_post_meta( $this->id, $key, $amount );
- }
-
- /**
- * Calculate taxes for all line items and shipping, and store the totals and tax rows.
- *
- * Will use the base country unless customer addresses are set.
- *
- * @return bool success or fail
- */
- public function calculate_taxes() {
- $shipping_tax_total = 0;
- $tax_total = 0;
- $taxes = array();
- $tax_based_on = get_option( 'woocommerce_tax_based_on' );
-
- if ( 'base' === $tax_based_on ) {
- $default = get_option( 'woocommerce_default_country' );
- $postcode = '';
- $city = '';
- if ( strstr( $default, ':' ) ) {
- list( $country, $state ) = explode( ':', $default );
- } else {
- $country = $default;
- $state = '';
- }
- } elseif ( 'billing' === $tax_based_on ) {
- $country = $this->billing_country;
- $state = $this->billing_state;
- $postcode = $this->billing_postcode;
- $city = $this->billing_city;
- } else {
- $country = $this->shipping_country;
- $state = $this->shipping_state;
- $postcode = $this->shipping_postcode;
- $city = $this->shipping_city;
- }
-
- // Get items
- foreach ( $this->get_items( array( 'line_item', 'fee' ) ) as $item_id => $item ) {
- $product = $this->get_product_from_item( $item );
- $line_total = isset( $item['line_total'] ) ? $item['line_total'] : 0;
- $line_subtotal = isset( $item['line_subtotal'] ) ? $item['line_subtotal'] : 0;
- $tax_class = $item['tax_class'];
- $item_tax_status = $product ? $product->get_tax_status() : 'taxable';
-
- if ( '0' !== $tax_class && 'taxable' === $item_tax_status ) {
- $tax_rates = WC_Tax::find_rates( array(
- 'country' => $country,
- 'state' => $state,
- 'postcode' => $postcode,
- 'city' => $city,
- 'tax_class' => $tax_class
- ) );
- $line_subtotal_taxes = WC_Tax::calc_tax( $line_subtotal, $tax_rates, false );
- $line_taxes = WC_Tax::calc_tax( $line_total, $tax_rates, false );
- $line_subtotal_tax = max( 0, array_sum( $line_subtotal_taxes ) );
- $line_tax = max( 0, array_sum( $line_taxes ) );
- $tax_total += $line_tax;
-
- wc_update_order_item_meta( $item_id, '_line_subtotal_tax', wc_format_decimal( $line_subtotal_tax ) );
- wc_update_order_item_meta( $item_id, '_line_tax', wc_format_decimal( $line_tax ) );
-
- // Sum the item taxes
- foreach ( array_keys( $taxes + $line_taxes ) as $key ) {
- $taxes[ $key ] = ( isset( $line_taxes[ $key ] ) ? $line_taxes[ $key ] : 0 ) + ( isset( $taxes[ $key ] ) ? $taxes[ $key ] : 0 );
- }
- }
- }
-
- // Now calculate shipping tax
- $matched_tax_rates = array();
- $tax_rates = WC_Tax::find_rates( array(
- 'country' => $country,
- 'state' => $state,
- 'postcode' => $postcode,
- 'city' => $city,
- 'tax_class' => ''
- ) );
-
- if ( $tax_rates ) {
- foreach ( $tax_rates as $key => $rate ) {
- if ( isset( $rate['shipping'] ) && 'yes' === $rate['shipping'] ) {
- $matched_tax_rates[ $key ] = $rate;
- }
- }
- }
-
- $shipping_taxes = WC_Tax::calc_shipping_tax( $this->order_shipping, $matched_tax_rates );
- $shipping_tax_total = WC_Tax::round( array_sum( $shipping_taxes ) );
-
- // Save tax totals
- $this->set_total( $shipping_tax_total, 'shipping_tax' );
- $this->set_total( $tax_total, 'tax' );
-
- // Tax rows
- $this->remove_order_items( 'tax' );
-
- // Now merge to keep tax rows
- foreach ( array_keys( $taxes + $shipping_taxes ) as $tax_rate_id ) {
- $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 );
- }
-
- return true;
- }
-
- /**
- * Calculate totals by looking at the contents of the order. Stores the totals and returns the orders final total.
- *
- * @return $total calculated grand total
- */
- public function calculate_totals() {
- $cart_subtotal = 0;
- $cart_total = 0;
- $fee_total = 0;
-
- $this->calculate_taxes();
-
- foreach ( $this->get_items() as $item ) {
- $cart_subtotal += wc_format_decimal( isset( $item['line_subtotal'] ) ? $item['line_subtotal'] : 0 );
- $cart_total += wc_format_decimal( isset( $item['line_total'] ) ? $item['line_total'] : 0 );
- }
-
- foreach ( $this->get_fees() as $item ) {
- $fee_total += $item['line_total'];
- }
-
- $grand_total = round( $cart_total + $fee_total + $this->get_total_shipping() - $this->get_order_discount() + $this->get_cart_tax() + $this->get_shipping_tax(), absint( get_option( 'woocommerce_price_num_decimals' ) ) );
-
- $this->set_total( $cart_subtotal - $cart_total, 'cart_discount' );
- $this->set_total( $grand_total, 'total' );
-
- return $grand_total;
- }
-
- /**
- * Gets an order from the database.
- *
- * @access public
- * @param int $id (default: 0)
- * @return bool
- */
- public function get_order( $id = 0 ) {
- if ( ! $id ) {
- return false;
- }
- if ( $result = get_post( $id ) ) {
- $this->populate( $result );
- return true;
- }
- return false;
- }
-
- /**
- * Populates an order from the loaded post data.
- *
- * @access public
- * @param mixed $result
- * @return void
- */
- public function populate( $result ) {
- // Standard post data
- $this->id = $result->ID;
- $this->order_date = $result->post_date;
- $this->modified_date = $result->post_modified;
- $this->customer_message = $result->post_excerpt;
- $this->customer_note = $result->post_excerpt;
- $this->post_status = $result->post_status;
-
- // Billing email cam default to user if set
- if ( empty( $this->billing_email ) && ! empty( $this->customer_user ) ) {
- $user = get_user_by( 'id', $this->customer_user );
- $this->billing_email = $user->user_email;
- }
- }
-
- /**
- * __isset function.
- *
- * @access public
- * @param mixed $key
- * @return bool
- */
- public function __isset( $key ) {
- if ( ! $this->id ) {
- return false;
- }
- return metadata_exists( 'post', $this->id, '_' . $key );
- }
-
- /**
- * __get function.
- *
- * @access public
- * @param mixed $key
- * @return mixed
- */
- public function __get( $key ) {
- // Get values or default if not set
- if ( 'completed_date' === $key ) {
- $value = ( $value = get_post_meta( $this->id, '_completed_date', true ) ) ? $value : $this->modified_date;
- } elseif ( 'user_id' === $key ) {
- $value = ( $value = get_post_meta( $this->id, '_customer_user', true ) ) ? absint( $value ) : '';
- } elseif ( 'status' === $key ) {
- $value = $this->get_status();
- } else {
- $value = get_post_meta( $this->id, '_' . $key, true );
- }
- return $value;
- }
-
- /**
- * Return the order statuses without wc- internal prefix
- * @return string
- */
- public function get_status() {
- return apply_filters( 'woocommerce_order_get_status', 'wc-' === substr( $this->post_status, 0, 3 ) ? substr( $this->post_status, 3 ) : $this->post_status, $this );
- }
-
- /**
- * Checks the order status against a passed in status.
- *
- * @access public
- * @param mixed $type Array or string of types
- * @return bool
- */
- public function has_status( $status ) {
- return apply_filters( 'woocommerce_order_has_status', ( is_array( $status ) && in_array( $this->get_status(), $status ) ) || $this->get_status() === $status ? true : false, $this, $status );
- }
-
- /**
- * Gets the user ID associated with the order. Guests are 0.
- * @since 2.2
- * @return int|false
- */
- public function get_user_id() {
- return $this->customer_user ? $this->customer_user : 0;
- }
-
- /**
- * Get the user associated with the order. False for guests.
- * @since 2.2
- * @return WP_User|false
- */
- public function get_user() {
- return $user_id = $this->get_user_id() ? get_user_by( 'id', $user_id ) : false;
- }
-
- /**
- * Check if an order key is valid.
- *
- * @access public
- * @param mixed $key
- * @return bool
- */
- public function key_is_valid( $key ) {
- if ( $key == $this->order_key ) {
- return true;
- }
- return false;
- }
-
- /**
- * get_order_number function.
- *
- * Gets the order number for display (by default, order ID)
- *
- * @access public
- * @return string
- */
- public function get_order_number() {
- return apply_filters( 'woocommerce_order_number', _x( '#', 'hash before order number', 'woocommerce' ) . $this->id, $this );
- }
-
- /**
- * Get a formatted billing address for the order.
- *
- * @access public
- * @return string
- */
- public function get_formatted_billing_address() {
- if ( ! $this->formatted_billing_address ) {
-
- // Formatted Addresses
- $address = apply_filters( 'woocommerce_order_formatted_billing_address', array(
- 'first_name' => $this->billing_first_name,
- 'last_name' => $this->billing_last_name,
- 'company' => $this->billing_company,
- 'address_1' => $this->billing_address_1,
- 'address_2' => $this->billing_address_2,
- 'city' => $this->billing_city,
- 'state' => $this->billing_state,
- 'postcode' => $this->billing_postcode,
- 'country' => $this->billing_country
- ), $this );
-
- $this->formatted_billing_address = WC()->countries->get_formatted_address( $address );
- }
- return $this->formatted_billing_address;
- }
-
- /**
- * Get the billing address in an array.
- *
- * @access public
- * @return string
- */
- public function get_billing_address() {
- if ( ! $this->billing_address ) {
- // Formatted Addresses
- $address = array(
- 'address_1' => $this->billing_address_1,
- 'address_2' => $this->billing_address_2,
- 'city' => $this->billing_city,
- 'state' => $this->billing_state,
- 'postcode' => $this->billing_postcode,
- 'country' => $this->billing_country
- );
- $joined_address = array();
- foreach ( $address as $part ) {
- if ( ! empty( $part ) ) {
- $joined_address[] = $part;
- }
- }
- $this->billing_address = implode( ', ', $joined_address );
- }
- return $this->billing_address;
- }
-
- /**
- * Get a formatted shipping address for the order.
- *
- * @access public
- * @return string
- */
- public function get_formatted_shipping_address() {
- if ( ! $this->formatted_shipping_address ) {
- if ( $this->shipping_address_1 ) {
-
- // Formatted Addresses
- $address = apply_filters( 'woocommerce_order_formatted_shipping_address', array(
- 'first_name' => $this->shipping_first_name,
- 'last_name' => $this->shipping_last_name,
- 'company' => $this->shipping_company,
- 'address_1' => $this->shipping_address_1,
- 'address_2' => $this->shipping_address_2,
- 'city' => $this->shipping_city,
- 'state' => $this->shipping_state,
- 'postcode' => $this->shipping_postcode,
- 'country' => $this->shipping_country
- ), $this );
-
- $this->formatted_shipping_address = WC()->countries->get_formatted_address( $address );
- }
- }
- return $this->formatted_shipping_address;
- }
-
- /**
- * Get the shipping address in an array.
- *
- * @access public
- * @return array
- */
- public function get_shipping_address() {
- if ( ! $this->shipping_address ) {
- if ( $this->shipping_address_1 ) {
- // Formatted Addresses
- $address = array(
- 'address_1' => $this->shipping_address_1,
- 'address_2' => $this->shipping_address_2,
- 'city' => $this->shipping_city,
- 'state' => $this->shipping_state,
- 'postcode' => $this->shipping_postcode,
- 'country' => $this->shipping_country
- );
- $joined_address = array();
- foreach ( $address as $part ) {
- if ( ! empty( $part ) ) {
- $joined_address[] = $part;
- }
- }
- $this->shipping_address = implode( ', ', $joined_address );
- }
- }
- return $this->shipping_address;
- }
-
- /**
- * Return an array of items/products within this order.
- *
- * @access public
- * @param string|array $type Types of line items to get (array or string)
- * @return array
- */
- public function get_items( $type = '' ) {
- global $wpdb;
-
- if ( empty( $type ) ) {
- $type = array( 'line_item' );
- }
-
- if ( ! is_array( $type ) ) {
- $type = array( $type );
- }
-
- $type = array_map( 'esc_attr', $type );
-
- $line_items = $wpdb->get_results( $wpdb->prepare( "
- SELECT order_item_id, order_item_name, order_item_type
- FROM {$wpdb->prefix}woocommerce_order_items
- WHERE order_id = %d
- AND order_item_type IN ( '" . implode( "','", $type ) . "' )
- ORDER BY order_item_id
- ", $this->id ) );
-
- $items = array();
-
- // Reserved meta keys
- $reserved_item_meta_keys = array(
- 'name',
- 'type',
- 'item_meta',
- 'qty',
- 'tax_class',
- 'product_id',
- 'variation_id',
- 'line_subtotal',
- 'line_total',
- 'line_tax',
- 'line_subtotal_tax'
- );
-
- // Loop items
- foreach ( $line_items as $item ) {
- // Place line item into array to return
- $items[ $item->order_item_id ]['name'] = $item->order_item_name;
- $items[ $item->order_item_id ]['type'] = $item->order_item_type;
- $items[ $item->order_item_id ]['item_meta'] = $this->get_item_meta( $item->order_item_id );
-
- // Expand meta data into the array
- foreach ( $items[ $item->order_item_id ]['item_meta'] as $name => $value ) {
- if ( in_array( $name, $reserved_item_meta_keys ) ) {
- continue;
- }
- if ( '_' === substr( $name, 0, 1 ) ) {
- $items[ $item->order_item_id ][ substr( $name, 1 ) ] = $value[0];
- } elseif ( ! in_array( $name, $reserved_item_meta_keys ) ) {
- $items[ $item->order_item_id ][ $name ] = $value[0];
- }
- }
- }
-
- return apply_filters( 'woocommerce_order_get_items', $items, $this );
- }
-
- /**
- * Gets order total - formatted for display.
- *
- * @access public
- * @return string
- */
- public function get_item_count( $type = '' ) {
- if ( empty( $type ) ) {
- $type = array( 'line_item' );
- }
-
- if ( ! is_array( $type ) ) {
- $type = array( $type );
- }
-
- $items = $this->get_items( $type );
-
- $count = 0;
-
- foreach ( $items as $item ) {
- if ( ! empty( $item['qty'] ) ) {
- $count += $item['qty'];
- } else {
- $count ++;
- }
- }
-
- return apply_filters( 'woocommerce_get_item_count', $count, $type, $this );
- }
-
- /**
- * Return an array of fees within this order.
- *
- * @access public
- * @return array
- */
- public function get_fees() {
- return $this->get_items( 'fee' );
- }
-
- /**
- * Return an array of taxes within this order.
- *
- * @access public
- * @return array
- */
- public function get_taxes() {
- return $this->get_items( 'tax' );
- }
-
- /**
- * Return an array of shipping costs within this order.
- *
- * @return array
- */
- public function get_shipping_methods() {
- return $this->get_items( 'shipping' );
- }
-
- /**
- * Check whether this order has a specific shipping method or not
- * @param string $method_id
- * @return bool
- */
- public function has_shipping_method( $method_id ) {
- $shipping_methods = $this->get_shipping_methods();
- $has_method = false;
-
- if ( ! $shipping_methods ) {
- return false;
- }
-
- foreach ( $shipping_methods as $shipping_method ) {
- if ( $shipping_method['method_id'] == $method_id ) {
- $has_method = true;
- }
- }
-
- return $has_method;
- }
-
- /**
- * Get taxes, merged by code, formatted ready for output.
- *
- * @access public
- * @return array
- */
- public function get_tax_totals() {
- $taxes = $this->get_items( 'tax' );
- $tax_totals = array();
-
- foreach ( $taxes as $key => $tax ) {
-
- $code = $tax[ 'name' ];
-
- if ( ! isset( $tax_totals[ $code ] ) ) {
- $tax_totals[ $code ] = new stdClass();
- $tax_totals[ $code ]->amount = 0;
- }
-
- $tax_totals[ $code ]->is_compound = $tax[ 'compound' ];
- $tax_totals[ $code ]->label = isset( $tax[ 'label' ] ) ? $tax[ 'label' ] : $tax[ 'name' ];
- $tax_totals[ $code ]->amount += $tax[ 'tax_amount' ] + $tax[ 'shipping_tax_amount' ];
- $tax_totals[ $code ]->formatted_amount = wc_price( wc_round_tax_total( $tax_totals[ $code ]->amount ), array('currency' => $this->get_order_currency()) );
- }
-
- return apply_filters( 'woocommerce_order_tax_totals', $tax_totals, $this );
- }
-
- /**
- * has_meta function for order items.
- * @access public
- * @param string $order_item_id
- * @return array of meta data
- */
- public function has_meta( $order_item_id ) {
- global $wpdb;
-
- return $wpdb->get_results( $wpdb->prepare( "SELECT meta_key, meta_value, meta_id, order_item_id
- FROM {$wpdb->prefix}woocommerce_order_itemmeta WHERE order_item_id = %d
- ORDER BY meta_id", absint( $order_item_id ) ), ARRAY_A );
- }
-
- /**
- * Get order item meta.
- *
- * @access public
- * @param mixed $order_item_id
- * @param string $key (default: '')
- * @param bool $single (default: false)
- * @return array|string
- */
- public function get_item_meta( $order_item_id, $key = '', $single = false ) {
- return get_metadata( 'order_item', $order_item_id, $key, $single );
- }
-
- /** Total Getters *******************************************************/
-
- /**
- * Gets the total (product) discount amount - these are applied before tax.
- *
- * @access public
- * @return float
- */
- public function get_cart_discount() {
- return apply_filters( 'woocommerce_order_amount_cart_discount', (double) $this->cart_discount, $this );
- }
-
- /**
- * Gets the total (product) discount amount - these are applied before tax.
- *
- * @access public
- * @return float
- */
- public function get_order_discount() {
- return apply_filters( 'woocommerce_order_amount_order_discount', (double) $this->order_discount, $this );
- }
-
- /**
- * Gets the total discount amount - both kinds
- *
- * @access public
- * @return float
- */
- public function get_total_discount() {
- return apply_filters( 'woocommerce_order_amount_total_discount', $this->get_cart_discount() + $this->get_order_discount(), $this );
- }
-
- /**
- * Gets shipping tax amount.
- *
- * @access public
- * @return float
- */
- public function get_cart_tax() {
- return apply_filters( 'woocommerce_order_amount_cart_tax', (double) $this->order_tax, $this );
- }
-
- /**
- * Gets shipping tax amount.
- *
- * @access public
- * @return float
- */
- public function get_shipping_tax() {
- return apply_filters( 'woocommerce_order_amount_shipping_tax', (double) $this->order_shipping_tax, $this );
- }
-
- /**
- * Gets shipping and product tax.
- *
- * @access public
- * @return float
- */
- public function get_total_tax() {
- return apply_filters( 'woocommerce_order_amount_total_tax', wc_round_tax_total( $this->get_cart_tax() + $this->get_shipping_tax() ), $this );
- }
-
- /**
- * Gets shipping total.
- *
- * @access public
- * @return float
- */
- public function get_total_shipping() {
- return apply_filters( 'woocommerce_order_amount_total_shipping', (double) $this->order_shipping, $this );
- }
-
- /**
- * Gets order total.
- *
- * @access public
- * @return float
- */
- public function get_total() {
- return apply_filters( 'woocommerce_order_amount_total', (double) $this->order_total, $this );
- }
-
- /**
- * Get item subtotal - this is the cost before discount.
- *
- * @access public
- * @param mixed $item
- * @param bool $inc_tax (default: false)
- * @param bool $round (default: true)
- * @return float
- */
- public function get_item_subtotal( $item, $inc_tax = false, $round = true ) {
- if ( $inc_tax ) {
- $price = ( $item['line_subtotal'] + $item['line_subtotal_tax'] ) / max( 1, $item['qty'] );
- } else {
- $price = ( $item['line_subtotal'] / $item['qty'] );
- }
-
- $price = $round ? round( $price, 2 ) : $price;
-
- return apply_filters( 'woocommerce_order_amount_item_subtotal', $price, $this, $item );
- }
-
- /**
- * Get line subtotal - this is the cost before discount.
- *
- * @access public
- * @param mixed $item
- * @param bool $inc_tax (default: false)
- * @param bool $round (default: true)
- * @return float
- */
- public function get_line_subtotal( $item, $inc_tax = false, $round = true ) {
- if ( $inc_tax ) {
- $price = $item['line_subtotal'] + $item['line_subtotal_tax'];
- } else {
- $price = $item['line_subtotal'];
- }
-
- $price = $round ? round( $price, 2 ) : $price;
-
- return apply_filters( 'woocommerce_order_amount_line_subtotal', $price, $this, $item );
- }
-
- /**
- * Calculate item cost - useful for gateways.
- *
- * @access public
- * @param mixed $item
- * @param bool $inc_tax (default: false)
- * @param bool $round (default: true)
- * @return float
- */
- public function get_item_total( $item, $inc_tax = false, $round = true ) {
- if ( $inc_tax ) {
- $price = ( $item['line_total'] + $item['line_tax'] ) / max( 1, $item['qty'] );
- } else {
- $price = $item['line_total'] / $item['qty'];
- }
-
- $price = $round ? round( $price, 2 ) : $price;
-
- return apply_filters( 'woocommerce_order_amount_item_total', $price, $this );
- }
-
- /**
- * Calculate line total - useful for gateways.
- *
- * @access public
- * @param mixed $item
- * @param bool $inc_tax (default: false)
- * @return float
- */
- public function get_line_total( $item, $inc_tax = false ) {
- $line_total = $inc_tax ? round( $item['line_total'] + $item['line_tax'], 2 ) : round( $item['line_total'], 2 );
- return apply_filters( 'woocommerce_order_amount_line_total', $line_total, $this );
- }
-
- /**
- * Calculate item tax - useful for gateways.
- *
- * @access public
- * @param mixed $item
- * @param bool $round (default: true)
- * @return float
- */
- public function get_item_tax( $item, $round = true ) {
- $price = $item['line_tax'] / max( 1, $item['qty'] );
- $price = $round ? wc_round_tax_total( $price ) : $price;
- return apply_filters( 'woocommerce_order_amount_item_tax', $price, $item, $round, $this );
- }
-
- /**
- * Calculate line tax - useful for gateways.
- *
- * @access public
- * @param mixed $item
- * @return float
- */
- public function get_line_tax( $item ) {
- return apply_filters( 'woocommerce_order_amount_line_tax', wc_round_tax_total( $item['line_tax'] ), $item, $this );
- }
-
- /**
- * Gets shipping total.
- *
- * @deprecated As of 2.1, use of get_total_shipping() is preferred
- * @access public
- * @return float
- */
- public function get_shipping() {
- _deprecated_function( 'get_shipping', '2.1', 'get_total_shipping' );
- return $this->get_total_shipping();
- }
-
- /**
- * get_order_total function. Alias for get_total()
- *
- * @deprecated As of 2.1, use of get_total() is preferred
- * @access public
- * @return float
- */
- public function get_order_total() {
- _deprecated_function( 'get_order_total', '2.1', 'get_total' );
- return $this->get_total();
- }
-
- /** End Total Getters *******************************************************/
-
- /**
- * Gets formatted shipping method title.
- *
- * @return string
- */
- public function get_shipping_method() {
- $labels = array();
-
- // Backwards compat < 2.1 - get shipping title stored in meta
- if ( $this->shipping_method_title ) {
- $labels[] = $this->shipping_method_title;
- } else {
- // 2.1+ get line items for shipping
- $shipping_methods = $this->get_shipping_methods();
-
- foreach ( $shipping_methods as $shipping ) {
- $labels[] = $shipping['name'];
- }
- }
-
- return apply_filters( 'woocommerce_order_shipping_method', implode( ', ', $labels ), $this );
- }
-
- /**
- * Gets line subtotal - formatted for display.
- *
- * @access public
- * @param array $item
- * @param string $tax_display
- * @return string
- */
- public function get_formatted_line_subtotal( $item, $tax_display = '' ) {
- if ( ! $tax_display ) {
- $tax_display = $this->tax_display_cart;
- }
-
- if ( ! isset( $item['line_subtotal'] ) || ! isset( $item['line_subtotal_tax'] ) ) {
- return '';
- }
-
- if ( 'excl' == $tax_display ) {
- $ex_tax_label = $this->prices_include_tax ? 1 : 0;
-
- $subtotal = wc_price( $this->get_line_subtotal( $item ), array( 'ex_tax_label' => $ex_tax_label, 'currency' => $this->get_order_currency() ) );
- } else {
- $subtotal = wc_price( $this->get_line_subtotal( $item, true ), array('currency' => $this->get_order_currency()) );
- }
-
- return apply_filters( 'woocommerce_order_formatted_line_subtotal', $subtotal, $item, $this );
- }
-
- /**
- * Gets order currency
- *
- * @access public
- * @return string
- */
- public function get_order_currency() {
-
- $currency = $this->order_currency;
-
- return apply_filters( 'woocommerce_get_order_currency', $currency, $this );
- }
-
- /**
- * Gets order total - formatted for display.
- *
- * @access public
- * @return string
- */
- public function get_formatted_order_total() {
-
- $formatted_total = wc_price( $this->order_total , array('currency' => $this->get_order_currency()));
-
- return apply_filters( 'woocommerce_get_formatted_order_total', $formatted_total, $this );
- }
-
-
- /**
- * Gets subtotal - subtotal is shown before discounts, but with localised taxes.
- *
- * @access public
- * @param bool $compound (default: false)
- * @param string $tax_display (default: the tax_display_cart value)
- * @return string
- */
- public function get_subtotal_to_display( $compound = false, $tax_display = '' ) {
- if ( ! $tax_display ) {
- $tax_display = $this->tax_display_cart;
- }
-
- $subtotal = 0;
-
- if ( ! $compound ) {
- foreach ( $this->get_items() as $item ) {
-
- if ( ! isset( $item['line_subtotal'] ) || ! isset( $item['line_subtotal_tax'] ) ) {
- return '';
- }
-
- $subtotal += $item['line_subtotal'];
-
- if ( 'incl' == $tax_display ) {
- $subtotal += $item['line_subtotal_tax'];
- }
- }
-
- $subtotal = wc_price( $subtotal, array('currency' => $this->get_order_currency()) );
-
- if ( $tax_display == 'excl' && $this->prices_include_tax ) {
- $subtotal .= ' ' . WC()->countries->ex_tax_or_vat() . '';
- }
-
- } else {
-
- if ( 'incl' == $tax_display ) {
- return '';
- }
-
- foreach ( $this->get_items() as $item ) {
-
- $subtotal += $item['line_subtotal'];
-
- }
-
- // Add Shipping Costs
- $subtotal += $this->get_total_shipping();
-
- // Remove non-compound taxes
- foreach ( $this->get_taxes() as $tax ) {
-
- if ( ! empty( $tax['compound'] ) ) {
- continue;
- }
-
- $subtotal = $subtotal + $tax['tax_amount'] + $tax['shipping_tax_amount'];
-
- }
-
- // Remove discounts
- $subtotal = $subtotal - $this->get_cart_discount();
-
- $subtotal = wc_price( $subtotal, array('currency' => $this->get_order_currency()) );
- }
-
- return apply_filters( 'woocommerce_order_subtotal_to_display', $subtotal, $compound, $this );
- }
-
-
- /**
- * Gets shipping (formatted).
- *
- * @access public
- * @return string
- */
- public function get_shipping_to_display( $tax_display = '' ) {
- if ( ! $tax_display ) {
- $tax_display = $this->tax_display_cart;
- }
-
- if ( $this->order_shipping > 0 ) {
-
- $tax_text = '';
-
- if ( $tax_display == 'excl' ) {
-
- // Show shipping excluding tax
- $shipping = wc_price( $this->order_shipping, array('currency' => $this->get_order_currency()) );
-
- if ( $this->order_shipping_tax > 0 && $this->prices_include_tax ) {
- $tax_text = WC()->countries->ex_tax_or_vat() . ' ';
- }
-
- } else {
-
- // Show shipping including tax
- $shipping = wc_price( $this->order_shipping + $this->order_shipping_tax, array('currency' => $this->get_order_currency()) );
-
- if ( $this->order_shipping_tax > 0 && ! $this->prices_include_tax ) {
- $tax_text = WC()->countries->inc_tax_or_vat() . ' ';
- }
-
- }
-
- $shipping .= sprintf( __( ' %svia %s', 'woocommerce' ), $tax_text, $this->get_shipping_method() );
-
- } elseif ( $this->get_shipping_method() ) {
- $shipping = $this->get_shipping_method();
- } else {
- $shipping = __( 'Free!', 'woocommerce' );
- }
-
- return apply_filters( 'woocommerce_order_shipping_to_display', $shipping, $this );
- }
-
-
- /**
- * Get cart discount (formatted).
- *
- * @access public
- * @return string.
- */
- public function get_cart_discount_to_display() {
- return apply_filters( 'woocommerce_order_cart_discount_to_display', wc_price( $this->get_cart_discount(), array( 'currency' => $this->get_order_currency() ) ), $this );
- }
-
-
- /**
- * Get cart discount (formatted).
- *
- * @access public
- * @return string
- */
- public function get_order_discount_to_display() {
- return apply_filters( 'woocommerce_order_discount_to_display', wc_price( $this->get_order_discount(), array( 'currency' => $this->get_order_currency() ) ), $this );
- }
-
-
- /**
- * Get a product (either product or variation).
- *
- * @access public
- * @param mixed $item
- * @return WC_Product
- */
- public function get_product_from_item( $item ) {
- if ( ! empty( $item['variation_id'] ) && 'product_variation' === get_post_type( $item['variation_id'] ) ) {
- $_product = get_product( $item['variation_id'] );
- } else {
- $_product = get_product( $item['product_id'] );
- }
- return apply_filters( 'woocommerce_get_product_from_item', $_product, $item, $this );
- }
-
-
- /**
- * Get totals for display on pages and in emails.
- *
- * @access public
- * @return array
- */
- public function get_order_item_totals( $tax_display = '' ) {
- if ( ! $tax_display ) {
- $tax_display = $this->tax_display_cart;
- }
-
- $total_rows = array();
-
- if ( $subtotal = $this->get_subtotal_to_display() ) {
- $total_rows['cart_subtotal'] = array(
- 'label' => __( 'Cart Subtotal:', 'woocommerce' ),
- 'value' => $subtotal
- );
- }
-
- if ( $this->get_cart_discount() > 0 ) {
- $total_rows['cart_discount'] = array(
- 'label' => __( 'Cart Discount:', 'woocommerce' ),
- 'value' => '-' . $this->get_cart_discount_to_display()
- );
- }
-
- if ( $this->get_shipping_method() ) {
- $total_rows['shipping'] = array(
- 'label' => __( 'Shipping:', 'woocommerce' ),
- 'value' => $this->get_shipping_to_display()
- );
- }
-
- if ( $fees = $this->get_fees() )
- foreach( $fees as $id => $fee ) {
- if ( apply_filters( 'woocommerce_get_order_item_totals_excl_free_fees', $fee['line_total'] + $fee['line_tax'] == 0, $id ) ) {
- continue;
- }
-
- if ( 'excl' == $tax_display ) {
-
- $total_rows[ 'fee_' . $id ] = array(
- 'label' => $fee['name'] . ':',
- 'value' => wc_price( $fee['line_total'], array('currency' => $this->get_order_currency()) )
- );
-
- } else {
-
- $total_rows[ 'fee_' . $id ] = array(
- 'label' => $fee['name'] . ':',
- 'value' => wc_price( $fee['line_total'] + $fee['line_tax'], array('currency' => $this->get_order_currency()) )
- );
-
- }
- }
-
- // Tax for tax exclusive prices
- if ( 'excl' == $tax_display ) {
- if ( get_option( 'woocommerce_tax_total_display' ) == 'itemized' ) {
- foreach ( $this->get_tax_totals() as $code => $tax ) {
- $total_rows[ sanitize_title( $code ) ] = array(
- 'label' => $tax->label . ':',
- 'value' => $tax->formatted_amount
- );
- }
- } else {
- $total_rows['tax'] = array(
- 'label' => WC()->countries->tax_or_vat() . ':',
- 'value' => wc_price( $this->get_total_tax(), array('currency' => $this->get_order_currency()) )
- );
- }
- }
-
- if ( $this->get_order_discount() > 0 ) {
- $total_rows['order_discount'] = array(
- 'label' => __( 'Order Discount:', 'woocommerce' ),
- 'value' => '-' . $this->get_order_discount_to_display()
- );
- }
-
- if ( $this->get_total() > 0 ) {
- $total_rows['payment_method'] = array(
- 'label' => __( 'Payment Method:', 'woocommerce' ),
- 'value' => $this->payment_method_title
- );
- }
-
- $total_rows['order_total'] = array(
- 'label' => __( 'Order Total:', 'woocommerce' ),
- 'value' => $this->get_formatted_order_total()
- );
-
- // Tax for inclusive prices
- if ( 'yes' == get_option( 'woocommerce_calc_taxes' ) && 'incl' == $tax_display ) {
-
- $tax_string_array = array();
-
- if ( 'itemized' == get_option( 'woocommerce_tax_total_display' ) ) {
- foreach ( $this->get_tax_totals() as $code => $tax ) {
- $tax_string_array[] = sprintf( '%s %s', $tax->formatted_amount, $tax->label );
- }
- } else {
- $tax_string_array[] = sprintf( '%s %s', wc_price( $this->get_total_tax(), array('currency' => $this->get_order_currency()) ), WC()->countries->tax_or_vat() );
- }
-
- if ( ! empty( $tax_string_array ) ) {
- $total_rows['order_total']['value'] .= ' ' . sprintf( __( '(Includes %s)', 'woocommerce' ), implode( ', ', $tax_string_array ) );
- }
- }
-
- return apply_filters( 'woocommerce_get_order_item_totals', $total_rows, $this );
- }
-
-
- /**
- * Output items for display in html emails.
- *
- * @access public
- * @param bool $show_download_links (default: false)
- * @param bool $show_sku (default: false)
- * @param bool $show_purchase_note (default: false)
- * @param bool $show_image (default: false)
- * @param array $image_size (default: array( 32, 32 )
- * @param bool plain text
- * @return string
- */
- public function email_order_items_table( $show_download_links = false, $show_sku = false, $show_purchase_note = false, $show_image = false, $image_size = array( 32, 32 ), $plain_text = false ) {
-
- ob_start();
-
- $template = $plain_text ? 'emails/plain/email-order-items.php' : 'emails/email-order-items.php';
-
- wc_get_template( $template, array(
- 'order' => $this,
- 'items' => $this->get_items(),
- 'show_download_links' => $show_download_links,
- 'show_sku' => $show_sku,
- 'show_purchase_note' => $show_purchase_note,
- 'show_image' => $show_image,
- 'image_size' => $image_size
- ) );
-
- $return = apply_filters( 'woocommerce_email_order_items_table', ob_get_clean(), $this );
-
- return $return;
- }
-
- /**
- * Checks if product download is permitted
- *
- * @access public
- * @return bool
- */
- public function is_download_permitted() {
- 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 );
- }
-
- /**
- * Returns true if the order contains a downloadable product.
- *
- * @access public
- * @return bool
- */
- public function has_downloadable_item() {
- $has_downloadable_item = false;
-
- foreach ( $this->get_items() as $item ) {
-
- $_product = $this->get_product_from_item( $item );
-
- if ( $_product && $_product->exists() && $_product->is_downloadable() && $_product->has_file() ) {
- $has_downloadable_item = true;
- }
-
- }
-
- return $has_downloadable_item;
- }
-
-
- /**
- * 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.
- *
- * @access public
- * @param boolean $on_checkout
- * @return string
- */
- public function get_checkout_payment_url( $on_checkout = false ) {
-
- $pay_url = wc_get_endpoint_url( 'order-pay', $this->id, get_permalink( wc_get_page_id( 'checkout' ) ) );
-
- if ( 'yes' == get_option( 'woocommerce_force_ssl_checkout' ) || is_ssl() ) {
- $pay_url = str_replace( 'http:', 'https:', $pay_url );
- }
-
- if ( $on_checkout ) {
- $pay_url = add_query_arg( 'key', $this->order_key, $pay_url );
- } else {
- $pay_url = add_query_arg( array( 'pay_for_order' => 'true', 'key' => $this->order_key ), $pay_url );
- }
-
- return apply_filters( 'woocommerce_get_checkout_payment_url', $pay_url, $this );
- }
-
-
- /**
- * Generates a URL for the thanks page (order received)
- *
- * @access public
- * @return string
- */
- public function get_checkout_order_received_url() {
-
- $order_received_url = wc_get_endpoint_url( 'order-received', $this->id, get_permalink( wc_get_page_id( 'checkout' ) ) );
-
- if ( 'yes' == get_option( 'woocommerce_force_ssl_checkout' ) || is_ssl() ) {
- $order_received_url = str_replace( 'http:', 'https:', $order_received_url );
- }
-
- $order_received_url = add_query_arg( 'key', $this->order_key, $order_received_url );
-
- return apply_filters( 'woocommerce_get_checkout_order_received_url', $order_received_url, $this );
- }
-
-
- /**
- * Generates a URL so that a customer can cancel their (unpaid - pending) order.
- *
- * @access public
- * @return string
- */
- public function get_cancel_order_url( $redirect = '' ) {
- $cancel_endpoint = get_permalink( wc_get_page_id( 'cart' ) );
- if ( ! $cancel_endpoint ) {
- $cancel_endpoint = home_url();
- }
-
- if ( false === strpos( $cancel_endpoint, '?' ) ) {
- $cancel_endpoint = trailingslashit( $cancel_endpoint );
- }
-
- return apply_filters('woocommerce_get_cancel_order_url', wp_nonce_url( add_query_arg( array( 'cancel_order' => 'true', 'order' => $this->order_key, 'order_id' => $this->id, 'redirect' => $redirect ), $cancel_endpoint ), 'woocommerce-cancel_order' ) );
- }
-
- /**
- * Generates a URL to view an order from the my account page
- *
- * @return string
- */
- public function get_view_order_url() {
- $view_order_url = wc_get_endpoint_url( 'view-order', $this->id, get_permalink( wc_get_page_id( 'myaccount' ) ) );
-
- return apply_filters( 'woocommerce_get_view_order_url', $view_order_url, $this );
- }
-
- /**
- * Gets any downloadable product file urls.
- *
- * @deprecated as of 2.1 get_item_downloads is preferred as downloads are more than just file urls
- * @param int $product_id product identifier
- * @param int $variation_id variation identifier, or null
- * @param array $item the item
- * @return array available downloadable file urls
- */
- public function get_downloadable_file_urls( $product_id, $variation_id, $item ) {
- global $wpdb;
-
- _deprecated_function( 'get_downloadable_file_urls', '2.1', 'get_item_downloads' );
-
- $download_file = $variation_id > 0 ? $variation_id : $product_id;
- $_product = get_product( $download_file );
-
- $user_email = $this->billing_email;
-
- $results = $wpdb->get_results( $wpdb->prepare("
- SELECT download_id
- FROM {$wpdb->prefix}woocommerce_downloadable_product_permissions
- WHERE user_email = %s
- AND order_key = %s
- AND product_id = %s
- ", $user_email, $this->order_key, $download_file ) );
-
- $file_urls = array();
- foreach ( $results as $result ) {
- if ( $_product->has_file( $result->download_id ) ) {
- $file_urls[ $_product->get_file_download_path( $result->download_id ) ] = $this->get_download_url( $download_file, $result->download_id );
- }
- }
-
- return apply_filters( 'woocommerce_get_downloadable_file_urls', $file_urls, $product_id, $variation_id, $item );
- }
-
- /**
- * Get the downloadable files for an item in this order
- * @param array $item
- * @return array
- */
- public function get_item_downloads( $item ) {
- global $wpdb;
-
- $product_id = $item['variation_id'] > 0 ? $item['variation_id'] : $item['product_id'];
- $product = get_product( $product_id );
- $download_ids = $wpdb->get_col( $wpdb->prepare("
- SELECT download_id
- FROM {$wpdb->prefix}woocommerce_downloadable_product_permissions
- WHERE user_email = %s
- AND order_key = %s
- AND product_id = %s
- ORDER BY permission_id
- ", $this->billing_email, $this->order_key, $product_id ) );
-
- $files = array();
-
- foreach ( $download_ids as $download_id ) {
- if ( $product->has_file( $download_id ) ) {
- $files[ $download_id ] = $product->get_file( $download_id );
- $files[ $download_id ]['download_url'] = $this->get_download_url( $product_id, $download_id );
- }
- }
-
- return apply_filters( 'woocommerce_get_item_downloads', $files, $item, $this );
- }
-
- /**
- * Get the Download URL
- * @param int $product_id
- * @param int $download_id
- * @return string
- */
- public function get_download_url( $product_id, $download_id ) {
- return add_query_arg( array(
- 'download_file' => $product_id,
- 'order' => $this->order_key,
- 'email' => urlencode( $this->billing_email ),
- 'key' => $download_id
- ), trailingslashit( home_url() ) );
- }
-
- /**
- * Adds a note (comment) to the order
- *
- * @access public
- * @param string $note Note to add
- * @param int $is_customer_note (default: 0) Is this a note for the customer?
- * @return id Comment ID
- */
- public function add_order_note( $note, $is_customer_note = 0 ) {
-
- $is_customer_note = intval( $is_customer_note );
-
- if ( is_user_logged_in() && current_user_can( 'edit_shop_order', $this->id ) ) {
- $user = get_user_by( 'id', get_current_user_id() );
- $comment_author = $user->display_name;
- $comment_author_email = $user->user_email;
- } else {
- $comment_author = __( 'WooCommerce', 'woocommerce' );
- $comment_author_email = strtolower( __( 'WooCommerce', 'woocommerce' ) ) . '@';
- $comment_author_email .= isset( $_SERVER['HTTP_HOST'] ) ? str_replace( 'www.', '', $_SERVER['HTTP_HOST'] ) : 'noreply.com';
- $comment_author_email = sanitize_email( $comment_author_email );
- }
-
- $comment_post_ID = $this->id;
- $comment_author_url = '';
- $comment_content = $note;
- $comment_agent = 'WooCommerce';
- $comment_type = 'order_note';
- $comment_parent = 0;
- $comment_approved = 1;
- $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 ) );
-
- $comment_id = wp_insert_comment( $commentdata );
-
- add_comment_meta( $comment_id, 'is_customer_note', $is_customer_note );
-
- if ( $is_customer_note ) {
- do_action( 'woocommerce_new_customer_note', array( 'order_id' => $this->id, 'customer_note' => $note ) );
- }
-
- return $comment_id;
- }
-
- /**
- * Updates status of order
- *
- * @access public
- * @param string $new_status Status to change the order to. No internal wc- prefix is required.
- * @param string $note (default: '') Optional note to add
- */
- public function update_status( $new_status, $note = '' ) {
- $old_status = $this->get_status();
- $new_status = 'wc-' === substr( $new_status, 0, 3 ) ? substr( $new_status, 3 ) : $new_status;
-
- // Only update if they differ
- if ( $this->id && $new_status !== $old_status ) {
-
- // Update the order
- wp_update_post( array( 'ID' => $this->id, 'post_status' => 'wc-' . $new_status ) );
- $this->post_status = 'wc-' . $new_status;
- $this->add_order_note( trim( $note . ' ' . sprintf( __( 'Order status changed from %s to %s.', 'woocommerce' ), $old_status, $new_status ) ) );
-
- // Status was changed
- do_action( 'woocommerce_order_status_' . $new_status, $this->id );
- do_action( 'woocommerce_order_status_' . $old_status . '_to_' . $new_status, $this->id );
- do_action( 'woocommerce_order_status_changed', $this->id, $old_status, $new_status );
-
- switch ( $new_status ) {
- case 'completed' :
- // Record the sales
- $this->record_product_sales();
-
- // Increase coupon usage counts
- $this->increase_coupon_usage_counts();
-
- // Record the completed date of the order
- update_post_meta( $this->id, '_completed_date', current_time('mysql') );
-
- // Update reports
- wc_delete_shop_order_transients( $this->id );
- break;
- case 'processing' :
- case 'on-hold' :
- // Record the sales
- $this->record_product_sales();
-
- // Increase coupon usage counts
- $this->increase_coupon_usage_counts();
-
- // Update reports
- wc_delete_shop_order_transients( $this->id );
- break;
- case 'cancelled' :
- // If the order is cancelled, restore used coupons
- $this->decrease_coupon_usage_counts();
-
- // Update reports
- wc_delete_shop_order_transients( $this->id );
- break;
- }
- }
- }
-
-
- /**
- * Cancel the order and restore the cart (before payment)
- *
- * @access public
- * @param string $note (default: '') Optional note to add
- * @return void
- */
- public function cancel_order( $note = '' ) {
- unset( WC()->session->order_awaiting_payment );
-
- $this->update_status( 'cancelled', $note );
-
- }
-
- /**
- * When a payment is complete this function is called
- *
- * Most of the time this should mark an order as 'processing' so that admin can process/post the items
- * If the cart contains only downloadable items then the order is 'completed' since the admin needs to take no action
- * Stock levels are reduced at this point
- * Sales are also recorded for products
- * Finally, record the date of payment
- *
- * @access public
- * @param $transaction_id string Optional transaction id to store in post meta
- * @return void
- */
- public function payment_complete( $transaction_id = '' ) {
-
- do_action( 'woocommerce_pre_payment_complete', $this->id );
-
- if ( ! empty( WC()->session->order_awaiting_payment ) ) {
- unset( WC()->session->order_awaiting_payment );
- }
-
- $valid_order_statuses = apply_filters( 'woocommerce_valid_order_statuses_for_payment_complete', array( 'on-hold', 'pending', 'failed' ), $this );
-
- if ( $this->id && $this->has_status( $valid_order_statuses ) ) {
-
- $order_needs_processing = true;
-
- if ( sizeof( $this->get_items() ) > 0 ) {
-
- foreach( $this->get_items() as $item ) {
-
- if ( $item['product_id'] > 0 ) {
-
- $_product = $this->get_product_from_item( $item );
-
- if ( false !== $_product && ( $_product->is_downloadable() && $_product->is_virtual() ) || ! apply_filters( 'woocommerce_order_item_needs_processing', true, $_product, $this->id ) ) {
- $order_needs_processing = false;
- continue;
- }
-
- }
- $order_needs_processing = true;
- break;
- }
- }
-
- $new_order_status = $order_needs_processing ? 'processing' : 'completed';
-
- $new_order_status = apply_filters( 'woocommerce_payment_complete_order_status', $new_order_status, $this->id );
-
- $this->update_status( $new_order_status );
-
- add_post_meta( $this->id, '_paid_date', current_time('mysql'), true );
-
- if ( ! empty( $transaction_id ) ) {
- add_post_meta( $this->id, '_transaction_id', $transaction_id );
- }
-
- $this_order = array(
- 'ID' => $this->id,
- 'post_date' => current_time( 'mysql', 0 ),
- 'post_date_gmt' => current_time( 'mysql', 1 )
- );
- wp_update_post( $this_order );
-
- if ( apply_filters( 'woocommerce_payment_complete_reduce_order_stock', true, $this->id ) ) {
- $this->reduce_order_stock(); // Payment is complete so reduce stock levels
- }
-
- do_action( 'woocommerce_payment_complete', $this->id );
-
- } else {
-
- do_action( 'woocommerce_payment_complete_order_status_' . $this->get_status(), $this->id );
-
- }
- }
-
-
- /**
- * Record sales
- *
- * @access public
- * @return void
- */
- public function record_product_sales() {
-
- if ( 'yes' == get_post_meta( $this->id, '_recorded_sales', true ) ) {
- return;
- }
-
- if ( sizeof( $this->get_items() ) > 0 ) {
- foreach ( $this->get_items() as $item ) {
- if ( $item['product_id'] > 0 ) {
- $sales = (int) get_post_meta( $item['product_id'], 'total_sales', true );
- $sales += (int) $item['qty'];
- if ( $sales ) {
- update_post_meta( $item['product_id'], 'total_sales', $sales );
- }
- }
- }
- }
-
- update_post_meta( $this->id, '_recorded_sales', 'yes' );
- }
-
-
- /**
- * Get coupon codes only.
- *
- * @access public
- * @return array
- */
- public function get_used_coupons() {
-
- $codes = array();
- $coupons = $this->get_items( 'coupon' );
-
- foreach ( $coupons as $item_id => $item ) {
- $codes[] = trim( $item['name'] );
- }
-
- return $codes;
- }
-
-
- /**
- * Increase applied coupon counts
- *
- * @access public
- * @return void
- */
- public function increase_coupon_usage_counts() {
-
- if ( 'yes' == get_post_meta( $this->id, '_recorded_coupon_usage_counts', true ) ) {
- return;
- }
-
- if ( sizeof( $this->get_used_coupons() ) > 0 ) {
- foreach ( $this->get_used_coupons() as $code ) {
- if ( ! $code ) {
- continue;
- }
-
- $coupon = new WC_Coupon( $code );
-
- $used_by = $this->user_id;
- if ( ! $used_by ) {
- $used_by = $this->billing_email;
- }
-
- $coupon->inc_usage_count( $used_by );
- }
- }
-
- update_post_meta( $this->id, '_recorded_coupon_usage_counts', 'yes' );
- }
-
-
- /**
- * Decrease applied coupon counts
- *
- * @access public
- * @return void
- */
- public function decrease_coupon_usage_counts() {
-
- if ( 'yes' != get_post_meta( $this->id, '_recorded_coupon_usage_counts', true ) ) {
- return;
- }
-
- if ( sizeof( $this->get_used_coupons() ) > 0 ) {
- foreach ( $this->get_used_coupons() as $code ) {
- if ( ! $code ) {
- continue;
- }
-
- $coupon = new WC_Coupon( $code );
-
- $used_by = $this->user_id;
- if ( ! $used_by ) {
- $used_by = $this->billing_email;
- }
-
- $coupon->dcr_usage_count( $used_by );
- }
- }
-
- delete_post_meta( $this->id, '_recorded_coupon_usage_counts' );
- }
-
-
- /**
- * Reduce stock levels
- *
- * @access public
- * @return void
- */
- public function reduce_order_stock() {
-
- if ( 'yes' == get_option('woocommerce_manage_stock') && sizeof( $this->get_items() ) > 0 ) {
-
- // Reduce stock levels and do any other actions with products in the cart
- foreach ( $this->get_items() as $item ) {
-
- if ( $item['product_id'] > 0 ) {
- $_product = $this->get_product_from_item( $item );
-
- if ( $_product && $_product->exists() && $_product->managing_stock() ) {
- $qty = apply_filters( 'woocommerce_order_item_quantity', $item['qty'], $this, $item );
- $new_stock = $_product->reduce_stock( $qty );
-
- $this->add_order_note( sprintf( __( 'Item #%s stock reduced from %s to %s.', 'woocommerce' ), $item['product_id'], $new_stock + $qty, $new_stock) );
- $this->send_stock_notifications( $_product, $new_stock, $item['qty'] );
- }
-
- }
-
- }
-
- do_action( 'woocommerce_reduce_order_stock', $this );
-
- $this->add_order_note( __( 'Order item stock reduced successfully.', 'woocommerce' ) );
- }
- }
-
- /**
- * send_stock_notifications function.
- *
- * @access public
- * @param object $product
- * @param int $new_stock
- * @param int $qty_ordered
- * @return void
- */
- public function send_stock_notifications( $product, $new_stock, $qty_ordered ) {
-
- // Backorders
- if ( $new_stock < 0 ) {
- do_action( 'woocommerce_product_on_backorder', array( 'product' => $product, 'order_id' => $this->id, 'quantity' => $qty_ordered ) );
- }
-
- // stock status notifications
- $notification_sent = false;
-
- if ( 'yes' == get_option( 'woocommerce_notify_no_stock' ) && get_option('woocommerce_notify_no_stock_amount') >= $new_stock ) {
- do_action( 'woocommerce_no_stock', $product );
- $notification_sent = true;
- }
- if ( ! $notification_sent && 'yes' == get_option( 'woocommerce_notify_low_stock' ) && get_option('woocommerce_notify_low_stock_amount') >= $new_stock ) {
- do_action( 'woocommerce_low_stock', $product );
- $notification_sent = true;
- }
-
- }
-
-
- /**
- * List order notes (public) for the customer
- *
- * @access public
- * @return array
- */
- public function get_customer_order_notes() {
-
- $notes = array();
-
- $args = array(
- 'post_id' => $this->id,
- 'approve' => 'approve',
- 'type' => ''
- );
-
- remove_filter( 'comments_clauses', array( 'WC_Comments', 'exclude_order_comments' ) );
-
- $comments = get_comments( $args );
-
- foreach ( $comments as $comment ) {
- $is_customer_note = get_comment_meta( $comment->comment_ID, 'is_customer_note', true );
- $comment->comment_content = make_clickable( $comment->comment_content );
- if ( $is_customer_note ) {
- $notes[] = $comment;
- }
- }
-
- add_filter( 'comments_clauses', array( 'WC_Comments', 'exclude_order_comments' ) );
-
- return (array) $notes;
-
- }
-
- /**
- * Checks if an order needs payment, based on status and order total
- *
- * @access public
- * @return bool
- */
- public function needs_payment() {
- $valid_order_statuses = apply_filters( 'woocommerce_valid_order_statuses_for_payment', array( 'pending', 'failed' ), $this );
-
- if ( $this->has_status( $valid_order_statuses ) && $this->get_total() > 0 ) {
- $needs_payment = true;
- } else {
- $needs_payment = false;
- }
-
- return apply_filters( 'woocommerce_order_needs_payment', $needs_payment, $this, $valid_order_statuses );
- }
-
- /**
- * Checks if an order needs display the shipping address, based on shipping method
- *
- * @access public
- * @return bool
- */
- public function needs_shipping_address() {
- $hide = apply_filters( 'woocommerce_order_hide_shipping_address', array( 'local_pickup' ), $this );
- $needs = false;
-
- foreach ( $this->get_shipping_methods() as $shipping_method ) {
- if ( ! in_array( $shipping_method['method_id'], $hide ) ) {
- $needs = true;
- break;
- }
- }
-
- return apply_filters( 'woocommerce_order_needs_shipping_address', $needs, $this, $hide );
+class WC_Order extends WC_Abstract_Order {
+ public function __construct( $order ) {
+ $this->order_type = 'simple';
+ parent::__construct( $order );
}
-}
+}
\ No newline at end of file
diff --git a/includes/emails/class-wc-email-customer-completed-order.php b/includes/emails/class-wc-email-customer-completed-order.php
index e8631245b7d..ed7aed2a4c1 100644
--- a/includes/emails/class-wc-email-customer-completed-order.php
+++ b/includes/emails/class-wc-email-customer-completed-order.php
@@ -52,7 +52,7 @@ class WC_Email_Customer_Completed_Order extends WC_Email {
function trigger( $order_id ) {
if ( $order_id ) {
- $this->object = new WC_Order( $order_id );
+ $this->object = get_order( $order_id );
$this->recipient = $this->object->billing_email;
$this->find['order-date'] = '{order_date}';
diff --git a/includes/emails/class-wc-email-customer-invoice.php b/includes/emails/class-wc-email-customer-invoice.php
index fbd4dd7ef41..0cecb6fc13b 100644
--- a/includes/emails/class-wc-email-customer-invoice.php
+++ b/includes/emails/class-wc-email-customer-invoice.php
@@ -54,7 +54,7 @@ class WC_Email_Customer_Invoice extends WC_Email {
function trigger( $order ) {
if ( ! is_object( $order ) ) {
- $order = new WC_Order( absint( $order ) );
+ $order = get_order( absint( $order ) );
}
if ( $order ) {
diff --git a/includes/emails/class-wc-email-customer-note.php b/includes/emails/class-wc-email-customer-note.php
index f280238e9bb..03e6bc44e63 100644
--- a/includes/emails/class-wc-email-customer-note.php
+++ b/includes/emails/class-wc-email-customer-note.php
@@ -63,7 +63,7 @@ class WC_Email_Customer_Note extends WC_Email {
extract( $args );
- $this->object = new WC_Order( $order_id );
+ $this->object = get_order( $order_id );
$this->recipient = $this->object->billing_email;
$this->customer_note = $customer_note;
diff --git a/includes/emails/class-wc-email-customer-processing-order.php b/includes/emails/class-wc-email-customer-processing-order.php
index 32836a69dd3..a648c69c27f 100644
--- a/includes/emails/class-wc-email-customer-processing-order.php
+++ b/includes/emails/class-wc-email-customer-processing-order.php
@@ -49,7 +49,7 @@ class WC_Email_Customer_Processing_Order extends WC_Email {
function trigger( $order_id ) {
if ( $order_id ) {
- $this->object = new WC_Order( $order_id );
+ $this->object = get_order( $order_id );
$this->recipient = $this->object->billing_email;
$this->find['order-date'] = '{order_date}';
diff --git a/includes/emails/class-wc-email-new-order.php b/includes/emails/class-wc-email-new-order.php
index 160ed1fdf78..3c7a62f2c4a 100644
--- a/includes/emails/class-wc-email-new-order.php
+++ b/includes/emails/class-wc-email-new-order.php
@@ -59,7 +59,7 @@ class WC_Email_New_Order extends WC_Email {
function trigger( $order_id ) {
if ( $order_id ) {
- $this->object = new WC_Order( $order_id );
+ $this->object = get_order( $order_id );
$this->find['order-date'] = '{order_date}';
$this->find['order-number'] = '{order_number}';
diff --git a/includes/gateways/bacs/class-wc-gateway-bacs.php b/includes/gateways/bacs/class-wc-gateway-bacs.php
index cb89ce5985c..dcbe2892a1d 100644
--- a/includes/gateways/bacs/class-wc-gateway-bacs.php
+++ b/includes/gateways/bacs/class-wc-gateway-bacs.php
@@ -291,7 +291,7 @@ class WC_Gateway_BACS extends WC_Payment_Gateway {
*/
public function process_payment( $order_id ) {
- $order = new WC_Order( $order_id );
+ $order = get_order( $order_id );
// Mark as on-hold (we're awaiting the payment)
$order->update_status( 'on-hold', __( 'Awaiting BACS payment', 'woocommerce' ) );
diff --git a/includes/gateways/cheque/class-wc-gateway-cheque.php b/includes/gateways/cheque/class-wc-gateway-cheque.php
index c2928217465..09069506e6f 100755
--- a/includes/gateways/cheque/class-wc-gateway-cheque.php
+++ b/includes/gateways/cheque/class-wc-gateway-cheque.php
@@ -108,7 +108,7 @@ class WC_Gateway_Cheque extends WC_Payment_Gateway {
*/
public function process_payment( $order_id ) {
- $order = new WC_Order( $order_id );
+ $order = get_order( $order_id );
// Mark as on-hold (we're awaiting the cheque)
$order->update_status( 'on-hold', __( 'Awaiting cheque payment', 'woocommerce' ) );
diff --git a/includes/gateways/cod/class-wc-gateway-cod.php b/includes/gateways/cod/class-wc-gateway-cod.php
index dcb8b1473df..389d9f28f3e 100644
--- a/includes/gateways/cod/class-wc-gateway-cod.php
+++ b/includes/gateways/cod/class-wc-gateway-cod.php
@@ -120,7 +120,7 @@ class WC_Gateway_COD extends WC_Payment_Gateway {
if ( is_page( wc_get_page_id( 'checkout' ) ) && 0 < get_query_var( 'order-pay' ) ) {
$order_id = absint( get_query_var( 'order-pay' ) );
- $order = new WC_Order( $order_id );
+ $order = get_order( $order_id );
// Test if order needs shipping.
$needs_shipping = false;
@@ -198,7 +198,7 @@ class WC_Gateway_COD extends WC_Payment_Gateway {
*/
public function process_payment( $order_id ) {
- $order = new WC_Order( $order_id );
+ $order = get_order( $order_id );
// Mark as processing (payment won't be taken until delivery)
$order->update_status( 'processing', __( 'Payment to be made upon delivery.', 'woocommerce' ) );
diff --git a/includes/gateways/mijireh/class-wc-gateway-mijireh.php b/includes/gateways/mijireh/class-wc-gateway-mijireh.php
index 9671b604bf8..f242e8dd7cf 100644
--- a/includes/gateways/mijireh/class-wc-gateway-mijireh.php
+++ b/includes/gateways/mijireh/class-wc-gateway-mijireh.php
@@ -88,7 +88,7 @@ class WC_Gateway_Mijireh extends WC_Payment_Gateway {
try {
$mj_order = new Mijireh_Order( esc_attr( $_GET['order_number'] ) );
$wc_order_id = $mj_order->get_meta_value( 'wc_order_id' );
- $wc_order = new WC_Order( absint( $wc_order_id ) );
+ $wc_order = get_order( absint( $wc_order_id ) );
// Mark order complete
$wc_order->payment_complete();
@@ -188,7 +188,7 @@ class WC_Gateway_Mijireh extends WC_Payment_Gateway {
$this->init_mijireh();
$mj_order = new Mijireh_Order();
- $wc_order = new WC_Order( $order_id );
+ $wc_order = get_order( $order_id );
// Avoid rounding issues altogether by sending the order as one lump
if ( get_option( 'woocommerce_prices_include_tax' ) == 'yes' ) {
diff --git a/includes/gateways/paypal/class-wc-gateway-paypal.php b/includes/gateways/paypal/class-wc-gateway-paypal.php
index c4d23897c9b..3789ef3b426 100644
--- a/includes/gateways/paypal/class-wc-gateway-paypal.php
+++ b/includes/gateways/paypal/class-wc-gateway-paypal.php
@@ -445,7 +445,7 @@ class WC_Gateway_Paypal extends WC_Payment_Gateway {
*/
function generate_paypal_form( $order_id ) {
- $order = new WC_Order( $order_id );
+ $order = get_order( $order_id );
if ( 'yes' == $this->testmode ) {
$paypal_adr = $this->testurl . '?test_ipn=1&';
@@ -506,7 +506,7 @@ class WC_Gateway_Paypal extends WC_Payment_Gateway {
*/
function process_payment( $order_id ) {
- $order = new WC_Order( $order_id );
+ $order = get_order( $order_id );
if ( ! $this->form_submission_method ) {
@@ -912,12 +912,12 @@ class WC_Gateway_Paypal extends WC_Payment_Gateway {
list( $order_id, $order_key ) = $custom;
}
- $order = new WC_Order( $order_id );
+ $order = get_order( $order_id );
if ( ! isset( $order->id ) ) {
// We have an invalid $order_id, probably because invoice_prefix has changed
$order_id = wc_get_order_id_by_order_key( $order_key );
- $order = new WC_Order( $order_id );
+ $order = get_order( $order_id );
}
// Validate key
diff --git a/includes/shortcodes/class-wc-shortcode-checkout.php b/includes/shortcodes/class-wc-shortcode-checkout.php
index 501264ff7a4..b09185dcc52 100644
--- a/includes/shortcodes/class-wc-shortcode-checkout.php
+++ b/includes/shortcodes/class-wc-shortcode-checkout.php
@@ -44,7 +44,7 @@ class WC_Shortcode_Checkout {
// Get the order to work out what we are showing
$order_id = absint( $_GET['order'] );
- $order = new WC_Order( $order_id );
+ $order = get_order( $order_id );
if ( $order->has_status( 'pending' ) ) {
$wp->query_vars['order-pay'] = absint( $_GET['order'] );
@@ -85,7 +85,7 @@ class WC_Shortcode_Checkout {
// Pay for existing order
$order_key = $_GET[ 'key' ];
- $order = new WC_Order( $order_id );
+ $order = get_order( $order_id );
$valid_order_statuses = apply_filters( 'woocommerce_valid_order_statuses_for_payment', array( 'pending', 'failed' ), $order );
if ( ! current_user_can( 'pay_for_order', $order_id ) ) {
@@ -119,7 +119,7 @@ class WC_Shortcode_Checkout {
// Pay for order after checkout step
$order_key = isset( $_GET['key'] ) ? wc_clean( $_GET['key'] ) : '';
- $order = new WC_Order( $order_id );
+ $order = get_order( $order_id );
$valid_order_statuses = apply_filters( 'woocommerce_valid_order_statuses_for_payment', array( 'pending', 'failed' ), $order );
if ( $order->id == $order_id && $order->order_key == $order_key ) {
@@ -186,7 +186,7 @@ class WC_Shortcode_Checkout {
$order_key = apply_filters( 'woocommerce_thankyou_order_key', empty( $_GET['key'] ) ? '' : wc_clean( $_GET['key'] ) );
if ( $order_id > 0 ) {
- $order = new WC_Order( $order_id );
+ $order = get_order( $order_id );
if ( $order->order_key != $order_key )
unset( $order );
}
diff --git a/includes/shortcodes/class-wc-shortcode-my-account.php b/includes/shortcodes/class-wc-shortcode-my-account.php
index 39eb0b028cc..074657c5473 100644
--- a/includes/shortcodes/class-wc-shortcode-my-account.php
+++ b/includes/shortcodes/class-wc-shortcode-my-account.php
@@ -105,7 +105,7 @@ class WC_Shortcode_My_Account {
private static function view_order( $order_id ) {
$user_id = get_current_user_id();
- $order = new WC_Order( $order_id );
+ $order = get_order( $order_id );
if ( ! current_user_can( 'view_order', $order_id ) ) {
echo '';
@@ -118,7 +118,7 @@ class WC_Shortcode_My_Account {
wc_get_template( 'myaccount/view-order.php', array(
'status' => $status, // @deprecated 2.2
- 'order' => new WC_Order( $order_id ),
+ 'order' => get_order( $order_id ),
'order_id' => $order_id
) );
}
diff --git a/includes/shortcodes/class-wc-shortcode-order-tracking.php b/includes/shortcodes/class-wc-shortcode-order-tracking.php
index 3ff436710e4..ff91de416fb 100644
--- a/includes/shortcodes/class-wc-shortcode-order-tracking.php
+++ b/includes/shortcodes/class-wc-shortcode-order-tracking.php
@@ -59,7 +59,7 @@ class WC_Shortcode_Order_Tracking {
} else {
- $order = new WC_Order( apply_filters( 'woocommerce_shortcode_order_tracking_order_id', $order_id ) );
+ $order = get_order( apply_filters( 'woocommerce_shortcode_order_tracking_order_id', $order_id ) );
if ( $order->id && $order_email ) {
diff --git a/includes/wc-cart-functions.php b/includes/wc-cart-functions.php
index 29388b0e46a..f877d6cae92 100644
--- a/includes/wc-cart-functions.php
+++ b/includes/wc-cart-functions.php
@@ -119,7 +119,7 @@ function wc_clear_cart_after_payment() {
$order_key = '';
if ( $order_id > 0 ) {
- $order = new WC_Order( $order_id );
+ $order = get_order( $order_id );
if ( $order->order_key == $order_key ) {
WC()->cart->empty_cart();
@@ -130,7 +130,7 @@ function wc_clear_cart_after_payment() {
if ( WC()->session->order_awaiting_payment > 0 ) {
- $order = new WC_Order( WC()->session->order_awaiting_payment );
+ $order = get_order( WC()->session->order_awaiting_payment );
if ( $order->id > 0 ) {
// If the order has not failed, or is not pending, the order must have gone through
diff --git a/includes/wc-order-functions.php b/includes/wc-order-functions.php
index 10d4c621e77..9f7dc522dbb 100644
--- a/includes/wc-order-functions.php
+++ b/includes/wc-order-functions.php
@@ -31,6 +31,17 @@ function wc_get_order_statuses() {
return apply_filters( 'wc_order_statuses', $order_statuses );
}
+/**
+ * Main function for returning orders, uses the WC_Order_Factory class.
+ *
+ * @param mixed $the_order Post object or post ID of the order.
+ * @param array $args (default: array()) Contains all arguments to be used to get this order.
+ * @return WC_Order
+ */
+function get_order( $the_order = false, $args = array() ) {
+ return WC()->order_factory->get_order( $the_order, $args );
+}
+
/**
* Get the nice name for an orer status
* @param string $status
@@ -135,7 +146,7 @@ function wc_downloadable_product_permissions( $order_id ) {
return; // Only do this once
}
- $order = new WC_Order( $order_id );
+ $order = get_order( $order_id );
if ( $order->has_status( 'processing' ) && get_option( 'woocommerce_downloads_grant_access_after_payment' ) == 'no' ) {
return;
@@ -312,7 +323,7 @@ function wc_cancel_unpaid_orders() {
if ( $unpaid_orders ) {
foreach ( $unpaid_orders as $unpaid_order ) {
- $order = new WC_Order( $unpaid_order );
+ $order = get_order( $unpaid_order );
if ( apply_filters( 'woocommerce_cancel_unpaid_order', true, $order ) )
$order->update_status( 'cancelled', __( 'Unpaid order cancelled - time limit reached.', 'woocommerce' ) );
diff --git a/includes/wc-user-functions.php b/includes/wc-user-functions.php
index 52aebcd524d..1b08dd4b2da 100644
--- a/includes/wc-user-functions.php
+++ b/includes/wc-user-functions.php
@@ -198,7 +198,7 @@ function wc_update_new_customer_past_orders( $customer_id ) {
*/
function wc_paying_customer( $order_id ) {
- $order = new WC_Order( $order_id );
+ $order = get_order( $order_id );
if ( $order->user_id > 0 ) {
update_user_meta( $order->user_id, 'paying_customer', 1 );
@@ -278,7 +278,7 @@ function wc_customer_has_capability( $allcaps, $caps, $args ) {
switch ( $caps[0] ) {
case 'view_order' :
$user_id = $args[1];
- $order = new WC_Order( $args[2] );
+ $order = get_order( $args[2] );
if ( $user_id == $order->user_id ) {
$allcaps['view_order'] = true;
@@ -295,14 +295,14 @@ function wc_customer_has_capability( $allcaps, $caps, $args ) {
break;
}
- $order = new WC_Order( $order_id );
+ $order = get_order( $order_id );
if ( $user_id == $order->user_id || empty( $order->user_id ) ) {
$allcaps['pay_for_order'] = true;
}
break;
case 'order_again' :
$user_id = $args[1];
- $order = new WC_Order( $args[2] );
+ $order = get_order( $args[2] );
if ( $user_id == $order->user_id ) {
$allcaps['order_again'] = true;
@@ -310,7 +310,7 @@ function wc_customer_has_capability( $allcaps, $caps, $args ) {
break;
case 'cancel_order' :
$user_id = $args[1];
- $order = new WC_Order( $args[2] );
+ $order = get_order( $args[2] );
if ( $user_id == $order->user_id ) {
$allcaps['cancel_order'] = true;
@@ -418,7 +418,7 @@ function wc_get_customer_available_downloads( $customer_id ) {
foreach ( $results as $result ) {
if ( ! $order || $order->id != $result->order_id ) {
// new order
- $order = new WC_Order( $result->order_id );
+ $order = get_order( $result->order_id );
$_product = null;
}
diff --git a/templates/myaccount/my-orders.php b/templates/myaccount/my-orders.php
index d43c1990c88..43558784469 100644
--- a/templates/myaccount/my-orders.php
+++ b/templates/myaccount/my-orders.php
@@ -39,7 +39,7 @@ if ( $customer_orders ) : ?>
populate( $customer_order );
$item_count = $order->get_item_count();
diff --git a/templates/order/order-details.php b/templates/order/order-details.php
index 52e8932a987..eab3a5a60bd 100755
--- a/templates/order/order-details.php
+++ b/templates/order/order-details.php
@@ -11,7 +11,7 @@ if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
global $woocommerce;
-$order = new WC_Order( $order_id );
+$order = get_order( $order_id );
?>
diff --git a/woocommerce.php b/woocommerce.php
index a5b6622d003..1982f27b22d 100644
--- a/woocommerce.php
+++ b/woocommerce.php
@@ -76,6 +76,11 @@ final class WooCommerce {
*/
public $customer = null;
+ /**
+ * @var WC_Order_Factory $order_factory
+ */
+ public $order_factory = null;
+
/**
* Main WooCommerce Instance
*
@@ -279,6 +284,7 @@ final class WooCommerce {
// Include abstract classes
include_once( 'includes/abstracts/abstract-wc-product.php' ); // Products
+ include_once( 'includes/abstracts/abstract-wc-order.php' ); // Orders
include_once( 'includes/abstracts/abstract-wc-settings-api.php' ); // Settings API (for gateways, shipping, and integrations)
include_once( 'includes/abstracts/abstract-wc-shipping-method.php' ); // A Shipping method
include_once( 'includes/abstracts/abstract-wc-payment-gateway.php' ); // A Payment gateway
@@ -362,6 +368,7 @@ final class WooCommerce {
// Load class instances
$this->product_factory = new WC_Product_Factory(); // Product Factory to create new product instances
+ $this->order_factory = new WC_Order_Factory(); // Order Factory to create new order instances
$this->countries = new WC_Countries(); // Countries class
$this->integrations = new WC_Integrations(); // Integrations class