File "class-kco-request-order.php"

Full Path: /home/siazco/grocery.siazco.se/wp-content/plugins/klarna-checkout-for-woocommerce/classes/requests/helpers/class-kco-request-order.php
File size: 13.61 KB
MIME-type: text/x-php
Charset: utf-8

<?php
/**
 * Gets the order information from an order.
 *
 * @package Klarna_Checkout/Classes
 */

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

/**
 * Class for processing order lines from a WooCommerce order.
 */
class KCO_Request_Order {

	/**
	 * Send sales tax as separate item (US merchants).
	 *
	 * @var bool
	 */
	public $separate_sales_tax = false;

	/**
	 * Total tax of order.
	 *
	 * @var int
	 */
	public $total_tax = 0;

	/**
	 * Gets the order lines for the order.
	 *
	 * @param int $order_id The WooCommerce order id.
	 * @return array
	 */
	public function get_order_lines( $order_id ) {
		$order       = wc_get_order( $order_id );
		$order_lines = array();

		foreach ( $order->get_items() as $item ) {
			array_push( $order_lines, $this->get_order_line_items( $item ) );
		}
		foreach ( $order->get_fees() as $fee ) {
			array_push( $order_lines, $this->get_order_line_fees( $fee ) );
		}
		if ( ! empty( $order->get_shipping_method() ) ) {
			array_push( $order_lines, $this->get_order_line_shipping( $order ) );
		}

		return array_values( $order_lines );
	}

	/**
	 * Gets the order amount
	 *
	 * @param int $order_id The WooCommerce order id.
	 * @return int
	 */
	public function get_order_amount( $order_id ) {
		$order = wc_get_order( $order_id );
		return round( $order->get_total() * 100 );
	}

	/**
	 * Get total tax of order.
	 *
	 * @return int
	 */
	public function get_total_tax() {
		return round( $this->total_tax );
	}

	/**
	 * Gets the formated order line.
	 *
	 * @param WC_Order_Item_Product $order_item The WooCommerce order line item.
	 * @return array
	 */
	public function get_order_line_items( $order_item ) {
		$order_id = $order_item->get_order_id();
		$order    = wc_get_order( $order_id );
		$product  = wc_get_product( $order_item->get_product_id() );

		$order_line = array(
			'reference'        => $this->get_item_reference( $order_item ),
			'name'             => $order_item->get_name(),
			'quantity'         => $order_item->get_quantity(),
			'total_amount'     => $this->get_item_total_amount( $order, $order_item ),
			'unit_price'       => $this->get_item_unit_price( $order, $order_item ),
			'total_tax_amount' => $this->get_item_total_tax_amount( $order, $order_item ),
			'tax_rate'         => $this->get_order_line_tax_rate( $order, $order_item ),
		);

		if ( class_exists( 'WC_Subscriptions_Product' ) && WC_Subscriptions_Product::is_subscription( $product ) ) {
			$order_line['subscription'] = array(
				'name'           => $order_line['name'],
				'interval'       => strtoupper( WC_Subscriptions_Product::get_period( $product ) ),
				'interval_count' => absint( WC_Subscriptions_Product::get_interval( $product ) ),
			);
		}

		$settings = get_option( 'woocommerce_kco_settings', array() );
		if ( isset( $settings['send_product_urls'] ) && 'yes' === $settings['send_product_urls'] ) {

			$image_url = wp_get_attachment_image_url( $product->get_image_id(), 'shop_single', false );
			if ( $image_url ) {
				$order_line['image_url'] = $image_url;
			}

			$order_line['product_url'] = $product->get_permalink();
		}

		return $order_line;
	}

