GRAYBYTE WORDPRESS FILE MANAGER9879

Server IP : 198.54.121.189 / Your IP : 216.73.216.112
System : Linux premium69.web-hosting.com 4.18.0-553.44.1.lve.el8.x86_64 #1 SMP Thu Mar 13 14:29:12 UTC 2025 x86_64
PHP Version : 7.4.33
Disable Function : NONE
cURL : ON | WGET : ON | Sudo : OFF | Pkexec : OFF
Directory : /home/giriqfky/chahida.co.in/wp-content/plugins/woocommerce/includes/
Upload Files :
Current_dir [ Writeable ] Document_root [ Writeable ]

Command :


Current File : /home/giriqfky/chahida.co.in/wp-content/plugins/woocommerce/includes//class-wc-order.php
<?php
/**
 * Regular order
 *
 * @package WooCommerce\Classes
 * @version 2.2.0
 */

use Automattic\WooCommerce\Enums\OrderStatus;
use Automattic\WooCommerce\Utilities\FeaturesUtil;
use Automattic\WooCommerce\StoreApi\Utilities\LocalPickupUtils;
use Automattic\WooCommerce\Utilities\NumberUtil;

defined( 'ABSPATH' ) || exit;

/**
 * Order Class.
 *
 * These are regular WooCommerce orders, which extend the abstract order class.
 */
class WC_Order extends WC_Abstract_Order {

	/**
	 * Stores data about status changes so relevant hooks can be fired.
	 *
	 * @var bool|array
	 */
	protected $status_transition = false;

	/**
	 * Order Data array. This is the core order data exposed in APIs since 3.0.0.
	 *
	 * @since 3.0.0
	 * @var array
	 */
	protected $data = array(
		// Abstract order props.
		'parent_id'                    => 0,
		'status'                       => '',
		'currency'                     => '',
		'version'                      => '',
		'prices_include_tax'           => false,
		'date_created'                 => null,
		'date_modified'                => null,
		'discount_total'               => 0,
		'discount_tax'                 => 0,
		'shipping_total'               => 0,
		'shipping_tax'                 => 0,
		'cart_tax'                     => 0,
		'total'                        => 0,
		'total_tax'                    => 0,

		// Order props.
		'customer_id'                  => 0,
		'order_key'                    => '',
		'billing'                      => array(
			'first_name' => '',
			'last_name'  => '',
			'company'    => '',
			'address_1'  => '',
			'address_2'  => '',
			'city'       => '',
			'state'      => '',
			'postcode'   => '',
			'country'    => '',
			'email'      => '',
			'phone'      => '',
		),
		'shipping'                     => array(
			'first_name' => '',
			'last_name'  => '',
			'company'    => '',
			'address_1'  => '',
			'address_2'  => '',
			'city'       => '',
			'state'      => '',
			'postcode'   => '',
			'country'    => '',
			'phone'      => '',
		),
		'payment_method'               => '',
		'payment_method_title'         => '',
		'transaction_id'               => '',
		'customer_ip_address'          => '',
		'customer_user_agent'          => '',
		'created_via'                  => '',
		'customer_note'                => '',
		'date_completed'               => null,
		'date_paid'                    => null,
		'cart_hash'                    => '',

		// Operational data.
		'order_stock_reduced'          => false,
		'download_permissions_granted' => false,
		'new_order_email_sent'         => false,
		'recorded_sales'               => false,
		'recorded_coupon_usage_counts' => false,
	);

	/**
	 * List of properties that were earlier managed by data store. However, since DataStore is a not a stored entity in itself, they used to store data in metadata of the data object.
	 * With custom tables, some of these are moved from metadata to their own columns, but existing code will still try to add them to metadata. This array is used to keep track of such properties.
	 *
	 * Only reason to add a property here is that you are moving properties from DataStore instance to data object. Otherwise, if you are adding a new property, consider adding it to $data array instead.
	 *
	 * @var array
	 */
	protected $legacy_datastore_props = array(
		'_recorded_sales',
		'_recorded_coupon_usage_counts',
		'_download_permissions_granted',
		'_order_stock_reduced',
		'_new_order_email_sent',
	);

	/**
	 * Refunds for an order. Use {@see get_refunds()} instead.
	 *
	 * @deprecated 2.2.0
	 * @var stdClass|WC_Order[]
	 */
	public $refunds;

	/**
	 * 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.
	 *
	 * @param string $transaction_id Optional transaction id to store in post meta.
	 * @return bool success
	 */
	public function payment_complete( $transaction_id = '' ) {
		if ( ! $this->get_id() ) { // Order must exist.
			return false;
		}

		try {
			do_action( 'woocommerce_pre_payment_complete', $this->get_id(), $transaction_id );

			if ( WC()->session ) {
				WC()->session->set( 'order_awaiting_payment', false );
			}

			/**
			 * Filters the valid order statuses for payment complete.
			 *
			 * @param array    $valid_completed_statuses Array of valid order statuses for payment complete.
			 * @param WC_Order $this                     Order object.
			 * @since 2.7.0
			 */
			$valid_completed_statuses = apply_filters( 'woocommerce_valid_order_statuses_for_payment_complete', array( OrderStatus::ON_HOLD, OrderStatus::PENDING, OrderStatus::FAILED, OrderStatus::CANCELLED ), $this );
			if ( $this->has_status( $valid_completed_statuses ) ) {
				if ( ! empty( $transaction_id ) ) {
					$this->set_transaction_id( $transaction_id );
				}
				if ( ! $this->get_date_paid( 'edit' ) ) {
					$this->set_date_paid( time() );
				}
				/**
				 * Filters the order status to set after payment complete.
				 *
				 * @param string   $status        Order status.
				 * @param int      $order_id      Order ID.
				 * @param WC_Order $this          Order object.
				 * @since 2.7.0
				 */
				$this->set_status( apply_filters( 'woocommerce_payment_complete_order_status', $this->needs_processing() ? OrderStatus::PROCESSING : OrderStatus::COMPLETED, $this->get_id(), $this ) );
				$this->save();

				do_action( 'woocommerce_payment_complete', $this->get_id(), $transaction_id );
			} else {
				do_action( 'woocommerce_payment_complete_order_status_' . $this->get_status(), $this->get_id(), $transaction_id );
			}
		} catch ( Exception $e ) {
			/**
			 * If there was an error completing the payment, log to a file and add an order note so the admin can take action.
			 */
			$logger = wc_get_logger();
			$logger->error(
				sprintf(
					'Error completing payment for order #%d',
					$this->get_id()
				),
				array(
					'order' => $this,
					'error' => $e,
				)
			);
			$this->add_order_note( __( 'Payment complete event failed.', 'woocommerce' ) . ' ' . $e->getMessage() );
			return false;
		}
		return true;
	}

	/**
	 * Gets order total - formatted for display.
	 *
	 * @param string $tax_display      Type of tax display.
	 * @param bool   $display_refunded If should include refunded value.
	 *
	 * @return string
	 */
	public function get_formatted_order_total( $tax_display = '', $display_refunded = true ) {
		$formatted_total = wc_price( $this->get_total(), array( 'currency' => $this->get_currency() ) );
		$order_total     = $this->get_total();
		$total_refunded  = $this->get_total_refunded();
		$tax_string      = '';

		// Tax for inclusive prices.
		if ( wc_tax_enabled() && 'incl' === $tax_display ) {
			$tax_string_array = array();
			$tax_totals       = $this->get_tax_totals();

			if ( 'itemized' === get_option( 'woocommerce_tax_total_display' ) ) {
				foreach ( $tax_totals as $code => $tax ) {
					$tax_amount         = ( $total_refunded && $display_refunded ) ? wc_price( WC_Tax::round( $tax->amount - $this->get_total_tax_refunded_by_rate_id( $tax->rate_id ) ), array( 'currency' => $this->get_currency() ) ) : $tax->formatted_amount;
					$tax_string_array[] = sprintf( '%s %s', $tax_amount, $tax->label );
				}
			} elseif ( ! empty( $tax_totals ) ) {
				$tax_amount         = ( $total_refunded && $display_refunded ) ? $this->get_total_tax() - $this->get_total_tax_refunded() : $this->get_total_tax();
				$tax_string_array[] = sprintf( '%s %s', wc_price( $tax_amount, array( 'currency' => $this->get_currency() ) ), WC()->countries->tax_or_vat() );
			}

			if ( ! empty( $tax_string_array ) ) {
				/* translators: %s: taxes */
				$tax_string = ' <small class="includes_tax">' . sprintf( __( '(includes %s)', 'woocommerce' ), implode( ', ', $tax_string_array ) ) . '</small>';
			}
		}

		if ( $total_refunded && $display_refunded ) {
			$formatted_total = '<del aria-hidden="true">' . wp_strip_all_tags( $formatted_total ) . '</del> <ins>' . wc_price( $order_total - $total_refunded, array( 'currency' => $this->get_currency() ) ) . $tax_string . '</ins>';
		} else {
			$formatted_total .= $tax_string;
		}

		/**
		 * Filter WooCommerce formatted order total.
		 *
		 * @param string   $formatted_total  Total to display.
		 * @param WC_Order $order            Order data.
		 * @param string   $tax_display      Type of tax display.
		 * @param bool     $display_refunded If should include refunded value.
		 */
		return apply_filters( 'woocommerce_get_formatted_order_total', $formatted_total, $this, $tax_display, $display_refunded );
	}

	/*
	|--------------------------------------------------------------------------
	| CRUD methods
	|--------------------------------------------------------------------------
	|
	| Methods which create, read, update and delete orders from the database.
	| Written in abstract fashion so that the way orders are stored can be
	| changed more easily in the future.
	|
	| A save method is included for convenience (chooses update or create based
	| on if the order exists yet).
	|
	*/

	/**
	 * Save data to the database.
	 *
	 * @since 3.0.0
	 * @return int order ID
	 */
	public function save() {
		$this->maybe_set_user_billing_email();
		parent::save();
		$this->status_transition();

		return $this->get_id();
	}

	/**
	 * Log an error about this order is exception is encountered.
	 *
	 * @param Exception $e Exception object.
	 * @param string    $message Message regarding exception thrown.
	 * @since 3.7.0
	 */
	protected function handle_exception( $e, $message = 'Error' ) {
		wc_get_logger()->error(
			$message,
			array(
				'order' => $this,
				'error' => $e,
			)
		);
		$this->add_order_note( $message . ' ' . $e->getMessage() );
	}

	/**
	 * Set order status.
	 *
	 * @since 3.0.0
	 * @param string $new_status    Status to change the order to. No internal wc- prefix is required.
	 * @param string $note          Optional note to add.
	 * @param bool   $manual_update Is this a manual order status change?.
	 * @return array
	 */
	public function set_status( $new_status, $note = '', $manual_update = false ) {
		$result = parent::set_status( $new_status );

		if ( true === $this->object_read && ! empty( $result['from'] ) && $result['from'] !== $result['to'] ) {
			$this->status_transition = array(
				'from'   => ! empty( $this->status_transition['from'] ) ? $this->status_transition['from'] : $result['from'],
				'to'     => $result['to'],
				'note'   => $note,
				'manual' => (bool) $manual_update,
			);

			if ( $manual_update ) {
				do_action( 'woocommerce_order_edit_status', $this->get_id(), $result['to'] );
			}

			$this->maybe_set_date_paid();
			$this->maybe_set_date_completed();
		}

		return $result;
	}

