2011-08-09 15:16:18 +00:00
< ? php
/**
2011-08-10 17:11:11 +00:00
* WooCommerce cart
2011-08-09 15:16:18 +00:00
*
2011-08-10 17:11:11 +00:00
* The WooCommerce cart class stores cart data and active coupons as well as handling customer sessions and some cart related urls .
2011-08-09 15:16:18 +00:00
* The cart class also has a price calculation function which calls upon other classes to calcualte totals .
*
2011-08-10 17:11:11 +00:00
* @ class woocommerce_cart
* @ package WooCommerce
* @ category Class
* @ author WooThemes
2011-08-09 15:16:18 +00:00
*/
2011-08-10 17:11:11 +00:00
class woocommerce_cart {
2011-08-09 15:16:18 +00:00
private static $_instance ;
public static $cart_contents_total ;
public static $cart_contents_total_ex_tax ;
public static $cart_contents_weight ;
public static $cart_contents_count ;
public static $cart_contents_tax ;
public static $cart_contents ;
public static $total ;
public static $subtotal ;
public static $subtotal_ex_tax ;
public static $tax_total ;
public static $discount_total ;
public static $shipping_total ;
public static $shipping_tax_total ;
public static $applied_coupons ;
/** constructor */
function __construct () {
add_action ( 'init' , array ( $this , 'init' ), 1 );
}
/** get class instance */
public static function get () {
if ( ! isset ( self :: $_instance )) {
$c = __CLASS__ ;
self :: $_instance = new $c ;
}
return self :: $_instance ;
}
public function init () {
self :: $applied_coupons = array ();
self :: get_cart_from_session ();
if ( isset ( $_SESSION [ 'coupons' ]) ) self :: $applied_coupons = $_SESSION [ 'coupons' ];
self :: calculate_totals ();
}
/** Gets the cart data from the PHP session */
function get_cart_from_session () {
if ( isset ( $_SESSION [ 'cart' ]) && is_array ( $_SESSION [ 'cart' ]) ) :
$cart = $_SESSION [ 'cart' ];
foreach ( $cart as $values ) :
if ( $values [ 'variation_id' ] > 0 ) :
2011-08-10 17:11:11 +00:00
$_product = & new woocommerce_product_variation ( $values [ 'variation_id' ]);
2011-08-09 15:16:18 +00:00
else :
2011-08-10 17:11:11 +00:00
$_product = & new woocommerce_product ( $values [ 'product_id' ]);
2011-08-09 15:16:18 +00:00
endif ;
if ( $_product -> exists ) :
self :: $cart_contents [] = array (
'product_id' => $values [ 'product_id' ],
'variation_id' => $values [ 'variation_id' ],
'variation' => $values [ 'variation' ],
'quantity' => $values [ 'quantity' ],
'data' => $_product
);
endif ;
endforeach ;
else :
self :: $cart_contents = array ();
endif ;
if ( ! is_array ( self :: $cart_contents )) self :: $cart_contents = array ();
}
/** sets the php session data for the cart and coupon */
function set_session () {
$cart = array ();
$_SESSION [ 'cart' ] = self :: $cart_contents ;
$_SESSION [ 'coupons' ] = self :: $applied_coupons ;
self :: calculate_totals ();
}
/** Empty the cart */
function empty_cart () {
unset ( $_SESSION [ 'cart' ]);
unset ( $_SESSION [ 'coupons' ]);
}
/** Check if product is in the cart */
function find_product_in_cart ( $product_id , $variation = '' ) {
foreach ( self :: $cart_contents as $cart_item_key => $cart_item ) :
if ( $variation ) :
if ( $cart_item [ 'product_id' ] == $product_id && $cart_item [ 'variation' ] == $variation ) :
return $cart_item_key ;
endif ;
else :
if ( $cart_item [ 'product_id' ] == $product_id ) :
return $cart_item_key ;
endif ;
endif ;
endforeach ;
}
/**
* Add a product to the cart
*
* @ param string product_id contains the id of the product to add to the cart
* @ param string quantity contains the quantity of the item to add
*/
function add_to_cart ( $product_id , $quantity = 1 , $variation = '' , $variation_id = '' ) {
$found_cart_item_key = self :: find_product_in_cart ( $product_id , $variation );
if ( is_numeric ( $found_cart_item_key )) :
$quantity = $quantity + self :: $cart_contents [ $found_cart_item_key ][ 'quantity' ];
self :: $cart_contents [ $found_cart_item_key ][ 'quantity' ] = $quantity ;
else :
$cart_item_key = sizeof ( self :: $cart_contents );
2011-08-10 17:11:11 +00:00
$data = & new woocommerce_product ( $product_id );
2011-08-09 15:16:18 +00:00
self :: $cart_contents [ $cart_item_key ] = array (
'product_id' => $product_id ,
'variation_id' => $variation_id ,
'variation' => $variation ,
'quantity' => $quantity ,
'data' => $data
);
endif ;
self :: set_session ();
}
/**
* Set the quantity for an item in the cart
*
* @ param string cart_item_key contains the id of the cart item
* @ param string quantity contains the quantity of the item
*/
function set_quantity ( $cart_item , $quantity = 1 ) {
if ( $quantity == 0 || $quantity < 0 ) :
unset ( self :: $cart_contents [ $cart_item ]);
else :
self :: $cart_contents [ $cart_item ][ 'quantity' ] = $quantity ;
endif ;
self :: set_session ();
}
/**
* Returns the contents of the cart
*
* @ return array cart_contents
*/
function get_cart () {
return self :: $cart_contents ;
}
/**
* Gets cross sells based on the items in the cart
*
* @ return array cross_sells item ids of cross sells
*/
function get_cross_sells () {
$cross_sells = array ();
$in_cart = array ();
if ( sizeof ( self :: $cart_contents ) > 0 ) : foreach ( self :: $cart_contents as $cart_item_key => $values ) :
if ( $values [ 'quantity' ] > 0 ) :
$cross_sells = array_merge ( $values [ 'data' ] -> get_cross_sells (), $cross_sells );
$in_cart [] = $values [ 'product_id' ];
endif ;
endforeach ; endif ;
$cross_sells = array_diff ( $cross_sells , $in_cart );
return $cross_sells ;
}
/** gets the url to the cart page */
function get_cart_url () {
2011-08-10 17:11:11 +00:00
$cart_page_id = get_option ( 'woocommerce_cart_page_id' );
2011-08-09 15:16:18 +00:00
if ( $cart_page_id ) return get_permalink ( $cart_page_id );
}
/** gets the url to the checkout page */
function get_checkout_url () {
2011-08-10 17:11:11 +00:00
$checkout_page_id = get_option ( 'woocommerce_checkout_page_id' );
2011-08-09 15:16:18 +00:00
if ( $checkout_page_id ) :
if ( is_ssl ()) return str_replace ( 'http:' , 'https:' , get_permalink ( $checkout_page_id ));
return get_permalink ( $checkout_page_id );
endif ;
}
/** gets the url to remove an item from the cart */
function get_remove_url ( $cart_item_key ) {
2011-08-10 17:11:11 +00:00
$cart_page_id = get_option ( 'woocommerce_cart_page_id' );
if ( $cart_page_id ) return woocommerce :: nonce_url ( 'cart' , add_query_arg ( 'remove_item' , $cart_item_key , get_permalink ( $cart_page_id )));
2011-08-09 15:16:18 +00:00
}
/** looks through the cart to see if shipping is actually required */
function needs_shipping () {
2011-08-10 17:11:11 +00:00
if ( ! woocommerce_shipping :: $enabled ) return false ;
2011-08-09 15:16:18 +00:00
if ( ! is_array ( self :: $cart_contents )) return false ;
$needs_shipping = false ;
foreach ( self :: $cart_contents as $cart_item_key => $values ) :
$_product = $values [ 'data' ];
if ( $_product -> is_type ( 'simple' ) || $_product -> is_type ( 'variable' ) ) :
$needs_shipping = true ;
endif ;
endforeach ;
return $needs_shipping ;
}
/** Sees if we need a shipping address */
function ship_to_billing_address_only () {
2011-08-10 17:11:11 +00:00
$ship_to_billing_address_only = get_option ( 'woocommerce_ship_to_billing_address_only' );
2011-08-09 15:16:18 +00:00
if ( $ship_to_billing_address_only == 'yes' ) return true ;
return false ;
}
/** looks at the totals to see if payment is actually required */
function needs_payment () {
if ( self :: $total > 0 ) return true ;
return false ;
}
/** looks through the cart to check each item is in stock */
function check_cart_item_stock () {
$error = new WP_Error ();
foreach ( self :: $cart_contents as $cart_item_key => $values ) :
$_product = $values [ 'data' ];
if ( $_product -> managing_stock ()) :
if ( $_product -> is_in_stock () && $_product -> has_enough_stock ( $values [ 'quantity' ] )) :
// :)
else :
2011-08-17 23:42:07 +00:00
$error -> add ( 'out-of-stock' , sprintf ( __ ( 'Sorry, we do not have enough "%s" in stock to fulfill your order (%s in stock). Please edit your cart and try again. We apologise for any inconvenience caused.' , 'woothemes' ), $_product -> get_title (), $_product -> stock ) );
2011-08-09 15:16:18 +00:00
return $error ;
endif ;
else :
if ( ! $_product -> is_in_stock ()) :
2011-08-10 17:11:11 +00:00
$error -> add ( 'out-of-stock' , sprintf ( __ ( 'Sorry, we do not have enough "%s" in stock to fulfill your order. Please edit your cart and try again. We apologise for any inconvenience caused.' , 'woothemes' ), $_product -> get_title () ) );
2011-08-09 15:16:18 +00:00
return $error ;
endif ;
endif ;
endforeach ;
return true ;
}
/** calculate totals for the items in the cart */
public static function calculate_totals () {
2011-08-10 17:11:11 +00:00
$_tax = & new woocommerce_tax ();
2011-08-09 15:16:18 +00:00
self :: $total = 0 ;
self :: $cart_contents_total = 0 ;
self :: $cart_contents_total_ex_tax = 0 ;
self :: $cart_contents_weight = 0 ;
self :: $cart_contents_count = 0 ;
self :: $cart_contents_tax = 0 ;
self :: $tax_total = 0 ;
self :: $shipping_tax_total = 0 ;
self :: $subtotal = 0 ;
self :: $subtotal_ex_tax = 0 ;
self :: $discount_total = 0 ;
self :: $shipping_total = 0 ;
if ( sizeof ( self :: $cart_contents ) > 0 ) : foreach ( self :: $cart_contents as $cart_item_key => $values ) :
$_product = $values [ 'data' ];
if ( $_product -> exists () && $values [ 'quantity' ] > 0 ) :
self :: $cart_contents_count = self :: $cart_contents_count + $values [ 'quantity' ];
self :: $cart_contents_weight = self :: $cart_contents_weight + ( $_product -> get_weight () * $values [ 'quantity' ]);
2011-08-11 22:39:02 +00:00
$total_item_price = $_product -> get_price () * $values [ 'quantity' ];
2011-08-10 17:11:11 +00:00
if ( get_option ( 'woocommerce_calc_taxes' ) == 'yes' ) :
2011-08-09 15:16:18 +00:00
if ( $_product -> is_taxable () ) :
2011-08-17 23:42:07 +00:00
$rate = $_tax -> get_rate ( $_product -> tax_class );
2011-08-09 15:16:18 +00:00
2011-08-10 17:11:11 +00:00
if ( get_option ( 'woocommerce_prices_include_tax' ) == 'yes' ) :
2011-08-09 15:16:18 +00:00
2011-08-11 22:39:02 +00:00
$tax_amount = $_tax -> calc_tax ( $_product -> get_price (), $rate , true ) * $values [ 'quantity' ];
2011-08-09 15:16:18 +00:00
else :
2011-08-11 22:39:02 +00:00
$tax_amount = $_tax -> calc_tax ( $_product -> get_price (), $rate , false ) * $values [ 'quantity' ];
2011-08-09 15:16:18 +00:00
endif ;
2011-08-10 17:11:11 +00:00
if ( get_option ( 'woocommerce_prices_include_tax' ) == 'yes' && woocommerce_customer :: is_customer_outside_base () && defined ( 'WOOCOMMERCE_CHECKOUT' ) && WOOCOMMERCE_CHECKOUT ) :
2011-08-09 15:16:18 +00:00
/**
* Our prices include tax so we need to take the base tax rate into consideration of our shop ' s country
*
* Lets get the base rate first
*/
2011-08-17 23:42:07 +00:00
$base_rate = $_tax -> get_shop_base_rate ( $_product -> tax_class );
2011-08-09 15:16:18 +00:00
// Calc tax for base country
2011-08-11 22:39:02 +00:00
$base_tax_amount = $_tax -> calc_tax ( $_product -> get_price (), $base_rate , true );
2011-08-09 15:16:18 +00:00
// Now calc tax for user county (which now excludes tax)
2011-08-11 22:39:02 +00:00
$tax_amount = $_tax -> calc_tax ( ( $_product -> get_price () - $base_tax_amount ), $rate , false );
$tax_amount = $tax_amount * $values [ 'quantity' ];
2011-08-09 15:16:18 +00:00
// Finally, update $total_item_price to reflect tax amounts
2011-08-11 22:39:02 +00:00
$total_item_price = ( $total_item_price - ( $base_tax_amount * $values [ 'quantity' ]) + $tax_amount );
2011-08-09 15:16:18 +00:00
endif ;
endif ;
endif ;
2011-08-11 22:39:02 +00:00
$tax_amount = ( isset ( $tax_amount ) ? $tax_amount : 0 );
2011-08-09 15:16:18 +00:00
self :: $cart_contents_tax = self :: $cart_contents_tax + $tax_amount ;
self :: $cart_contents_total = self :: $cart_contents_total + $total_item_price ;
2011-08-11 22:39:02 +00:00
self :: $cart_contents_total_ex_tax = self :: $cart_contents_total_ex_tax + ( $_product -> get_price_excluding_tax () * $values [ 'quantity' ]);
2011-08-09 15:16:18 +00:00
// Product Discounts
if ( self :: $applied_coupons ) foreach ( self :: $applied_coupons as $code ) :
2011-08-10 17:11:11 +00:00
$coupon = woocommerce_coupons :: get_coupon ( $code );
2011-08-09 15:16:18 +00:00
if ( $coupon [ 'type' ] == 'fixed_product' && in_array ( $values [ 'product_id' ], $coupon [ 'products' ])) :
self :: $discount_total = self :: $discount_total + ( $coupon [ 'amount' ] * $values [ 'quantity' ] );
endif ;
endforeach ;
endif ;
endforeach ; endif ;
// Cart Shipping
2011-08-10 17:11:11 +00:00
if ( self :: needs_shipping ()) woocommerce_shipping :: calculate_shipping (); else woocommerce_shipping :: reset_shipping ();
2011-08-09 15:16:18 +00:00
2011-08-10 17:11:11 +00:00
self :: $shipping_total = woocommerce_shipping :: $shipping_total ;
2011-08-09 15:16:18 +00:00
2011-08-10 17:11:11 +00:00
self :: $shipping_tax_total = woocommerce_shipping :: $shipping_tax ;
2011-08-09 15:16:18 +00:00
self :: $tax_total = self :: $cart_contents_tax ;
// Subtotal
self :: $subtotal_ex_tax = self :: $cart_contents_total_ex_tax ;
self :: $subtotal = self :: $cart_contents_total ;
// Cart Discounts
if ( self :: $applied_coupons ) foreach ( self :: $applied_coupons as $code ) :
2011-08-10 17:11:11 +00:00
$coupon = woocommerce_coupons :: get_coupon ( $code );
if ( woocommerce_coupons :: is_valid ( $code )) :
2011-08-09 15:16:18 +00:00
if ( $coupon [ 'type' ] == 'fixed_cart' ) :
self :: $discount_total = self :: $discount_total + $coupon [ 'amount' ];
elseif ( $coupon [ 'type' ] == 'percent' ) :
self :: $discount_total = self :: $discount_total + ( self :: $subtotal / 100 ) * $coupon [ 'amount' ];
endif ;
endif ;
endforeach ;
// Total
2011-08-10 17:11:11 +00:00
if ( get_option ( 'woocommerce_prices_include_tax' ) == 'yes' ) :
self :: $total = self :: $subtotal + self :: $shipping_tax_total - self :: $discount_total + woocommerce_shipping :: $shipping_total ;
2011-08-09 15:16:18 +00:00
else :
2011-08-10 17:11:11 +00:00
self :: $total = self :: $subtotal + self :: $tax_total + self :: $shipping_tax_total - self :: $discount_total + woocommerce_shipping :: $shipping_total ;
2011-08-09 15:16:18 +00:00
endif ;
if ( self :: $total < 0 ) self :: $total = 0 ;
}
/** gets the total (after calculation) */
function get_total () {
2011-08-10 17:11:11 +00:00
return woocommerce_price ( self :: $total );
2011-08-09 15:16:18 +00:00
}
/** gets the cart contens total (after calculation) */
function get_cart_total () {
2011-08-10 17:11:11 +00:00
return woocommerce_price ( self :: $cart_contents_total );
2011-08-09 15:16:18 +00:00
}
/** gets the sub total (after calculation) */
function get_cart_subtotal () {
2011-08-10 17:11:11 +00:00
if ( get_option ( 'woocommerce_display_totals_tax' ) == 'excluding' || ( defined ( 'WOOCOMMERCE_CHECKOUT' ) && WOOCOMMERCE_CHECKOUT )) :
2011-08-09 15:16:18 +00:00
2011-08-10 17:11:11 +00:00
if ( get_option ( 'woocommerce_prices_include_tax' ) == 'yes' ) :
2011-08-09 15:16:18 +00:00
2011-08-10 17:11:11 +00:00
$return = woocommerce_price ( self :: $subtotal - self :: $tax_total );
2011-08-09 15:16:18 +00:00
else :
2011-08-10 17:11:11 +00:00
$return = woocommerce_price ( self :: $subtotal );
2011-08-09 15:16:18 +00:00
endif ;
if ( self :: $tax_total > 0 ) :
2011-08-10 17:11:11 +00:00
$return .= __ ( ' <small>(ex. tax)</small>' , 'woothemes' );
2011-08-09 15:16:18 +00:00
endif ;
return $return ;
else :
2011-08-10 17:11:11 +00:00
if ( get_option ( 'woocommerce_prices_include_tax' ) == 'yes' ) :
2011-08-09 15:16:18 +00:00
2011-08-10 17:11:11 +00:00
$return = woocommerce_price ( self :: $subtotal );
2011-08-09 15:16:18 +00:00
else :
2011-08-10 17:11:11 +00:00
$return = woocommerce_price ( self :: $subtotal + self :: $tax_total );
2011-08-09 15:16:18 +00:00
endif ;
if ( self :: $tax_total > 0 ) :
2011-08-10 17:11:11 +00:00
$return .= __ ( ' <small>(inc. tax)</small>' , 'woothemes' );
2011-08-09 15:16:18 +00:00
endif ;
return $return ;
endif ;
}
/** gets the cart tax (after calculation) */
function get_cart_tax () {
$cart_total_tax = self :: $tax_total + self :: $shipping_tax_total ;
2011-08-10 17:11:11 +00:00
if ( $cart_total_tax > 0 ) return woocommerce_price ( $cart_total_tax );
2011-08-09 15:16:18 +00:00
return false ;
}
/** gets the shipping total (after calculation) */
function get_cart_shipping_total () {
2011-08-10 17:11:11 +00:00
if ( isset ( woocommerce_shipping :: $shipping_label )) :
if ( woocommerce_shipping :: $shipping_total > 0 ) :
2011-08-09 15:16:18 +00:00
2011-08-10 17:11:11 +00:00
if ( get_option ( 'woocommerce_display_totals_tax' ) == 'excluding' ) :
2011-08-09 15:16:18 +00:00
2011-08-10 17:11:11 +00:00
$return = woocommerce_price ( woocommerce_shipping :: $shipping_total );
2011-08-09 15:16:18 +00:00
if ( self :: $shipping_tax_total > 0 ) :
2011-08-10 17:11:11 +00:00
$return .= __ ( ' <small>(ex. tax)</small>' , 'woothemes' );
2011-08-09 15:16:18 +00:00
endif ;
return $return ;
else :
2011-08-10 17:11:11 +00:00
$return = woocommerce_price ( woocommerce_shipping :: $shipping_total + woocommerce_shipping :: $shipping_tax );
2011-08-09 15:16:18 +00:00
if ( self :: $shipping_tax_total > 0 ) :
2011-08-10 17:11:11 +00:00
$return .= __ ( ' <small>(inc. tax)</small>' , 'woothemes' );
2011-08-09 15:16:18 +00:00
endif ;
return $return ;
endif ;
else :
2011-08-10 17:11:11 +00:00
return __ ( 'Free!' , 'woothemes' );
2011-08-09 15:16:18 +00:00
endif ;
endif ;
}
/** gets title of the chosen shipping method */
function get_cart_shipping_title () {
2011-08-10 17:11:11 +00:00
if ( isset ( woocommerce_shipping :: $shipping_label )) :
return __ ( 'via ' , 'woothemes' ) . woocommerce_shipping :: $shipping_label ;
2011-08-09 15:16:18 +00:00
endif ;
return false ;
}
/**
* Applies a coupon code
*
* @ param string code The code to apply
* @ return bool True if the coupon is applied , false if it does not exist or cannot be applied
*/
function add_discount ( $coupon_code ) {
2011-08-10 17:11:11 +00:00
if ( $the_coupon = woocommerce_coupons :: get_coupon ( $coupon_code )) :
2011-08-09 15:16:18 +00:00
// Check if applied
2011-08-10 17:11:11 +00:00
if ( woocommerce_cart :: has_discount ( $coupon_code )) :
woocommerce :: add_error ( __ ( 'Discount code already applied!' , 'woothemes' ) );
2011-08-09 15:16:18 +00:00
return false ;
endif ;
// Check it can be used with cart
2011-08-10 17:11:11 +00:00
if ( ! woocommerce_coupons :: is_valid ( $coupon_code )) :
woocommerce :: add_error ( __ ( 'Invalid coupon.' , 'woothemes' ) );
2011-08-09 15:16:18 +00:00
return false ;
endif ;
// If its individual use then remove other coupons
2011-08-15 16:48:24 +00:00
if ( $the_coupon [ 'individual_use' ] == 1 ) :
2011-08-09 15:16:18 +00:00
self :: $applied_coupons = array ();
endif ;
foreach ( self :: $applied_coupons as $coupon ) :
2011-08-10 17:11:11 +00:00
$coupon = woocommerce_coupons :: get_coupon ( $coupon );
2011-08-15 16:48:24 +00:00
if ( $coupon [ 'individual_use' ] == 1 ) :
2011-08-09 15:16:18 +00:00
self :: $applied_coupons = array ();
endif ;
endforeach ;
self :: $applied_coupons [] = $coupon_code ;
self :: set_session ();
2011-08-10 17:11:11 +00:00
woocommerce :: add_message ( __ ( 'Discount code applied successfully.' , 'woothemes' ) );
2011-08-09 15:16:18 +00:00
return true ;
else :
2011-08-10 17:11:11 +00:00
woocommerce :: add_error ( __ ( 'Coupon does not exist!' , 'woothemes' ) );
2011-08-09 15:16:18 +00:00
return false ;
endif ;
return false ;
}
/** returns whether or not a discount has been applied */
function has_discount ( $code ) {
if ( in_array ( $code , self :: $applied_coupons )) return true ;
return false ;
}
/** gets the total discount amount */
function get_total_discount () {
2011-08-10 17:11:11 +00:00
if ( self :: $discount_total ) return woocommerce_price ( self :: $discount_total ); else return false ;
2011-08-09 15:16:18 +00:00
}
/** clears the cart/coupon data and re-calcs totals */
function clear_cache () {
self :: $cart_contents = array ();
self :: $applied_coupons = array ();
unset ( $_SESSION [ 'cart' ] );
unset ( $_SESSION [ 'coupons' ] );
self :: calculate_totals ();
}
}