	/**
	 * Gets the formated order line shipping.
	 *
	 * @param WC_Order $order The WooCommerce order.
	 * @return array
	 */
	public function get_order_line_shipping( $order ) {
		$shipping_item = array_slice( $order->get_shipping_methods(), 0, 1 )[0];

		return array(
			'type'             => 'shipping_fee',
			'reference'        => $this->get_item_reference( $shipping_item ),
			'name'             => $order->get_shipping_method(),
			'quantity'         => 1,
			'total_amount'     => $this->get_shipping_total_amount( $order ),
			'unit_price'       => $this->get_shipping_total_amount( $order ),
			'total_tax_amount' => $this->get_shipping_total_tax_amount( $order ),
			'tax_rate'         => ( ! empty( floatval( $order->get_shipping_tax() ) ) ) ? $this->get_order_line_tax_rate( $order, current( $order->get_items( 'shipping' ) ) ) : 0,
		);
	}

	/**
	 * Gets the formated order line fees.
	 *
	 * @param WC_Order_Item_Fee $order_fee The order item fee.
	 * @return array
	 */
	public function get_order_line_fees( $order_fee ) {
		$order_id = $order_fee->get_order_id();
		$order    = wc_get_order( $order_id );
		return array(
			'type'                  => 'surcharge',
			'reference'             => $this->get_item_reference( $order_fee ),
			'name'                  => substr( $order_fee->get_name(), 0, 254 ),
			'quantity'              => $order_fee->get_quantity(),
			'total_amount'          => $this->get_fee_total_amount( $order, $order_fee ),
			'unit_price'            => $this->get_fee_unit_price( $order_fee ),
			'total_discount_amount' => 0,
			'total_tax_amount'      => $this->get_fee_total_tax_amount( $order, $order_fee ),
			'tax_rate'              => ( ! empty( floatval( $order->get_total_tax() ) ) ) ? $this->get_order_line_tax_rate( $order, current( $order->get_items( 'fee' ) ) ) : 0,
		);
	}

	/**
	 * Gets the order line tax rate.
	 *
	 * @param WC_Order $order The WooCommerce order.
	 * @param mixed    $order_item If not false the WooCommerce order item WC_Order_Item.
	 * @return int
	 */
	public function get_order_line_tax_rate( $order, $order_item = false ) {
		$tax_items = $order->get_items( 'tax' );
		foreach ( $tax_items as $tax_item ) {
			$rate_id = $tax_item->get_rate_id();
			foreach ( $order_item->get_taxes()['total'] as $key => $value ) {
				if ( '' !== $value ) {
					if ( $rate_id === $key ) {
						return round( WC_Tax::_get_tax_rate( $rate_id )['tax_rate'] * 100 );
					}
				}
			}
		}
		// If we get here, there is no tax set for the order item. Return zero.
		return 0;
	}

	/**
	 * Get item total amount.
	 *
	 * @param WC_Order       $order WC order.
	 * @param boolean|object $order_item Order item.
	 * @return int
	 */
	public function get_item_total_amount( $order, $order_item = false ) {
		if ( $this->separate_sales_tax ) {
			$item_total_amount     = number_format( ( $order_item->get_total() ) * ( 1 + ( $this->get_order_line_tax_rate( $order, $order_item ) / 10000 ) ), wc_get_price_decimals(), '.', '' ) * 100;
			$max_order_line_amount = ( number_format( ( $order_item->get_total() + $order_item->get_total_tax() ) * 100, wc_get_price_decimals(), '.', '' ) * $order_item->get_quantity() ) * 100;
		} else {
			$item_total_amount     = ( number_format( $order_item->get_total(), wc_get_price_decimals(), '.', '' ) + number_format( $order_item->get_total_tax(), wc_get_price_decimals(), '.', '' ) ) * 100;
			$max_order_line_amount = ( number_format( ( $order_item->get_total() + $order_item->get_total_tax() ) * 100, wc_get_price_decimals(), '.', '' ) * $order_item->get_quantity() ) * 100;
		}
		// Check so the line_total isn't greater than product price x quantity.
		// This can happen when having price display set to 0 decimals.
		if ( $item_total_amount > $max_order_line_amount ) {
			$item_total_amount = $max_order_line_amount;
		}
		return round( $item_total_amount );
	}