	/**
	 * Maybe set date paid.
	 *
	 * Sets the date paid variable when transitioning to the payment complete
	 * order status. This is either processing or completed. This is not filtered
	 * to avoid infinite loops e.g. if loading an order via the filter.
	 *
	 * Date paid is set once in this manner - only when it is not already set.
	 * This ensures the data exists even if a gateway does not use the
	 * `payment_complete` method.
	 *
	 * @since 3.0.0
	 */
	public function maybe_set_date_paid() {
		// This logic only runs if the date_paid prop has not been set yet.
		if ( ! $this->get_date_paid( 'edit' ) ) {
			/**
			 * Filters the order status to set after payment complete.
			 *
			 * @param string   $status        Order status.
			 * @param int      $order_id      Order ID.
			 * @param WC_Order $this          Order object.
			 * @since 2.7.0
			 */
			$payment_completed_status = apply_filters( 'woocommerce_payment_complete_order_status', $this->needs_processing() ? OrderStatus::PROCESSING : OrderStatus::COMPLETED, $this->get_id(), $this );

			if ( $this->has_status( $payment_completed_status ) ) {
				// If payment complete status is reached, set paid now.
				$this->set_date_paid( time() );

			} elseif ( OrderStatus::PROCESSING === $payment_completed_status && $this->has_status( OrderStatus::COMPLETED ) ) {
				// If payment complete status was processing, but we've passed that and still have no date, set it now.
				$this->set_date_paid( time() );
			}
		}
	}

	/**
	 * Maybe set date completed.
	 *
	 * Sets the date completed variable when transitioning to completed status.
	 *
	 * @since 3.0.0
	 */
	protected function maybe_set_date_completed() {
		if ( $this->has_status( OrderStatus::COMPLETED ) ) {
			$this->set_date_completed( time() );
		}
	}

	/**
	 * Updates status of order immediately.
	 *
	 * @uses self::set_status()
	 * @param string $new_status    Status to change the order to. No internal wc- prefix is required.
	 * @param string $note          Optional note to add.
	 * @param bool   $manual        Is this a manual order status change?.
	 * @return bool
	 */
	public function update_status( $new_status, $note = '', $manual = false ) {
		if ( ! $this->get_id() ) { // Order must exist.
			return false;
		}

		try {
			$this->set_status( $new_status, $note, $manual );
			$this->save();
		} catch ( Exception $e ) {
			$logger = wc_get_logger();
			$logger->error(
				sprintf(
					'Error updating status for order #%d',
					$this->get_id()
				),
				array(
					'order' => $this,
					'error' => $e,
				)
			);
			$this->add_order_note( __( 'Update status event failed.', 'woocommerce' ) . ' ' . $e->getMessage() );
			return false;
		}
		return true;
	}

	/**
	 * Handle the status transition.
	 */
	protected function status_transition() {
		$status_transition = $this->status_transition;

		// Reset status transition variable.
		$this->status_transition = false;

		if ( $status_transition ) {
			try {
				/**
				 * Fires when order status is changed.
				 *
				 * @since 1.0.0
				 *
				 * @param int Order ID.
				 * @param WC_Order $order Order object.
				 * @param array $status_transition {
				 *      Status transition data.
				 *
				 *      @type string $from Order status from.
				 *      @type string $to Order status to
				 *      @type string $note Order note.
				 *      @type boolean $manual True if the order is manually changed.
				 * }
				 */
				do_action( 'woocommerce_order_status_' . $status_transition['to'], $this->get_id(), $this, $status_transition );

				if ( ! empty( $status_transition['from'] ) ) {
					/* translators: 1: old order status 2: new order status */
					$transition_note = sprintf( __( 'Order status changed from %1$s to %2$s.', 'woocommerce' ), wc_get_order_status_name( $status_transition['from'] ), wc_get_order_status_name( $status_transition['to'] ) );

					// Note the transition occurred.
					$this->add_status_transition_note( $transition_note, $status_transition );

					do_action( 'woocommerce_order_status_' . $status_transition['from'] . '_to_' . $status_transition['to'], $this->get_id(), $this );
					do_action( 'woocommerce_order_status_changed', $this->get_id(), $status_transition['from'], $status_transition['to'], $this );

					// Work out if this was for a payment, and trigger a payment_status hook instead.
					if (
						/**
						 * Filter the valid order statuses for payment.
						 *
						 * @param array    $valid_order_statuses Array of valid order statuses for payment.
						 * @param WC_Order $order                Order object.
						 * @since 4.0.0
						 */
						in_array( $status_transition['from'], apply_filters( 'woocommerce_valid_order_statuses_for_payment', array( OrderStatus::PENDING, OrderStatus::FAILED ), $this ), true )
						&& in_array( $status_transition['to'], wc_get_is_paid_statuses(), true )
					) {
						/**
						 * Fires when the order progresses from a pending payment status to a paid one.
						 *
						 * @since 3.9.0
						 * @param int Order ID
						 * @param WC_Order Order object
						 */
						do_action( 'woocommerce_order_payment_status_changed', $this->get_id(), $this );
					}
				} else {
					/* translators: %s: new order status */
					$transition_note = sprintf( __( 'Order status set to %s.', 'woocommerce' ), wc_get_order_status_name( $status_transition['to'] ) );

					// Note the transition occurred.
					$this->add_status_transition_note( $transition_note, $status_transition );
				}
			} catch ( Exception $e ) {
				$logger = wc_get_logger();
				$logger->error(
					sprintf(
						'Status transition of order #%d errored!',
						$this->get_id()
					),
					array(
						'order' => $this,
						'error' => $e,
					)
				);
				$this->add_order_note( __( 'Error during status transition.', 'woocommerce' ) . ' ' . $e->getMessage() );
			}
		}
	}

	/*
	|--------------------------------------------------------------------------
	| Getters
	|--------------------------------------------------------------------------
	|
	| Methods for getting data from the order object.
	|
	*/

	/**
	 * Get basic order data in array format.
	 *
	 * @return array
	 */
	public function get_base_data() {
		return array_merge(
			array( 'id' => $this->get_id() ),
			$this->data,
			array( 'number' => $this->get_order_number() )
		);
	}

	/**
	 * Get all class data in array format.
	 *
	 * @since 3.0.0
	 * @return array
	 */
	public function get_data() {
		return array_merge(
			$this->get_base_data(),
			array(
				'meta_data'      => $this->get_meta_data(),
				'line_items'     => $this->get_items( 'line_item' ),
				'tax_lines'      => $this->get_items( 'tax' ),
				'shipping_lines' => $this->get_items( 'shipping' ),
				'fee_lines'      => $this->get_items( 'fee' ),
				'coupon_lines'   => $this->get_items( 'coupon' ),
			)
		);
	}

	/**
	 * Expands the shipping and billing information in the changes array.
	 */
	public function get_changes() {
		$changed_props = parent::get_changes();
		$subs          = array( 'shipping', 'billing' );
		foreach ( $subs as $sub ) {
			if ( ! empty( $changed_props[ $sub ] ) ) {
				foreach ( $changed_props[ $sub ] as $sub_prop => $value ) {
					$changed_props[ $sub . '_' . $sub_prop ] = $value;
				}
			}
		}
		if ( isset( $changed_props['customer_note'] ) ) {
			$changed_props['post_excerpt'] = $changed_props['customer_note'];
		}
		return $changed_props;
	}

	/**
	 * Gets the order number for display (by default, order ID).
	 *
	 * @return string
	 */
	public function get_order_number() {
		return (string) apply_filters( 'woocommerce_order_number', $this->get_id(), $this );
	}

	/**
	 * Get order key.
	 *
	 * @since  3.0.0
	 * @param  string $context What the value is for. Valid values are view and edit.
	 * @return string
	 */
	public function get_order_key( $context = 'view' ) {
		return $this->get_prop( 'order_key', $context );
	}

	/**
	 * Get customer_id.
	 *
	 * @param  string $context What the value is for. Valid values are view and edit.
	 * @return int
	 */
	public function get_customer_id( $context = 'view' ) {
		return $this->get_prop( 'customer_id', $context );
	}

	/**
	 * Alias for get_customer_id().
	 *
	 * @param  string $context What the value is for. Valid values are view and edit.
	 * @return int
	 */
	public function get_user_id( $context = 'view' ) {
		return $this->get_customer_id( $context );
	}

	/**
	 * Get the user associated with the order. False for guests.
	 *
	 * @return WP_User|false
	 */
	public function get_user() {
		return $this->get_user_id() ? get_user_by( 'id', $this->get_user_id() ) : false;
	}

	/**
	 * Gets a prop for a getter method.
	 *
	 * @since  3.0.0
	 * @param  string $prop Name of prop to get.
	 * @param  string $address_type Type of address; 'billing' or 'shipping'.
	 * @param  string $context What the value is for. Valid values are view and edit.
	 * @return mixed
	 */
	protected function get_address_prop( $prop, $address_type = 'billing', $context = 'view' ) {
		$value = null;

		if ( array_key_exists( $prop, $this->data[ $address_type ] ) ) {
			$value = isset( $this->changes[ $address_type ][ $prop ] ) ? $this->changes[ $address_type ][ $prop ] : $this->data[ $address_type ][ $prop ];

			if ( 'view' === $context ) {
				/**
				 * Filter: 'woocommerce_order_get_[billing|shipping]_[prop]'
				 *
				 * Allow developers to change the returned value for any order address property.
				 *
				 * @since 3.6.0
				 * @param string   $value The address property value.
				 * @param WC_Order $order The order object being read.
				 */
				$value = apply_filters( $this->get_hook_prefix() . $address_type . '_' . $prop, $value, $this );
			}
		}
		return $value;
	}

	/**
	 * Get billing first name.
	 *
	 * @param  string $context What the value is for. Valid values are view and edit.
	 * @return string
	 */
	public function get_billing_first_name( $context = 'view' ) {
		return $this->get_address_prop( 'first_name', 'billing', $context );
	}

	/**
	 * Get billing last name.
	 *
	 * @param  string $context What the value is for. Valid values are view and edit.
	 * @return string
	 */
	public function get_billing_last_name( $context = 'view' ) {
		return $this->get_address_prop( 'last_name', 'billing', $context );
	}

	/**
	 * Get billing company.
	 *
	 * @param  string $context What the value is for. Valid values are view and edit.
	 * @return string
	 */
	public function get_billing_company( $context = 'view' ) {
		return $this->get_address_prop( 'company', 'billing', $context );
	}

	/**
	 * Get billing address line 1.
	 *
	 * @param  string $context What the value is for. Valid values are view and edit.
	 * @return string
	 */
	public function get_billing_address_1( $context = 'view' ) {
		return $this->get_address_prop( 'address_1', 'billing', $context );
	}

	/**
	 * Get billing address line 2.
	 *
	 * @param  string $context What the value is for. Valid values are view and edit.
	 * @return string
	 */
	public function get_billing_address_2( $context = 'view' ) {
		return $this->get_address_prop( 'address_2', 'billing', $context );
	}

	/**
	 * Get billing city.
	 *
	 * @param  string $context What the value is for. Valid values are view and edit.
	 * @return string
	 */
	public function get_billing_city( $context = 'view' ) {
		return $this->get_address_prop( 'city', 'billing', $context );
	}

	/**
	 * Get billing state.
	 *
	 * @param  string $context What the value is for. Valid values are view and edit.
	 * @return string
	 */
	public function get_billing_state( $context = 'view' ) {
		return $this->get_address_prop( 'state', 'billing', $context );
	}

	/**
	 * Get billing postcode.
	 *
	 * @param  string $context What the value is for. Valid values are view and edit.
	 * @return string
	 */
	public function get_billing_postcode( $context = 'view' ) {
		return $this->get_address_prop( 'postcode', 'billing', $context );
	}

