2017-08-18 09:54:41 +00:00
< ? php
/**
* Cart session handling class .
*
* @ package WooCommerce / Classes
2018-03-16 17:45:28 +00:00
* @ version 3.2 . 0
2017-08-18 09:54:41 +00:00
*/
if ( ! defined ( 'ABSPATH' ) ) {
exit ;
}
/**
* WC_Cart_Session class .
*
* @ since 3.2 . 0
*/
final class WC_Cart_Session {
/**
* Reference to cart object .
*
* @ since 3.2 . 0
2017-09-27 16:12:45 +00:00
* @ var WC_Cart
2017-08-18 09:54:41 +00:00
*/
protected $cart ;
/**
* Sets up the items provided , and calculate totals .
*
* @ since 3.2 . 0
2017-09-27 16:12:45 +00:00
* @ throws Exception If missing WC_Cart object .
2017-09-27 16:16:33 +00:00
* @ param WC_Cart $cart Cart object to calculate totals for .
2017-08-18 09:54:41 +00:00
*/
2017-09-27 16:12:45 +00:00
public function __construct ( & $cart ) {
if ( ! is_a ( $cart , 'WC_Cart' ) ) {
throw new Exception ( 'A valid WC_Cart object is required' );
}
2017-08-18 09:54:41 +00:00
$this -> cart = $cart ;
2017-11-03 19:49:45 +00:00
}
2017-08-18 09:54:41 +00:00
2017-11-03 19:49:45 +00:00
/**
* Register methods for this object on the appropriate WordPress hooks .
*/
2017-11-08 15:17:52 +00:00
public function init () {
2017-08-18 09:54:41 +00:00
add_action ( 'wp_loaded' , array ( $this , 'get_cart_from_session' ) );
add_action ( 'woocommerce_cart_emptied' , array ( $this , 'destroy_cart_session' ) );
add_action ( 'wp' , array ( $this , 'maybe_set_cart_cookies' ), 99 );
add_action ( 'shutdown' , array ( $this , 'maybe_set_cart_cookies' ), 0 );
add_action ( 'woocommerce_add_to_cart' , array ( $this , 'maybe_set_cart_cookies' ) );
add_action ( 'woocommerce_after_calculate_totals' , array ( $this , 'set_session' ) );
add_action ( 'woocommerce_cart_loaded_from_session' , array ( $this , 'set_session' ) );
add_action ( 'woocommerce_removed_coupon' , array ( $this , 'set_session' ) );
add_action ( 'woocommerce_cart_updated' , array ( $this , 'persistent_cart_update' ) );
}
/**
* Get the cart data from the PHP session and store it in class variables .
*
* @ since 3.2 . 0
*/
public function get_cart_from_session () {
2018-03-05 19:57:57 +00:00
// Flag to indicate the stored cart should be updated.
2017-08-18 09:54:41 +00:00
$update_cart_session = false ;
$totals = WC () -> session -> get ( 'cart_totals' , null );
$cart = WC () -> session -> get ( 'cart' , null );
$this -> cart -> set_totals ( $totals );
$this -> cart -> set_applied_coupons ( WC () -> session -> get ( 'applied_coupons' , array () ) );
$this -> cart -> set_coupon_discount_totals ( WC () -> session -> get ( 'coupon_discount_totals' , array () ) );
$this -> cart -> set_coupon_discount_tax_totals ( WC () -> session -> get ( 'coupon_discount_tax_totals' , array () ) );
$this -> cart -> set_removed_cart_contents ( WC () -> session -> get ( 'removed_cart_contents' , array () ) );
2018-02-19 16:36:26 +00:00
if ( apply_filters ( 'woocommerce_persistent_cart_enabled' , true ) ) {
$saved_cart = get_user_meta ( get_current_user_id (), '_woocommerce_persistent_cart_' . get_current_blog_id (), true );
} else {
$saved_cart = false ;
}
if ( is_null ( $cart ) && $saved_cart ) {
2017-08-18 09:54:41 +00:00
$cart = $saved_cart [ 'cart' ];
$update_cart_session = true ;
} elseif ( is_null ( $cart ) ) {
$cart = array ();
2018-02-19 16:36:26 +00:00
} elseif ( is_array ( $cart ) && $saved_cart ) {
2017-12-05 06:45:52 +00:00
$cart = array_merge ( $saved_cart [ 'cart' ], $cart );
$update_cart_session = true ;
2017-08-18 09:54:41 +00:00
}
if ( is_array ( $cart ) ) {
$cart_contents = array ();
update_meta_cache ( 'post' , wp_list_pluck ( $cart , 'product_id' ) ); // Prime meta cache to reduce future queries.
update_object_term_cache ( wp_list_pluck ( $cart , 'product_id' ), 'product' );
foreach ( $cart as $key => $values ) {
$product = wc_get_product ( $values [ 'variation_id' ] ? $values [ 'variation_id' ] : $values [ 'product_id' ] );
if ( ! empty ( $product ) && $product -> exists () && $values [ 'quantity' ] > 0 ) {
if ( ! $product -> is_purchasable () ) {
2018-03-05 19:57:57 +00:00
$update_cart_session = true ;
2017-08-18 09:54:41 +00:00
/* translators: %s: product name */
wc_add_notice ( sprintf ( __ ( '%s has been removed from your cart because it can no longer be purchased. Please contact us if you need assistance.' , 'woocommerce' ), $product -> get_name () ), 'error' );
do_action ( 'woocommerce_remove_cart_item_from_session' , $key , $values );
2018-03-16 17:45:28 +00:00
} elseif ( ! empty ( $values [ 'data_hash' ] ) && ! hash_equals ( $values [ 'data_hash' ], wc_get_cart_item_data_hash ( $product ) ) ) { // phpcs:ignore PHPCompatibility.PHP.NewFunctions.hash_equalsFound
2018-03-05 19:57:57 +00:00
$update_cart_session = true ;
2018-02-02 00:54:15 +00:00
/* translators: %1$s: product name. %2$s product permalink */
2018-03-05 19:57:57 +00:00
wc_add_notice ( sprintf ( __ ( '%1$s has been removed from your cart because it has since been modified. You can add it back to your cart <a href="%2$s">here</a>.' , 'woocommerce' ), $product -> get_name (), $product -> get_permalink () ), 'notice' );
2018-02-02 00:54:15 +00:00
do_action ( 'woocommerce_remove_cart_item_from_session' , $key , $values );
2017-08-18 09:54:41 +00:00
} else {
// Put session data into array. Run through filter so other plugins can load their own session data.
2018-03-16 17:45:28 +00:00
$session_data = array_merge (
$values , array (
'data' => $product ,
)
);
2017-08-18 09:54:41 +00:00
$cart_contents [ $key ] = apply_filters ( 'woocommerce_get_cart_item_from_session' , $session_data , $values , $key );
2017-08-22 15:39:51 +00:00
// Add to cart right away so the product is visible in woocommerce_get_cart_item_from_session hook.
$this -> cart -> set_cart_contents ( $cart_contents );
2017-08-18 09:54:41 +00:00
}
}
}
}
do_action ( 'woocommerce_cart_loaded_from_session' , $this -> cart );
2017-11-07 20:10:13 +00:00
if ( $update_cart_session || is_null ( WC () -> session -> get ( 'cart_totals' , null ) ) ) {
2017-08-18 09:54:41 +00:00
WC () -> session -> set ( 'cart' , $this -> get_cart_for_session () );
$this -> cart -> calculate_totals ();
}
}
/**
* Destroy cart session data .
*
* @ since 3.2 . 0
*/
public function destroy_cart_session () {
WC () -> session -> set ( 'cart' , null );
WC () -> session -> set ( 'cart_totals' , null );
WC () -> session -> set ( 'applied_coupons' , null );
WC () -> session -> set ( 'coupon_discount_totals' , null );
WC () -> session -> set ( 'coupon_discount_tax_totals' , null );
WC () -> session -> set ( 'removed_cart_contents' , null );
WC () -> session -> set ( 'order_awaiting_payment' , null );
}
/**
* Will set cart cookies if needed and when possible .
*
* @ since 3.2 . 0
*/
public function maybe_set_cart_cookies () {
if ( ! headers_sent () && did_action ( 'wp_loaded' ) ) {
if ( ! $this -> cart -> is_empty () ) {
$this -> set_cart_cookies ( true );
2018-03-16 17:45:28 +00:00
} elseif ( isset ( $_COOKIE [ 'woocommerce_items_in_cart' ] ) ) { // WPCS: input var ok.
2017-08-18 09:54:41 +00:00
$this -> set_cart_cookies ( false );
}
}
}
/**
* Sets the php session data for the cart and coupons .
*/
public function set_session () {
WC () -> session -> set ( 'cart' , $this -> get_cart_for_session () );
WC () -> session -> set ( 'cart_totals' , $this -> cart -> get_totals () );
WC () -> session -> set ( 'applied_coupons' , $this -> cart -> get_applied_coupons () );
WC () -> session -> set ( 'coupon_discount_totals' , $this -> cart -> get_coupon_discount_totals () );
WC () -> session -> set ( 'coupon_discount_tax_totals' , $this -> cart -> get_coupon_discount_tax_totals () );
WC () -> session -> set ( 'removed_cart_contents' , $this -> cart -> get_removed_cart_contents () );
do_action ( 'woocommerce_cart_updated' );
}
/**
* Returns the contents of the cart in an array without the 'data' element .
*
* @ return array contents of the cart
*/
public function get_cart_for_session () {
$cart_session = array ();
foreach ( $this -> cart -> get_cart () as $key => $values ) {
$cart_session [ $key ] = $values ;
unset ( $cart_session [ $key ][ 'data' ] ); // Unset product object.
}
return $cart_session ;
}
/**
* Save the persistent cart when the cart is updated .
*/
public function persistent_cart_update () {
2018-02-19 16:36:26 +00:00
if ( get_current_user_id () && apply_filters ( 'woocommerce_persistent_cart_enabled' , true ) ) {
2018-03-16 17:45:28 +00:00
update_user_meta (
get_current_user_id (), '_woocommerce_persistent_cart_' . get_current_blog_id (), array (
'cart' => $this -> get_cart_for_session (),
)
);
2017-08-18 09:54:41 +00:00
}
}
/**
* Delete the persistent cart permanently .
*/
public function persistent_cart_destroy () {
2018-02-19 16:36:26 +00:00
if ( get_current_user_id () && apply_filters ( 'woocommerce_persistent_cart_enabled' , true ) ) {
2017-08-18 09:54:41 +00:00
delete_user_meta ( get_current_user_id (), '_woocommerce_persistent_cart_' . get_current_blog_id () );
}
}
/**
* Set cart hash cookie and items in cart .
*
* @ access private
* @ param bool $set Should cookies be set ( true ) or unset .
*/
private function set_cart_cookies ( $set = true ) {
if ( $set ) {
wc_setcookie ( 'woocommerce_items_in_cart' , 1 );
wc_setcookie ( 'woocommerce_cart_hash' , md5 ( wp_json_encode ( $this -> get_cart_for_session () ) ) );
2018-03-16 17:45:28 +00:00
} elseif ( isset ( $_COOKIE [ 'woocommerce_items_in_cart' ] ) ) { // WPCS: input var ok.
2017-08-18 09:54:41 +00:00
wc_setcookie ( 'woocommerce_items_in_cart' , 0 , time () - HOUR_IN_SECONDS );
wc_setcookie ( 'woocommerce_cart_hash' , '' , time () - HOUR_IN_SECONDS );
}
do_action ( 'woocommerce_set_cart_cookies' , $set );
}
}