	/**
	 * Get item unit price.
	 *
	 * @param WC_Order       $order WC order.
	 * @param boolean|object $order_item Order item.
	 * @return int
	 */
	public function get_item_unit_price( $order, $order_item = false ) {
		if ( $this->separate_sales_tax ) {
			$item_subtotal = $order_item->get_total() / $order_item->get_quantity();
		} else {
			$item_subtotal = ( ( number_format( $order_item->get_total(), wc_get_price_decimals(), '.', '' ) + number_format( $order_item->get_total_tax(), wc_get_price_decimals(), '.', '' ) ) / $order_item->get_quantity() ) * 100;
		}
		return round( $item_subtotal );
	}

	/**
	 * Get item total tax amount.
	 *
	 * @param WC_Order       $order WC order.
	 * @param boolean|object $order_item Order item.
	 * @return int
	 */
	public function get_item_total_tax_amount( $order, $order_item = false ) {
		if ( $this->separate_sales_tax ) {
			$item_tax_amount = 0;
		} else {
			$item_total_amount       = $this->get_item_total_amount( $order, $order_item );
			$item_total_exluding_tax = $item_total_amount / ( 1 + ( $this->get_order_line_tax_rate( $order, $order_item ) / 10000 ) );
			$item_tax_amount         = $item_total_amount - $item_total_exluding_tax;
		}
		$this->total_tax += round( $item_tax_amount );
		return round( $item_tax_amount );
	}

	/**
	 * Get shipping total amount.
	 *
	 * @param WC_Order $order WC order.
	 * @return int
	 */
	public function get_shipping_total_amount( $order ) {
		if ( $this->separate_sales_tax ) {
			$shipping_amount = (int) number_format( $order->get_shipping_total() * 100, 0, '', '' );
		} else {
			$shipping_amount = number_format( $order->get_shipping_total() + $order->get_shipping_tax(), wc_get_price_decimals(), '.', '' ) * 100;
		}
		return $shipping_amount;
	}

	/**
	 * Get shipping total tax amount.
	 *
	 * @param WC_Order $order WC order.
	 * @return int
	 */
	public function get_shipping_total_tax_amount( $order ) {
		if ( $this->separate_sales_tax ) {
			$shipping_tax_amount = 0;
		} else {
			$shipping_total_amount       = $this->get_shipping_total_amount( $order );
			$shipping_tax_rate           = ( '0' !== $order->get_shipping_tax() ) ? $this->get_order_line_tax_rate( $order, current( $order->get_items( 'shipping' ) ) ) : 0;
			$shipping_total_exluding_tax = $shipping_total_amount / ( 1 + ( $shipping_tax_rate / 10000 ) );
			$shipping_tax_amount         = $shipping_total_amount - $shipping_total_exluding_tax;
		}
		$this->total_tax += round( $shipping_tax_amount );
		return round( $shipping_tax_amount );
	}

	/**
	 * Get fee total amount.
	 *
	 * @param WC_Order       $order WC order.
	 * @param boolean|object $order_fee Order fee.
	 * @return int
	 */
	public function get_fee_total_amount( $order, $order_fee ) {
		if ( $this->separate_sales_tax ) {
			$fee_total_amount      = number_format( ( $order_fee->get_total() ) * ( 1 + ( $this->get_order_line_tax_rate( $order, $order_fee ) / 10000 ) ), wc_get_price_decimals(), '.', '' ) * 100;
			$max_order_line_amount = ( number_format( ( $order_fee->get_total() + $order_fee->get_total_tax() ) * 100, wc_get_price_decimals(), '.', '' ) * $order_fee->get_quantity() );
		} else {
			$fee_total_amount      = number_format( ( $order_fee->get_total() ) * ( 1 + ( $this->get_order_line_tax_rate( $order, $order_fee ) / 10000 ) ), wc_get_price_decimals(), '.', '' ) * 100;
			$max_order_line_amount = ( number_format( ( $order_fee->get_total() + $order_fee->get_total_tax() ) * 100, wc_get_price_decimals(), '.', '' ) * $order_fee->get_quantity() );
		}
		// Check so the line_total isn't greater than product price x quantity.
		// This can happen when having price display set to 0 decimals.
		if ( $fee_total_amount > $max_order_line_amount ) {
			$fee_total_amount = $max_order_line_amount;
		}
		return round( $fee_total_amount );
	}