	/**
	 * Get billing country.
	 *
	 * @param  string $context What the value is for. Valid values are view and edit.
	 * @return string
	 */
	public function get_billing_country( $context = 'view' ) {
		return $this->get_address_prop( 'country', 'billing', $context );
	}

	/**
	 * Get billing email.
	 *
	 * @param  string $context What the value is for. Valid values are view and edit.
	 * @return string
	 */
	public function get_billing_email( $context = 'view' ) {
		return $this->get_address_prop( 'email', 'billing', $context );
	}

	/**
	 * Get billing phone.
	 *
	 * @param  string $context What the value is for. Valid values are view and edit.
	 * @return string
	 */
	public function get_billing_phone( $context = 'view' ) {
		return $this->get_address_prop( 'phone', 'billing', $context );
	}

	/**
	 * Get shipping first name.
	 *
	 * @param  string $context What the value is for. Valid values are view and edit.
	 * @return string
	 */
	public function get_shipping_first_name( $context = 'view' ) {
		return $this->get_address_prop( 'first_name', 'shipping', $context );
	}

	/**
	 * Get shipping_last_name.
	 *
	 * @param  string $context What the value is for. Valid values are view and edit.
	 * @return string
	 */
	public function get_shipping_last_name( $context = 'view' ) {
		return $this->get_address_prop( 'last_name', 'shipping', $context );
	}

	/**
	 * Get shipping company.
	 *
	 * @param  string $context What the value is for. Valid values are view and edit.
	 * @return string
	 */
	public function get_shipping_company( $context = 'view' ) {
		return $this->get_address_prop( 'company', 'shipping', $context );
	}

	/**
	 * Get shipping address line 1.
	 *
	 * @param  string $context What the value is for. Valid values are view and edit.
	 * @return string
	 */
	public function get_shipping_address_1( $context = 'view' ) {
		return $this->get_address_prop( 'address_1', 'shipping', $context );
	}

	/**
	 * Get shipping address line 2.
	 *
	 * @param  string $context What the value is for. Valid values are view and edit.
	 * @return string
	 */
	public function get_shipping_address_2( $context = 'view' ) {
		return $this->get_address_prop( 'address_2', 'shipping', $context );
	}

	/**
	 * Get shipping city.
	 *
	 * @param  string $context What the value is for. Valid values are view and edit.
	 * @return string
	 */
	public function get_shipping_city( $context = 'view' ) {
		return $this->get_address_prop( 'city', 'shipping', $context );
	}

	/**
	 * Get shipping state.
	 *
	 * @param  string $context What the value is for. Valid values are view and edit.
	 * @return string
	 */
	public function get_shipping_state( $context = 'view' ) {
		return $this->get_address_prop( 'state', 'shipping', $context );
	}

	/**
	 * Get shipping postcode.
	 *
	 * @param  string $context What the value is for. Valid values are view and edit.
	 * @return string
	 */
	public function get_shipping_postcode( $context = 'view' ) {
		return $this->get_address_prop( 'postcode', 'shipping', $context );
	}

	/**
	 * Get shipping country.
	 *
	 * @param  string $context What the value is for. Valid values are view and edit.
	 * @return string
	 */
	public function get_shipping_country( $context = 'view' ) {
		return $this->get_address_prop( 'country', 'shipping', $context );
	}

	/**
	 * Get shipping phone.
	 *
	 * @since  5.6.0
	 * @param  string $context What the value is for. Valid values are view and edit.
	 * @return string
	 */
	public function get_shipping_phone( $context = 'view' ) {
		return $this->get_address_prop( 'phone', 'shipping', $context );
	}

	/**
	 * Get the payment method.
	 *
	 * @param  string $context What the value is for. Valid values are view and edit.
	 * @return string
	 */
	public function get_payment_method( $context = 'view' ) {
		return $this->get_prop( 'payment_method', $context );
	}

	/**
	 * Get payment method title.
	 *
	 * @param  string $context What the value is for. Valid values are view and edit.
	 * @return string
	 */
	public function get_payment_method_title( $context = 'view' ) {
		return $this->get_prop( 'payment_method_title', $context );
	}

	/**
	 * Get transaction id.
	 *
	 * @param  string $context What the value is for. Valid values are view and edit.
	 * @return string
	 */
	public function get_transaction_id( $context = 'view' ) {
		return $this->get_prop( 'transaction_id', $context );
	}

	/**
	 * Get customer ip address.
	 *
	 * @param  string $context What the value is for. Valid values are view and edit.
	 * @return string
	 */
	public function get_customer_ip_address( $context = 'view' ) {
		return $this->get_prop( 'customer_ip_address', $context );
	}

	/**
	 * Get customer user agent.
	 *
	 * @param  string $context What the value is for. Valid values are view and edit.
	 * @return string
	 */
	public function get_customer_user_agent( $context = 'view' ) {
		return $this->get_prop( 'customer_user_agent', $context );
	}

	/**
	 * Get created via.
	 *
	 * @param  string $context What the value is for. Valid values are view and edit.
	 * @return string
	 */
	public function get_created_via( $context = 'view' ) {
		return $this->get_prop( 'created_via', $context );
	}

	/**
	 * Get customer note.
	 *
	 * @param  string $context What the value is for. Valid values are view and edit.
	 * @return string
	 */
	public function get_customer_note( $context = 'view' ) {
		return $this->get_prop( 'customer_note', $context );
	}

	/**
	 * Get date completed.
	 *
	 * @param  string $context What the value is for. Valid values are view and edit.
	 * @return WC_DateTime|NULL object if the date is set or null if there is no date.
	 */
	public function get_date_completed( $context = 'view' ) {
		return $this->get_prop( 'date_completed', $context );
	}

	/**
	 * Get date paid.
	 *
	 * @param  string $context What the value is for. Valid values are view and edit.
	 * @return WC_DateTime|NULL object if the date is set or null if there is no date.
	 */
	public function get_date_paid( $context = 'view' ) {
		$date_paid = $this->get_prop( 'date_paid', $context );

		if ( 'view' === $context && ! $date_paid && version_compare( $this->get_version( 'edit' ), '3.0', '<' )
			/**
			 * Filters the order status to set after payment complete.
			 *
			 * @param string   $status        Order status.
			 * @param int      $order_id      Order ID.
			 * @param WC_Order $this          Order object.
			 * @since 3.0.0
			 */
			&& $this->has_status( apply_filters( 'woocommerce_payment_complete_order_status', $this->needs_processing() ? OrderStatus::PROCESSING : OrderStatus::COMPLETED, $this->get_id(), $this ) ) ) {
			// In view context, return a date if missing.
			$date_paid = $this->get_date_created( 'edit' );
		}
		return $date_paid;
	}

	/**
	 * Get cart hash.
	 *
	 * @param  string $context What the value is for. Valid values are view and edit.
	 * @return string
	 */
	public function get_cart_hash( $context = 'view' ) {
		return $this->get_prop( 'cart_hash', $context );
	}

	/**
	 * Returns the requested address in raw, non-formatted way.
	 * Note: Merges raw data with get_prop data so changes are returned too.
	 *
	 * @since  2.4.0
	 * @param  string $address_type Type of address; 'billing' or 'shipping'.
	 * @return array The stored address after filter.
	 */
	public function get_address( $address_type = 'billing' ) {
		/**
		 * Filter: 'woocommerce_get_order_address'
		 *
		 * Allow developers to change the returned value for an order's billing or shipping address.
		 *
		 * @since 2.4.0
		 * @param array  $address_data The raw address data merged with the data from get_prop.
		 * @param string $address_type Type of address; 'billing' or 'shipping'.
		 */
		return apply_filters( 'woocommerce_get_order_address', array_merge( $this->data[ $address_type ], $this->get_prop( $address_type, 'view' ) ), $address_type, $this );
	}

	/**
	 * Get a formatted shipping address for the order.
	 *
	 * @return string
	 */
	public function get_shipping_address_map_url() {
		$address = $this->get_address( 'shipping' );

		// Remove name and company before generate the Google Maps URL.
		unset( $address['first_name'], $address['last_name'], $address['company'], $address['phone'] );

		$address = apply_filters( 'woocommerce_shipping_address_map_url_parts', $address, $this );

		return apply_filters( 'woocommerce_shipping_address_map_url', 'https://maps.google.com/maps?&q=' . rawurlencode( implode( ', ', $address ) ) . '&z=16', $this );
	}

	/**
	 * Get a formatted billing full name.
	 *
	 * @return string
	 */
	public function get_formatted_billing_full_name() {
		/* translators: 1: first name 2: last name */
		return sprintf( _x( '%1$s %2$s', 'full name', 'woocommerce' ), $this->get_billing_first_name(), $this->get_billing_last_name() );
	}

	/**
	 * Get a formatted shipping full name.
	 *
	 * @return string
	 */
	public function get_formatted_shipping_full_name() {
		/* translators: 1: first name 2: last name */
		return sprintf( _x( '%1$s %2$s', 'full name', 'woocommerce' ), $this->get_shipping_first_name(), $this->get_shipping_last_name() );
	}

	/**
	 * Get a formatted billing address for the order.
	 *
	 * @param string $empty_content Content to show if no address is present. @since 3.3.0.
	 * @return string
	 */
	public function get_formatted_billing_address( $empty_content = '' ) {
		$raw_address = apply_filters( 'woocommerce_order_formatted_billing_address', $this->get_address( 'billing' ), $this );
		$address     = WC()->countries->get_formatted_address( $raw_address );

		/**
		 * Filter orders formatted billing address.
		 *
		 * @since 3.8.0
		 * @param string   $address     Formatted billing address string.
		 * @param array    $raw_address Raw billing address.
		 * @param WC_Order $order       Order data. @since 3.9.0
		 */
		return apply_filters( 'woocommerce_order_get_formatted_billing_address', $address ? $address : $empty_content, $raw_address, $this );
	}

	/**
	 * Get a formatted shipping address for the order.
	 *
	 * @param string $empty_content Content to show if no address is present. @since 3.3.0.
	 * @return string
	 */
	public function get_formatted_shipping_address( $empty_content = '' ) {
		$address     = '';
		$raw_address = $this->get_address( 'shipping' );

		if ( $this->has_shipping_address() ) {
			$raw_address = apply_filters( 'woocommerce_order_formatted_shipping_address', $raw_address, $this );
			$address     = WC()->countries->get_formatted_address( $raw_address );
		}

		/**
		 * Filter orders formatted shipping address.
		 *
		 * @since 3.8.0
		 * @param string   $address     Formatted shipping address string.
		 * @param array    $raw_address Raw shipping address.
		 * @param WC_Order $order       Order data. @since 3.9.0
		 */
		return apply_filters( 'woocommerce_order_get_formatted_shipping_address', $address ? $address : $empty_content, $raw_address, $this );
	}

	/**
	 * Returns true if the order has a billing address.
	 *
	 * @since  3.0.4
	 * @return boolean
	 */
	public function has_billing_address() {
		return $this->get_billing_address_1() || $this->get_billing_address_2();
	}

	/**
	 * Returns true if the order has a shipping address.
	 *
	 * @since  3.0.4
	 * @return boolean
	 */
	public function has_shipping_address() {
		return $this->get_shipping_address_1() || $this->get_shipping_address_2();
	}

	/**
	 * Gets information about whether stock was reduced.
	 *
	 * @since 7.0.0
	 * @param string $context What the value is for. Valid values are view and edit.
	 * @return bool
	 */
	public function get_order_stock_reduced( string $context = 'view' ) {
		return wc_string_to_bool( $this->get_prop( 'order_stock_reduced', $context ) );
	}

