WCML_Cart

The WooCommerce Multilingual WCML Cart class.

Defined (1)

The class is defined in the following location(s).

/inc/class-wcml-cart.php  
  1. class WCML_Cart 
  2.  
  3. private $woocommerce_wpml; 
  4. private $sitepress; 
  5. private $woocommerce; 
  6.  
  7. public function __construct( &$woocommerce_wpml, &$sitepress, &$woocommerce ) 
  8. $this->woocommerce_wpml = $woocommerce_wpml; 
  9. $this->sitepress = $sitepress; 
  10. $this->woocommerce = $woocommerce; 
  11.  
  12. if( $this->woocommerce_wpml->settings[ 'cart_sync' ][ 'currency_switch' ] == WCML_CART_CLEAR || $this->woocommerce_wpml->settings[ 'cart_sync' ][ 'lang_switch' ] == WCML_CART_CLEAR ) { 
  13. $this->enqueue_dialog_ui(); 
  14.  
  15. add_action( 'wcml_removed_cart_items', array( $this, 'wcml_removed_cart_items_widget' ) ); 
  16. add_action( 'wp_ajax_wcml_cart_clear_removed_items', array( $this, 'wcml_cart_clear_removed_items' ) ); 
  17. add_action( 'wp_ajax_nopriv_wcml_cart_clear_removed_items', array( $this, 'wcml_cart_clear_removed_items' ) ); 
  18.  
  19. add_filter( 'wcml_switch_currency_exception', array( $this, 'cart_switching_currency' ), 10, 3 ); 
  20. add_action( 'wcml_before_switch_currency', array( $this, 'switching_currency_empty_cart_if_needed' ), 10, 2 ); 
  21. else{ 
  22. //cart widget 
  23. add_action( 'wp_ajax_woocommerce_get_refreshed_fragments', array( $this, 'wcml_refresh_fragments' ), 0 ); 
  24. add_action( 'wp_ajax_woocommerce_add_to_cart', array( $this, 'wcml_refresh_fragments' ), 0 ); 
  25. add_action( 'wp_ajax_nopriv_woocommerce_get_refreshed_fragments', array( $this, 'wcml_refresh_fragments' ), 0 ); 
  26. add_action( 'wp_ajax_nopriv_woocommerce_add_to_cart', array( $this, 'wcml_refresh_fragments' ), 0 ); 
  27.  
  28. //cart 
  29. add_action( 'woocommerce_before_calculate_totals', array( $this, 'woocommerce_calculate_totals' ), 100 ); 
  30. add_action( 'woocommerce_get_cart_item_from_session', array( $this, 'translate_cart_contents' ), 10 ); 
  31. add_action( 'woocommerce_cart_loaded_from_session', array( $this, 'translate_cart_subtotal' ) ); 
  32. add_action( 'woocommerce_before_checkout_process', array( $this, 'wcml_refresh_cart_total' ) ); 
  33.  
  34. add_filter('woocommerce_paypal_args', array($this, 'filter_paypal_args')); 
  35. add_filter( 'woocommerce_add_to_cart_sold_individually_quantity', array( $this, 'woocommerce_add_to_cart_sold_individually_quantity' ), 10, 5 ); 
  36.  
  37. $this->localize_flat_rates_shipping_classes(); 
  38.  
  39.  
  40. public function enqueue_dialog_ui() { 
  41.  
  42. wp_enqueue_script( 'jquery-ui-dialog' ); 
  43. wp_enqueue_style( 'wp-jquery-ui-dialog' ); 
  44.  
  45.  
  46. public function wcml_removed_cart_items_widget( $args = array() ) { 
  47.  
  48. if( !empty( $this->woocommerce->session ) ) { 
  49. $removed_cart_items = new WCML_Removed_Cart_Items_UI( $args, $this->woocommerce_wpml, $this->sitepress, $this->woocommerce ); 
  50. $preview = $removed_cart_items->get_view(); 
  51.  
  52. if ( !isset($args['echo']) || $args['echo'] ) { 
  53. echo $preview; 
  54. } else { 
  55. return $preview; 
  56.  
  57.  
  58. public function switching_currency_empty_cart_if_needed( $currency, $force_switch ) { 
  59. if( $force_switch && $this->woocommerce_wpml->settings[ 'cart_sync' ][ 'currency_switch' ] == WCML_CART_CLEAR ) { 
  60. $this->empty_cart_if_needed('currency_switch'); 
  61. $this->woocommerce->session->set('wcml_switched_type', 'currency'); 
  62.  
  63. public function empty_cart_if_needed( $switching_type ) { 
  64.  
  65. if( $this->woocommerce_wpml->settings[ 'cart_sync' ][ $switching_type ] == WCML_CART_CLEAR ) { 
  66. $removed_products = $this->woocommerce->session->get( 'wcml_removed_items' ) ? maybe_unserialize( $this->woocommerce->session->get( 'wcml_removed_items' ) ) : array(); 
  67.  
  68. foreach( WC()->cart->get_cart_for_session() as $item_key => $cart ) { 
  69. if( !in_array( $cart[ 'product_id' ], $removed_products ) ) { 
  70. $removed_products[] = $cart[ 'product_id' ]; 
  71. WC()->cart->remove_cart_item( $item_key ); 
  72.  
  73. if( !empty( $this->woocommerce->session ) ) { 
  74. $this->woocommerce->session->set( 'wcml_removed_items', serialize( $removed_products ) ); 
  75.  
  76. public function wcml_cart_clear_removed_items( ) { 
  77.  
  78. $nonce = filter_input( INPUT_POST, 'wcml_nonce', FILTER_SANITIZE_FULL_SPECIAL_CHARS ); 
  79. if(!$nonce || !wp_verify_nonce($nonce, 'wcml_clear_removed_items')) { 
  80. die('Invalid nonce'); 
  81.  
  82. $this->woocommerce->session->__unset( 'wcml_removed_items' ); 
  83. $this->woocommerce->session->__unset( 'wcml_switched_type' ); 
  84.  
  85. public function cart_switching_currency( $exc, $current_currency, $new_currency, $return = false ) { 
  86.  
  87. $cart_for_session = WC()->cart->get_cart_for_session(); 
  88. if( $this->woocommerce_wpml->settings[ 'cart_sync' ][ 'currency_switch' ] == WCML_CART_SYNC || empty( $cart_for_session ) ) { 
  89. return $exc; 
  90.  
  91. $dialog_title = __( 'Switching currency?', 'woocommerce-multilingual'); 
  92. $confirmation_message = __( 'Your cart is not empty! After you switched the currency, all items from the cart will be removed and you have to add them again.', 'woocommerce-multilingual'); 
  93. $stay_in = sprintf( __( 'Keep using %s', 'woocommerce-multilingual'), $current_currency ); 
  94. $switch_to = __( 'Proceed', 'woocommerce-multilingual'); 
  95.  
  96. ob_start(); 
  97. $this->cart_alert( $dialog_title, $confirmation_message, $switch_to, $stay_in, $new_currency, $current_currency ); 
  98. $html = ob_get_contents(); 
  99. ob_end_clean(); 
  100.  
  101. if( $return ) { 
  102. return array( 'prevent_switching' => $html ); 
  103. }else{ 
  104. echo json_encode( array( 'prevent_switching' => $html ) ); 
  105.  
  106. return true; 
  107.  
  108. public function cart_alert( $dialog_title, $confirmation_message, $switch_to, $stay_in, $switch_to_value, $stay_in_value = false, $language_switch = false ) { 
  109. ?> 
  110. <div id="wcml-cart-dialog-confirm" title="<?php echo $dialog_title ?>"> 
  111. <p><?php echo $confirmation_message; ?></p> 
  112. </div> 
  113.  
  114. <script type="text/javascript"> 
  115. jQuery( document).ready( function() { 
  116. jQuery( "#wcml-cart-dialog-confirm" ).dialog({ 
  117. resizable: false,  
  118. draggable: false,  
  119. height: "auto",  
  120. width: 500,  
  121. modal: true,  
  122. closeOnEscape: false,  
  123. dialogClass: "wcml-cart-dialog",  
  124. open: function(event, ui) { 
  125. jQuery(".ui-dialog-titlebar-close", ui.dialog | ui).hide(); 
  126. },  
  127. buttons: { 
  128. "<?php echo $switch_to; ?>": function() { 
  129. jQuery( this ).dialog( "close" ); 
  130. <?php if( $language_switch ): ?> 
  131. window.location = '<?php echo $switch_to_value; ?>'; 
  132. <?php else: ?> 
  133. jQuery('.wcml_currency_switcher').parent().find('img').remove(); 
  134. wcml_load_currency( "<?php echo $switch_to_value; ?>", true ); 
  135. <?php endif; ?> 
  136.  
  137. },  
  138. "<?php echo $stay_in; ?>": function() { 
  139. jQuery( this ).dialog( "close" ); 
  140. <?php if( $language_switch ): ?> 
  141. window.location = '<?php echo $stay_in_value; ?>'; 
  142. <?php else: ?> 
  143. jQuery('.wcml_currency_switcher').parent().find('img').remove(); 
  144. jQuery('.wcml_currency_switcher').removeAttr('disabled'); 
  145. jQuery('.wcml_currency_switcher').val( '<?php echo $stay_in_value; ?>' ); 
  146. <?php endif; ?> 
  147. }); 
  148. }); 
  149. </script> 
  150. <?php 
  151.  
  152. public function wcml_refresh_fragments() { 
  153. WC()->cart->calculate_totals(); 
  154. $this->woocommerce_wpml->locale->wcml_refresh_text_domain(); 
  155.  
  156. /** 
  157. * Update cart and cart session when switch language 
  158. */ 
  159. public function woocommerce_calculate_totals( $cart, $currency = false ) { 
  160.  
  161. $current_language = $this->sitepress->get_current_language(); 
  162. $new_cart_data = array(); 
  163.  
  164. foreach( $cart->cart_contents as $key => $cart_item ) { 
  165. $tr_product_id = apply_filters( 'translate_object_id', $cart_item[ 'product_id' ], 'product', false, $current_language ); 
  166. //translate custom attr labels in cart object 
  167.  
  168. if( version_compare( WC_VERSION , '3.0.0', '<' ) && isset( $cart_item[ 'data' ]->product_attributes ) ) { 
  169. foreach( $cart_item[ 'data' ]->product_attributes as $attr_key => $product_attribute ) { 
  170. if( isset( $product_attribute[ 'is_taxonomy' ]) && !$product_attribute[ 'is_taxonomy' ] ) { 
  171. $cart->cart_contents[ $key ][ 'data' ]->product_attributes[ $attr_key ][ 'name' ] = $this->woocommerce_wpml->strings->translated_attribute_label( 
  172. $product_attribute[ 'name' ],  
  173. $product_attribute[ 'name' ],  
  174. $tr_product_id ); 
  175.  
  176. //translate custom attr value in cart object 
  177. if( isset( $cart_item[ 'variation' ] ) && is_array( $cart_item[ 'variation' ] ) ) { 
  178. foreach( $cart_item[ 'variation' ] as $attr_key => $attribute ) { 
  179. $cart->cart_contents[ $key ][ 'variation' ][ $attr_key ] = $this->get_cart_attribute_translation( 
  180. $attr_key,  
  181. $attribute,  
  182. $cart_item[ 'variation_id' ],  
  183. $current_language,  
  184. $cart_item[ 'product_id' ],  
  185. $tr_product_id 
  186. ); 
  187.  
  188. if( $currency !== false ) { 
  189. $cart->cart_contents[ $key ][ 'data' ]->price = get_post_meta( $cart_item['product_id'], '_price', 1 ); 
  190.  
  191. if( $cart_item[ 'product_id' ] == $tr_product_id ) { 
  192. $new_cart_data[ $key ] = apply_filters( 'wcml_cart_contents_not_changed', $cart->cart_contents[$key], $key, $current_language ); 
  193. continue; 
  194.  
  195. if( isset( $cart->cart_contents[ $key ][ 'variation_id' ] ) && $cart->cart_contents[ $key ][ 'variation_id' ] ) { 
  196. $tr_variation_id = apply_filters( 'translate_object_id', $cart_item[ 'variation_id' ], 'product_variation', false, $current_language ); 
  197. if( !is_null( $tr_variation_id ) ) { 
  198. $cart->cart_contents[ $key ][ 'product_id' ] = intval( $tr_product_id ); 
  199. $cart->cart_contents[ $key ][ 'variation_id' ] = intval( $tr_variation_id ); 
  200. if( defined('WC_VERSION') && version_compare( WC_VERSION , '2.7', '<' ) ) { 
  201. $cart->cart_contents[ $key ][ 'data' ]->id = intval( $tr_product_id ); 
  202. }else{ 
  203. $cart->cart_contents[ $key ][ 'data' ]->set_id( intval( $tr_product_id ) ); 
  204. $cart->cart_contents[ $key ][ 'data' ]->post = get_post( $tr_product_id ); 
  205. }else{ 
  206. if( !is_null( $tr_product_id ) ) { 
  207. $cart->cart_contents[ $key ][ 'product_id' ] = intval( $tr_product_id ); 
  208. if( defined('WC_VERSION') && version_compare( WC_VERSION , '2.7', '<' ) ) { 
  209. $cart->cart_contents[ $key ][ 'data' ]->id = intval( $tr_product_id ); 
  210. }else{ 
  211. $cart->cart_contents[ $key ][ 'data' ]->set_id( intval( $tr_product_id ) ); 
  212. $cart->cart_contents[ $key ][ 'data' ]->post = get_post( $tr_product_id ); 
  213.  
  214. if( !is_null( $tr_product_id ) ) { 
  215.  
  216. $new_key = $this->wcml_generate_cart_key( $cart->cart_contents, $key ); 
  217. $cart->cart_contents = apply_filters( 'wcml_update_cart_contents_lang_switch', $cart->cart_contents, $key, $new_key, $current_language ); 
  218. $new_cart_data[ $new_key ] = $cart->cart_contents[ $key ]; 
  219.  
  220. $new_cart_data = apply_filters( 'wcml_cart_contents', $new_cart_data, $cart->cart_contents, $key, $new_key ); 
  221.  
  222. $cart->cart_contents = $this->wcml_check_on_duplicate_products_in_cart( $new_cart_data ); 
  223. $this->woocommerce->session->cart = $cart->cart_contents; 
  224. return $cart->cart_contents; 
  225.  
  226. public function wcml_check_on_duplicate_products_in_cart( $cart_contents ) { 
  227.  
  228. $exists_products = array(); 
  229. remove_action( 'woocommerce_before_calculate_totals', array( $this, 'woocommerce_calculate_totals' ), 100 ); 
  230.  
  231. foreach( $cart_contents as $key => $cart_content ) { 
  232. $cart_contents = apply_filters( 'wcml_check_on_duplicated_products_in_cart', $cart_contents, $key, $cart_content ); 
  233. if( apply_filters( 'wcml_exception_duplicate_products_in_cart', false, $cart_content ) ) { 
  234. continue; 
  235.  
  236. $quantity = $cart_content['quantity']; 
  237.  
  238. $search_key = $this->wcml_generate_cart_key( $cart_contents, $key ); 
  239. if( array_key_exists( $search_key, $exists_products ) ) { 
  240. unset( $cart_contents[ $key ] ); 
  241. $cart_contents[ $exists_products[ $search_key ] ][ 'quantity' ] = $cart_contents[ $exists_products[ $search_key ] ][ 'quantity' ] + $quantity; 
  242. $this->woocommerce->cart->calculate_totals(); 
  243. }else{ 
  244. $exists_products[ $search_key ] = $key; 
  245.  
  246. add_action( 'woocommerce_before_calculate_totals', array( $this, 'woocommerce_calculate_totals' ), 100 ); 
  247. return $cart_contents; 
  248.  
  249. public function get_cart_attribute_translation( $attr_key, $attribute, $variation_id, $current_language, $product_id, $tr_product_id ) { 
  250.  
  251. $attr_translation = $attribute; 
  252.  
  253. if( !empty( $attribute ) ) { 
  254. //delete 'attribute_' at the beginning 
  255. $taxonomy = substr( $attr_key, 10, strlen( $attr_key ) - 1 ); 
  256.  
  257. if( taxonomy_exists( $taxonomy ) ) { 
  258. if( $this->woocommerce_wpml->attributes->is_translatable_attribute( $taxonomy ) ) { 
  259. $term_id = $this->woocommerce_wpml->terms->wcml_get_term_id_by_slug( $taxonomy, $attribute ); 
  260. $trnsl_term_id = apply_filters( 'translate_object_id', $term_id, $taxonomy, true, $current_language ); 
  261. $term = $this->woocommerce_wpml->terms->wcml_get_term_by_id( $trnsl_term_id, $taxonomy ); 
  262. $attr_translation = $term->slug; 
  263. }else{ 
  264.  
  265. $trnsl_attr = get_post_meta( $variation_id, $attr_key, true ); 
  266.  
  267. if( $trnsl_attr ) { 
  268. $attr_translation = $trnsl_attr; 
  269. }else{ 
  270. $attr_translation = $this->woocommerce_wpml->attributes->get_custom_attr_translation( $product_id, $tr_product_id, $taxonomy, $attribute ); 
  271.  
  272. return $attr_translation; 
  273.  
  274. public function wcml_generate_cart_key( $cart_contents, $key ) { 
  275. $cart_item_data = $this->get_cart_item_data_from_cart( $cart_contents[ $key ] ); 
  276.  
  277. return $this->woocommerce->cart->generate_cart_id( 
  278. $cart_contents[ $key ][ 'product_id' ],  
  279. $cart_contents[ $key ][ 'variation_id' ],  
  280. $cart_contents[ $key ][ 'variation' ],  
  281. $cart_item_data 
  282. ); 
  283.  
  284. //get cart_item_data from existing cart array ( from session ) 
  285. public function get_cart_item_data_from_cart( $cart_contents ) { 
  286. unset( $cart_contents[ 'product_id' ] ); 
  287. unset( $cart_contents[ 'variation_id' ] ); 
  288. unset( $cart_contents[ 'variation' ] ); 
  289. unset( $cart_contents[ 'quantity' ] ); 
  290. unset( $cart_contents[ 'line_total' ] ); 
  291. unset( $cart_contents[ 'line_subtotal' ] ); 
  292. unset( $cart_contents[ 'line_tax' ] ); 
  293. unset( $cart_contents[ 'line_subtotal_tax' ] ); 
  294. unset( $cart_contents[ 'line_tax_data' ] ); 
  295. unset( $cart_contents[ 'data' ] ); 
  296.  
  297. return apply_filters( 'wcml_filter_cart_item_data', $cart_contents ); 
  298.  
  299. public function translate_cart_contents( $item ) { 
  300.  
  301. // translate the product id and product data 
  302. $item[ 'product_id' ] = apply_filters( 'translate_object_id', $item[ 'product_id' ], 'product', true ); 
  303. if ($item[ 'variation_id' ]) { 
  304. $item[ 'variation_id' ] = apply_filters( 'translate_object_id', $item[ 'variation_id' ], 'product_variation', true ); 
  305.  
  306. if( version_compare( WC()->version, '3.0.0', '>=' ) ) { 
  307. $item[ 'data' ]->set_name( get_the_title( $item[ 'product_id' ] ) ); 
  308. } else { 
  309. $item[ 'data' ]->post->post_title = get_the_title( $item[ 'product_id' ] ); 
  310.  
  311. return $item; 
  312.  
  313. public function translate_cart_subtotal( $cart ) { 
  314.  
  315. if( isset( $_SERVER['REQUEST_URI'] ) ) { 
  316. //special case: check if attachment loading 
  317. $attachments = array( 'png', 'jpg', 'jpeg', 'gif', 'js', 'css' ); 
  318.  
  319. foreach( $attachments as $attachment ) { 
  320. $match = preg_match( '/\.'.$attachment.'$/', $_SERVER['REQUEST_URI'] ); 
  321. if( !empty( $match ) ) { 
  322. return false; 
  323.  
  324. if( apply_filters( 'wcml_calculate_totals_exception', true, $cart ) ) { 
  325. $cart->calculate_totals(); 
  326.  
  327.  
  328. // refresh cart total to return correct price from WC object 
  329. public function wcml_refresh_cart_total() { 
  330. WC()->cart->calculate_totals(); 
  331.  
  332.  
  333. public function localize_flat_rates_shipping_classes() { 
  334.  
  335. if(is_ajax() && isset($_POST['action']) && $_POST['action'] == 'woocommerce_update_order_review') { 
  336. $this->woocommerce->shipping->load_shipping_methods(); 
  337. $shipping_methods = $this->woocommerce->shipping->get_shipping_methods(); 
  338. foreach($shipping_methods as $method) { 
  339. if(isset($method->flat_rate_option)) { 
  340. add_filter('option_' . $method->flat_rate_option, array($this, 'translate_shipping_class')); 
  341.  
  342.  
  343. public function translate_shipping_class($rates) { 
  344.  
  345. if(is_array($rates)) { 
  346. foreach($rates as $shipping_class => $value) { 
  347. $term_id = $this->woocommerce_wpml->terms->wcml_get_term_id_by_slug('product_shipping_class', $shipping_class ); 
  348.  
  349. if($term_id && !is_wp_error($term_id)) { 
  350. $translated_term_id = apply_filters( 'translate_object_id', $term_id, 'product_shipping_class', true); 
  351. if($translated_term_id != $term_id) { 
  352. $term = $this->woocommerce_wpml->terms->wcml_get_term_by_id( $translated_term_id, 'product_shipping_class' ); 
  353. unset($rates[$shipping_class]); 
  354. $rates[$term->slug] = $value; 
  355.  
  356. return $rates; 
  357.  
  358. public function filter_paypal_args( $args ) { 
  359. $args['lc'] = $this->sitepress->get_current_language(); 
  360.  
  361. //filter URL when default permalinks uses 
  362. $wpml_settings = $this->sitepress->get_settings(); 
  363. if( $wpml_settings[ 'language_negotiation_type' ] == 3 ) { 
  364. $args[ 'notify_url' ] = str_replace( '%2F&', '&', $args[ 'notify_url' ] ); 
  365.  
  366. return $args; 
  367.  
  368. public function woocommerce_add_to_cart_sold_individually_quantity( $qt, $quantity, $product_id, $variation_id, $cart_item_data ) { 
  369.  
  370. //check if product already added to cart in another language 
  371. $current_product_trid = $this->sitepress->get_element_trid( $product_id, 'post_product' ); 
  372.  
  373. foreach( WC()->cart->cart_contents as $cart_item ) { 
  374. $cart_element_trid = $this->sitepress->get_element_trid( $cart_item[ 'product_id' ], 'post_product' ); 
  375. if( apply_filters( 'wcml_add_to_cart_sold_individually', true, $cart_item_data, $product_id, $quantity ) && $current_product_trid == $cart_element_trid && $cart_item[ 'quantity' ] > 0 ) { 
  376. throw new Exception( sprintf( '<a href="%s" class="button wc-forward">%s</a> %s', esc_url( wc_get_cart_url() ), __( 'View Cart', 'woocommerce' ), sprintf( __( 'You cannot add another "%s" to your cart.', 'woocommerce' ), get_the_title( $product_id ) ) ) ); 
  377.  
  378. return $qt;