	/**
	 * Get fee unit price.
	 *
	 * @param boolean|object $order_fee Order fee.
	 * @return int
	 */
	public function get_fee_unit_price( $order_fee ) {
		if ( $this->separate_sales_tax ) {
			$fee_subtotal = $order_fee->get_total();
		} else {
			$fee_subtotal = ( $order_fee->get_total() + $order_fee->get_total_tax() );
		}
		$fee_price = number_format( $fee_subtotal, wc_get_price_decimals(), '.', '' ) * 100;
		return round( $fee_price );
	}

	/**
	 * Get fee total tax amount.
	 *
	 * @param WC_Order       $order WC order.
	 * @param boolean|object $order_fee Order fee.
	 * @return int
	 */
	public function get_fee_total_tax_amount( $order, $order_fee ) {
		if ( $this->separate_sales_tax ) {
			$fee_tax_amount = 0;
		} else {
			$fee_total_amount       = $this->get_fee_total_amount( $order, $order_fee );
			$fee_tax_rate           = ( '0' !== $order->get_total_tax() ) ? $this->get_order_line_tax_rate( $order, current( $order->get_items( 'fee' ) ) ) : 0;
			$fee_total_exluding_tax = $fee_total_amount / ( 1 + ( $fee_tax_rate / 10000 ) );
			$fee_tax_amount         = $fee_total_amount - $fee_total_exluding_tax;
		}
		$this->total_tax += round( $fee_tax_amount );
		return round( $fee_tax_amount );
	}

	/**
	 * Get cart item reference.
	 *
	 * @param WC_Order_Item_Product|WC_Order_Item_Shipping|WC_Order_Item_Fee|WC_Order_Item_Coupon $order_line_item WooCommerce order line item.
	 *
	 * @return string $item_reference Cart item reference.
	 */
	public function get_item_reference( $order_line_item ) {
		if ( 'line_item' === $order_line_item->get_type() ) {
			$product = $order_line_item['variation_id'] ? wc_get_product( $order_line_item['variation_id'] ) : wc_get_product( $order_line_item['product_id'] );
			if ( $product ) {
				if ( $product->get_sku() ) {
					$item_reference = $product->get_sku();
				} else {
					$item_reference = $product->get_id();
				}
			} else {
				$item_reference = $order_line_item->get_name();
			}
		} elseif ( 'shipping' === $order_line_item->get_type() ) {
			// Matching the shipping reference from KCO order.
			$item_reference = $order_line_item->get_method_id() . ':' . $order_line_item->get_instance_id();
		} elseif ( 'coupon' === $order_line_item->get_type() ) {
			$item_reference = 'Discount';
		} elseif ( 'fee' === $order_line_item->get_type() ) {
			$item_reference = 'Fee';
		} else {
			$item_reference = $order_line_item->get_name();
		}

		return substr( (string) $item_reference, 0, 64 );
	}

	/**
	 * Gets the upsell order lines for the order.
	 *
	 * @param WC_Order $order The WooCommerce order id.
	 * @param string   $upsell_request_id The order line upsell id.
	 * @return array
	 */
	public function get_upsell_order_lines( $order, $upsell_request_id ) {
		$order_lines = array();

		/**
		 * Process order item products.
		 *
		 * @var WC_Order_Item_Product $order_item WooCommerce order item product.
		 */
		foreach ( $order->get_items() as $order_item ) {
			if ( $upsell_request_id === $order_item->get_meta( '_ppu_upsell_id' ) ) {
				$order_lines[] = self::get_order_line_items( $order_item, $order );
			}
		}

		return array_values( $order_lines );
	}
}