	/**
	 * Gets information about whether permissions were generated yet.
	 *
	 * @param string $context What the value is for. Valid values are view and edit.
	 *
	 * @return bool True if permissions were generated, false otherwise.
	 */
	public function get_download_permissions_granted( string $context = 'view' ) {
		return wc_string_to_bool( $this->get_prop( 'download_permissions_granted', $context ) );
	}

	/**
	 * Whether email have been sent for this order.
	 *
	 * @param string $context What the value is for. Valid values are view and edit.
	 *
	 * @return bool
	 */
	public function get_new_order_email_sent( string $context = 'view' ) {
		return wc_string_to_bool( $this->get_prop( 'new_order_email_sent', $context ) );
	}

	/**
	 * Gets information about whether sales were recorded.
	 *
	 * @param string $context What the value is for. Valid values are view and edit.
	 *
	 * @return bool True if sales were recorded, false otherwise.
	 */
	public function get_recorded_sales( string $context = 'view' ) {
		return wc_string_to_bool( $this->get_prop( 'recorded_sales', $context ) );
	}

	/*
	|--------------------------------------------------------------------------
	| Setters
	|--------------------------------------------------------------------------
	|
	| Functions for setting order data. These should not update anything in the
	| database itself and should only change what is stored in the class
	| object. However, for backwards compatibility pre 3.0.0 some of these
	| setters may handle both.
	|
	*/

	/**
	 * Sets a prop for a setter method.
	 *
	 * @since 3.0.0
	 * @param string $prop Name of prop to set.
	 * @param string $address_type Type of address; 'billing' or 'shipping'.
	 * @param mixed  $value Value of the prop.
	 */
	protected function set_address_prop( $prop, $address_type, $value ) {
		if ( array_key_exists( $prop, $this->data[ $address_type ] ) ) {
			if ( true === $this->object_read ) {
				if ( $value !== $this->data[ $address_type ][ $prop ] || ( isset( $this->changes[ $address_type ] ) && array_key_exists( $prop, $this->changes[ $address_type ] ) ) ) {
					$this->changes[ $address_type ][ $prop ] = $value;
				}
			} else {
				$this->data[ $address_type ][ $prop ] = $value;
			}
		}
	}

	/**
	 * Setter for billing address, expects the $address parameter to be key value pairs for individual address props.
	 *
	 * @param array $address Address to set.
	 *
	 * @return void
	 */
	public function set_billing_address( array $address ) {
		foreach ( $address as $key => $value ) {
			$this->set_address_prop( $key, 'billing', $value );
		}
	}

	/**
	 * Shortcut for calling set_billing_address.
	 *
	 * This is useful in scenarios where set_$prop_name is invoked, and since we store the billing address as 'billing' prop in data, it can be called directly.
	 *
	 * @param array $address Address to set.
	 *
	 * @return void
	 */
	public function set_billing( array $address ) {
		$this->set_billing_address( $address );
	}

	/**
	 * Setter for shipping address, expects the $address parameter to be key value pairs for individual address props.
	 *
	 * @param array $address Address to set.
	 *
	 * @return void
	 */
	public function set_shipping_address( array $address ) {
		foreach ( $address as $key => $value ) {
			$this->set_address_prop( $key, 'shipping', $value );
		}
	}

	/**
	 * Shortcut for calling set_shipping_address. This is useful in scenarios where set_$prop_name is invoked, and since we store the shipping address as 'shipping' prop in data, it can be called directly.
	 *
	 * @param array $address Address to set.
	 *
	 * @return void
	 */
	public function set_shipping( array $address ) {
		$this->set_shipping_address( $address );
	}

	/**
	 * Set order key.
	 *
	 * @param string $value Max length 22 chars.
	 * @throws WC_Data_Exception Throws exception when invalid data is found.
	 */
	public function set_order_key( $value ) {
		$this->set_prop( 'order_key', substr( $value, 0, 22 ) );
	}

	/**
	 * Set customer id.
	 *
	 * @param int $value Customer ID.
	 * @throws WC_Data_Exception Throws exception when invalid data is found.
	 */
	public function set_customer_id( $value ) {
		$this->set_prop( 'customer_id', absint( $value ) );
	}

	/**
	 * Set billing first name.
	 *
	 * @param string $value Billing first name.
	 * @throws WC_Data_Exception Throws exception when invalid data is found.
	 */
	public function set_billing_first_name( $value ) {
		$this->set_address_prop( 'first_name', 'billing', $value );
	}

	/**
	 * Set billing last name.
	 *
	 * @param string $value Billing last name.
	 * @throws WC_Data_Exception Throws exception when invalid data is found.
	 */
	public function set_billing_last_name( $value ) {
		$this->set_address_prop( 'last_name', 'billing', $value );
	}

	/**
	 * Set billing company.
	 *
	 * @param string $value Billing company.
	 * @throws WC_Data_Exception Throws exception when invalid data is found.
	 */
	public function set_billing_company( $value ) {
		$this->set_address_prop( 'company', 'billing', $value );
	}

	/**
	 * Set billing address line 1.
	 *
	 * @param string $value Billing address line 1.
	 * @throws WC_Data_Exception Throws exception when invalid data is found.
	 */
	public function set_billing_address_1( $value ) {
		$this->set_address_prop( 'address_1', 'billing', $value );
	}

	/**
	 * Set billing address line 2.
	 *
	 * @param string $value Billing address line 2.
	 * @throws WC_Data_Exception Throws exception when invalid data is found.
	 */
	public function set_billing_address_2( $value ) {
		$this->set_address_prop( 'address_2', 'billing', $value );
	}

	/**
	 * Set billing city.
	 *
	 * @param string $value Billing city.
	 * @throws WC_Data_Exception Throws exception when invalid data is found.
	 */
	public function set_billing_city( $value ) {
		$this->set_address_prop( 'city', 'billing', $value );
	}

	/**
	 * Set billing state.
	 *
	 * @param string $value Billing state.
	 * @throws WC_Data_Exception Throws exception when invalid data is found.
	 */
	public function set_billing_state( $value ) {
		$this->set_address_prop( 'state', 'billing', $value );
	}

	/**
	 * Set billing postcode.
	 *
	 * @param string $value Billing postcode.
	 * @throws WC_Data_Exception Throws exception when invalid data is found.
	 */
	public function set_billing_postcode( $value ) {
		$this->set_address_prop( 'postcode', 'billing', $value );
	}

	/**
	 * Set billing country.
	 *
	 * @param string $value Billing country.
	 * @throws WC_Data_Exception Throws exception when invalid data is found.
	 */
	public function set_billing_country( $value ) {
		$this->set_address_prop( 'country', 'billing', $value );
	}

	/**
	 * Maybe set empty billing email to that of the user who owns the order.
	 */
	protected function maybe_set_user_billing_email() {
		$user = $this->get_user();
		if ( ! $this->get_billing_email() && $user ) {
			try {
				$this->set_billing_email( $user->user_email );
			} catch ( WC_Data_Exception $e ) {
				unset( $e );
			}
		}
	}

	/**
	 * Set billing email.
	 *
	 * @param string $value Billing email.
	 * @throws WC_Data_Exception Throws exception when invalid data is found.
	 */
	public function set_billing_email( $value ) {
		if ( $value && ! is_email( $value ) ) {
			$this->error( 'order_invalid_billing_email', __( 'Invalid billing email address', 'woocommerce' ) );
		}
		$this->set_address_prop( 'email', 'billing', sanitize_email( $value ) );
	}

	/**
	 * Set billing phone.
	 *
	 * @param string $value Billing phone.
	 * @throws WC_Data_Exception Throws exception when invalid data is found.
	 */
	public function set_billing_phone( $value ) {
		$this->set_address_prop( 'phone', 'billing', $value );
	}

	/**
	 * Set shipping first name.
	 *
	 * @param string $value Shipping first name.
	 * @throws WC_Data_Exception Throws exception when invalid data is found.
	 */
	public function set_shipping_first_name( $value ) {
		$this->set_address_prop( 'first_name', 'shipping', $value );
	}

	/**
	 * Set shipping last name.
	 *
	 * @param string $value Shipping last name.
	 * @throws WC_Data_Exception Throws exception when invalid data is found.
	 */
	public function set_shipping_last_name( $value ) {
		$this->set_address_prop( 'last_name', 'shipping', $value );
	}

	/**
	 * Set shipping company.
	 *
	 * @param string $value Shipping company.
	 * @throws WC_Data_Exception Throws exception when invalid data is found.
	 */
	public function set_shipping_company( $value ) {
		$this->set_address_prop( 'company', 'shipping', $value );
	}

	/**
	 * Set shipping address line 1.
	 *
	 * @param string $value Shipping address line 1.
	 * @throws WC_Data_Exception Throws exception when invalid data is found.
	 */
	public function set_shipping_address_1( $value ) {
		$this->set_address_prop( 'address_1', 'shipping', $value );
	}

	/**
	 * Set shipping address line 2.
	 *
	 * @param string $value Shipping address line 2.
	 * @throws WC_Data_Exception Throws exception when invalid data is found.
	 */
	public function set_shipping_address_2( $value ) {
		$this->set_address_prop( 'address_2', 'shipping', $value );
	}

	/**
	 * Set shipping city.
	 *
	 * @param string $value Shipping city.
	 * @throws WC_Data_Exception Throws exception when invalid data is found.
	 */
	public function set_shipping_city( $value ) {
		$this->set_address_prop( 'city', 'shipping', $value );
	}

	/**
	 * Set shipping state.
	 *
	 * @param string $value Shipping state.
	 * @throws WC_Data_Exception Throws exception when invalid data is found.
	 */
	public function set_shipping_state( $value ) {
		$this->set_address_prop( 'state', 'shipping', $value );
	}

	/**
	 * Set shipping postcode.
	 *
	 * @param string $value Shipping postcode.
	 * @throws WC_Data_Exception Throws exception when invalid data is found.
	 */
	public function set_shipping_postcode( $value ) {
		$this->set_address_prop( 'postcode', 'shipping', $value );
	}

	/**
	 * Set shipping country.
	 *
	 * @param string $value Shipping country.
	 * @throws WC_Data_Exception Throws exception when invalid data is found.
	 */
	public function set_shipping_country( $value ) {
		$this->set_address_prop( 'country', 'shipping', $value );
	}

	/**
	 * Set shipping phone.
	 *
	 * @since 5.6.0
	 * @param string $value Shipping phone.
	 * @throws WC_Data_Exception Throws exception when invalid data is found.
	 */
	public function set_shipping_phone( $value ) {
		$this->set_address_prop( 'phone', 'shipping', $value );
	}

	/**
	 * Set the payment method.
	 *
	 * @param string $payment_method Supports WC_Payment_Gateway for bw compatibility with < 3.0.
	 * @throws WC_Data_Exception Throws exception when invalid data is found.
	 */
	public function set_payment_method( $payment_method = '' ) {
		if ( is_object( $payment_method ) ) {
			$this->set_payment_method( $payment_method->id );
			$this->set_payment_method_title( $payment_method->get_title() );
		} elseif ( '' === $payment_method ) {
			$this->set_prop( 'payment_method', '' );
			$this->set_prop( 'payment_method_title', '' );
		} else {
			$this->set_prop( 'payment_method', $payment_method );
		}
	}

	/**
	 * Set payment method title.
	 *
	 * @param string $value Payment method title.
	 * @throws WC_Data_Exception Throws exception when invalid data is found.
	 */
	public function set_payment_method_title( $value ) {
		$this->set_prop( 'payment_method_title', $value );
	}

	/**
	 * Set transaction id.
	 *
	 * @param string $value Transaction id.
	 * @throws WC_Data_Exception Throws exception when invalid data is found.
	 */
	public function set_transaction_id( $value ) {
		$this->set_prop( 'transaction_id', $value );
	}

