Create New Item
×
Item Type
File
Folder
Item Name
×
Search file in folder and subfolders...
File Manager
/
wp-content
/
plugins
/
woocommerce
/
includes
Advanced Search
Upload
New Item
Settings
Back
Back Up
Advanced Editor
Save
<?php use Automattic\WooCommerce\Utilities\NumberUtil; defined('ABSPATH') || exit; require_once WC_ABSPATH . 'includes/legacy/class-wc-legacy-cart.php'; require_once WC_ABSPATH . 'includes/class-wc-cart-fees.php'; require_once WC_ABSPATH . 'includes/class-wc-cart-session.php'; class WC_Cart extends WC_Legacy_Cart { public $cart_contents = array(); public $removed_cart_contents = array(); public $applied_coupons = array(); protected $shipping_methods; protected $default_totals = array('subtotal' => 0, 'subtotal_tax' => 0, 'shipping_total' => 0, 'shipping_tax' => 0, 'shipping_taxes' => array(), 'discount_total' => 0, 'discount_tax' => 0, 'cart_contents_total' => 0, 'cart_contents_tax' => 0, 'cart_contents_taxes' => array(), 'fee_total' => 0, 'fee_tax' => 0, 'fee_taxes' => array(), 'total' => 0, 'total_tax' => 0); protected $totals = array(); protected $session; protected $fees_api; public function __construct() { $this->session = new WC_Cart_Session($this); $this->fees_api = new WC_Cart_Fees($this); $this->session->init(); add_action('woocommerce_add_to_cart', array($this, 'calculate_totals'), 20, 0); add_action('woocommerce_applied_coupon', array($this, 'calculate_totals'), 20, 0); add_action('woocommerce_cart_item_removed', array($this, 'calculate_totals'), 20, 0); add_action('woocommerce_cart_item_restored', array($this, 'calculate_totals'), 20, 0); add_action('woocommerce_check_cart_items', array($this, 'check_cart_items'), 1); add_action('woocommerce_check_cart_items', array($this, 'check_cart_coupons'), 1); add_action('woocommerce_after_checkout_validation', array($this, 'check_customer_coupons'), 1, 2); } public function __clone() { $this->session = clone $this->session; $this->fees_api = clone $this->fees_api; } public function get_cart_contents() { return apply_filters('woocommerce_get_cart_contents', (array) $this->cart_contents); } public function get_removed_cart_contents() { return (array) $this->removed_cart_contents; } public function get_applied_coupons() { return (array) $this->applied_coupons; } public function get_coupon_discount_totals() { return (array) $this->coupon_discount_totals; } public function get_coupon_discount_tax_totals() { return (array) $this->coupon_discount_tax_totals; } public function get_totals() { return empty($this->totals) ? $this->default_totals : $this->totals; } protected function get_totals_var($key) { return isset($this->totals[$key]) ? $this->totals[$key] : $this->default_totals[$key]; } public function get_subtotal() { return apply_filters('woocommerce_cart_' . __FUNCTION__, $this->get_totals_var('subtotal')); } public function get_subtotal_tax() { return apply_filters('woocommerce_cart_' . __FUNCTION__, $this->get_totals_var('subtotal_tax')); } public function get_discount_total() { return apply_filters('woocommerce_cart_' . __FUNCTION__, $this->get_totals_var('discount_total')); } public function get_discount_tax() { return apply_filters('woocommerce_cart_' . __FUNCTION__, $this->get_totals_var('discount_tax')); } public function get_shipping_total() { return apply_filters('woocommerce_cart_' . __FUNCTION__, $this->get_totals_var('shipping_total')); } public function get_shipping_tax() { return apply_filters('woocommerce_cart_' . __FUNCTION__, $this->get_totals_var('shipping_tax')); } public function get_cart_contents_total() { return apply_filters('woocommerce_cart_' . __FUNCTION__, $this->get_totals_var('cart_contents_total')); } public function get_cart_contents_tax() { return apply_filters('woocommerce_cart_' . __FUNCTION__, $this->get_totals_var('cart_contents_tax')); } public function get_total($context = 'view') { $total = apply_filters('woocommerce_cart_' . __FUNCTION__, $this->get_totals_var('total')); return 'view' === $context ? apply_filters('woocommerce_cart_total', wc_price($total)) : $total; } public function get_total_tax() { return apply_filters('woocommerce_cart_' . __FUNCTION__, $this->get_totals_var('total_tax')); } public function get_fee_total() { return apply_filters('woocommerce_cart_' . __FUNCTION__, $this->get_totals_var('fee_total')); } public function get_fee_tax() { return apply_filters('woocommerce_cart_' . __FUNCTION__, $this->get_totals_var('fee_tax')); } public function get_shipping_taxes() { return apply_filters('woocommerce_cart_' . __FUNCTION__, $this->get_totals_var('shipping_taxes')); } public function get_cart_contents_taxes() { return apply_filters('woocommerce_cart_' . __FUNCTION__, $this->get_totals_var('cart_contents_taxes')); } public function get_fee_taxes() { return apply_filters('woocommerce_cart_' . __FUNCTION__, $this->get_totals_var('fee_taxes')); } public function display_prices_including_tax() { return apply_filters('woocommerce_cart_' . __FUNCTION__, 'incl' === $this->get_tax_price_display_mode()); } public function set_cart_contents($value) { $this->cart_contents = (array) $value; } public function set_removed_cart_contents($value = array()) { $this->removed_cart_contents = (array) $value; } public function set_applied_coupons($value = array()) { $this->applied_coupons = (array) $value; } public function set_coupon_discount_totals($value = array()) { $this->coupon_discount_totals = (array) $value; } public function set_coupon_discount_tax_totals($value = array()) { $this->coupon_discount_tax_totals = (array) $value; } public function set_totals($value = array()) { $this->totals = wp_parse_args($value, $this->default_totals); } public function set_subtotal($value) { $this->totals['subtotal'] = wc_format_decimal($value); } public function set_subtotal_tax($value) { $this->totals['subtotal_tax'] = $value; } public function set_discount_total($value) { $this->totals['discount_total'] = $value; } public function set_discount_tax($value) { $this->totals['discount_tax'] = $value; } public function set_shipping_total($value) { $this->totals['shipping_total'] = wc_format_decimal($value); } public function set_shipping_tax($value) { $this->totals['shipping_tax'] = $value; } public function set_cart_contents_total($value) { $this->totals['cart_contents_total'] = wc_format_decimal($value); } public function set_cart_contents_tax($value) { $this->totals['cart_contents_tax'] = $value; } public function set_total($value) { $this->totals['total'] = wc_format_decimal($value, wc_get_price_decimals()); } public function set_total_tax($value) { $this->totals['total_tax'] = wc_round_tax_total($value); } public function set_fee_total($value) { $this->totals['fee_total'] = wc_format_decimal($value); } public function set_fee_tax($value) { $this->totals['fee_tax'] = $value; } public function set_shipping_taxes($value) { $this->totals['shipping_taxes'] = (array) $value; } public function set_cart_contents_taxes($value) { $this->totals['cart_contents_taxes'] = (array) $value; } public function set_fee_taxes($value) { $this->totals['fee_taxes'] = (array) $value; } public function get_taxes() { return apply_filters('woocommerce_cart_get_taxes', wc_array_merge_recursive_numeric($this->get_shipping_taxes(), $this->get_cart_contents_taxes(), $this->get_fee_taxes()), $this); } public function get_cart() { if (!did_action('wp_loaded')) { wc_doing_it_wrong(__FUNCTION__, __('Get cart should not be called before the wp_loaded action.', 'woocommerce'), '2.3'); } if (!did_action('woocommerce_load_cart_from_session')) { $this->session->get_cart_from_session(); } return array_filter($this->get_cart_contents()); } public function get_cart_item($item_key) { return isset($this->cart_contents[$item_key]) ? $this->cart_contents[$item_key] : array(); } public function is_empty() { return 0 === count($this->get_cart()); } public function empty_cart($clear_persistent_cart = true) { do_action('woocommerce_before_cart_emptied', $clear_persistent_cart); $this->cart_contents = array(); $this->removed_cart_contents = array(); $this->shipping_methods = array(); $this->coupon_discount_totals = array(); $this->coupon_discount_tax_totals = array(); $this->applied_coupons = array(); $this->totals = $this->default_totals; if ($clear_persistent_cart) { $this->session->persistent_cart_destroy(); } $this->fees_api->remove_all_fees(); do_action('woocommerce_cart_emptied', $clear_persistent_cart); } public function get_cart_contents_count() { return apply_filters('woocommerce_cart_contents_count', array_sum(wp_list_pluck($this->get_cart(), 'quantity'))); } public function get_cart_contents_weight() { $weight = 0.0; foreach ($this->get_cart() as $cart_item_key => $values) { if ($values['data']->has_weight()) { $weight += (float) $values['data']->get_weight() * $values['quantity']; } } return apply_filters('woocommerce_cart_contents_weight', $weight); } public function get_cart_item_quantities() { $quantities = array(); foreach ($this->get_cart() as $cart_item_key => $values) { $product = $values['data']; $quantities[$product->get_stock_managed_by_id()] = isset($quantities[$product->get_stock_managed_by_id()]) ? $quantities[$product->get_stock_managed_by_id()] + $values['quantity'] : $values['quantity']; } return $quantities; } public function check_cart_items() { $return = true; $result = $this->check_cart_item_validity(); if (is_wp_error($result)) { wc_add_notice($result->get_error_message(), 'error'); $return = false; } $result = $this->check_cart_item_stock(); if (is_wp_error($result)) { wc_add_notice($result->get_error_message(), 'error'); $return = false; } return $return; } public function check_cart_coupons() { foreach ($this->get_applied_coupons() as $code) { $coupon = new WC_Coupon($code); if (!$coupon->is_valid()) { $coupon->add_coupon_message(WC_Coupon::E_WC_COUPON_INVALID_REMOVED); $this->remove_coupon($code); } } } public function check_cart_item_validity() { $return = true; foreach ($this->get_cart() as $cart_item_key => $values) { $product = $values['data']; if (!$product || !$product->exists() || 'trash' === $product->get_status()) { $this->set_quantity($cart_item_key, 0); $return = new WP_Error('invalid', __('An item which is no longer available was removed from your cart.', 'woocommerce')); } } return $return; } public function check_cart_item_stock() { $error = new WP_Error(); $product_qty_in_cart = $this->get_cart_item_quantities(); $current_session_order_id = isset(WC()->session->order_awaiting_payment) ? absint(WC()->session->order_awaiting_payment) : 0; foreach ($this->get_cart() as $cart_item_key => $values) { $product = $values['data']; if (!$product->is_in_stock()) { $error->add('out-of-stock', sprintf(__('Sorry, "%s" is not in stock. Please edit your cart and try again. We apologize for any inconvenience caused.', 'woocommerce'), $product->get_name())); return $error; } if (!$product->managing_stock() || $product->backorders_allowed()) { continue; } $held_stock = wc_get_held_stock_quantity($product, $current_session_order_id); $required_stock = $product_qty_in_cart[$product->get_stock_managed_by_id()]; if (apply_filters('woocommerce_cart_item_required_stock_is_not_enough', $product->get_stock_quantity() < $held_stock + $required_stock, $product, $values)) { $error->add('out-of-stock', sprintf(__('Sorry, we do not have enough "%1$s" in stock to fulfill your order (%2$s available). We apologize for any inconvenience caused.', 'woocommerce'), $product->get_name(), wc_format_stock_quantity_for_display($product->get_stock_quantity() - $held_stock, $product))); return $error; } } return true; } public function get_item_data($cart_item, $flat = false) { wc_deprecated_function('WC_Cart::get_item_data', '3.3', 'wc_get_formatted_cart_item_data'); return wc_get_formatted_cart_item_data($cart_item, $flat); } public function get_cross_sells() { $cross_sells = array(); $in_cart = array(); if (!$this->is_empty()) { foreach ($this->get_cart() as $cart_item_key => $values) { if ($values['quantity'] > 0) { $cross_sells = array_merge($values['data']->get_cross_sell_ids(), $cross_sells); $in_cart[] = $values['product_id']; } } } $cross_sells = array_diff($cross_sells, $in_cart); return apply_filters('woocommerce_cart_crosssell_ids', wp_parse_id_list($cross_sells), $this); } public function get_remove_url($cart_item_key) { wc_deprecated_function('WC_Cart::get_remove_url', '3.3', 'wc_get_cart_remove_url'); return wc_get_cart_remove_url($cart_item_key); } public function get_undo_url($cart_item_key) { wc_deprecated_function('WC_Cart::get_undo_url', '3.3', 'wc_get_cart_undo_url'); return wc_get_cart_undo_url($cart_item_key); } public function get_tax_totals() { $shipping_taxes = $this->get_shipping_taxes(); $taxes = $this->get_taxes(); $tax_totals = array(); foreach ($taxes as $key => $tax) { $code = WC_Tax::get_rate_code($key); if ($code || apply_filters('woocommerce_cart_remove_taxes_zero_rate_id', 'zero-rated') === $key) { if (!isset($tax_totals[$code])) { $tax_totals[$code] = new stdClass(); $tax_totals[$code]->amount = 0; } $tax_totals[$code]->tax_rate_id = $key; $tax_totals[$code]->is_compound = WC_Tax::is_compound($key); $tax_totals[$code]->label = WC_Tax::get_rate_label($key); if (isset($shipping_taxes[$key])) { $tax -= $shipping_taxes[$key]; $tax = wc_round_tax_total($tax); $tax += NumberUtil::round($shipping_taxes[$key], wc_get_price_decimals()); unset($shipping_taxes[$key]); } $tax_totals[$code]->amount += wc_round_tax_total($tax); $tax_totals[$code]->formatted_amount = wc_price($tax_totals[$code]->amount); } } if (apply_filters('woocommerce_cart_hide_zero_taxes', true)) { $amounts = array_filter(wp_list_pluck($tax_totals, 'amount')); $tax_totals = array_intersect_key($tax_totals, $amounts); } return apply_filters('woocommerce_cart_tax_totals', $tax_totals, $this); } public function get_cart_item_tax_classes() { $found_tax_classes = array(); foreach (WC()->cart->get_cart() as $item) { if ($item['data'] && ($item['data']->is_taxable() || $item['data']->is_shipping_taxable())) { $found_tax_classes[] = $item['data']->get_tax_class(); } } return array_unique($found_tax_classes); } public function get_cart_item_tax_classes_for_shipping() { $found_tax_classes = array(); foreach (WC()->cart->get_cart() as $item) { if ($item['data'] && $item['data']->is_shipping_taxable()) { $found_tax_classes[] = $item['data']->get_tax_class(); } } return array_unique($found_tax_classes); } public function get_displayed_subtotal() { return $this->display_prices_including_tax() ? $this->get_subtotal() + $this->get_subtotal_tax() : $this->get_subtotal(); } public function find_product_in_cart($cart_id = false) { if (false !== $cart_id) { if (is_array($this->cart_contents) && isset($this->cart_contents[$cart_id])) { return $cart_id; } } return ''; } public function generate_cart_id($product_id, $variation_id = 0, $variation = array(), $cart_item_data = array()) { $id_parts = array($product_id); if ($variation_id && 0 !== $variation_id) { $id_parts[] = $variation_id; } if (is_array($variation) && !empty($variation)) { $variation_key = ''; foreach ($variation as $key => $value) { $variation_key .= trim($key) . trim($value); } $id_parts[] = $variation_key; } if (is_array($cart_item_data) && !empty($cart_item_data)) { $cart_item_data_key = ''; foreach ($cart_item_data as $key => $value) { if (is_array($value) || is_object($value)) { $value = http_build_query($value); } $cart_item_data_key .= trim($key) . trim($value); } $id_parts[] = $cart_item_data_key; } return apply_filters('woocommerce_cart_id', md5(implode('_', $id_parts)), $product_id, $variation_id, $variation, $cart_item_data); } public function add_to_cart($product_id = 0, $quantity = 1, $variation_id = 0, $variation = array(), $cart_item_data = array()) { try { $product_id = absint($product_id); $variation_id = absint($variation_id); if ('product_variation' === get_post_type($product_id)) { $variation_id = $product_id; $product_id = wp_get_post_parent_id($variation_id); } $product_data = wc_get_product($variation_id ? $variation_id : $product_id); $quantity = apply_filters('woocommerce_add_to_cart_quantity', $quantity, $product_id); if ($quantity <= 0 || !$product_data || 'trash' === $product_data->get_status()) { return false; } if ($product_data->is_type('variation')) { $missing_attributes = array(); $parent_data = wc_get_product($product_data->get_parent_id()); $variation_attributes = $product_data->get_variation_attributes(); $variation_attributes = array_filter($variation_attributes); $posted_attributes = array(); foreach ($parent_data->get_attributes() as $attribute) { if (!$attribute['is_variation']) { continue; } $attribute_key = 'attribute_' . sanitize_title($attribute['name']); if (isset($variation[$attribute_key])) { if ($attribute['is_taxonomy']) { $value = sanitize_title(wp_unslash($variation[$attribute_key])); } else { $value = html_entity_decode(wc_clean(wp_unslash($variation[$attribute_key])), ENT_QUOTES, get_bloginfo('charset')); } if (!empty($value) || '0' === $value) { $posted_attributes[$attribute_key] = $value; } } } $posted_and_variation_attributes = array_merge($variation_attributes, $posted_attributes); if (empty($variation_id)) { $data_store = WC_Data_Store::load('product'); $variation_id = $data_store->find_matching_product_variation($parent_data, $posted_attributes); } if (empty($variation_id)) { throw new Exception(__('Please choose product options…', 'woocommerce')); } $variation_data = wc_get_product_variation_attributes($variation_id); $attributes = array(); foreach ($parent_data->get_attributes() as $attribute) { if (!$attribute['is_variation']) { continue; } $attribute_key = 'attribute_' . sanitize_title($attribute['name']); $valid_value = isset($variation_data[$attribute_key]) ? $variation_data[$attribute_key] : ''; if (isset($posted_and_variation_attributes[$attribute_key])) { $value = $posted_and_variation_attributes[$attribute_key]; if ($valid_value === $value) { $attributes[$attribute_key] = $value; } elseif ('' === $valid_value && in_array($value, $attribute->get_slugs(), true)) { $attributes[$attribute_key] = $value; } else { throw new Exception(sprintf(__('Invalid value posted for %s', 'woocommerce'), wc_attribute_label($attribute['name']))); } } elseif ('' === $valid_value) { $missing_attributes[] = wc_attribute_label($attribute['name']); } $variation = $attributes; } if (!empty($missing_attributes)) { throw new Exception(sprintf(_n('%s is a required field', '%s are required fields', count($missing_attributes), 'woocommerce'), wc_format_list_of_items($missing_attributes))); } } if (0 < $variation_id && (!$product_data->is_type('variation') || $product_data->get_parent_id() !== $product_id)) { $product = wc_get_product($product_id); throw new Exception(sprintf(__('The selected product isn\'t a variation of %2$s, please choose product options by visiting <a href="%1$s" title="%2$s">%2$s</a>.', 'woocommerce'), esc_url($product->get_permalink()), esc_html($product->get_name()))); } $cart_item_data = (array) apply_filters('woocommerce_add_cart_item_data', $cart_item_data, $product_id, $variation_id, $quantity); $cart_id = $this->generate_cart_id($product_id, $variation_id, $variation, $cart_item_data); $cart_item_key = $this->find_product_in_cart($cart_id); if ($product_data->is_sold_individually()) { $quantity = apply_filters('woocommerce_add_to_cart_sold_individually_quantity', 1, $quantity, $product_id, $variation_id, $cart_item_data); $found_in_cart = apply_filters('woocommerce_add_to_cart_sold_individually_found_in_cart', $cart_item_key && $this->cart_contents[$cart_item_key]['quantity'] > 0, $product_id, $variation_id, $cart_item_data, $cart_id); if ($found_in_cart) { $message = sprintf(__('You cannot add another "%s" to your cart.', 'woocommerce'), $product_data->get_name()); $message = apply_filters('woocommerce_cart_product_cannot_add_another_message', $message, $product_data); throw new Exception(sprintf('<a href="%s" class="button wc-forward">%s</a> %s', wc_get_cart_url(), __('View cart', 'woocommerce'), $message)); } } if (!$product_data->is_purchasable()) { $message = __('Sorry, this product cannot be purchased.', 'woocommerce'); $message = apply_filters('woocommerce_cart_product_cannot_be_purchased_message', $message, $product_data); throw new Exception($message); } if (!$product_data->is_in_stock()) { $message = sprintf(__('You cannot add "%s" to the cart because the product is out of stock.', 'woocommerce'), $product_data->get_name()); $message = apply_filters('woocommerce_cart_product_out_of_stock_message', $message, $product_data); throw new Exception($message); } if (!$product_data->has_enough_stock($quantity)) { $stock_quantity = $product_data->get_stock_quantity(); $message = sprintf(__('You cannot add that amount of "%1$s" to the cart because there is not enough stock (%2$s remaining).', 'woocommerce'), $product_data->get_name(), wc_format_stock_quantity_for_display($stock_quantity, $product_data)); $message = apply_filters('woocommerce_cart_product_not_enough_stock_message', $message, $product_data, $stock_quantity); throw new Exception($message); } if ($product_data->managing_stock()) { $products_qty_in_cart = $this->get_cart_item_quantities(); if (isset($products_qty_in_cart[$product_data->get_stock_managed_by_id()]) && !$product_data->has_enough_stock($products_qty_in_cart[$product_data->get_stock_managed_by_id()] + $quantity)) { $stock_quantity = $product_data->get_stock_quantity(); $stock_quantity_in_cart = $products_qty_in_cart[$product_data->get_stock_managed_by_id()]; $message = sprintf('<a href="%s" class="button wc-forward">%s</a> %s', wc_get_cart_url(), __('View cart', 'woocommerce'), sprintf(__('You cannot add that amount to the cart — we have %1$s in stock and you already have %2$s in your cart.', 'woocommerce'), wc_format_stock_quantity_for_display($stock_quantity, $product_data), wc_format_stock_quantity_for_display($stock_quantity_in_cart, $product_data))); $message = apply_filters('woocommerce_cart_product_not_enough_stock_already_in_cart_message', $message, $product_data, $stock_quantity, $stock_quantity_in_cart); throw new Exception($message); } } if ($cart_item_key) { $new_quantity = $quantity + $this->cart_contents[$cart_item_key]['quantity']; $this->set_quantity($cart_item_key, $new_quantity, false); } else { $cart_item_key = $cart_id; $this->cart_contents[$cart_item_key] = apply_filters('woocommerce_add_cart_item', array_merge($cart_item_data, array('key' => $cart_item_key, 'product_id' => $product_id, 'variation_id' => $variation_id, 'variation' => $variation, 'quantity' => $quantity, 'data' => $product_data, 'data_hash' => wc_get_cart_item_data_hash($product_data))), $cart_item_key); } $this->cart_contents = apply_filters('woocommerce_cart_contents_changed', $this->cart_contents); do_action('woocommerce_add_to_cart', $cart_item_key, $product_id, $quantity, $variation_id, $variation, $cart_item_data); return $cart_item_key; } catch (Exception $e) { if ($e->getMessage()) { wc_add_notice($e->getMessage(), 'error'); } return false; } } public function remove_cart_item($cart_item_key) { if (isset($this->cart_contents[$cart_item_key])) { $this->removed_cart_contents[$cart_item_key] = $this->cart_contents[$cart_item_key]; unset($this->removed_cart_contents[$cart_item_key]['data']); do_action('woocommerce_remove_cart_item', $cart_item_key, $this); unset($this->cart_contents[$cart_item_key]); do_action('woocommerce_cart_item_removed', $cart_item_key, $this); return true; } return false; } public function restore_cart_item($cart_item_key) { if (isset($this->removed_cart_contents[$cart_item_key])) { $restore_item = $this->removed_cart_contents[$cart_item_key]; $this->cart_contents[$cart_item_key] = $restore_item; $this->cart_contents[$cart_item_key]['data'] = wc_get_product($restore_item['variation_id'] ? $restore_item['variation_id'] : $restore_item['product_id']); do_action('woocommerce_restore_cart_item', $cart_item_key, $this); unset($this->removed_cart_contents[$cart_item_key]); do_action('woocommerce_cart_item_restored', $cart_item_key, $this); return true; } return false; } public function set_quantity($cart_item_key, $quantity = 1, $refresh_totals = true) { if (0 === $quantity || $quantity < 0) { wc_do_deprecated_action('woocommerce_before_cart_item_quantity_zero', array($cart_item_key, $this), '3.7.0', 'woocommerce_remove_cart_item'); return $this->remove_cart_item($cart_item_key); } $old_quantity = $this->cart_contents[$cart_item_key]['quantity']; $this->cart_contents[$cart_item_key]['quantity'] = $quantity; do_action('woocommerce_after_cart_item_quantity_update', $cart_item_key, $quantity, $old_quantity, $this); if ($refresh_totals) { $this->calculate_totals(); } do_action('woocommerce_cart_item_set_quantity', $cart_item_key, $quantity, $this); return true; } public function get_customer() { return WC()->customer; } public function calculate_totals() { $this->reset_totals(); if ($this->is_empty()) { $this->session->set_session(); return; } do_action('woocommerce_before_calculate_totals', $this); new WC_Cart_Totals($this); do_action('woocommerce_after_calculate_totals', $this); } public function needs_payment() { return apply_filters('woocommerce_cart_needs_payment', 0 < $this->get_total('edit'), $this); } public function calculate_shipping() { $this->shipping_methods = $this->needs_shipping() ? $this->get_chosen_shipping_methods(WC()->shipping()->calculate_shipping($this->get_shipping_packages())) : array(); $shipping_taxes = wp_list_pluck($this->shipping_methods, 'taxes'); $merged_taxes = array(); foreach ($shipping_taxes as $taxes) { foreach ($taxes as $tax_id => $tax_amount) { if (!isset($merged_taxes[$tax_id])) { $merged_taxes[$tax_id] = 0; } $merged_taxes[$tax_id] += $tax_amount; } } $this->set_shipping_total(array_sum(wp_list_pluck($this->shipping_methods, 'cost'))); $this->set_shipping_tax(array_sum($merged_taxes)); $this->set_shipping_taxes($merged_taxes); return $this->shipping_methods; } protected function get_chosen_shipping_methods($calculated_shipping_packages = array()) { $chosen_methods = array(); foreach ($calculated_shipping_packages as $key => $package) { $chosen_method = wc_get_chosen_shipping_method_for_package($key, $package); if ($chosen_method) { $chosen_methods[$key] = $package['rates'][$chosen_method]; } } return $chosen_methods; } protected function filter_items_needing_shipping($item) { $product = $item['data']; return $product && $product->needs_shipping(); } protected function get_items_needing_shipping() { return array_filter($this->get_cart(), array($this, 'filter_items_needing_shipping')); } public function get_shipping_packages() { return apply_filters('woocommerce_cart_shipping_packages', array(array('contents' => $this->get_items_needing_shipping(), 'contents_cost' => array_sum(wp_list_pluck($this->get_items_needing_shipping(), 'line_total')), 'applied_coupons' => $this->get_applied_coupons(), 'user' => array('ID' => get_current_user_id()), 'destination' => array('country' => $this->get_customer()->get_shipping_country(), 'state' => $this->get_customer()->get_shipping_state(), 'postcode' => $this->get_customer()->get_shipping_postcode(), 'city' => $this->get_customer()->get_shipping_city(), 'address' => $this->get_customer()->get_shipping_address(), 'address_1' => $this->get_customer()->get_shipping_address(), 'address_2' => $this->get_customer()->get_shipping_address_2()), 'cart_subtotal' => $this->get_displayed_subtotal()))); } public function needs_shipping() { if (!wc_shipping_enabled() || 0 === wc_get_shipping_method_count(true)) { return false; } $needs_shipping = false; foreach ($this->get_cart_contents() as $cart_item_key => $values) { if ($values['data']->needs_shipping()) { $needs_shipping = true; break; } } return apply_filters('woocommerce_cart_needs_shipping', $needs_shipping); } public function needs_shipping_address() { return apply_filters('woocommerce_cart_needs_shipping_address', true === $this->needs_shipping() && !wc_ship_to_billing_address_only()); } public function show_shipping() { if (!wc_shipping_enabled() || !$this->get_cart_contents()) { return false; } if ('yes' === get_option('woocommerce_shipping_cost_requires_address')) { $country = $this->get_customer()->get_shipping_country(); if (!$country) { return false; } $country_fields = WC()->countries->get_address_fields($country, 'shipping_'); if (isset($country_fields['shipping_state']) && $country_fields['shipping_state']['required'] && !$this->get_customer()->get_shipping_state()) { return false; } if (isset($country_fields['shipping_postcode']) && $country_fields['shipping_postcode']['required'] && !$this->get_customer()->get_shipping_postcode()) { return false; } } return apply_filters('woocommerce_cart_ready_to_calc_shipping', true); } public function get_cart_shipping_total() { $total = __('Free!', 'woocommerce'); if (0 < $this->get_shipping_total()) { if ($this->display_prices_including_tax()) { $total = wc_price($this->shipping_total + $this->shipping_tax_total); if ($this->shipping_tax_total > 0 && !wc_prices_include_tax()) { $total .= ' <small class="tax_label">' . WC()->countries->inc_tax_or_vat() . '</small>'; } } else { $total = wc_price($this->shipping_total); if ($this->shipping_tax_total > 0 && wc_prices_include_tax()) { $total .= ' <small class="tax_label">' . WC()->countries->ex_tax_or_vat() . '</small>'; } } } return apply_filters('woocommerce_cart_shipping_total', $total, $this); } public function check_customer_coupons($posted) { foreach ($this->get_applied_coupons() as $code) { $coupon = new WC_Coupon($code); if ($coupon->is_valid()) { $current_user = wp_get_current_user(); $billing_email = isset($posted['billing_email']) ? $posted['billing_email'] : ''; $check_emails = array_unique(array_filter(array_map('strtolower', array_map('sanitize_email', array($billing_email, $current_user->user_email))))); $restrictions = $coupon->get_email_restrictions(); if (is_array($restrictions) && 0 < count($restrictions) && !$this->is_coupon_emails_allowed($check_emails, $restrictions)) { $coupon->add_coupon_message(WC_Coupon::E_WC_COUPON_NOT_YOURS_REMOVED); $this->remove_coupon($code); } $coupon_usage_limit = $coupon->get_usage_limit_per_user(); if (0 < $coupon_usage_limit && 0 === get_current_user_id()) { $coupon_data_store = $coupon->get_data_store(); $billing_email = strtolower(sanitize_email($billing_email)); if ($coupon_data_store && $coupon_data_store->get_usage_by_email($coupon, $billing_email) >= $coupon_usage_limit) { if ($coupon_data_store->get_tentative_usages_for_user($coupon->get_id(), array($billing_email))) { $coupon->add_coupon_message(WC_Coupon::E_WC_COUPON_USAGE_LIMIT_COUPON_STUCK_GUEST); } else { $coupon->add_coupon_message(WC_Coupon::E_WC_COUPON_USAGE_LIMIT_REACHED); } } } } } } public function is_coupon_emails_allowed($check_emails, $restrictions) { foreach ($check_emails as $check_email) { if (in_array($check_email, $restrictions, true)) { return true; } foreach ($restrictions as $restriction) { $regex = '/^' . str_replace('*', '(.+)?', $restriction) . '$/'; preg_match($regex, $check_email, $match); if (!empty($match)) { return true; } } } return false; } public function has_discount($coupon_code = '') { return $coupon_code ? in_array(wc_format_coupon_code($coupon_code), $this->applied_coupons, true) : count($this->applied_coupons) > 0; } public function apply_coupon($coupon_code) { if (!wc_coupons_enabled()) { return false; } $coupon_code = wc_format_coupon_code($coupon_code); $the_coupon = new WC_Coupon($coupon_code); if ($the_coupon->get_code() !== $coupon_code) { $the_coupon->set_code($coupon_code); $the_coupon->add_coupon_message(WC_Coupon::E_WC_COUPON_NOT_EXIST); return false; } if (!$the_coupon->is_valid()) { wc_add_notice($the_coupon->get_error_message(), 'error'); return false; } if ($this->has_discount($coupon_code)) { $the_coupon->add_coupon_message(WC_Coupon::E_WC_COUPON_ALREADY_APPLIED); return false; } if ($the_coupon->get_individual_use()) { $coupons_to_keep = apply_filters('woocommerce_apply_individual_use_coupon', array(), $the_coupon, $this->applied_coupons); foreach ($this->applied_coupons as $applied_coupon) { $keep_key = array_search($applied_coupon, $coupons_to_keep, true); if (false === $keep_key) { $this->remove_coupon($applied_coupon); } else { unset($coupons_to_keep[$keep_key]); } } if (!empty($coupons_to_keep)) { $this->applied_coupons += $coupons_to_keep; } } if ($this->applied_coupons) { foreach ($this->applied_coupons as $code) { $coupon = new WC_Coupon($code); if ($coupon->get_individual_use() && false === apply_filters('woocommerce_apply_with_individual_use_coupon', false, $the_coupon, $coupon, $this->applied_coupons)) { $coupon->add_coupon_message(WC_Coupon::E_WC_COUPON_ALREADY_APPLIED_INDIV_USE_ONLY); return false; } } } $this->applied_coupons[] = $coupon_code; if ($the_coupon->get_free_shipping()) { $packages = WC()->shipping()->get_packages(); $chosen_shipping_methods = WC()->session->get('chosen_shipping_methods'); foreach ($packages as $i => $package) { $chosen_shipping_methods[$i] = 'free_shipping'; } WC()->session->set('chosen_shipping_methods', $chosen_shipping_methods); } $the_coupon->add_coupon_message(WC_Coupon::WC_COUPON_SUCCESS); do_action('woocommerce_applied_coupon', $coupon_code); return true; } public function get_coupons($deprecated = null) { $coupons = array(); if ('order' === $deprecated) { return $coupons; } foreach ($this->get_applied_coupons() as $code) { $coupon = new WC_Coupon($code); $coupons[$code] = $coupon; } return $coupons; } public function get_coupon_discount_amount($code, $ex_tax = true) { $totals = $this->get_coupon_discount_totals(); $discount_amount = isset($totals[$code]) ? $totals[$code] : 0; if (!$ex_tax) { $discount_amount += $this->get_coupon_discount_tax_amount($code); } return wc_cart_round_discount($discount_amount, wc_get_price_decimals()); } public function get_coupon_discount_tax_amount($code) { $totals = $this->get_coupon_discount_tax_totals(); return wc_cart_round_discount(isset($totals[$code]) ? $totals[$code] : 0, wc_get_price_decimals()); } public function remove_coupons($deprecated = null) { $this->set_coupon_discount_totals(array()); $this->set_coupon_discount_tax_totals(array()); $this->set_applied_coupons(array()); $this->session->set_session(); } public function remove_coupon($coupon_code) { $coupon_code = wc_format_coupon_code($coupon_code); $position = array_search($coupon_code, array_map('wc_format_coupon_code', $this->get_applied_coupons()), true); if (false !== $position) { unset($this->applied_coupons[$position]); } WC()->session->set('refresh_totals', true); do_action('woocommerce_removed_coupon', $coupon_code); return true; } public function calculate_fees() { do_action('woocommerce_cart_calculate_fees', $this); } public function fees_api() { return $this->fees_api; } public function add_fee($name, $amount, $taxable = false, $tax_class = '') { $this->fees_api()->add_fee(array('name' => $name, 'amount' => (float) $amount, 'taxable' => $taxable, 'tax_class' => $tax_class)); } public function get_fees() { $fees = $this->fees_api()->get_fees(); if (property_exists($this, 'fees')) { $fees = $fees + (array) $this->fees; } return $fees; } public function get_total_ex_tax() { return apply_filters('woocommerce_cart_total_ex_tax', wc_price(max(0, $this->get_total('edit') - $this->get_total_tax()))); } public function get_cart_total() { return apply_filters('woocommerce_cart_contents_total', wc_price(wc_prices_include_tax() ? $this->get_cart_contents_total() + $this->get_cart_contents_tax() : $this->get_cart_contents_total())); } public function get_cart_subtotal($compound = false) { if ($compound) { $cart_subtotal = wc_price($this->get_cart_contents_total() + $this->get_shipping_total() + $this->get_taxes_total(false, false)); } elseif ($this->display_prices_including_tax()) { $cart_subtotal = wc_price($this->get_subtotal() + $this->get_subtotal_tax()); if ($this->get_subtotal_tax() > 0 && !wc_prices_include_tax()) { $cart_subtotal .= ' <small class="tax_label">' . WC()->countries->inc_tax_or_vat() . '</small>'; } } else { $cart_subtotal = wc_price($this->get_subtotal()); if ($this->get_subtotal_tax() > 0 && wc_prices_include_tax()) { $cart_subtotal .= ' <small class="tax_label">' . WC()->countries->ex_tax_or_vat() . '</small>'; } } return apply_filters('woocommerce_cart_subtotal', $cart_subtotal, $compound, $this); } public function get_product_price($product) { if ($this->display_prices_including_tax()) { $product_price = wc_get_price_including_tax($product); } else { $product_price = wc_get_price_excluding_tax($product); } return apply_filters('woocommerce_cart_product_price', wc_price($product_price), $product); } public function get_product_subtotal($product, $quantity) { $price = $product->get_price(); if ($product->is_taxable()) { if ($this->display_prices_including_tax()) { $row_price = wc_get_price_including_tax($product, array('qty' => $quantity)); $product_subtotal = wc_price($row_price); if (!wc_prices_include_tax() && $this->get_subtotal_tax() > 0) { $product_subtotal .= ' <small class="tax_label">' . WC()->countries->inc_tax_or_vat() . '</small>'; } } else { $row_price = wc_get_price_excluding_tax($product, array('qty' => $quantity)); $product_subtotal = wc_price($row_price); if (wc_prices_include_tax() && $this->get_subtotal_tax() > 0) { $product_subtotal .= ' <small class="tax_label">' . WC()->countries->ex_tax_or_vat() . '</small>'; } } } else { $row_price = $price * $quantity; $product_subtotal = wc_price($row_price); } return apply_filters('woocommerce_cart_product_subtotal', $product_subtotal, $product, $quantity, $this); } public function get_cart_tax() { $cart_total_tax = wc_round_tax_total($this->get_cart_contents_tax() + $this->get_shipping_tax() + $this->get_fee_tax()); return apply_filters('woocommerce_get_cart_tax', $cart_total_tax ? wc_price($cart_total_tax) : ''); } public function get_tax_amount($tax_rate_id) { $taxes = wc_array_merge_recursive_numeric($this->get_cart_contents_taxes(), $this->get_fee_taxes()); return isset($taxes[$tax_rate_id]) ? $taxes[$tax_rate_id] : 0; } public function get_shipping_tax_amount($tax_rate_id) { $taxes = $this->get_shipping_taxes(); return isset($taxes[$tax_rate_id]) ? $taxes[$tax_rate_id] : 0; } public function get_taxes_total($compound = true, $display = true) { $total = 0; $taxes = $this->get_taxes(); foreach ($taxes as $key => $tax) { if (!$compound && WC_Tax::is_compound($key)) { continue; } $total += $tax; } if ($display) { $total = wc_format_decimal($total, wc_get_price_decimals()); } return apply_filters('woocommerce_cart_taxes_total', $total, $compound, $display, $this); } public function get_total_discount() { return apply_filters('woocommerce_cart_total_discount', $this->get_discount_total() ? wc_price($this->get_discount_total()) : false, $this); } private function reset_totals() { $this->totals = $this->default_totals; $this->fees_api->remove_all_fees(); do_action('woocommerce_cart_reset', $this, false); } public function get_tax_price_display_mode() { if ($this->get_customer() && $this->get_customer()->get_is_vat_exempt()) { return 'excl'; } return get_option('woocommerce_tax_display_cart'); } public function get_cart_hash() { $cart_session = $this->session->get_cart_for_session(); $hash = $cart_session ? md5(wp_json_encode($cart_session) . $this->get_total('edit')) : ''; $hash = apply_filters_deprecated('woocommerce_add_to_cart_hash', array($hash, $cart_session), '3.6.0', 'woocommerce_cart_hash'); return apply_filters('woocommerce_cart_hash', $hash, $cart_session); } }