/includes/wc-cart-functions.php

  1. <?php 
  2. /** 
  3. * WooCommerce Cart Functions 
  4. * 
  5. * Functions for cart specific things. 
  6. * 
  7. * @author WooThemes 
  8. * @category Core 
  9. * @package WooCommerce/Functions 
  10. * @version 2.5.0 
  11. */ 
  12.  
  13. if ( ! defined( 'ABSPATH' ) ) { 
  14. exit; // Exit if accessed directly 
  15.  
  16. /** 
  17. * Prevent password protected products being added to the cart. 
  18. * 
  19. * @param bool $passed 
  20. * @param int $product_id 
  21. * @return bool 
  22. */ 
  23. function wc_protected_product_add_to_cart( $passed, $product_id ) { 
  24. if ( post_password_required( $product_id ) ) { 
  25. $passed = false; 
  26. wc_add_notice( __( 'This product is protected and cannot be purchased.', 'woocommerce' ), 'error' ); 
  27. return $passed; 
  28. add_filter( 'woocommerce_add_to_cart_validation', 'wc_protected_product_add_to_cart', 10, 2 ); 
  29.  
  30. /** 
  31. * Clears the cart session when called. 
  32. */ 
  33. function wc_empty_cart() { 
  34. if ( ! isset( WC()->cart ) || '' === WC()->cart ) { 
  35. WC()->cart = new WC_Cart(); 
  36. WC()->cart->empty_cart( false ); 
  37.  
  38. /** 
  39. * Load the persistent cart. 
  40. * 
  41. * @param string $user_login 
  42. * @param WP_User $user 
  43. * @deprecated 2.3 
  44. */ 
  45. function wc_load_persistent_cart( $user_login, $user ) { 
  46. if ( ! $user || ! ( $saved_cart = get_user_meta( $user->ID, '_woocommerce_persistent_cart', true ) ) ) { 
  47. return; 
  48.  
  49. if ( empty( WC()->session->cart ) || ! is_array( WC()->session->cart ) || 0 === sizeof( WC()->session->cart ) ) { 
  50. WC()->session->cart = $saved_cart['cart']; 
  51.  
  52. /** 
  53. * Retrieves unvalidated referer from '_wp_http_referer' or HTTP referer. 
  54. * 
  55. * Do not use for redirects, use {@see wp_get_referer()} instead. 
  56. * 
  57. * @since 2.6.1 
  58. * @return string|false Referer URL on success, false on failure. 
  59. */ 
  60. function wc_get_raw_referer() { 
  61. if ( function_exists( 'wp_get_raw_referer' ) ) { 
  62. return wp_get_raw_referer(); 
  63.  
  64. if ( ! empty( $_REQUEST['_wp_http_referer'] ) ) { 
  65. return wp_unslash( $_REQUEST['_wp_http_referer'] ); 
  66. } elseif ( ! empty( $_SERVER['HTTP_REFERER'] ) ) { 
  67. return wp_unslash( $_SERVER['HTTP_REFERER'] ); 
  68.  
  69. return false; 
  70.  
  71. /** 
  72. * Add to cart messages. 
  73. * 
  74. * @param int|array $products 
  75. * @param bool $show_qty Should qty's be shown? Added in 2.6.0 
  76. * @param bool $return Return message rather than add it. 
  77. */ 
  78. function wc_add_to_cart_message( $products, $show_qty = false, $return = false ) { 
  79. $titles = array(); 
  80. $count = 0; 
  81.  
  82. if ( ! is_array( $products ) ) { 
  83. $products = array( $products => 1 ); 
  84. $show_qty = false; 
  85.  
  86. if ( ! $show_qty ) { 
  87. $products = array_fill_keys( array_keys( $products ), 1 ); 
  88.  
  89. foreach ( $products as $product_id => $qty ) { 
  90. $titles[] = ( $qty > 1 ? absint( $qty ) . ' × ' : '' ) . sprintf( _x( '“%s”', 'Item name in quotes', 'woocommerce' ), strip_tags( get_the_title( $product_id ) ) ); 
  91. $count += $qty; 
  92.  
  93. $titles = array_filter( $titles ); 
  94. $added_text = sprintf( _n( '%s has been added to your cart.', '%s have been added to your cart.', $count, 'woocommerce' ), wc_format_list_of_items( $titles ) ); 
  95.  
  96. // Output success messages 
  97. if ( 'yes' === get_option( 'woocommerce_cart_redirect_after_add' ) ) { 
  98. $return_to = apply_filters( 'woocommerce_continue_shopping_redirect', wc_get_raw_referer() ? wp_validate_redirect( wc_get_raw_referer(), false ) : wc_get_page_permalink( 'shop' ) ); 
  99. $message = sprintf( '<a href="%s" class="button wc-forward">%s</a> %s', esc_url( $return_to ), esc_html__( 'Continue shopping', 'woocommerce' ), esc_html( $added_text ) ); 
  100. } else { 
  101. $message = sprintf( '<a href="%s" class="button wc-forward">%s</a> %s', esc_url( wc_get_page_permalink( 'cart' ) ), esc_html__( 'View cart', 'woocommerce' ), esc_html( $added_text ) ); 
  102.  
  103. if ( has_filter( 'wc_add_to_cart_message' ) ) { 
  104. wc_deprecated_function( 'The wc_add_to_cart_message filter', '3.0', 'wc_add_to_cart_message_html' ); 
  105. $message = apply_filters( 'wc_add_to_cart_message', $message, $product_id ); 
  106.  
  107. $message = apply_filters( 'wc_add_to_cart_message_html', $message, $products ); 
  108.  
  109. if ( $return ) { 
  110. return $message; 
  111. } else { 
  112. wc_add_notice( $message ); 
  113.  
  114. /** 
  115. * Comma separate a list of item names, and replace final comma with 'and' 
  116. * @param array $items 
  117. * @return string 
  118. */ 
  119. function wc_format_list_of_items( $items ) { 
  120. $item_string = ''; 
  121.  
  122. foreach ( $items as $key => $item ) { 
  123. $item_string .= $item; 
  124.  
  125. if ( sizeof( $items ) === $key + 2 ) { 
  126. $item_string .= ' ' . __( 'and', 'woocommerce' ) . ' '; 
  127. } elseif ( sizeof( $items ) !== $key + 1 ) { 
  128. $item_string .= ', '; 
  129.  
  130. return $item_string; 
  131.  
  132. /** 
  133. * Clear cart after payment. 
  134. * 
  135. * @access public 
  136. */ 
  137. function wc_clear_cart_after_payment() { 
  138. global $wp; 
  139.  
  140. if ( ! empty( $wp->query_vars['order-received'] ) ) { 
  141.  
  142. $order_id = absint( $wp->query_vars['order-received'] ); 
  143. $order_key = isset( $_GET['key'] ) ? wc_clean( $_GET['key'] ) : ''; 
  144.  
  145. if ( $order_id > 0 ) { 
  146. $order = wc_get_order( $order_id ); 
  147.  
  148. if ( $order && $order->get_order_key() === $order_key ) { 
  149. WC()->cart->empty_cart(); 
  150.  
  151. if ( WC()->session->order_awaiting_payment > 0 ) { 
  152. $order = wc_get_order( WC()->session->order_awaiting_payment ); 
  153.  
  154. if ( $order && $order->get_id() > 0 ) { 
  155. // If the order has not failed, or is not pending, the order must have gone through 
  156. if ( ! $order->has_status( array( 'failed', 'pending', 'cancelled' ) ) ) { 
  157. WC()->cart->empty_cart(); 
  158. add_action( 'get_header', 'wc_clear_cart_after_payment' ); 
  159.  
  160. /** 
  161. * Get the subtotal. 
  162. * 
  163. * @access public 
  164. * @return string 
  165. */ 
  166. function wc_cart_totals_subtotal_html() { 
  167. echo WC()->cart->get_cart_subtotal(); 
  168.  
  169. /** 
  170. * Get shipping methods. 
  171. * 
  172. * @access public 
  173. */ 
  174. function wc_cart_totals_shipping_html() { 
  175. $packages = WC()->shipping->get_packages(); 
  176.  
  177. foreach ( $packages as $i => $package ) { 
  178. $chosen_method = isset( WC()->session->chosen_shipping_methods[ $i ] ) ? WC()->session->chosen_shipping_methods[ $i ] : ''; 
  179. $product_names = array(); 
  180.  
  181. if ( sizeof( $packages ) > 1 ) { 
  182. foreach ( $package['contents'] as $item_id => $values ) { 
  183. $product_names[ $item_id ] = $values['data']->get_name() . ' ×' . $values['quantity']; 
  184. $product_names = apply_filters( 'woocommerce_shipping_package_details_array', $product_names, $package ); 
  185.  
  186. wc_get_template( 'cart/cart-shipping.php', array( 
  187. 'package' => $package,  
  188. 'available_methods' => $package['rates'],  
  189. 'show_package_details' => sizeof( $packages ) > 1,  
  190. 'package_details' => implode( ', ', $product_names ),  
  191. // @codingStandardsIgnoreStart 
  192. 'package_name' => apply_filters( 'woocommerce_shipping_package_name', sprintf( _nx( 'Shipping', 'Shipping %d', ( $i + 1 ), 'shipping packages', 'woocommerce' ), ( $i + 1 ) ), $i, $package ),  
  193. // @codingStandardsIgnoreEnd 
  194. 'index' => $i,  
  195. 'chosen_method' => $chosen_method,  
  196. ) ); 
  197.  
  198. /** 
  199. * Get taxes total. 
  200. * 
  201. * @access public 
  202. */ 
  203. function wc_cart_totals_taxes_total_html() { 
  204. echo apply_filters( 'woocommerce_cart_totals_taxes_total_html', wc_price( WC()->cart->get_taxes_total() ) ); 
  205.  
  206. /** 
  207. * Get a coupon label. 
  208. * 
  209. * @access public 
  210. * @param string $coupon 
  211. * @param bool $echo or return 
  212. */ 
  213. function wc_cart_totals_coupon_label( $coupon, $echo = true ) { 
  214. if ( is_string( $coupon ) ) { 
  215. $coupon = new WC_Coupon( $coupon ); 
  216.  
  217. $label = apply_filters( 'woocommerce_cart_totals_coupon_label', sprintf( esc_html__( 'Coupon: %s', 'woocommerce' ), $coupon->get_code() ), $coupon ); 
  218.  
  219. if ( $echo ) { 
  220. echo $label; 
  221. } else { 
  222. return $label; 
  223.  
  224. /** 
  225. * Get coupon display HTML. 
  226. * 
  227. * @param string $coupon 
  228. */ 
  229. function wc_cart_totals_coupon_html( $coupon ) { 
  230. if ( is_string( $coupon ) ) { 
  231. $coupon = new WC_Coupon( $coupon ); 
  232.  
  233. $discount_amount_html = ''; 
  234.  
  235. if ( $amount = WC()->cart->get_coupon_discount_amount( $coupon->get_code(), WC()->cart->display_cart_ex_tax ) ) { 
  236. $discount_amount_html = '-' . wc_price( $amount ); 
  237. } elseif ( $coupon->get_free_shipping() ) { 
  238. $discount_amount_html = __( 'Free shipping coupon', 'woocommerce' ); 
  239.  
  240. $discount_amount_html = apply_filters( 'woocommerce_coupon_discount_amount_html', $discount_amount_html, $coupon ); 
  241. $coupon_html = $discount_amount_html . ' <a href="' . esc_url( add_query_arg( 'remove_coupon', urlencode( $coupon->get_code() ), defined( 'WOOCOMMERCE_CHECKOUT' ) ? wc_get_checkout_url() : wc_get_cart_url() ) ) . '" class="woocommerce-remove-coupon" data-coupon="' . esc_attr( $coupon->get_code() ) . '">' . __( '[Remove]', 'woocommerce' ) . '</a>'; 
  242.  
  243. echo wp_kses( apply_filters( 'woocommerce_cart_totals_coupon_html', $coupon_html, $coupon, $discount_amount_html ), array_replace_recursive( wp_kses_allowed_html( 'post' ), array( 'a' => array( 'data-coupon' => true ) ) ) ); 
  244.  
  245. /** 
  246. * Get order total html including inc tax if needed. 
  247. * 
  248. * @access public 
  249. */ 
  250. function wc_cart_totals_order_total_html() { 
  251. $value = '<strong>' . WC()->cart->get_total() . '</strong> '; 
  252.  
  253. // If prices are tax inclusive, show taxes here 
  254. if ( wc_tax_enabled() && WC()->cart->tax_display_cart == 'incl' ) { 
  255. $tax_string_array = array(); 
  256.  
  257. if ( get_option( 'woocommerce_tax_total_display' ) == 'itemized' ) { 
  258. foreach ( WC()->cart->get_tax_totals() as $code => $tax ) 
  259. $tax_string_array[] = sprintf( '%s %s', $tax->formatted_amount, $tax->label ); 
  260. } else { 
  261. $tax_string_array[] = sprintf( '%s %s', wc_price( WC()->cart->get_taxes_total( true, true ) ), WC()->countries->tax_or_vat() ); 
  262.  
  263. if ( ! empty( $tax_string_array ) ) { 
  264. $taxable_address = WC()->customer->get_taxable_address(); 
  265. $estimated_text = WC()->customer->is_customer_outside_base() && ! WC()->customer->has_calculated_shipping() 
  266. ? sprintf( ' ' . __( 'estimated for %s', 'woocommerce' ), WC()->countries->estimated_for_prefix( $taxable_address[0] ) . WC()->countries->countries[ $taxable_address[0] ] ) 
  267. : ''; 
  268. $value .= '<small class="includes_tax">' . sprintf( __( '(includes %s)', 'woocommerce' ), implode( ', ', $tax_string_array ) . $estimated_text ) . '</small>'; 
  269.  
  270. echo apply_filters( 'woocommerce_cart_totals_order_total_html', $value ); 
  271.  
  272. /** 
  273. * Get the fee value. 
  274. * 
  275. * @param object $fee 
  276. */ 
  277. function wc_cart_totals_fee_html( $fee ) { 
  278. $cart_totals_fee_html = ( 'excl' == WC()->cart->tax_display_cart ) ? wc_price( $fee->amount ) : wc_price( $fee->amount + $fee->tax ); 
  279.  
  280. echo apply_filters( 'woocommerce_cart_totals_fee_html', $cart_totals_fee_html, $fee ); 
  281.  
  282. /** 
  283. * Get a shipping methods full label including price. 
  284. * @param WC_Shipping_Rate $method 
  285. * @return string 
  286. */ 
  287. function wc_cart_totals_shipping_method_label( $method ) { 
  288. $label = $method->get_label(); 
  289.  
  290. if ( $method->cost > 0 ) { 
  291. if ( WC()->cart->tax_display_cart == 'excl' ) { 
  292. $label .= ': ' . wc_price( $method->cost ); 
  293. if ( $method->get_shipping_tax() > 0 && WC()->cart->prices_include_tax ) { 
  294. $label .= ' <small class="tax_label">' . WC()->countries->ex_tax_or_vat() . '</small>'; 
  295. } else { 
  296. $label .= ': ' . wc_price( $method->cost + $method->get_shipping_tax() ); 
  297. if ( $method->get_shipping_tax() > 0 && ! WC()->cart->prices_include_tax ) { 
  298. $label .= ' <small class="tax_label">' . WC()->countries->inc_tax_or_vat() . '</small>'; 
  299.  
  300. return apply_filters( 'woocommerce_cart_shipping_method_full_label', $label, $method ); 
  301.  
  302. /** 
  303. * Round discount. 
  304. * 
  305. * @param float $value 
  306. * @param int $precision 
  307. * @return float 
  308. */ 
  309. function wc_cart_round_discount( $value, $precision ) { 
  310. if ( version_compare( PHP_VERSION, '5.3.0', '>=' ) ) { 
  311. return round( $value, $precision, WC_DISCOUNT_ROUNDING_MODE ); 
  312. } else { 
  313. return round( $value, $precision ); 
  314.  
  315. /** 
  316. * Gets chosen shipping method IDs from chosen_shipping_methods session, without instance IDs. 
  317. * @since 2.6.2 
  318. * @return string[] 
  319. */ 
  320. function wc_get_chosen_shipping_method_ids() { 
  321. $method_ids = array(); 
  322. $chosen_methods = WC()->session->get( 'chosen_shipping_methods', array() ); 
  323. foreach ( $chosen_methods as $chosen_method ) { 
  324. $chosen_method = explode( ':', $chosen_method ); 
  325. $method_ids[] = current( $chosen_method ); 
  326. return $method_ids; 
.