	/**
	 * Set customer ip address.
	 *
	 * @param string $value Customer ip address.
	 * @throws WC_Data_Exception Throws exception when invalid data is found.
	 */
	public function set_customer_ip_address( $value ) {
		$this->set_prop( 'customer_ip_address', $value );
	}

	/**
	 * Set customer user agent.
	 *
	 * @param string $value Customer user agent.
	 * @throws WC_Data_Exception Throws exception when invalid data is found.
	 */
	public function set_customer_user_agent( $value ) {
		$this->set_prop( 'customer_user_agent', $value );
	}

	/**
	 * Set created via.
	 *
	 * @param string $value Created via.
	 * @throws WC_Data_Exception Throws exception when invalid data is found.
	 */
	public function set_created_via( $value ) {
		$this->set_prop( 'created_via', $value );
	}

	/**
	 * Set customer note.
	 *
	 * @param string $value Customer note.
	 * @throws WC_Data_Exception Throws exception when invalid data is found.
	 */
	public function set_customer_note( $value ) {
		$this->set_prop( 'customer_note', $value );
	}

	/**
	 * Set date completed.
	 *
	 * @param  string|integer|null $date UTC timestamp, or ISO 8601 DateTime. If the DateTime string has no timezone or offset, WordPress site timezone will be assumed. Null if their is no date.
	 * @throws WC_Data_Exception Throws exception when invalid data is found.
	 */
	public function set_date_completed( $date = null ) {
		$this->set_date_prop( 'date_completed', $date );
	}

	/**
	 * Set date paid.
	 *
	 * @param  string|integer|null $date UTC timestamp, or ISO 8601 DateTime. If the DateTime string has no timezone or offset, WordPress site timezone will be assumed. Null if their is no date.
	 * @throws WC_Data_Exception Throws exception when invalid data is found.
	 */
	public function set_date_paid( $date = null ) {
		$this->set_date_prop( 'date_paid', $date );
	}

	/**
	 * Set cart hash.
	 *
	 * @param string $value Cart hash.
	 * @throws WC_Data_Exception Throws exception when invalid data is found.
	 */
	public function set_cart_hash( $value ) {
		$this->set_prop( 'cart_hash', $value );
	}

	/**
	 * Stores information about whether stock was reduced.
	 *
	 * @param bool|string $value True if stock was reduced, false if not.
	 *
	 * @return void
	 */
	public function set_order_stock_reduced( $value ) {
		$this->set_prop( 'order_stock_reduced', wc_string_to_bool( $value ) );
	}

	/**
	 * Stores information about whether permissions were generated yet.
	 *
	 * @param bool|string $value True if permissions were generated, false if not.
	 *
	 * @return void
	 */
	public function set_download_permissions_granted( $value ) {
		$this->set_prop( 'download_permissions_granted', wc_string_to_bool( $value ) );
	}

	/**
	 * Stores information about whether email was sent.
	 *
	 * @param bool|string $value True if email was sent, false if not.
	 *
	 * @return void
	 */
	public function set_new_order_email_sent( $value ) {
		$this->set_prop( 'new_order_email_sent', wc_string_to_bool( $value ) );
	}

	/**
	 * Stores information about whether sales were recorded.
	 *
	 * @param bool|string $value True if sales were recorded, false if not.
	 *
	 * @return void
	 */
	public function set_recorded_sales( $value ) {
		$this->set_prop( 'recorded_sales', wc_string_to_bool( $value ) );
	}

	/*
	|--------------------------------------------------------------------------
	| Conditionals
	|--------------------------------------------------------------------------
	|
	| Checks if a condition is true or false.
	|
	*/

	/**
	 * Check if an order key is valid.
	 *
	 * @param string $key Order key.
	 * @return bool
	 */
	public function key_is_valid( $key ) {
		return hash_equals( $this->get_order_key(), $key );
	}

	/**
	 * See if order matches cart_hash.
	 *
	 * @param string $cart_hash Cart hash.
	 * @return bool
	 */
	public function has_cart_hash( $cart_hash = '' ) {
		return hash_equals( $this->get_cart_hash(), $cart_hash ); // @codingStandardsIgnoreLine
	}

	/**
	 * Checks if an order can be edited, specifically for use on the Edit Order screen.
	 *
	 * @return bool
	 */
	public function is_editable() {
		/**
		 * Filter to check if an order is editable.
		 *
		 * @param bool     $is_editable Is the order editable.
		 * @param WC_Order $this        Order object.
		 * @since 2.7.0
		 */
		return apply_filters( 'wc_order_is_editable', in_array( $this->get_status(), array( OrderStatus::PENDING, OrderStatus::ON_HOLD, OrderStatus::AUTO_DRAFT ), true ), $this );
	}

	/**
	 * Returns if an order has been paid for based on the order status.
	 *
	 * @since 2.5.0
	 * @return bool
	 */
	public function is_paid() {
		return apply_filters( 'woocommerce_order_is_paid', $this->has_status( wc_get_is_paid_statuses() ), $this );
	}

	/**
	 * Checks if product download is permitted.
	 *
	 * @return bool
	 */
	public function is_download_permitted() {
		/**
		 * Filter to check if an order is downloadable.
		 *
		 * @param bool     $is_download_permitted Is the order downloadable.
		 * @param WC_Order $this                  Order object.
		 * @since 2.7.0
		 */
		return apply_filters( 'woocommerce_order_is_download_permitted', $this->has_status( OrderStatus::COMPLETED ) || ( 'yes' === get_option( 'woocommerce_downloads_grant_access_after_payment' ) && $this->has_status( OrderStatus::PROCESSING ) ), $this );
	}

	/**
	 * Checks if an order needs display the shipping address, based on shipping method.
	 *
	 * @return bool
	 */
	public function needs_shipping_address() {
		if ( 'no' === get_option( 'woocommerce_calc_shipping' ) ) {
			return false;
		}

		/**
		 * Filter to hide the shipping address for an order.
		 *
		 * @param array    $hide The shipping methods to hide the shipping address for.
		 * @param WC_Order $this The order object.
		 * @since 2.7.0
		 */
		$hide          = apply_filters( 'woocommerce_order_hide_shipping_address', LocalPickupUtils::get_local_pickup_method_ids(), $this );
		$needs_address = false;

		foreach ( $this->get_shipping_methods() as $shipping_method ) {
			$shipping_method_id = $shipping_method->get_method_id();

			if ( ! in_array( $shipping_method_id, $hide, true ) ) {
				$needs_address = true;
				break;
			}
		}

		return apply_filters( 'woocommerce_order_needs_shipping_address', $needs_address, $hide, $this );
	}

	/**
	 * Returns true if the order contains a downloadable product.
	 *
	 * @return bool
	 */
	public function has_downloadable_item() {
		foreach ( $this->get_items() as $item ) {
			if ( $item->is_type( 'line_item' ) ) {
				$product = $item->get_product();

				if ( $product && $product->has_file() ) {
					return true;
				}
			}
		}
		return false;
	}

	/**
	 * Get downloads from all line items for this order.
	 *
	 * @since  3.2.0
	 * @return array
	 */
	public function get_downloadable_items() {
		$downloads = array();

		foreach ( $this->get_items() as $item ) {
			if ( ! is_object( $item ) ) {
				continue;
			}

			// Check item refunds.
			$refunded_qty = abs( $this->get_qty_refunded_for_item( $item->get_id() ) );
			if ( $refunded_qty && $item->get_quantity() === $refunded_qty ) {
				continue;
			}

			if ( $item->is_type( 'line_item' ) ) {
				$item_downloads = $item->get_item_downloads();
				$product        = $item->get_product();
				if ( $product && $item_downloads ) {
					foreach ( $item_downloads as $file ) {
						$downloads[] = array(
							'download_url'        => $file['download_url'],
							'download_id'         => $file['id'],
							'product_id'          => $product->get_id(),
							'product_name'        => $product->get_name(),
							'product_url'         => $product->is_visible() ? $product->get_permalink() : '', // Since 3.3.0.
							'download_name'       => $file['name'],
							'order_id'            => $this->get_id(),
							'order_key'           => $this->get_order_key(),
							'downloads_remaining' => $file['downloads_remaining'],
							'access_expires'      => $file['access_expires'],
							'file'                => array(
								'name' => $file['name'],
								'file' => $file['file'],
							),
						);
					}
				}
			}
		}

		return apply_filters( 'woocommerce_order_get_downloadable_items', $downloads, $this );
	}

	/**
	 * Checks if an order needs payment, based on status and order total.
	 *
	 * @return bool
	 */
	public function needs_payment() {
		/**
		 * Filter the valid order statuses for payment.
		 *
		 * @param array    $valid_order_statuses Array of valid order statuses for payment.
		 * @param WC_Order $order                Order object.
		 * @since 2.7.0
		 */
		$valid_order_statuses = apply_filters( 'woocommerce_valid_order_statuses_for_payment', array( OrderStatus::PENDING, OrderStatus::FAILED ), $this );
		return apply_filters( 'woocommerce_order_needs_payment', ( $this->has_status( $valid_order_statuses ) && $this->get_total() > 0 ), $this, $valid_order_statuses );
	}

	/**
	 * See if the order needs processing before it can be completed.
	 *
	 * Orders which only contain virtual, downloadable items do not need admin
	 * intervention.
	 *
	 * Uses a transient so these calls are not repeated multiple times, and because
	 * once the order is processed this code/transient does not need to persist.
	 *
	 * @since 3.0.0
	 * @return bool
	 */
	public function needs_processing() {
		$transient_name   = 'wc_order_' . $this->get_id() . '_needs_processing';
		$needs_processing = get_transient( $transient_name );

		if ( false === $needs_processing ) {
			$needs_processing = 0;

			if ( count( $this->get_items() ) > 0 ) {
				foreach ( $this->get_items() as $item ) {
					if ( $item->is_type( 'line_item' ) ) {
						$product = $item->get_product();

						if ( ! $product ) {
							continue;
						}

						$virtual_downloadable_item = $product->is_downloadable() && $product->is_virtual();

						if ( apply_filters( 'woocommerce_order_item_needs_processing', ! $virtual_downloadable_item, $product, $this->get_id() ) ) {
							$needs_processing = 1;
							break;
						}
					}
				}
			}

			set_transient( $transient_name, $needs_processing, DAY_IN_SECONDS );
		}

		return 1 === absint( $needs_processing );
	}

	/*
	|--------------------------------------------------------------------------
	| URLs and Endpoints
	|--------------------------------------------------------------------------
	*/

	/**
	 * 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.
	 *
	 * @param  bool $on_checkout If on checkout.
	 * @return string
	 */
	public function get_checkout_payment_url( $on_checkout = false ) {
		$pay_url = wc_get_endpoint_url( 'order-pay', $this->get_id(), wc_get_checkout_url() );

		if ( $on_checkout ) {
			$pay_url = add_query_arg( 'key', $this->get_order_key(), $pay_url );
		} else {
			$pay_url = add_query_arg(
				array(
					'pay_for_order' => 'true',
					'key'           => $this->get_order_key(),
				),
				$pay_url
			);
		}

		return apply_filters( 'woocommerce_get_checkout_payment_url', $pay_url, $this );
	}

	/**
	 * Generates a URL for the thanks page (order received).
	 *
	 * @return string
	 */
	public function get_checkout_order_received_url() {
		$order_received_url = wc_get_endpoint_url( 'order-received', $this->get_id(), wc_get_checkout_url() );
		$order_received_url = add_query_arg( 'key', $this->get_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.
	 *
	 * @param string $redirect Redirect URL.
	 * @return string
	 */
	public function get_cancel_order_url( $redirect = '' ) {
		/**
		 * Filter the URL to cancel the order in the frontend.
		 *
		 * @since 2.2.0
		 *
		 * @param string $url
		 * @param WC_Order $order Order data.
		 * @param string $redirect Redirect URL.
		 */
		return apply_filters(
			'woocommerce_get_cancel_order_url',
			wp_nonce_url(
				add_query_arg(
					array(
						'cancel_order' => 'true',
						'order'        => $this->get_order_key(),
						'order_id'     => $this->get_id(),
						'redirect'     => $redirect,
					),
					$this->get_cancel_endpoint()
				),
				'woocommerce-cancel_order'
			),
			$this,
			$redirect
		);
	}

	/**
	 * Generates a raw (unescaped) cancel-order URL for use by payment gateways.
	 *
	 * @param string $redirect Redirect URL.
	 * @return string The unescaped cancel-order URL.
	 */
	public function get_cancel_order_url_raw( $redirect = '' ) {
		/**
		 * Filter the raw URL to cancel the order in the frontend.
		 *
		 * @since 2.2.0
		 *
		 * @param string $url
		 * @param WC_Order $order Order data.
		 * @param string $redirect Redirect URL.
		 */
		return apply_filters(
			'woocommerce_get_cancel_order_url_raw',
			add_query_arg(
				array(
					'cancel_order' => 'true',
					'order'        => $this->get_order_key(),
					'order_id'     => $this->get_id(),
					'redirect'     => $redirect,
					'_wpnonce'     => wp_create_nonce( 'woocommerce-cancel_order' ),
				),
				$this->get_cancel_endpoint()
			),
			$this,
			$redirect
		);
	}

	/**
	 * Helper method to return the cancel endpoint.
	 *
	 * @return string the cancel endpoint; either the cart page or the home page.
	 */
	public function get_cancel_endpoint() {
		$cancel_endpoint = wc_get_cart_url();
		if ( ! $cancel_endpoint ) {
			$cancel_endpoint = home_url();
		}

		if ( false === strpos( $cancel_endpoint, '?' ) ) {
			$cancel_endpoint = trailingslashit( $cancel_endpoint );
		}

		return $cancel_endpoint;
	}

	/**
	 * Generates a URL to view an order from the my account page.
	 *
	 * @return string
	 */
	public function get_view_order_url() {
		return apply_filters( 'woocommerce_get_view_order_url', wc_get_endpoint_url( 'view-order', $this->get_id(), wc_get_page_permalink( 'myaccount' ) ), $this );
	}

	/**
	 * Get's the URL to edit the order in the backend.
	 *
	 * @since 3.3.0
	 * @return string
	 */
	public function get_edit_order_url() {
		$edit_url = \Automattic\WooCommerce\Utilities\OrderUtil::get_order_admin_edit_url( $this->get_id() );
		/**
		 * Filter the URL to edit the order in the backend.
		 *
		 * @since 3.3.0
		 */
		return apply_filters( 'woocommerce_get_edit_order_url', $edit_url, $this );
	}

	/*
	|--------------------------------------------------------------------------
	| Order notes.
	|--------------------------------------------------------------------------
	*/

	/**
	 * Adds a note (comment) to the order. Order must exist.
	 *
	 * @param  string $note              Note to add.
	 * @param  int    $is_customer_note  Is this a note for the customer?.
	 * @param  bool   $added_by_user     Was the note added by a user?.
	 * @return int                       Comment ID.
	 */
	public function add_order_note( $note, $is_customer_note = 0, $added_by_user = false ) {
		if ( ! $this->get_id() ) {
			return 0;
		}

		if ( is_user_logged_in() && current_user_can( 'edit_shop_orders', $this->get_id() ) && $added_by_user ) {
			$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.', '', sanitize_text_field( wp_unslash( $_SERVER['HTTP_HOST'] ) ) ) : 'noreply.com'; // WPCS: input var ok.
			$comment_author_email  = sanitize_email( $comment_author_email );
		}
		$commentdata = apply_filters(
			'woocommerce_new_order_note_data',
			array(
				'comment_post_ID'      => $this->get_id(),
				'comment_author'       => $comment_author,
				'comment_author_email' => $comment_author_email,
				'comment_author_url'   => '',
				'comment_content'      => $note,
				'comment_agent'        => 'WooCommerce',
				'comment_type'         => 'order_note',
				'comment_parent'       => 0,
				'comment_approved'     => 1,
			),
			array(
				'order_id'         => $this->get_id(),
				'is_customer_note' => $is_customer_note,
			)
		);

		$comment_id = wp_insert_comment( $commentdata );

		if ( $is_customer_note ) {
			add_comment_meta( $comment_id, 'is_customer_note', 1 );

			do_action(
				'woocommerce_new_customer_note',
				array(
					'order_id'      => $this->get_id(),
					'customer_note' => $commentdata['comment_content'],
				)
			);
		}

		/**
		 * Action hook fired after an order note is added.
		 *
		 * @param int      $order_note_id Order note ID.
		 * @param WC_Order $order         Order data.
		 *
		 * @since 4.4.0
		 */
		do_action( 'woocommerce_order_note_added', $comment_id, $this );

		return $comment_id;
	}

	/**
	 * Add an order note for status transition
	 *
	 * @since 3.9.0
	 * @uses self::add_order_note()
	 * @param string $note          Note to be added giving status transition from and to details.
	 * @param bool   $transition    Details of the status transition.
	 * @return int                  Comment ID.
	 */
	private function add_status_transition_note( $note, $transition ) {
		return $this->add_order_note( trim( $transition['note'] . ' ' . $note ), 0, $transition['manual'] );
	}

	/**
	 * List order notes (public) for the customer.
	 *
	 * @return array
	 */
	public function get_customer_order_notes() {
		$notes = array();
		$args  = array(
			'post_id' => $this->get_id(),
			'approve' => 'approve',
			'type'    => '',
		);

		remove_filter( 'comments_clauses', array( 'WC_Comments', 'exclude_order_comments' ) );

		$comments = get_comments( $args );

		foreach ( $comments as $comment ) {
			if ( ! get_comment_meta( $comment->comment_ID, 'is_customer_note', true ) ) {
				continue;
			}
			$comment->comment_content = make_clickable( $comment->comment_content );
			$notes[]                  = $comment;
		}

		add_filter( 'comments_clauses', array( 'WC_Comments', 'exclude_order_comments' ) );

		return $notes;
	}

	/*
	|--------------------------------------------------------------------------
	| Refunds
	|--------------------------------------------------------------------------
	*/

	/**
	 * Get order refunds.
	 *
	 * @since 2.2
	 * @return array of WC_Order_Refund objects
	 */
	public function get_refunds() {
		$cache_key   = WC_Cache_Helper::get_cache_prefix( 'orders' ) . 'refunds' . $this->get_id();
		$cached_data = wp_cache_get( $cache_key, $this->cache_group );

		if ( false !== $cached_data ) {
			return $cached_data;
		}

		$this->refunds = wc_get_orders(
			array(
				'type'   => 'shop_order_refund',
				'parent' => $this->get_id(),
				'limit'  => -1,
			)
		);

		wp_cache_set( $cache_key, $this->refunds, $this->cache_group );

		return $this->refunds;
	}

	/**
	 * Get amount already refunded.
	 *
	 * @since 2.2
	 * @return string
	 */
	public function get_total_refunded() {
		$cache_key   = WC_Cache_Helper::get_cache_prefix( 'orders' ) . 'total_refunded' . $this->get_id();
		$cached_data = wp_cache_get( $cache_key, $this->cache_group );

		if ( false !== $cached_data ) {
			return $cached_data;
		}

		$total_refunded = $this->data_store->get_total_refunded( $this );

		wp_cache_set( $cache_key, $total_refunded, $this->cache_group );

		return $total_refunded;
	}

	/**
	 * Get the total tax refunded.
	 *
	 * @since  2.3
	 * @return float
	 */
	public function get_total_tax_refunded() {
		$cache_key   = WC_Cache_Helper::get_cache_prefix( 'orders' ) . 'total_tax_refunded' . $this->get_id();
		$cached_data = wp_cache_get( $cache_key, $this->cache_group );

		if ( false !== $cached_data ) {
			return $cached_data;
		}

		$total_refunded = $this->data_store->get_total_tax_refunded( $this );

		wp_cache_set( $cache_key, $total_refunded, $this->cache_group );

		return $total_refunded;
	}

	/**
	 * Get the total shipping refunded.
	 *
	 * @since  2.4
	 * @return float
	 */
	public function get_total_shipping_refunded() {
		$cache_key   = WC_Cache_Helper::get_cache_prefix( 'orders' ) . 'total_shipping_refunded' . $this->get_id();
		$cached_data = wp_cache_get( $cache_key, $this->cache_group );

		if ( false !== $cached_data ) {
			return $cached_data;
		}

		$total_refunded = $this->data_store->get_total_shipping_refunded( $this );

		wp_cache_set( $cache_key, $total_refunded, $this->cache_group );

		return $total_refunded;
	}

	/**
	 * Gets the count of order items of a certain type that have been refunded.
	 *
	 * @since  2.4.0
	 * @param string $item_type Item type.
	 * @return string
	 */
	public function get_item_count_refunded( $item_type = '' ) {
		if ( empty( $item_type ) ) {
			$item_type = array( 'line_item' );
		}
		if ( ! is_array( $item_type ) ) {
			$item_type = array( $item_type );
		}
		$count = 0;

		foreach ( $this->get_refunds() as $refund ) {
			foreach ( $refund->get_items( $item_type ) as $refunded_item ) {
				$count += abs( $refunded_item->get_quantity() );
			}
		}

		return apply_filters( 'woocommerce_get_item_count_refunded', $count, $item_type, $this );
	}

	/**
	 * Get the total number of items refunded.
	 *
	 * @since  2.4.0
	 *
	 * @param  string $item_type Type of the item we're checking, if not a line_item.
	 * @return int
	 */
	public function get_total_qty_refunded( $item_type = 'line_item' ) {
		$qty = 0;
		foreach ( $this->get_refunds() as $refund ) {
			foreach ( $refund->get_items( $item_type ) as $refunded_item ) {
				$qty += $refunded_item->get_quantity();
			}
		}
		return $qty;
	}

	/**
	 * Get the refunded amount for a line item.
	 *
	 * @param  int    $item_id   ID of the item we're checking.
	 * @param  string $item_type Type of the item we're checking, if not a line_item.
	 * @return int
	 */
	public function get_qty_refunded_for_item( $item_id, $item_type = 'line_item' ) {
		$qty = 0;
		foreach ( $this->get_refunds() as $refund ) {
			foreach ( $refund->get_items( $item_type ) as $refunded_item ) {
				if ( absint( $refunded_item->get_meta( '_refunded_item_id' ) ) === $item_id ) {
					$qty += $refunded_item->get_quantity();
				}
			}
		}
		return $qty;
	}

	/**
	 * Get the "refunded cost" (the combined Cost of Goods Sold of the refunded items) for a line item.
	 *
	 * @param  int    $item_id   ID of the item we're checking.
	 * @param  string $item_type Type of the item we're checking, if not a line_item.
	 * @return float
	 */
	public function get_cogs_refunded_for_item( $item_id, $item_type = 'line_item' ) {
		if ( ! $this->cogs_is_enabled() || ! $this->has_cogs() ) {
			return 0;
		}

		$cogs_value = 0;
		foreach ( $this->get_refunds() as $refund ) {
			foreach ( $refund->get_items( $item_type ) as $refunded_item ) {
				if ( absint( $refunded_item->get_meta( '_refunded_item_id' ) ) === $item_id ) {
					$cogs_value += $refunded_item->has_cogs() ? $refunded_item->get_cogs_value() : 0;
				}
			}
		}
		return $cogs_value;
	}

	/**
	 * Get the refunded amount for a line item.
	 *
	 * @param  int    $item_id   ID of the item we're checking.
	 * @param  string $item_type Type of the item we're checking, if not a line_item.
	 * @return float
	 */
	public function get_total_refunded_for_item( $item_id, $item_type = 'line_item' ) {
		$total = 0;
		foreach ( $this->get_refunds() as $refund ) {
			foreach ( $refund->get_items( $item_type ) as $refunded_item ) {
				if ( absint( $refunded_item->get_meta( '_refunded_item_id' ) ) === $item_id ) {
					$total += (float) $refunded_item->get_total();
				}
			}
		}
		return NumberUtil::round( $total * -1, wc_get_price_decimals() );
	}

	/**
	 * Get the refunded tax amount for a line item.
	 *
	 * @param  int    $item_id   ID of the item we're checking.
	 * @param  int    $tax_id    ID of the tax we're checking.
	 * @param  string $item_type Type of the item we're checking, if not a line_item.
	 * @return double
	 */
	public function get_tax_refunded_for_item( $item_id, $tax_id, $item_type = 'line_item' ) {
		$total = 0;
		foreach ( $this->get_refunds() as $refund ) {
			foreach ( $refund->get_items( $item_type ) as $refunded_item ) {
				$refunded_item_id = (int) $refunded_item->get_meta( '_refunded_item_id' );
				if ( $refunded_item_id === $item_id ) {
					$taxes  = $refunded_item->get_taxes();
					$total += isset( $taxes['total'][ $tax_id ] ) ? (float) $taxes['total'][ $tax_id ] : 0;
					break;
				}
			}
		}
		return wc_round_tax_total( $total ) * -1;
	}

	/**
	 * Get total tax refunded by rate ID.
	 *
	 * @param  int $rate_id Rate ID.
	 * @return float
	 */
	public function get_total_tax_refunded_by_rate_id( $rate_id ) {
		$total = 0;
		foreach ( $this->get_refunds() as $refund ) {
			foreach ( $refund->get_items( 'tax' ) as $refunded_item ) {
				if ( absint( $refunded_item->get_rate_id() ) === $rate_id ) {
					$total += abs( $refunded_item->get_tax_total() ) + abs( $refunded_item->get_shipping_tax_total() );
				}
			}
		}

		return $total;
	}

	/**
	 * How much money is left to refund?
	 *
	 * @return string
	 */
	public function get_remaining_refund_amount() {
		return wc_format_decimal( $this->get_total() - $this->get_total_refunded(), wc_get_price_decimals() );
	}

	/**
	 * How many items are left to refund?
	 *
	 * @return int
	 */
	public function get_remaining_refund_items() {
		return absint( $this->get_item_count() - $this->get_item_count_refunded() );
	}

	/**
	 * Add total row for the payment method.
	 *
	 * @param array  $total_rows  Total rows.
	 * @param string $tax_display Tax to display.
	 */
	protected function add_order_item_totals_payment_method_row( &$total_rows, $tax_display ) {
		if ( $this->get_total() > 0 && $this->get_payment_method_title() && 'other' !== $this->get_payment_method() ) {
			$value = $this->get_payment_method_title();

			$card_info = $this->get_payment_card_info();
			if ( isset( $card_info['last4'] ) && $card_info['last4'] ) {
				$value .= ' - ' . $card_info['last4'];
			}

			$total_rows['payment_method'] = array(
				'type'  => 'payment_method',
				'label' => __( 'Payment method:', 'woocommerce' ),
				'value' => $value,
			);
		}
	}

	/**
	 * Add total row for refunds.
	 *
	 * @param array  $total_rows  Total rows.
	 * @param string $tax_display Tax to display.
	 */
	protected function add_order_item_totals_refund_rows( &$total_rows, $tax_display ) {
		$refunds = $this->get_refunds();
		if ( $refunds ) {
			foreach ( $refunds as $id => $refund ) {
				$reason = trim( $refund->get_reason() );

				if ( strlen( $reason ) > 0 ) {
					$reason = "<br><small>$reason</small>";
				}

				$total_rows[ 'refund_' . $id ] = array(
					'type'  => 'refund',
					'label' => __( 'Refund', 'woocommerce' ) . ':',
					'value' => wc_price( '-' . $refund->get_amount(), array( 'currency' => $this->get_currency() ) ) . $reason,
				);
			}
		}
	}

	/**
	 * Get totals for display on pages and in emails.
	 *
	 * @param string $tax_display Tax to display.
	 * @return array
	 */
	public function get_order_item_totals( $tax_display = '' ) {
		$tax_display = $tax_display ? $tax_display : get_option( 'woocommerce_tax_display_cart' );
		$total_rows  = array();

		$email_improvements_enabled = FeaturesUtil::feature_is_enabled( 'email_improvements' );

		$this->add_order_item_totals_subtotal_row( $total_rows, $tax_display );
		$this->add_order_item_totals_discount_row( $total_rows, $tax_display );
		$this->add_order_item_totals_shipping_row( $total_rows, $tax_display );
		$this->add_order_item_totals_fee_rows( $total_rows, $tax_display );
		$this->add_order_item_totals_tax_rows( $total_rows, $tax_display );
		if ( ! $email_improvements_enabled ) {
			$this->add_order_item_totals_payment_method_row( $total_rows, $tax_display );
		}
		$this->add_order_item_totals_refund_rows( $total_rows, $tax_display );
		$this->add_order_item_totals_total_row( $total_rows, $tax_display );
		if ( $email_improvements_enabled ) {
			$this->add_order_item_totals_payment_method_row( $total_rows, $tax_display );
		}

		return apply_filters( 'woocommerce_get_order_item_totals', $total_rows, $this, $tax_display );
	}

	/**
	 * Check if order has been created via admin, checkout, or in another way.
	 *
	 * @since 4.0.0
	 * @param string $modus Way of creating the order to test for.
	 * @return bool
	 */
	public function is_created_via( $modus ) {
		return apply_filters( 'woocommerce_order_is_created_via', $modus === $this->get_created_via(), $this, $modus );
	}

	/**
	 * Attempts to restore the specified order back to its original status (after having been trashed).
	 *
	 * @return bool If the operation was successful.
	 */
	public function untrash(): bool {
		return (bool) $this->data_store->untrash_order( $this );
	}

	/**
	 * Indicates that regular orders have an associated Cost of Goods Sold value.
	 * Note that this is true even if the order has no line items with COGS values (in that case the COGS value for the order will be zero)-
	 *
	 * @return bool Always true.
	 */
	public function has_cogs() {
		return true;
	}

	/**
	 * Calculate the Cost of Goods Sold value for this order
	 * as the base cost minus the cost of the refunded items.
	 *
	 * @return float The calculated value.
	 */
	protected function calculate_cogs_total_value_core(): float {
		$value = parent::calculate_cogs_total_value_core();

		$refunds = $this->get_refunds();
		foreach ( $refunds as $refund ) {
			$refund_items = $refund->get_items();
			foreach ( $refund_items as $refund_item ) {
				if ( $refund_item->has_cogs() ) {
					$refund_item->calculate_cogs_value();
					$value -= abs( $refund_item->get_cogs_value() );
				}
			}
		}

		return $value;
	}
}

[ Back ]
Name
Size
Last Modified
Owner / Group
Permissions
Options
..
--
July 10 2025 04:32:19
giriqfky / giriqfky
0755
abstracts
--
July 10 2025 04:32:20
giriqfky / giriqfky
0755
admin
--
July 10 2025 04:32:20
giriqfky / giriqfky
0755
blocks
--
July 10 2025 04:32:20
giriqfky / giriqfky
0755
cli
--
July 10 2025 04:32:20
giriqfky / giriqfky
0755
customizer
--
July 10 2025 04:32:20
giriqfky / giriqfky
0755
data-stores
--
July 10 2025 04:32:20
giriqfky / giriqfky
0755
emails
--
July 10 2025 04:32:20
giriqfky / giriqfky
0755
export
--
July 10 2025 04:32:20
giriqfky / giriqfky
0755
gateways
--
July 10 2025 04:32:20
giriqfky / giriqfky
0755
import
--
July 10 2025 04:32:20
giriqfky / giriqfky
0755
integrations
--
July 10 2025 04:32:20
giriqfky / giriqfky
0755
interfaces
--
July 10 2025 04:32:20
giriqfky / giriqfky
0755
legacy
--
July 10 2025 04:32:20
giriqfky / giriqfky
0755
libraries
--
July 10 2025 04:32:20
giriqfky / giriqfky
0755
log-handlers
--
July 10 2025 04:32:20
giriqfky / giriqfky
0755
payment-tokens
--
July 10 2025 04:32:20
giriqfky / giriqfky
0755
product-usage
--
July 10 2025 04:32:20
giriqfky / giriqfky
0755
queue
--
July 10 2025 04:32:20
giriqfky / giriqfky
0755
react-admin
--
July 10 2025 04:32:20
giriqfky / giriqfky
0755
rest-api
--
July 10 2025 04:32:20
giriqfky / giriqfky
0755
shipping
--
July 10 2025 04:32:20
giriqfky / giriqfky
0755
shortcodes
--
July 10 2025 04:32:20
giriqfky / giriqfky
0755
theme-support
--
July 10 2025 04:32:20
giriqfky / giriqfky
0755
tracks
--
July 10 2025 04:32:20
giriqfky / giriqfky
0755
traits
--
July 10 2025 04:32:20
giriqfky / giriqfky
0755
walkers
--
July 10 2025 04:32:20
giriqfky / giriqfky
0755
wccom-site
--
July 10 2025 04:32:20
giriqfky / giriqfky
0755
widgets
--
July 10 2025 04:32:20
giriqfky / giriqfky
0755
.htaccess
0.41 KB
July 10 2025 04:32:20
giriqfky / giriqfky
0644
class-wc-ajax.php
118.694 KB
May 12 2025 21:07:28
giriqfky / giriqfky
0644
class-wc-auth.php
12.69 KB
July 30 2024 19:31:16
giriqfky / giriqfky
0644
class-wc-autoloader.php
3.321 KB
September 23 2024 20:44:04
giriqfky / giriqfky
0644
class-wc-background-emailer.php
4.575 KB
August 20 2020 23:18:50
giriqfky / giriqfky
0644
class-wc-background-updater.php
3.452 KB
August 20 2020 23:18:50
giriqfky / giriqfky
0644
class-wc-brands-brand-settings-manager.php
1.783 KB
September 23 2024 20:44:04
giriqfky / giriqfky
0644
class-wc-brands-coupons.php
6.894 KB
January 21 2025 18:53:44
giriqfky / giriqfky
0644
class-wc-brands.php
33.975 KB
May 12 2025 21:07:28
giriqfky / giriqfky
0644
class-wc-breadcrumb.php
9.494 KB
October 21 2020 03:38:50
giriqfky / giriqfky
0644
class-wc-cache-helper.php
11.17 KB
August 27 2024 23:04:44
giriqfky / giriqfky
0644
class-wc-cart-fees.php
3.367 KB
September 26 2023 21:42:36
giriqfky / giriqfky
0644
class-wc-cart-session.php
18.921 KB
March 03 2025 22:28:12
giriqfky / giriqfky
0644
class-wc-cart-totals.php
28.399 KB
May 12 2025 21:07:28
giriqfky / giriqfky
0644
class-wc-cart.php
70.182 KB
May 12 2025 21:07:28
giriqfky / giriqfky
0644
class-wc-checkout.php
50.146 KB
May 12 2025 21:07:28
giriqfky / giriqfky
0644
class-wc-cli.php
2.866 KB
May 12 2025 21:07:28
giriqfky / giriqfky
0644
class-wc-comments.php
22.191 KB
June 02 2025 20:47:42
giriqfky / giriqfky
0644
class-wc-countries.php
49.162 KB
May 12 2025 21:07:28
giriqfky / giriqfky
0644
class-wc-coupon.php
39.642 KB
May 12 2025 21:07:28
giriqfky / giriqfky
0644
class-wc-customer-download-log.php
3.371 KB
August 20 2020 23:18:50
giriqfky / giriqfky
0644
class-wc-customer-download.php
10.339 KB
July 30 2024 19:31:16
giriqfky / giriqfky
0644
class-wc-customer.php
32.034 KB
May 12 2025 15:44:58
giriqfky / giriqfky
0644
class-wc-data-exception.php
1.29 KB
May 23 2018 19:30:10
giriqfky / giriqfky
0644
class-wc-data-store.php
6.594 KB
October 19 2022 00:34:38
giriqfky / giriqfky
0644
class-wc-datetime.php
2.256 KB
April 20 2022 06:50:54
giriqfky / giriqfky
0644
class-wc-deprecated-action-hooks.php
6.588 KB
February 27 2024 18:59:46
giriqfky / giriqfky
0644
class-wc-deprecated-filter-hooks.php
7.342 KB
February 22 2023 07:17:34
giriqfky / giriqfky
0644
class-wc-discounts.php
36.509 KB
May 12 2025 21:07:28
giriqfky / giriqfky
0644
class-wc-download-handler.php
28.372 KB
December 18 2024 22:19:16
giriqfky / giriqfky
0644
class-wc-emails.php
28.2 KB
May 12 2025 21:07:28
giriqfky / giriqfky
0644
class-wc-embed.php
4.24 KB
January 21 2025 18:53:44
giriqfky / giriqfky
0644
class-wc-form-handler.php
45.735 KB
May 12 2025 21:07:28
giriqfky / giriqfky
0644
class-wc-frontend-scripts.php
27.843 KB
May 12 2025 21:07:28
giriqfky / giriqfky
0644
class-wc-geo-ip.php
30.407 KB
September 23 2024 20:44:04
giriqfky / giriqfky
0644
class-wc-geolite-integration.php
1.988 KB
January 16 2020 06:10:02
giriqfky / giriqfky
0644
class-wc-geolocation.php
11.322 KB
May 12 2025 21:07:28
giriqfky / giriqfky
0644
class-wc-https.php
4.335 KB
June 20 2023 23:45:50
giriqfky / giriqfky
0644
class-wc-install.php
106.709 KB
June 02 2025 15:59:32
giriqfky / giriqfky
0644
class-wc-integrations.php
1.277 KB
August 20 2020 23:18:50
giriqfky / giriqfky
0644
class-wc-log-levels.php
3.898 KB
January 30 2024 23:24:56
giriqfky / giriqfky
0644
class-wc-logger.php
9.376 KB
May 12 2025 21:07:28
giriqfky / giriqfky
0644
class-wc-meta-data.php
2.207 KB
April 20 2022 06:50:54
giriqfky / giriqfky
0644
class-wc-order-factory.php
8.523 KB
April 30 2024 19:35:34
giriqfky / giriqfky
0644
class-wc-order-item-coupon.php
4.077 KB
December 22 2021 00:24:58
giriqfky / giriqfky
0644
class-wc-order-item-fee.php
9.21 KB
March 03 2025 22:28:12
giriqfky / giriqfky
0644
class-wc-order-item-meta.php
5.803 KB
December 22 2021 00:24:58
giriqfky / giriqfky
0644
class-wc-order-item-product.php
15.841 KB
May 12 2025 21:07:28
giriqfky / giriqfky
0644
class-wc-order-item-shipping.php
8.802 KB
May 12 2025 21:07:28
giriqfky / giriqfky
0644
class-wc-order-item-tax.php
6.488 KB
December 22 2021 00:24:58
giriqfky / giriqfky
0644
class-wc-order-item.php
18.545 KB
May 12 2025 21:07:28
giriqfky / giriqfky
0644
class-wc-order-query.php
2.554 KB
July 28 2021 04:11:34
giriqfky / giriqfky
0644
class-wc-order-refund.php
5.991 KB
May 12 2025 21:07:28
giriqfky / giriqfky
0644
class-wc-order.php
74.093 KB
June 02 2025 15:59:32
giriqfky / giriqfky
0644
class-wc-payment-gateways.php
11.897 KB
May 26 2025 19:11:58
giriqfky / giriqfky
0644
class-wc-payment-tokens.php
6.24 KB
November 23 2022 05:58:58
giriqfky / giriqfky
0644
class-wc-post-data.php
21.725 KB
March 03 2025 22:28:12
giriqfky / giriqfky
0644
class-wc-post-types.php
32.003 KB
May 12 2025 21:07:28
giriqfky / giriqfky
0644
class-wc-privacy-background-process.php
1.79 KB
March 03 2025 22:28:12
giriqfky / giriqfky
0644
class-wc-privacy-erasers.php
13.608 KB
September 23 2024 20:44:04
giriqfky / giriqfky
0644
class-wc-privacy-exporters.php
14.691 KB
July 28 2021 04:11:34
giriqfky / giriqfky
0644
class-wc-privacy.php
17.189 KB
March 03 2025 22:28:12
giriqfky / giriqfky
0644
class-wc-product-attribute.php
6.97 KB
January 19 2022 02:24:34
giriqfky / giriqfky
0644
class-wc-product-download.php
12.253 KB
April 10 2024 16:54:10
giriqfky / giriqfky
0644
class-wc-product-external.php
4.984 KB
March 03 2025 22:28:12
giriqfky / giriqfky
0644
class-wc-product-factory.php
3.881 KB
January 21 2025 18:53:44
giriqfky / giriqfky
0644
class-wc-product-grouped.php
5.603 KB
May 12 2025 21:07:28
giriqfky / giriqfky
0644
class-wc-product-query.php
2.277 KB
January 21 2025 18:53:44
giriqfky / giriqfky
0644
class-wc-product-simple.php
2.697 KB
January 21 2025 18:53:44
giriqfky / giriqfky
0644
class-wc-product-variable.php
24.576 KB
June 02 2025 15:59:32
giriqfky / giriqfky
0644
class-wc-product-variation.php
20.177 KB
May 12 2025 21:07:28
giriqfky / giriqfky
0644
class-wc-query.php
33.36 KB
May 12 2025 21:07:28
giriqfky / giriqfky
0644
class-wc-rate-limiter.php
4.004 KB
December 01 2021 04:23:30
giriqfky / giriqfky
0644
class-wc-regenerate-images-request.php
7.737 KB
January 25 2023 03:19:12
giriqfky / giriqfky
0644
class-wc-regenerate-images.php
15.436 KB
June 25 2024 21:17:40
giriqfky / giriqfky
0644
class-wc-register-wp-admin-settings.php
5.05 KB
June 22 2021 15:24:06
giriqfky / giriqfky
0644
class-wc-rest-authentication.php
21.551 KB
June 25 2024 21:17:40
giriqfky / giriqfky
0644
class-wc-rest-exception.php
0.27 KB
September 23 2020 01:16:50
giriqfky / giriqfky
0644
class-wc-session-handler.php
15.611 KB
May 12 2025 21:07:28
giriqfky / giriqfky
0644
class-wc-shipping-rate.php
8.065 KB
March 03 2025 22:28:12
giriqfky / giriqfky
0644
class-wc-shipping-zone.php
13.078 KB
September 23 2020 01:16:50
giriqfky / giriqfky
0644
class-wc-shipping-zones.php
4.01 KB
August 20 2020 23:18:50
giriqfky / giriqfky
0644
class-wc-shipping.php
12.852 KB
May 12 2025 21:07:28
giriqfky / giriqfky
0644
class-wc-shortcodes.php
18.822 KB
January 21 2025 18:53:44
giriqfky / giriqfky
0644
class-wc-structured-data.php
23.796 KB
March 03 2025 22:28:12
giriqfky / giriqfky
0644
class-wc-tax.php
37.079 KB
June 20 2023 23:45:50
giriqfky / giriqfky
0644
class-wc-template-loader.php
21.38 KB
June 09 2025 15:55:46
giriqfky / giriqfky
0644
class-wc-tracker.php
48.207 KB
June 02 2025 15:59:32
giriqfky / giriqfky
0644
class-wc-validation.php
5.79 KB
May 28 2024 14:28:20
giriqfky / giriqfky
0644
class-wc-webhook.php
29.405 KB
December 18 2024 22:19:16
giriqfky / giriqfky
0644
class-woocommerce.php
49.085 KB
June 23 2025 15:50:22
giriqfky / giriqfky
0644
wc-account-functions.php
14.014 KB
December 18 2024 22:19:16
giriqfky / giriqfky
0644
wc-attribute-functions.php
21.179 KB
January 21 2025 18:53:44
giriqfky / giriqfky
0644
wc-brands-functions.php
4.17 KB
September 23 2024 20:44:04
giriqfky / giriqfky
0644
wc-cart-functions.php
20.049 KB
May 12 2025 21:07:28
giriqfky / giriqfky
0644
wc-conditional-functions.php
14.199 KB
May 12 2025 21:07:28
giriqfky / giriqfky
0644
wc-core-functions.php
86.207 KB
May 12 2025 21:07:28
giriqfky / giriqfky
0644
wc-coupon-functions.php
3.095 KB
May 12 2025 21:07:28
giriqfky / giriqfky
0644
wc-deprecated-functions.php
38.115 KB
May 12 2025 21:07:28
giriqfky / giriqfky
0644
wc-formatting-functions.php
47.764 KB
May 12 2025 21:07:28
giriqfky / giriqfky
0644
wc-notice-functions.php
8.057 KB
May 12 2025 21:07:28
giriqfky / giriqfky
0644
wc-order-functions.php
40.503 KB
May 12 2025 21:07:28
giriqfky / giriqfky
0644
wc-order-item-functions.php
5.032 KB
January 25 2023 03:19:12
giriqfky / giriqfky
0644
wc-order-step-logger-functions.php
5.015 KB
May 12 2025 21:07:28
giriqfky / giriqfky
0644
wc-page-functions.php
9.431 KB
September 23 2024 20:44:04
giriqfky / giriqfky
0644
wc-product-functions.php
58.515 KB
May 12 2025 21:07:28
giriqfky / giriqfky
0644
wc-rest-functions.php
12.951 KB
May 12 2025 21:07:28
giriqfky / giriqfky
0644
wc-stock-functions.php
17.133 KB
January 21 2025 18:53:44
giriqfky / giriqfky
0644
wc-template-functions.php
132.676 KB
May 12 2025 21:07:28
giriqfky / giriqfky
0644
wc-template-hooks.php
12.653 KB
May 12 2025 21:07:28
giriqfky / giriqfky
0644
wc-term-functions.php
23.81 KB
June 16 2025 19:21:28
giriqfky / giriqfky
0644
wc-update-functions.php
91.822 KB
June 02 2025 15:59:32
giriqfky / giriqfky
0644
wc-user-functions.php
33.352 KB
May 12 2025 21:07:28
giriqfky / giriqfky
0644
wc-webhook-functions.php
5.767 KB
June 25 2024 21:17:40
giriqfky / giriqfky
0644
wc-widget-functions.php
2.015 KB
August 20 2020 23:18:50
giriqfky / giriqfky
0644

GRAYBYTE WORDPRESS FILE MANAGER @ 2025
CONTACT ME
Static GIF