Guest User

class-wc-pb-display.php

a guest
Oct 9th, 2020
71
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 61.83 KB | None | 0 0
  1. <?php
  2. /**
  3. * WC_PB_Display class
  4. *
  5. * @author SomewhereWarm <[email protected]>
  6. * @package WooCommerce Product Bundles
  7. * @since 4.5.0
  8. */
  9.  
  10. // Exit if accessed directly.
  11. if ( ! defined( 'ABSPATH' ) ) {
  12. exit;
  13. }
  14.  
  15. /**
  16. * Product Bundle display functions and filters.
  17. *
  18. * @class WC_PB_Display
  19. * @version 6.3.3
  20. */
  21. class WC_PB_Display {
  22.  
  23. /**
  24. * Indicates whether the bundled table item indent JS has already been enqueued.
  25. * @var boolean
  26. */
  27. private $enqueued_bundled_table_item_js = false;
  28.  
  29. /**
  30. * Workaround for $order arg missing from 'woocommerce_order_item_name' filter - set within the 'woocommerce_order_item_class' filter - @see 'order_item_class()'.
  31. * @var boolean|WC_Order
  32. */
  33. private $order_item_order = false;
  34.  
  35. /**
  36. * Active element position/column when rendering a grid of bundled items, applicable when the "Grid" layout is active.
  37. * @var integer
  38. */
  39. private $grid_layout_pos = 1;
  40.  
  41. /**
  42. * Runtime cache.
  43. * @var bool
  44. */
  45. private $display_cart_prices_incl_tax;
  46.  
  47. /**
  48. * The single instance of the class.
  49. * @var WC_PB_Display
  50. *
  51. * @since 5.0.0
  52. */
  53. protected static $_instance = null;
  54.  
  55. /**
  56. * Main WC_PB_Display instance. Ensures only one instance of WC_PB_Display is loaded or can be loaded.
  57. *
  58. * @since 5.0.0
  59. *
  60. * @return WC_PB_Display
  61. */
  62. public static function instance() {
  63. if ( is_null( self::$_instance ) ) {
  64. self::$_instance = new self();
  65. }
  66. return self::$_instance;
  67. }
  68.  
  69. /**
  70. * Cloning is forbidden.
  71. *
  72. * @since 5.0.0
  73. */
  74. public function __clone() {
  75. _doing_it_wrong( __FUNCTION__, __( 'Foul!', 'woocommerce-product-bundles' ), '5.0.0' );
  76. }
  77.  
  78. /**
  79. * Unserializing instances of this class is forbidden.
  80. *
  81. * @since 5.0.0
  82. */
  83. public function __wakeup() {
  84. _doing_it_wrong( __FUNCTION__, __( 'Foul!', 'woocommerce-product-bundles' ), '5.0.0' );
  85. }
  86.  
  87. /**
  88. * Setup hooks and functions.
  89. */
  90. protected function __construct() {
  91.  
  92. // Single product template functions and hooks.
  93. require_once( 'wc-pb-template-functions.php' );
  94. require_once( 'wc-pb-template-hooks.php' );
  95.  
  96. // Front end bundle add-to-cart script.
  97. add_action( 'wp_enqueue_scripts', array( $this, 'frontend_scripts' ), 100 );
  98.  
  99. /*
  100. * Single-product.
  101. */
  102.  
  103. // Display info notice when editing a bundle from the cart. Notices are rendered at priority 10.
  104. add_action( 'woocommerce_before_single_product', array( $this, 'add_edit_in_cart_notice' ), 0 );
  105.  
  106. // Modify structured data.
  107. add_filter( 'woocommerce_structured_data_product_offer', array( $this, 'structured_product_data' ), 10, 2 );
  108.  
  109. // Replace 'in_stock' post class with 'insufficient_stock' and 'out_of_stock' post class.
  110. add_filter( 'woocommerce_post_class', array( $this, 'post_classes' ), 10, 2 );
  111.  
  112. /*
  113. * Cart.
  114. */
  115.  
  116. // Filter cart item price.
  117. add_filter( 'woocommerce_cart_item_price', array( $this, 'cart_item_price' ), 10, 3 );
  118.  
  119. // Filter cart item subtotals.
  120. add_filter( 'woocommerce_cart_item_subtotal', array( $this, 'cart_item_subtotal' ), 10, 3 );
  121. add_filter( 'woocommerce_checkout_item_subtotal', array( $this, 'cart_item_subtotal' ), 10, 3 );
  122.  
  123. // Keep quantities in sync.
  124. add_filter( 'woocommerce_cart_item_quantity', array( $this, 'cart_item_quantity' ), 10, 2 );
  125. add_filter( 'woocommerce_cart_item_remove_link', array( $this, 'cart_item_remove_link' ), 10, 2 );
  126.  
  127. // Visibility.
  128. add_filter( 'woocommerce_cart_item_visible', array( $this, 'cart_item_visible' ), 10, 3 );
  129. add_filter( 'woocommerce_widget_cart_item_visible', array( $this, 'cart_item_visible' ), 10, 3 );
  130. add_filter( 'woocommerce_checkout_cart_item_visible', array( $this, 'cart_item_visible' ), 10, 3 );
  131.  
  132. // Modify titles.
  133. add_filter( 'woocommerce_cart_item_name', array( $this, 'cart_item_title' ), 10, 3 );
  134.  
  135. // Add table item classes.
  136. add_filter( 'woocommerce_cart_item_class', array( $this, 'cart_item_class' ), 10, 3 );
  137.  
  138. // Filter cart item count.
  139. add_filter( 'woocommerce_cart_contents_count', array( $this, 'cart_contents_count' ) );
  140.  
  141. // Item data.
  142. add_filter( 'woocommerce_get_item_data', array( $this, 'cart_item_data' ), 10, 2 );
  143.  
  144. // Hide thumbnail in cart when 'Hide thumbnail' option is selected.
  145. add_filter( 'woocommerce_cart_item_thumbnail', array( $this, 'cart_item_thumbnail' ), 10, 3);
  146.  
  147. // Filter cart widget items.
  148. add_action( 'woocommerce_before_mini_cart', array( $this, 'add_cart_widget_filters' ) );
  149. add_action( 'woocommerce_after_mini_cart', array( $this, 'remove_cart_widget_filters' ) );
  150.  
  151. /*
  152. * Orders.
  153. */
  154.  
  155. // Filter order item subtotals.
  156. add_filter( 'woocommerce_order_formatted_line_subtotal', array( $this, 'order_item_subtotal' ), 10, 3 );
  157.  
  158. // Visibility.
  159. add_filter( 'woocommerce_order_item_visible', array( $this, 'order_item_visible' ), 10, 2 );
  160.  
  161. // Modify titles.
  162. add_filter( 'woocommerce_order_item_name', array( $this, 'order_item_title' ), 10, 2 );
  163.  
  164. // Add table item classes.
  165. add_filter( 'woocommerce_order_item_class', array( $this, 'order_item_class' ), 10, 3 );
  166.  
  167. // Filter order item count.
  168. add_filter( 'woocommerce_get_item_count', array( $this, 'order_item_count' ), 10, 3 );
  169.  
  170. // Indentation of bundled items in emails.
  171. add_action( 'woocommerce_email_styles', array( $this, 'email_styles' ) );
  172.  
  173. /*
  174. * Archives.
  175. */
  176.  
  177. // Allow ajax add-to-cart to work in WC 2.3/2.4.
  178. add_filter( 'woocommerce_loop_add_to_cart_link', array( $this, 'loop_add_to_cart_link' ), 10, 2 );
  179. }
  180.  
  181. /**
  182. * Frontend scripts.
  183. *
  184. * @return void
  185. */
  186. public function frontend_scripts() {
  187.  
  188. $suffix = defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ? '' : '.min';
  189. /**
  190. * Frontend scripts. FIX
  191. *
  192. * @return void
  193. */
  194. $is_multiple = 1;
  195. if (class_exists('WOOCS')) {
  196. global $WOOCS;
  197. if (!$WOOCS->is_multiple_allowed) {
  198. $is_multiple = 0;
  199. $suffix = "";
  200. }
  201. }
  202. /**
  203. * Frontend scripts. FIX END
  204. *
  205. * @return void
  206. */
  207. wp_register_script( 'wc-add-to-cart-bundle', WC_PB()->plugin_url() . '/assets/js/frontend/add-to-cart-bundle' . $suffix . '.js', array( 'jquery', 'wc-add-to-cart-variation' ), WC_PB()->version, true );
  208.  
  209. wp_register_style( 'wc-bundle-css', WC_PB()->plugin_url() . '/assets/css/frontend/single-product.css', false, WC_PB()->version );
  210. wp_style_add_data( 'wc-bundle-css', 'rtl', 'replace' );
  211.  
  212. wp_register_style( 'wc-bundle-style', WC_PB()->plugin_url() . '/assets/css/frontend/woocommerce.css', false, WC_PB()->version );
  213. wp_style_add_data( 'wc-bundle-style', 'rtl', 'replace' );
  214.  
  215. wp_enqueue_style( 'wc-bundle-style' );
  216.  
  217. /**
  218. * 'woocommerce_bundle_front_end_params' filter.
  219. *
  220. * @param array
  221. */
  222. $params = apply_filters( 'woocommerce_bundle_front_end_params', array(
  223. 'i18n_free' => __( 'Free!', 'woocommerce' ),
  224. 'i18n_total' => __( 'Total: ', 'woocommerce-product-bundles' ),
  225. 'i18n_subtotal' => __( 'Subtotal: ', 'woocommerce-product-bundles' ),
  226. 'i18n_price_format' => sprintf( _x( '%1$s%2$s%3$s', '"Total/Subtotal" string followed by price followed by price suffix', 'woocommerce-product-bundles' ), '%t', '%p', '%s' ),
  227. 'i18n_strikeout_price_string' => sprintf( _x( '<del>%1$s</del> <ins>%2$s</ins>', 'Sale/strikeout price', 'woocommerce-product-bundles' ), '%f', '%t' ),
  228. 'i18n_partially_out_of_stock' => __( 'Insufficient stock', 'woocommerce-product-bundles' ),
  229. 'i18n_partially_on_backorder' => __( 'Available on backorder', 'woocommerce' ),
  230. 'i18n_select_options' => __( 'To continue, please choose product options&hellip;', 'woocommerce-product-bundles' ),
  231. 'i18n_select_options_for' => __( 'To continue, please choose %s options&hellip;', 'woocommerce-product-bundles' ),
  232. 'i18n_enter_valid_price' => __( 'Please enter valid amounts&hellip;', 'woocommerce-product-bundles' ),
  233. 'i18n_enter_valid_price_for' => __( 'Please enter a valid %s amount.', 'woocommerce-product-bundles' ),
  234. 'i18n_string_list_item' => _x( '&quot;%s&quot;', 'string list item', 'woocommerce-product-bundles' ),
  235. 'i18n_string_list_sep' => sprintf( _x( '%1$s, %2$s', 'string list item separator', 'woocommerce-product-bundles' ), '%s', '%v' ),
  236. 'i18n_string_list_last_sep' => sprintf( _x( '%1$s and %2$s', 'string list item last separator', 'woocommerce-product-bundles' ), '%s', '%v' ),
  237. 'i18n_qty_string' => _x( ' &times; %s', 'qty string', 'woocommerce-product-bundles' ),
  238. 'i18n_optional_string' => _x( ' &mdash; %s', 'suffix', 'woocommerce-product-bundles' ),
  239. 'i18n_optional' => __( 'optional', 'woocommerce-product-bundles' ),
  240. 'i18n_contents' => __( 'Includes', 'woocommerce-product-bundles' ),
  241. 'i18n_title_meta_string' => sprintf( _x( '%1$s &ndash; %2$s', 'title followed by meta', 'woocommerce-product-bundles' ), '%t', '%m' ),
  242. 'i18n_title_string' => sprintf( _x( '%1$s%2$s%3$s%4$s', 'title, quantity, price, suffix', 'woocommerce-product-bundles' ), '<span class="item_title">%t</span>', '<span class="item_qty">%q</span>', '', '<span class="item_suffix">%o</span>' ),
  243. 'i18n_unavailable_text' => __( 'This product is currently unavailable.', 'woocommerce-product-bundles' ),
  244. 'i18n_validation_alert' => __( 'Please resolve all pending issues before adding this product to your cart.', 'woocommerce-product-bundles' ),
  245. 'i18n_zero_qty_error' => __( 'Please choose at least 1 item.', 'woocommerce-product-bundles' ),
  246. 'responsive_breakpoint' => 380,
  247. 'currency_symbol' => get_woocommerce_currency_symbol(),
  248. 'currency_position' => esc_attr( stripslashes( get_option( 'woocommerce_currency_pos' ) ) ),
  249. 'currency_format_num_decimals' => wc_get_price_decimals(),
  250. 'currency_format_decimal_sep' => esc_attr( stripslashes( get_option( 'woocommerce_price_decimal_sep' ) ) ),
  251. 'currency_format_thousand_sep' => esc_attr( stripslashes( get_option( 'woocommerce_price_thousand_sep' ) ) ),
  252. 'currency_format_trim_zeros' => false === apply_filters( 'woocommerce_price_trim_zeros', false ) ? 'no' : 'yes',
  253. 'price_display_suffix' => esc_attr( get_option( 'woocommerce_price_display_suffix' ) ),
  254. 'prices_include_tax' => esc_attr( get_option( 'woocommerce_prices_include_tax' ) ),
  255. 'tax_display_shop' => esc_attr( get_option( 'woocommerce_tax_display_shop' ) ),
  256. 'calc_taxes' => esc_attr( get_option( 'woocommerce_calc_taxes' ) ),
  257. 'photoswipe_enabled' => current_theme_supports( 'wc-product-gallery-lightbox' ) ? 'yes' : 'no',
  258. 'force_min_max_qty_input' => 'yes'
  259. 'woocs_is_multiple' => $is_multiple
  260.  
  261. ) );
  262.  
  263. wp_localize_script( 'wc-add-to-cart-bundle', 'wc_bundle_params', $params );
  264. }
  265.  
  266. /**
  267. * Enqeue js that wraps bundled table items in a div in order to apply indentation reliably.
  268. * This obviously sucks but if you can find a CSS-only way to do it better that works reliably with any theme out there, drop us a line, will you?
  269. *
  270. * @return void
  271. */
  272. private function enqueue_bundled_table_item_js() {
  273.  
  274. /**
  275. * 'woocommerce_bundled_table_item_js_enqueued' filter.
  276. *
  277. * Use this filter to get rid of this ugly hack:
  278. * Return 'false' and add your own CSS to indent '.bundled_table_item' elements.
  279. *
  280. * @since 5.5.0
  281. *
  282. * @param boolean $is_enqueued
  283. */
  284. $is_enqueued = apply_filters( 'woocommerce_bundled_table_item_js_enqueued', $this->enqueued_bundled_table_item_js );
  285.  
  286. if ( ! $is_enqueued ) {
  287.  
  288. wc_enqueue_js( "
  289. var wc_pb_wrap_bundled_table_item = function() {
  290. jQuery( '.bundled_table_item td.product-name' ).each( function() {
  291. var el = jQuery( this );
  292. if ( el.find( '.bundled-product-name' ).length === 0 ) {
  293. el.wrapInner( '<div class=\"bundled-product-name bundled_table_item_indent\"></div>' );
  294. }
  295. } );
  296. };
  297.  
  298. jQuery( 'body' ).on( 'updated_checkout updated_cart_totals', function() {
  299. wc_pb_wrap_bundled_table_item();
  300. } );
  301.  
  302. wc_pb_wrap_bundled_table_item();
  303. " );
  304.  
  305. $this->enqueued_bundled_table_item_js = true;
  306. }
  307. }
  308.  
  309. /*
  310. |--------------------------------------------------------------------------
  311. | Single-product.
  312. |--------------------------------------------------------------------------
  313. */
  314.  
  315. /**
  316. * The number of bundled item columns when the "Grid" layout is active.
  317. *
  318. * @since 5.8.0
  319. *
  320. * @param WC_Product_Bundle $bundle
  321. * @return int
  322. */
  323. public function get_grid_layout_columns( $bundle ) {
  324.  
  325. /**
  326. * 'woocommerce_bundled_items_grid_columns' filter.
  327. *
  328. * @since 5.8.0
  329. *
  330. * @param int $count
  331. * @param WC_Product_Bundle $bundle
  332. */
  333. return apply_filters( 'woocommerce_bundled_items_grid_layout_columns', 3, $bundle );
  334. }
  335.  
  336. /**
  337. * Class associated with the position of a bundled item in the grid when the "Grid" layout is active.
  338. *
  339. * @since 5.8.0
  340. *
  341. * @param WC_Bundled_Item $bundled_item
  342. * @return int
  343. */
  344. public function get_grid_layout_class( $bundled_item ) {
  345.  
  346. $class = '';
  347.  
  348. if ( $this->grid_layout_pos === 1 ) {
  349. $class = 'first';
  350. } elseif ( $this->grid_layout_pos === $this->get_grid_layout_columns( $bundled_item->get_bundle() ) ) {
  351. $class = 'last';
  352. }
  353.  
  354. return $class;
  355. }
  356.  
  357. /**
  358. * Increments the position of a bundled item in the grid when the "Grid" layout is active.
  359. *
  360. * @since 5.8.0
  361. *
  362. * @param WC_Bundled_Item $bundled_item
  363. * @return int
  364. */
  365. public function incr_grid_layout_pos( $bundled_item ) {
  366.  
  367. if ( $this->grid_layout_pos === $this->get_grid_layout_columns( $bundled_item->get_bundle() ) ) {
  368. $this->grid_layout_pos = 1;
  369. } else {
  370. $this->grid_layout_pos++;
  371. }
  372. }
  373.  
  374. /**
  375. * Resets the position of a bundled item in the grid when the "Grid" layout is active.
  376. *
  377. * @since 5.8.0
  378. *
  379. * @return void
  380. */
  381. public function reset_grid_layout_pos() {
  382. $this->grid_layout_pos = 1;
  383. }
  384.  
  385. /**
  386. * Display info notice when editing a bundle from the cart.
  387. */
  388. public function add_edit_in_cart_notice() {
  389.  
  390. global $product;
  391.  
  392. if ( $product->is_type( 'bundle' ) && isset( $_GET[ 'update-bundle' ] ) ) {
  393. $updating_cart_key = wc_clean( $_GET[ 'update-bundle' ] );
  394. if ( isset( WC()->cart->cart_contents[ $updating_cart_key ] ) ) {
  395. $notice = sprintf ( __( 'You are currently editing &quot;%1$s&quot;. When finished, click the <strong>Update Cart</strong> button.', 'woocommerce-product-bundles' ), $product->get_title() );
  396. wc_add_notice( $notice, 'notice' );
  397. }
  398. }
  399. }
  400.  
  401. /**
  402. * Modify structured data for bundle-type products.
  403. *
  404. * @param array $data
  405. * @param WC_Product $product
  406. * @return array
  407. */
  408. public function structured_product_data( $data, $product ) {
  409.  
  410. if ( is_object( $product ) && $product->is_type( 'bundle' ) ) {
  411. $data[ 'price' ] = $product->get_bundle_price();
  412. }
  413.  
  414. return $data;
  415. }
  416.  
  417. /**
  418. * Replace 'in_stock' post class with 'insufficient_stock' and 'out_of_stock' post class.
  419. *
  420. * @since 5.11.2
  421. *
  422. * @param array $classes
  423. * @param WC_Product $product
  424. * @return array
  425. */
  426. public function post_classes( $classes, $product ) {
  427.  
  428. if ( ! $product->is_type( 'bundle' ) ) {
  429. return $classes;
  430. }
  431.  
  432. if ( in_array( 'instock', $classes ) && 'outofstock' === $product->get_bundled_items_stock_status() ) {
  433. $classes = array_diff( $classes, array( 'instock' ) );
  434. $classes = array_merge( $classes, array( 'outofstock', 'insufficientstock' ) );
  435. }
  436.  
  437. return $classes;
  438. }
  439.  
  440. /*
  441. |--------------------------------------------------------------------------
  442. | Cart.
  443. |--------------------------------------------------------------------------
  444. */
  445.  
  446. /**
  447. * Back-compat wrapper for 'WC_Cart::display_price_including_tax'.
  448. *
  449. * @since 6.3.2
  450. *
  451. * @return string
  452. */
  453. private function display_cart_prices_including_tax() {
  454.  
  455. if ( is_null( $this->display_cart_prices_incl_tax ) ) {
  456. $this->display_cart_prices_incl_tax = WC_PB_Core_Compatibility::is_wc_version_gte( '3.3' ) ? WC()->cart->display_prices_including_tax() : ( 'incl' === get_option( 'woocommerce_tax_display_cart' ) );
  457. }
  458.  
  459. return $this->display_cart_prices_incl_tax;
  460. }
  461.  
  462. /**
  463. * Outputs a formatted subtotal.
  464. *
  465. * @param WC_Product $product
  466. * @param string $subtotal
  467. * @return string
  468. */
  469. public function format_subtotal( $product, $subtotal ) {
  470.  
  471. $cart = WC()->cart;
  472. $taxable = $product->is_taxable();
  473. $formatted_subtotal = wc_price( $subtotal );
  474.  
  475. if ( $taxable ) {
  476.  
  477. $tax_subtotal = WC_PB_Core_Compatibility::is_wc_version_gte( '3.2' ) ? $cart->get_subtotal_tax() : $cart->tax_total;
  478.  
  479. if ( ! $this->display_cart_prices_including_tax() ) {
  480.  
  481. if ( wc_prices_include_tax() && $tax_subtotal > 0 ) {
  482. $formatted_subtotal .= ' <small class="tax_label">' . WC()->countries->ex_tax_or_vat() . '</small>';
  483. }
  484.  
  485. } else {
  486.  
  487. if ( ! wc_prices_include_tax() && $tax_subtotal > 0 ) {
  488. $formatted_subtotal .= ' <small class="tax_label">' . WC()->countries->inc_tax_or_vat() . '</small>';
  489. }
  490. }
  491. }
  492.  
  493. return $formatted_subtotal;
  494. }
  495.  
  496. /**
  497. * Modify the front-end price of bundled items and container items depending on their pricing setup.
  498. *
  499. * @param double $price
  500. * @param array $values
  501. * @param string $cart_item_key
  502. * @return string
  503. */
  504. public function cart_item_price( $price, $cart_item, $cart_item_key ) {
  505.  
  506. if ( $bundle_container_item = wc_pb_get_bundled_cart_item_container( $cart_item ) ) {
  507. $price = $this->get_child_cart_item_price( $price, $cart_item, $cart_item_key, $bundle_container_item );
  508. } elseif ( wc_pb_is_bundle_container_cart_item( $cart_item ) ) {
  509. $price = $this->get_container_cart_item_price( $price, $cart_item, $cart_item_key );
  510. }
  511.  
  512. return $price;
  513. }
  514.  
  515. /**
  516. * Modifies child cart item prices.
  517. *
  518. * @since 5.8.0
  519. *
  520. * @param string $price
  521. * @param array $cart_item
  522. * @param string $cart_item_key
  523. * @return string
  524. */
  525. public function get_child_cart_item_price( $price, $cart_item, $cart_item_key, $bundle_container_item = false ) {
  526.  
  527. if ( false === $bundle_container_item ) {
  528. $bundle_container_item = wc_pb_get_bundled_cart_item_container( $cart_item );
  529. }
  530.  
  531. if ( $bundle_container_item ) {
  532.  
  533. $bundled_item_id = $cart_item[ 'bundled_item_id' ];
  534.  
  535. if ( $bundled_item = $bundle_container_item[ 'data' ]->get_bundled_item( $bundled_item_id ) ) {
  536.  
  537. if ( empty( $cart_item[ 'line_subtotal' ] ) && false === $bundled_item->is_priced_individually() ) {
  538.  
  539. $price = '';
  540.  
  541. } elseif ( false === $bundled_item->is_price_visible( 'cart' ) ) {
  542.  
  543. $price = '';
  544.  
  545. } elseif ( WC_Product_Bundle::group_mode_has( $bundle_container_item[ 'data' ]->get_group_mode(), 'aggregated_prices' ) ) {
  546.  
  547. if ( WC_PB()->compatibility->is_composited_cart_item( $bundle_container_item ) ) {
  548. $price = '';
  549. } elseif ( $price ) {
  550. $price = '<span class="bundled_' . ( $this->is_cart_widget() ? 'mini_cart' : 'table' ) . '_item_price">' . $price . '</span>';
  551. }
  552.  
  553. } elseif ( $price && function_exists( 'wc_cp_get_composited_cart_item_container' ) && ( $composite_container_item_key = wc_cp_get_composited_cart_item_container( $bundle_container_item, WC()->cart->cart_contents, true ) ) ) {
  554.  
  555. $composite_container_item = WC()->cart->cart_contents[ $composite_container_item_key ];
  556.  
  557. if ( apply_filters( 'woocommerce_add_composited_cart_item_prices', true, $composite_container_item, $composite_container_item_key ) ) {
  558.  
  559. $show_price = true;
  560.  
  561. if ( empty( $cart_item[ 'line_subtotal' ] ) && false === $bundled_item->is_priced_individually() ) {
  562.  
  563. $component_id = $bundle_container_item[ 'composite_item' ];
  564. $composite_container_item = wc_cp_get_composited_cart_item_container( $bundle_container_item );
  565.  
  566. if ( $composite_container_item ) {
  567. $component = $composite_container_item[ 'data' ]->get_component( $component_id );
  568. $show_price = $component && $component->is_priced_individually();
  569. }
  570. }
  571.  
  572. if ( $show_price ) {
  573. $price = '<span class="bundled_' . ( $this->is_cart_widget() ? 'mini_cart' : 'table' ) . '_item_price">' . $price . '</span>';
  574. } else {
  575. $price = '';
  576. }
  577. }
  578. }
  579. }
  580. }
  581.  
  582. return $price;
  583. }
  584.  
  585. /**
  586. * Aggregates parent + child cart item prices.
  587. *
  588. * @param string $price
  589. * @param array $cart_item
  590. * @param string $cart_item_key
  591. * @return string
  592. */
  593. private function get_container_cart_item_price( $price, $cart_item, $cart_item_key ) {
  594.  
  595. if ( wc_pb_is_bundle_container_cart_item( $cart_item ) ) {
  596.  
  597. $aggregate_prices = WC_Product_Bundle::group_mode_has( $cart_item[ 'data' ]->get_group_mode(), 'aggregated_prices' );
  598.  
  599. if ( $aggregate_prices ) {
  600.  
  601. $calc_type = ! $this->display_cart_prices_including_tax() ? 'excl_tax' : 'incl_tax';
  602. $bundle_price = WC_PB_Product_Prices::get_product_price( $cart_item[ 'data' ], array( 'price' => $cart_item[ 'data' ]->get_price(), 'calc' => $calc_type ) );
  603. $bundled_cart_items = wc_pb_get_bundled_cart_items( $cart_item, WC()->cart->cart_contents );
  604. $bundled_items_price = 0.0;
  605.  
  606. foreach ( $bundled_cart_items as $bundled_cart_item ) {
  607.  
  608. $bundled_item_id = $bundled_cart_item[ 'bundled_item_id' ];
  609. $bundled_item_raw_price = $bundled_cart_item[ 'data' ]->get_price();
  610.  
  611. if ( WC_PB()->compatibility->is_subscription( $bundled_cart_item[ 'data' ] ) ) {
  612.  
  613. $bundled_item = $cart_item[ 'data' ]->get_bundled_item( $bundled_item_id );
  614.  
  615. if ( $bundled_item ) {
  616. $bundled_item_raw_recurring_fee = $bundled_cart_item[ 'data' ]->get_price();
  617. $bundled_item_raw_sign_up_fee = (double) WC_Subscriptions_Product::get_sign_up_fee( $bundled_cart_item[ 'data' ] );
  618. $bundled_item_raw_price = $bundled_item->get_up_front_subscription_price( $bundled_item_raw_recurring_fee, $bundled_item_raw_sign_up_fee, $bundled_cart_item[ 'data' ] );
  619. }
  620. }
  621.  
  622. $bundled_item_qty = $bundled_cart_item[ 'data' ]->is_sold_individually() ? 1 : $bundled_cart_item[ 'quantity' ] / $cart_item[ 'quantity' ];
  623. $bundled_item_price = WC_PB_Product_Prices::get_product_price( $bundled_cart_item[ 'data' ], array( 'price' => $bundled_item_raw_price, 'calc' => $calc_type, 'qty' => $bundled_item_qty ) );
  624. $bundled_items_price += wc_format_decimal( (double) $bundled_item_price, wc_get_price_decimals() );
  625. }
  626.  
  627. $price = wc_price( (double) $bundle_price + $bundled_items_price );
  628.  
  629. } elseif ( empty( $cart_item[ 'line_subtotal' ] ) ) {
  630.  
  631. $bundled_items = wc_pb_get_bundled_cart_items( $cart_item, WC()->cart->cart_contents );
  632. $bundled_item_subtotals = wp_list_pluck( $bundled_items, 'line_subtotal' );
  633.  
  634. if ( array_sum( $bundled_item_subtotals ) > 0 ) {
  635. $price = '';
  636. }
  637. }
  638. }
  639.  
  640. return $price;
  641. }
  642.  
  643. /**
  644. * Modifies child cart item subtotals.
  645. *
  646. * @since 5.8.0
  647. *
  648. * @param string $price
  649. * @param array $cart_item
  650. * @param string $cart_item_key
  651. * @return string
  652. */
  653. public function get_child_cart_item_subtotal( $subtotal, $cart_item, $cart_item_key, $bundle_container_item = false ) {
  654.  
  655. if ( false === $bundle_container_item ) {
  656. $bundle_container_item = wc_pb_get_bundled_cart_item_container( $cart_item );
  657. }
  658.  
  659. if ( $bundle_container_item ) {
  660.  
  661. $bundled_item_id = $cart_item[ 'bundled_item_id' ];
  662.  
  663. if ( $bundled_item = $bundle_container_item[ 'data' ]->get_bundled_item( $bundled_item_id ) ) {
  664.  
  665. if ( empty( $cart_item[ 'line_subtotal' ] ) && false === $bundled_item->is_priced_individually() ) {
  666.  
  667. $subtotal = '';
  668.  
  669. } elseif ( false === $bundled_item->is_price_visible( 'cart' ) ) {
  670.  
  671. $subtotal = '';
  672.  
  673. } elseif ( WC_Product_Bundle::group_mode_has( $bundle_container_item[ 'data' ]->get_group_mode(), 'aggregated_subtotals' ) ) {
  674.  
  675. if ( WC_PB()->compatibility->is_composited_cart_item( $bundle_container_item ) ) {
  676. $subtotal = '';
  677. } elseif ( $subtotal ) {
  678. $subtotal = '<span class="bundled_' . ( $this->is_cart_widget() ? 'mini_cart' : 'table' ) . '_item_subtotal">' . sprintf( _x( '%1$s: %2$s', 'bundled product subtotal', 'woocommerce-product-bundles' ), __( 'Subtotal', 'woocommerce-product-bundles' ), $subtotal ) . '</span>';
  679. }
  680.  
  681. } elseif ( $subtotal && function_exists( 'wc_cp_get_composited_cart_item_container' ) && ( $composite_container_item_key = wc_cp_get_composited_cart_item_container( $bundle_container_item, WC()->cart->cart_contents, true ) ) ) {
  682.  
  683. $composite_container_item = WC()->cart->cart_contents[ $composite_container_item_key ];
  684.  
  685. if ( apply_filters( 'woocommerce_add_composited_cart_item_subtotals', true, $composite_container_item, $composite_container_item_key ) ) {
  686.  
  687. $show_subtotal = true;
  688.  
  689. if ( empty( $cart_item[ 'line_subtotal' ] ) && false === $bundled_item->is_priced_individually() ) {
  690.  
  691. $component_id = $bundle_container_item[ 'composite_item' ];
  692. $composite_container_item = wc_cp_get_composited_cart_item_container( $bundle_container_item );
  693.  
  694. if ( $composite_container_item ) {
  695. $component = $composite_container_item[ 'data' ]->get_component( $component_id );
  696. $show_subtotal = $component && $component->is_priced_individually();
  697. }
  698. }
  699.  
  700. if ( $show_subtotal ) {
  701. $subtotal = '<span class="bundled_' . ( $this->is_cart_widget() ? 'mini_cart' : 'table' ) . '_item_subtotal">' . sprintf( _x( '%1$s: %2$s', 'bundled product subtotal', 'woocommerce-product-bundles' ), __( 'Subtotal', 'woocommerce-product-bundles' ), $subtotal ) . '</span>';
  702. } else {
  703. $subtotal = '';
  704. }
  705. }
  706. }
  707. }
  708. }
  709.  
  710. return $subtotal;
  711. }
  712.  
  713. /**
  714. * Aggregates parent + child cart item subtotals.
  715. *
  716. * @param string $subtotal
  717. * @param array $cart_item
  718. * @param string $cart_item_key
  719. * @return string
  720. */
  721. private function get_container_cart_item_subtotal( $subtotal, $cart_item, $cart_item_key ) {
  722.  
  723. if ( wc_pb_is_bundle_container_cart_item( $cart_item ) ) {
  724.  
  725. $aggregate_subtotals = WC_Product_Bundle::group_mode_has( $cart_item[ 'data' ]->get_group_mode(), 'aggregated_subtotals' );
  726.  
  727. if ( $aggregate_subtotals ) {
  728.  
  729. $calc_type = ! $this->display_cart_prices_including_tax() ? 'excl_tax' : 'incl_tax';
  730. $bundle_price = WC_PB_Product_Prices::get_product_price( $cart_item[ 'data' ], array( 'price' => $cart_item[ 'data' ]->get_price(), 'calc' => $calc_type, 'qty' => $cart_item[ 'quantity' ] ) );
  731. $bundled_cart_items = wc_pb_get_bundled_cart_items( $cart_item, WC()->cart->cart_contents );
  732. $bundled_items_price = 0.0;
  733.  
  734. foreach ( $bundled_cart_items as $bundled_cart_item ) {
  735.  
  736. $bundled_item_id = $bundled_cart_item[ 'bundled_item_id' ];
  737. $bundled_item_raw_price = $bundled_cart_item[ 'data' ]->get_price();
  738.  
  739. if ( WC_PB()->compatibility->is_subscription( $bundled_cart_item[ 'data' ] ) ) {
  740.  
  741. $bundled_item = $cart_item[ 'data' ]->get_bundled_item( $bundled_item_id );
  742.  
  743. if ( $bundled_item ) {
  744. $bundled_item_raw_recurring_fee = $bundled_cart_item[ 'data' ]->get_price();
  745. $bundled_item_raw_sign_up_fee = (double) WC_Subscriptions_Product::get_sign_up_fee( $bundled_cart_item[ 'data' ] );
  746. $bundled_item_raw_price = $bundled_item->get_up_front_subscription_price( $bundled_item_raw_recurring_fee, $bundled_item_raw_sign_up_fee, $bundled_cart_item[ 'data' ] );
  747. }
  748. }
  749.  
  750. $bundled_item_price = WC_PB_Product_Prices::get_product_price( $bundled_cart_item[ 'data' ], array( 'price' => $bundled_item_raw_price, 'calc' => $calc_type, 'qty' => $bundled_cart_item[ 'quantity' ] ) );
  751. $bundled_items_price += wc_format_decimal( (double) $bundled_item_price, wc_get_price_decimals() );
  752. }
  753.  
  754. $subtotal = $this->format_subtotal( $cart_item[ 'data' ], (double) $bundle_price + $bundled_items_price );
  755.  
  756. } elseif ( empty( $cart_item[ 'line_subtotal' ] ) ) {
  757.  
  758. $bundled_items = wc_pb_get_bundled_cart_items( $cart_item, WC()->cart->cart_contents );
  759. $bundled_item_subtotals = wp_list_pluck( $bundled_items, 'line_subtotal' );
  760.  
  761. if ( array_sum( $bundled_item_subtotals ) > 0 ) {
  762. $subtotal = '';
  763. }
  764. }
  765. }
  766.  
  767. return $subtotal;
  768. }
  769.  
  770. /**
  771. * Modifies line item subtotals in the 'cart.php' & 'review-order.php' templates.
  772. *
  773. * @param string $subtotal
  774. * @param array $cart_item
  775. * @param string $cart_item_key
  776. * @return string
  777. */
  778. public function cart_item_subtotal( $subtotal, $cart_item, $cart_item_key ) {
  779.  
  780. if ( wc_pb_is_bundled_cart_item( $cart_item ) ) {
  781. $subtotal = $this->get_child_cart_item_subtotal( $subtotal, $cart_item, $cart_item_key );
  782. } elseif ( wc_pb_is_bundle_container_cart_item( $cart_item ) ) {
  783. $subtotal = $this->get_container_cart_item_subtotal( $subtotal, $cart_item, $cart_item_key );
  784. }
  785.  
  786. return $subtotal;
  787. }
  788.  
  789. /**
  790. * Bundled item quantities can't be changed individually. When adjusting quantity for the container item, the bundled products must follow.
  791. *
  792. * @param int $quantity
  793. * @param string $cart_item_key
  794. * @return int
  795. */
  796. public function cart_item_quantity( $quantity, $cart_item_key ) {
  797.  
  798. $cart_item = WC()->cart->cart_contents[ $cart_item_key ];
  799.  
  800. if ( $container_item = wc_pb_get_bundled_cart_item_container( $cart_item ) ) {
  801.  
  802. $bundled_item_id = $cart_item[ 'bundled_item_id' ];
  803. $bundled_item = $container_item[ 'data' ]->get_bundled_item( $bundled_item_id );
  804.  
  805. $min_quantity = $bundled_item->get_quantity( 'min' );
  806. $max_quantity = $bundled_item->get_quantity( 'max' );
  807.  
  808. if ( $min_quantity === $max_quantity ) {
  809.  
  810. $quantity = $cart_item[ 'quantity' ];
  811.  
  812. } else {
  813.  
  814. $parent_quantity = $container_item[ 'quantity' ];
  815.  
  816. $min_qty = $parent_quantity * $min_quantity;
  817. $max_qty = '' !== $max_quantity ? $parent_quantity * $max_quantity : '';
  818.  
  819. if ( ( $max_qty > $min_qty || '' === $max_qty ) && ! $cart_item[ 'data' ]->is_sold_individually() ) {
  820.  
  821. $quantity = woocommerce_quantity_input( array(
  822. 'input_name' => "cart[{$cart_item_key}][qty]",
  823. 'input_value' => $cart_item[ 'quantity' ],
  824. 'min_value' => $min_qty,
  825. 'max_value' => $max_qty,
  826. 'step' => $parent_quantity
  827. ), $cart_item[ 'data' ], false );
  828.  
  829. } else {
  830. $quantity = $cart_item[ 'quantity' ];
  831. }
  832. }
  833. }
  834.  
  835. return $quantity;
  836. }
  837.  
  838. /**
  839. * Bundled items can't be removed individually from the cart - this hides the remove buttons.
  840. *
  841. * @param string $link
  842. * @param string $cart_item_key
  843. * @return string
  844. */
  845. public function cart_item_remove_link( $link, $cart_item_key ) {
  846.  
  847. $cart_item = WC()->cart->cart_contents[ $cart_item_key ];
  848.  
  849. if ( $bundle_container_item_key = wc_pb_get_bundled_cart_item_container( $cart_item, false, true ) ) {
  850.  
  851. $bundle_container_item = WC()->cart->cart_contents[ $bundle_container_item_key ];
  852.  
  853. $bundle = $bundle_container_item[ 'data' ];
  854.  
  855. if ( false === WC_Product_Bundle::group_mode_has( $bundle->get_group_mode(), 'parent_item' ) ) {
  856.  
  857. /*
  858. * If it's the first child, show a button that relays the remove action to the parent.
  859. * Here we assume that the first child is visible.
  860. */
  861. $bundled_cart_item_keys = wc_pb_get_bundled_cart_items( $bundle_container_item, false, true );
  862.  
  863. if ( empty( $bundled_cart_item_keys ) || current( $bundled_cart_item_keys ) !== $cart_item_key ) {
  864. return '';
  865. } else {
  866. $link = sprintf(
  867. '<a href="%s" class="remove remove_bundle" aria-label="%s" data-product_id="%s" data-product_sku="%s">&times;</a>',
  868. esc_url( WC_PB_Core_Compatibility::wc_get_cart_remove_url( $bundle_container_item_key ) ),
  869. __( 'Remove this item', 'woocommerce' ),
  870. esc_attr( $bundle->get_id() ),
  871. esc_attr( $bundle->get_sku() )
  872. );
  873. }
  874.  
  875. } else {
  876. return '';
  877. }
  878. }
  879.  
  880. return $link;
  881. }
  882.  
  883. /**
  884. * Visibility of bundled item in cart.
  885. *
  886. * @param boolean $visible
  887. * @param array $cart_item
  888. * @param string $cart_item_key
  889. * @return boolean
  890. */
  891. public function cart_item_visible( $visible, $cart_item, $cart_item_key ) {
  892.  
  893. if ( $bundle_container_item = wc_pb_get_bundled_cart_item_container( $cart_item ) ) {
  894.  
  895. $bundle = $bundle_container_item[ 'data' ];
  896. $bundled_item_id = $cart_item[ 'bundled_item_id' ];
  897.  
  898. if ( $bundled_item = $bundle->get_bundled_item( $bundled_item_id ) ) {
  899. if ( false === $bundled_item->is_visible( 'cart' ) ) {
  900. $visible = false;
  901. }
  902. }
  903.  
  904. } elseif ( wc_pb_is_bundle_container_cart_item( $cart_item ) ) {
  905.  
  906. $bundle = $cart_item[ 'data' ];
  907.  
  908. if ( false === WC_Product_Bundle::group_mode_has( $bundle->get_group_mode(), 'parent_item' ) ) {
  909. $visible = false;
  910. }
  911. }
  912.  
  913. return $visible;
  914. }
  915.  
  916. /**
  917. * Override bundled item title in cart/checkout templates.
  918. *
  919. * @param string $content
  920. * @param array $cart_item
  921. * @param string $cart_item_key
  922. * @return string
  923. */
  924. public function cart_item_title( $content, $cart_item, $cart_item_key ) {
  925.  
  926. if ( $bundle_container_item_key = wc_pb_get_bundled_cart_item_container( $cart_item, false, true ) ) {
  927.  
  928. $bundle_container_item = WC()->cart->cart_contents[ $bundle_container_item_key ];
  929. $bundle = $bundle_container_item[ 'data' ];
  930.  
  931. if ( WC_Product_Bundle::group_mode_has( $bundle->get_group_mode(), 'child_item_indent' ) ) {
  932. $this->enqueue_bundled_table_item_js();
  933. }
  934.  
  935. if ( WC_Product_Bundle::group_mode_has( $bundle->get_group_mode(), 'faked_parent_item' ) ) {
  936.  
  937. $bundled_cart_item_keys = wc_pb_get_bundled_cart_items( $bundle_container_item, false, true );
  938.  
  939. if ( ! empty( $bundled_cart_item_keys ) && current( $bundled_cart_item_keys ) === $cart_item_key ) {
  940.  
  941. if ( function_exists( 'is_cart' ) && is_cart() && ! $this->is_cart_widget() ) {
  942.  
  943. if ( $bundle->is_editable_in_cart( $bundle_container_item ) ) {
  944.  
  945. $edit_in_cart_link = esc_url( add_query_arg( array( 'update-bundle' => $bundle_container_item_key ), $bundle->get_permalink( $bundle_container_item ) ) );
  946. $edit_in_cart_text = _x( 'Edit', 'edit in cart link text', 'woocommerce-product-bundles' );
  947. $content = sprintf( _x( '%1$s<br/><a class="edit_bundle_in_cart_text edit_in_cart_text" rel="no-follow" href="%2$s"><small>%3$s</small></a>', 'edit in cart text', 'woocommerce-product-bundles' ), $content, $edit_in_cart_link, $edit_in_cart_text );
  948. }
  949. }
  950. }
  951. }
  952.  
  953. } elseif ( wc_pb_is_bundle_container_cart_item( $cart_item ) ) {
  954.  
  955. $bundle = $cart_item[ 'data' ];
  956.  
  957. if ( function_exists( 'is_cart' ) && is_cart() && ! $this->is_cart_widget() ) {
  958.  
  959. if ( $bundle->is_editable_in_cart( $cart_item ) ) {
  960.  
  961. $edit_in_cart_link = esc_url( add_query_arg( array( 'update-bundle' => $cart_item_key ), $bundle->get_permalink( $cart_item ) ) );
  962. $edit_in_cart_text = _x( 'Edit', 'edit in cart link text', 'woocommerce-product-bundles' );
  963. $content = sprintf( _x( '%1$s<br/><a class="edit_bundle_in_cart_text edit_in_cart_text" href="%2$s"><small>%3$s</small></a>', 'edit in cart text', 'woocommerce-product-bundles' ), $content, $edit_in_cart_link, $edit_in_cart_text );
  964. }
  965.  
  966. if ( WC_Product_Bundle::group_mode_has( $cart_item[ 'data' ]->get_group_mode(), 'parent_cart_item_meta' ) ) {
  967. $content .= $this->get_bundle_container_cart_item_data( $cart_item, true );
  968. }
  969. }
  970. }
  971.  
  972. return $content;
  973. }
  974.  
  975. /**
  976. * Change the tr class of bundled items in cart templates to allow their styling.
  977. *
  978. * @param string $classname
  979. * @param array $cart_item
  980. * @param string $cart_item_key
  981. * @return string
  982. */
  983. public function cart_item_class( $classname, $cart_item, $cart_item_key ) {
  984.  
  985. if ( $bundle_container_item = wc_pb_get_bundled_cart_item_container( $cart_item ) ) {
  986.  
  987. $bundle = $bundle_container_item[ 'data' ];
  988.  
  989. if ( WC_Product_Bundle::group_mode_has( $bundle->get_group_mode(), 'child_item_indent' ) ) {
  990.  
  991. if ( WC_Product_Bundle::group_mode_has( $bundle->get_group_mode(), 'faked_parent_item' ) ) {
  992.  
  993. // Ensure this isn't the first child (shamelessly assuming that the first one is visible).
  994. $bundled_cart_item_keys = wc_pb_get_bundled_cart_items( $bundle_container_item, false, true );
  995.  
  996. if ( empty( $bundled_cart_item_keys ) || current( $bundled_cart_item_keys ) !== $cart_item_key ) {
  997. $classname .= ' bundled_table_item';
  998. }
  999.  
  1000. } else {
  1001. $classname .= ' bundled_table_item';
  1002. }
  1003. }
  1004.  
  1005. } elseif ( wc_pb_is_bundle_container_cart_item( $cart_item ) ) {
  1006. $classname .= ' bundle_table_item';
  1007. }
  1008.  
  1009. return $classname;
  1010. }
  1011.  
  1012. /**
  1013. * Filters the reported number of cart items.
  1014. *
  1015. * @param int $count
  1016. * @return int
  1017. */
  1018. public function cart_contents_count( $count ) {
  1019.  
  1020. $cart = WC()->cart->get_cart();
  1021. $subtract = 0;
  1022.  
  1023. foreach ( $cart as $cart_item_key => $cart_item ) {
  1024. if ( wc_pb_is_bundle_container_cart_item( $cart_item ) ) {
  1025.  
  1026. $parent_item_visible = $this->cart_item_visible( true, $cart_item, $cart_item_key );
  1027.  
  1028. if ( ! $parent_item_visible ) {
  1029. $subtract += $cart_item[ 'quantity' ];
  1030. }
  1031.  
  1032. $bundled_cart_items = wc_pb_get_bundled_cart_items( $cart_item );
  1033.  
  1034. foreach ( $bundled_cart_items as $bundled_item_key => $bundled_cart_item ) {
  1035.  
  1036. $subtract_bundled_item_qty = $parent_item_visible || false === $this->cart_item_visible( true, $bundled_cart_item, $bundled_item_key );
  1037.  
  1038. if ( $subtract_bundled_item_qty ) {
  1039. $subtract += $bundled_cart_item[ 'quantity' ];
  1040. }
  1041. }
  1042. }
  1043. }
  1044.  
  1045. return $count - $subtract;
  1046. }
  1047.  
  1048. /**
  1049. * Add "Part of" and "Purchased with" cart item data to bundled items.
  1050. *
  1051. * @param array $data
  1052. * @param array $cart_item
  1053. * @return array
  1054. */
  1055. public function cart_item_data( $data, $cart_item ) {
  1056.  
  1057. if ( $container = wc_pb_get_bundled_cart_item_container( $cart_item ) ) {
  1058.  
  1059. $bundle = $container[ 'data' ];
  1060.  
  1061. if ( WC_Product_Bundle::group_mode_has( $bundle->get_group_mode(), 'child_item_meta' ) ) {
  1062. $data[] = array(
  1063. 'key' => __( 'Part of', 'woocommerce-product-bundles' ),
  1064. 'value' => $bundle->get_title()
  1065. );
  1066. }
  1067. }
  1068.  
  1069. return $data;
  1070. }
  1071.  
  1072. /**
  1073. * Hide thumbnail in cart when 'Hide thumbnail' option is selected.
  1074. *
  1075. * @param string $image
  1076. * @param array $cart_item
  1077. * @param string $cart_item_key
  1078. * @return string
  1079. */
  1080.  
  1081. public function cart_item_thumbnail( $image, $cart_item, $cart_item_key ) {
  1082.  
  1083. if ( $bundle_container_item = wc_pb_get_bundled_cart_item_container( $cart_item ) ) {
  1084.  
  1085. $bundled_item_id = $cart_item[ 'bundled_item_id' ];
  1086.  
  1087. if ( $bundled_item = $bundle_container_item[ 'data' ]->get_bundled_item( $bundled_item_id) ) {
  1088.  
  1089. if ( false === $bundled_item->is_thumbnail_visible() ) {
  1090.  
  1091. $is_faked_parent_item = false;
  1092.  
  1093. if ( WC_Product_Bundle::group_mode_has( $bundle_container_item[ 'data' ]->get_group_mode(), 'faked_parent_item' ) ) {
  1094.  
  1095. $bundled_cart_item_keys = wc_pb_get_bundled_cart_items( $bundle_container_item, false, true );
  1096.  
  1097. if ( ! empty( $bundled_cart_item_keys ) && current( $bundled_cart_item_keys ) === $cart_item_key ) {
  1098. $is_faked_parent_item = true;
  1099. }
  1100. }
  1101.  
  1102. if ( ! $is_faked_parent_item ) {
  1103. $image = '';
  1104. }
  1105. }
  1106. }
  1107. }
  1108.  
  1109. return $image;
  1110. }
  1111.  
  1112. /**
  1113. * Rendering cart widget?
  1114. *
  1115. * @since 5.8.0
  1116. * @return boolean
  1117. */
  1118. protected function is_cart_widget() {
  1119. return did_action( 'woocommerce_before_mini_cart' ) > did_action( 'woocommerce_after_mini_cart' );
  1120. }
  1121.  
  1122. /**
  1123. * Add cart widget filters.
  1124. *
  1125. * @return void
  1126. */
  1127. public function add_cart_widget_filters() {
  1128. add_filter( 'woocommerce_mini_cart_item_class', array( $this, 'mini_cart_item_class' ), 10, 2 );
  1129. add_filter( 'woocommerce_widget_cart_item_visible', array( $this, 'cart_widget_item_visible' ), 10, 3 );
  1130. add_filter( 'woocommerce_widget_cart_item_quantity', array( $this, 'cart_widget_item_qty' ), 10, 3 );
  1131. add_filter( 'woocommerce_cart_item_name', array( $this, 'cart_widget_container_item_name' ), 10, 3 );
  1132. add_filter( 'woocommerce_get_item_data', array( $this, 'cart_widget_container_item_data' ), 10, 2 );
  1133. }
  1134.  
  1135. /**
  1136. * Remove cart widget filters.
  1137. *
  1138. * @return void
  1139. */
  1140. public function remove_cart_widget_filters() {
  1141. remove_filter( 'woocommerce_mini_cart_item_class', array( $this, 'mini_cart_item_class' ), 10, 2 );
  1142. remove_filter( 'woocommerce_widget_cart_item_visible', array( $this, 'cart_widget_item_visible' ), 10, 3 );
  1143. remove_filter( 'woocommerce_widget_cart_item_quantity', array( $this, 'cart_widget_item_qty' ), 10, 3 );
  1144. remove_filter( 'woocommerce_cart_item_name', array( $this, 'cart_widget_container_item_name' ), 10, 3 );
  1145. remove_filter( 'woocommerce_get_item_data', array( $this, 'cart_widget_container_item_data' ), 10, 2 );
  1146. }
  1147.  
  1148. /**
  1149. * Change the li class of composite parent/child items in mini-cart templates to allow their styling.
  1150. *
  1151. * @since 5.8.0
  1152. *
  1153. * @param string $classname
  1154. * @param array $cart_item
  1155. * @return string
  1156. */
  1157. public function mini_cart_item_class( $classname, $cart_item ) {
  1158.  
  1159. if ( wc_pb_is_bundled_cart_item( $cart_item ) ) {
  1160. $classname .= ' bundled_mini_cart_item';
  1161. } elseif ( wc_pb_is_bundle_container_cart_item( $cart_item ) ) {
  1162. $classname .= ' bundle_container_mini_cart_item';
  1163. }
  1164.  
  1165. return $classname;
  1166. }
  1167.  
  1168.  
  1169. /**
  1170. * Only show bundled items in the mini cart if their parent line item is hidden.
  1171. *
  1172. * @param boolean $show
  1173. * @param array $cart_item
  1174. * @param string $cart_item_key
  1175. * @return boolean
  1176. */
  1177. public function cart_widget_item_visible( $show, $cart_item, $cart_item_key ) {
  1178.  
  1179. if ( $container = wc_pb_get_bundled_cart_item_container( $cart_item ) ) {
  1180.  
  1181. $bundle = $container[ 'data' ];
  1182.  
  1183. if ( WC_Product_Bundle::group_mode_has( $bundle->get_group_mode(), 'parent_item' ) && WC_Product_Bundle::group_mode_has( $bundle->get_group_mode(), 'parent_cart_widget_item_meta' ) ) {
  1184. $show = false;
  1185. } elseif ( WC_Product_Bundle::group_mode_has( $bundle->get_group_mode(), 'component_multiselect' ) ) {
  1186. $show = false;
  1187. }
  1188. }
  1189.  
  1190. return $show;
  1191. }
  1192.  
  1193. /**
  1194. * Tweak bundle container qty.
  1195. *
  1196. * @param bool $qty
  1197. * @param array $cart_item
  1198. * @param string $cart_item_key
  1199. * @return bool
  1200. */
  1201. public function cart_widget_item_qty( $qty, $cart_item, $cart_item_key ) {
  1202.  
  1203. if ( wc_pb_is_bundle_container_cart_item( $cart_item ) ) {
  1204.  
  1205. if ( WC_Product_Bundle::group_mode_has( $cart_item[ 'data' ]->get_group_mode(), 'aggregated_subtotals' ) ) {
  1206.  
  1207. if ( WC_PB()->cart->container_cart_item_contains( $cart_item, 'sold_individually' ) ) {
  1208. $qty = apply_filters( 'woocommerce_cart_item_subtotal', WC()->cart->get_product_subtotal( $cart_item[ 'data' ], $cart_item[ 'quantity' ] ), $cart_item, $cart_item_key );
  1209. }
  1210.  
  1211. } elseif ( empty( $cart_item[ 'line_subtotal' ] ) && $cart_item[ 'data' ]->contains( 'priced_individually' ) ) {
  1212.  
  1213. $bundled_item_keys = wc_pb_get_bundled_cart_items( $cart_item, WC()->cart->cart_contents, true );
  1214.  
  1215. if ( ! empty( $bundled_item_keys ) ) {
  1216. $qty = '';
  1217. }
  1218. }
  1219.  
  1220. } elseif ( $bundle_container_item = wc_pb_get_bundled_cart_item_container( $cart_item ) ) {
  1221.  
  1222. if ( ! empty( $cart_item[ 'line_subtotal' ] ) ) {
  1223. return $qty;
  1224. }
  1225.  
  1226. $bundled_item_id = $cart_item[ 'bundled_item_id' ];
  1227. $bundled_item = $bundle_container_item[ 'data' ]->get_bundled_item( $cart_item[ 'bundled_item_id' ] );
  1228.  
  1229. if ( ! $bundled_item ) {
  1230. return $qty;
  1231. }
  1232.  
  1233. if ( ! $bundled_item->is_priced_individually() && ! WC_Product_Bundle::group_mode_has( $bundle_container_item[ 'data' ]->get_group_mode(), 'parent_cart_widget_item_meta' ) ) {
  1234. $qty = '';
  1235. }
  1236. }
  1237.  
  1238. return $qty;
  1239. }
  1240.  
  1241. /**
  1242. * Tweak bundle container name.
  1243. *
  1244. * @param bool $show
  1245. * @param array $cart_item
  1246. * @param string $cart_item_key
  1247. * @return bool
  1248. */
  1249. public function cart_widget_container_item_name( $name, $cart_item, $cart_item_key ) {
  1250.  
  1251. if ( wc_pb_is_bundle_container_cart_item( $cart_item ) ) {
  1252.  
  1253. if ( WC_Product_Bundle::group_mode_has( $cart_item[ 'data' ]->get_group_mode(), 'aggregated_subtotals' ) ) {
  1254.  
  1255. if ( WC_PB()->cart->container_cart_item_contains( $cart_item, 'sold_individually' ) && ! WC_PB()->compatibility->is_composited_cart_item( $cart_item ) ) {
  1256. $name = WC_PB_Helpers::format_product_shop_title( $name, $cart_item[ 'quantity' ] );
  1257. }
  1258.  
  1259. } elseif ( empty( $cart_item[ 'line_subtotal' ] ) && $cart_item[ 'data' ]->contains( 'priced_individually' ) ) {
  1260.  
  1261. $bundled_item_keys = wc_pb_get_bundled_cart_items( $cart_item, WC()->cart->cart_contents, true );
  1262.  
  1263. if ( ! empty( $bundled_item_keys ) ) {
  1264. $name = WC_PB_Helpers::format_product_shop_title( $name, $cart_item[ 'quantity' ] );
  1265. }
  1266. }
  1267.  
  1268. } elseif ( $bundle_container_item = wc_pb_get_bundled_cart_item_container( $cart_item ) ) {
  1269.  
  1270. if ( ! empty( $cart_item[ 'line_subtotal' ] ) ) {
  1271. return $name;
  1272. }
  1273.  
  1274. $bundled_item_id = $cart_item[ 'bundled_item_id' ];
  1275. $bundled_item = $bundle_container_item[ 'data' ]->get_bundled_item( $cart_item[ 'bundled_item_id' ] );
  1276.  
  1277. if ( ! $bundled_item ) {
  1278. return $name;
  1279. }
  1280.  
  1281. if ( ! $bundled_item->is_priced_individually() && ! WC_Product_Bundle::group_mode_has( $bundle_container_item[ 'data' ]->get_group_mode(), 'parent_cart_widget_item_meta' ) ) {
  1282. $name = WC_PB_Helpers::format_product_shop_title( $name, $cart_item[ 'quantity' ] );
  1283. }
  1284. }
  1285.  
  1286. return $name;
  1287. }
  1288.  
  1289. /**
  1290. * Gets bundled content data.
  1291. *
  1292. * @since 5.8.0
  1293. *
  1294. * @param array $cart_item
  1295. * @return array
  1296. */
  1297. public function get_bundle_container_cart_item_data( $cart_item, $formatted = false ) {
  1298.  
  1299. $data = array();
  1300.  
  1301. $bundled_cart_items = wc_pb_get_bundled_cart_items( $cart_item );
  1302.  
  1303. if ( ! empty( $bundled_cart_items ) ) {
  1304.  
  1305. $bundled_item_descriptions = array();
  1306.  
  1307. foreach ( $bundled_cart_items as $bundled_cart_item_key => $bundled_cart_item ) {
  1308.  
  1309. $bundled_item_id = $bundled_cart_item[ 'bundled_item_id' ];
  1310. $bundled_item_description = '';
  1311.  
  1312. if ( $bundled_item = $cart_item[ 'data' ]->get_bundled_item( $bundled_item_id ) ) {
  1313.  
  1314. if ( $bundled_item->is_visible( 'cart' ) ) {
  1315. $bundled_item_description = WC_PB_Helpers::format_product_shop_title( $bundled_cart_item[ 'data' ]->get_name(), $bundled_cart_item[ 'quantity' ] );
  1316. }
  1317.  
  1318. /**
  1319. * 'woocommerce_bundle_container_cart_item_data_value' filter.
  1320. *
  1321. * @since 5.8.0
  1322. *
  1323. * @param string $bundled_item_description
  1324. * @param array $bundled_cart_item
  1325. * @param string $bundled_cart_item_key
  1326. */
  1327. $bundled_item_description = apply_filters( 'woocommerce_bundle_container_cart_item_data_value', $bundled_item_description, $bundled_cart_item, $bundled_cart_item_key );
  1328. }
  1329.  
  1330. if ( $bundled_item_description ) {
  1331. $bundled_item_descriptions[] = $bundled_item_description;
  1332. }
  1333. }
  1334.  
  1335. if ( ! empty( $bundled_item_descriptions ) ) {
  1336.  
  1337. $data[] = array(
  1338. 'key' => __( 'Includes', 'woocommerce-product-bundles' ),
  1339. 'value' => implode( '<br/>', $bundled_item_descriptions )
  1340. );
  1341. }
  1342. }
  1343.  
  1344. if ( $formatted ) {
  1345.  
  1346. $formatted_data = '';
  1347.  
  1348. if ( ! empty( $data ) ) {
  1349.  
  1350. ob_start();
  1351.  
  1352. wc_get_template( 'cart/bundle-container-item-data.php', array(
  1353. 'data' => $data
  1354. ), false, WC_PB()->plugin_path() . '/templates/' );
  1355.  
  1356. $formatted_data = ob_get_clean();
  1357. }
  1358.  
  1359. $data = $formatted_data;
  1360. }
  1361.  
  1362. return $data;
  1363. }
  1364.  
  1365. /**
  1366. * Adds content data as parent item meta (by default in the mini-cart only).
  1367. *
  1368. * @param array $data
  1369. * @param array $cart_item
  1370. * @return array
  1371. */
  1372. public function cart_widget_container_item_data( $data, $cart_item ) {
  1373.  
  1374. if ( wc_pb_is_bundle_container_cart_item( $cart_item ) ) {
  1375. if ( WC_Product_Bundle::group_mode_has( $cart_item[ 'data' ]->get_group_mode(), 'parent_cart_widget_item_meta' ) ) {
  1376. $data = array_merge( $data, $this->get_bundle_container_cart_item_data( $cart_item ) );
  1377. }
  1378. }
  1379.  
  1380. return $data;
  1381. }
  1382.  
  1383. /*
  1384. |--------------------------------------------------------------------------
  1385. | Orders.
  1386. |--------------------------------------------------------------------------
  1387. */
  1388.  
  1389. /**
  1390. * Modify the subtotal of order items depending on their pricing setup.
  1391. *
  1392. * @param string $subtotal
  1393. * @param WC_Order_Item $item
  1394. * @param WC_Order $order
  1395. * @return string
  1396. */
  1397. public function order_item_subtotal( $subtotal, $item, $order ) {
  1398.  
  1399. // If it's a bundled item...
  1400. if ( $bundle_container_item = wc_pb_get_bundled_order_item_container( $item, $order ) ) {
  1401.  
  1402. $bundled_item_priced_individually = $item->get_meta( '_bundled_item_priced_individually', true );
  1403. $bundled_item_price_hidden = $item->get_meta( '_bundled_item_price_hidden', true );
  1404.  
  1405. // Back-compat.
  1406. if ( ! in_array( $bundled_item_priced_individually, array( 'yes', 'no' ) ) ) {
  1407. $bundled_item_priced_individually = isset( $bundle_container_item[ 'per_product_pricing' ] ) ? $bundle_container_item[ 'per_product_pricing' ] : get_post_meta( $bundle_container_item[ 'product_id' ], '_wc_pb_v4_per_product_pricing', true );
  1408. }
  1409.  
  1410. $is_pip = WC_PB()->compatibility->is_pip( 'invoice' );
  1411.  
  1412. if ( 'no' === $bundled_item_priced_individually && $item->get_subtotal( 'edit' ) == 0 ) {
  1413.  
  1414. $subtotal = '';
  1415.  
  1416. } elseif ( ! $is_pip && 'yes' === $bundled_item_price_hidden ) {
  1417.  
  1418. $subtotal = '';
  1419.  
  1420. } elseif ( ! $is_pip ) {
  1421.  
  1422. $group_mode = $bundle_container_item->get_meta( '_bundle_group_mode', true );
  1423. $group_mode = $group_mode ? $group_mode : 'parent';
  1424.  
  1425. if ( WC_Product_Bundle::group_mode_has( $group_mode, 'aggregated_subtotals' ) ) {
  1426.  
  1427. if ( WC_PB()->compatibility->is_composited_order_item( $bundle_container_item, $order ) ) {
  1428. $subtotal = '';
  1429. } elseif ( $subtotal ) {
  1430. $subtotal = '<span class="bundled_table_item_subtotal">' . sprintf( _x( '%1$s: %2$s', 'bundled product subtotal', 'woocommerce-product-bundles' ), __( 'Subtotal', 'woocommerce-product-bundles' ), $subtotal ) . '</span>';
  1431. }
  1432.  
  1433. } elseif ( $subtotal && function_exists( 'wc_cp_get_composited_order_item_container' ) && ( $composite_container_item = wc_cp_get_composited_order_item_container( $bundle_container_item, $order ) ) ) {
  1434.  
  1435. if ( apply_filters( 'woocommerce_add_composited_order_item_subtotals', true, $composite_container_item, $order ) ) {
  1436.  
  1437. $show_subtotal = true;
  1438.  
  1439. if ( $item->get_subtotal( 'edit' ) == 0 && 'yes' === $bundled_item_priced_individually ) {
  1440. if ( $component_priced_individually = $bundle_container_item->get_meta( '_component_priced_individually', true ) ) {
  1441. $show_subtotal = 'yes' === $component_priced_individually;
  1442. }
  1443. }
  1444.  
  1445. if ( $show_subtotal ) {
  1446. $subtotal = '<span class="bundled_table_item_subtotal">' . sprintf( _x( '%1$s: %2$s', 'bundled product subtotal', 'woocommerce-product-bundles' ), __( 'Subtotal', 'woocommerce-product-bundles' ), $subtotal ) . '</span>';
  1447. } else {
  1448. $subtotal = '';
  1449. }
  1450. }
  1451. }
  1452. }
  1453.  
  1454. // If it's a bundle (parent item)...
  1455. } elseif ( wc_pb_is_bundle_container_order_item( $item ) ) {
  1456.  
  1457. if ( ! isset( $item->child_subtotals_added ) ) {
  1458.  
  1459. $group_mode = $item->get_meta( '_bundle_group_mode', true );
  1460. $group_mode = $group_mode ? $group_mode : 'parent';
  1461.  
  1462. $children = wc_pb_get_bundled_order_items( $item, $order );
  1463. $aggregate_subtotals = WC_Product_Bundle::group_mode_has( $group_mode, 'aggregated_subtotals' ) && false === WC_PB()->compatibility->is_pip( 'invoice' );
  1464.  
  1465. // Aggregate subtotals if required the bundle's group mode. Important: Don't aggregate when rendering PIP invoices!
  1466. if ( $aggregate_subtotals ) {
  1467.  
  1468. if ( ! empty( $children ) ) {
  1469.  
  1470. // Create a clone to ensure the original item will not be modified.
  1471. $cloned_item = clone $item;
  1472.  
  1473. foreach ( $children as $child ) {
  1474. $cloned_item->set_subtotal( $cloned_item->get_subtotal( 'edit' ) + round( $child->get_subtotal( 'edit' ), wc_get_price_decimals() ) );
  1475. $cloned_item->set_subtotal_tax( $cloned_item->get_subtotal_tax( 'edit' ) + round( $child->get_subtotal_tax( 'edit' ), wc_get_price_decimals() ) );
  1476. }
  1477.  
  1478. $cloned_item->child_subtotals_added = 'yes';
  1479.  
  1480. $subtotal = $order->get_formatted_line_subtotal( $cloned_item );
  1481. }
  1482.  
  1483. } elseif ( sizeof( $children ) && $item->get_subtotal( 'edit' ) == 0 ) {
  1484. $subtotal = '';
  1485. }
  1486. }
  1487. }
  1488.  
  1489. return $subtotal;
  1490. }
  1491.  
  1492. /**
  1493. * Visibility of bundled item in orders.
  1494. *
  1495. * @param boolean $visible
  1496. * @param array order_item
  1497. * @return boolean
  1498. */
  1499. public function order_item_visible( $visible, $order_item ) {
  1500.  
  1501. if ( wc_pb_maybe_is_bundled_order_item( $order_item ) ) {
  1502.  
  1503. $bundled_item_hidden = $order_item->get_meta( '_bundled_item_hidden' );
  1504.  
  1505. if ( ! empty( $bundled_item_hidden ) ) {
  1506. $visible = false;
  1507. }
  1508.  
  1509. } elseif ( wc_pb_is_bundle_container_order_item( $order_item ) ) {
  1510.  
  1511. $group_mode = $order_item->get_meta( '_bundle_group_mode', true );
  1512. $group_mode = $group_mode ? $group_mode : 'parent';
  1513.  
  1514. if ( false === WC_Product_Bundle::group_mode_has( $group_mode, 'parent_item' ) ) {
  1515. $visible = false;
  1516. }
  1517. }
  1518.  
  1519. return $visible;
  1520. }
  1521.  
  1522. /**
  1523. * Override bundled item title in order-details template.
  1524. *
  1525. * @param string $content
  1526. * @param array $order_item
  1527. * @return string
  1528. */
  1529. public function order_item_title( $content, $order_item ) {
  1530.  
  1531. if ( false !== $this->order_item_order && wc_pb_is_bundled_order_item( $order_item, $this->order_item_order ) ) {
  1532.  
  1533. $this->order_item_order = false;
  1534.  
  1535. $group_mode = $order_item->get_meta( '_bundle_group_mode', true );
  1536. $group_mode = $group_mode ? $group_mode : 'parent';
  1537.  
  1538. if ( WC_Product_Bundle::group_mode_has( $group_mode, 'child_item_indent' ) ) {
  1539. if ( did_action( 'woocommerce_view_order' ) || did_action( 'woocommerce_thankyou' ) || did_action( 'before_woocommerce_pay' ) || did_action( 'woocommerce_account_view-subscription_endpoint' ) ) {
  1540. $this->enqueue_bundled_table_item_js();
  1541. }
  1542. }
  1543. }
  1544.  
  1545. return $content;
  1546. }
  1547.  
  1548. /**
  1549. * Add class to bundled items in order templates.
  1550. *
  1551. * @param string $classname
  1552. * @param array $order_item
  1553. * @return string
  1554. */
  1555. public function order_item_class( $classname, $order_item, $order ) {
  1556.  
  1557. if ( $bundle_container_order_item = wc_pb_get_bundled_order_item_container( $order_item, $order ) ) {
  1558.  
  1559. $group_mode = $bundle_container_order_item->get_meta( '_bundle_group_mode', true );
  1560. $group_mode = $group_mode ? $group_mode : 'parent';
  1561.  
  1562. if ( WC_Product_Bundle::group_mode_has( $group_mode, 'child_item_indent' ) ) {
  1563.  
  1564. if ( WC_Product_Bundle::group_mode_has( $group_mode, 'faked_parent_item' ) ) {
  1565.  
  1566. // Ensure this isn't the first child.
  1567. $bundled_order_item_ids = wc_pb_get_bundled_order_items( $bundle_container_order_item, $order, true );
  1568.  
  1569. if ( empty( $bundled_order_item_ids ) || current( $bundled_order_item_ids ) !== $order_item->get_id() ) {
  1570. $classname .= ' bundled_table_item';
  1571. }
  1572.  
  1573. } else {
  1574. $classname .= ' bundled_table_item';
  1575. }
  1576. }
  1577.  
  1578. $this->order_item_order = $order;
  1579.  
  1580. } elseif ( wc_pb_is_bundle_container_order_item( $order_item ) ) {
  1581. $classname .= ' bundle_table_item';
  1582. }
  1583.  
  1584. return $classname;
  1585. }
  1586.  
  1587. /**
  1588. * Filters the reported number of order items.
  1589. *
  1590. * @param int $count
  1591. * @param string $type
  1592. * @param WC_Order $order
  1593. * @return int
  1594. */
  1595. public function order_item_count( $count, $type, $order ) {
  1596.  
  1597. $subtract = 0;
  1598.  
  1599. if ( function_exists( 'is_account_page' ) && is_account_page() ) {
  1600.  
  1601. foreach ( $order->get_items() as $item ) {
  1602. if ( wc_pb_is_bundle_container_order_item( $item, $order ) ) {
  1603.  
  1604. $parent_item_visible = $this->order_item_visible( true, $item );
  1605.  
  1606. if ( ! $parent_item_visible ) {
  1607. $subtract += $item->get_quantity();
  1608. }
  1609.  
  1610.  
  1611. $bundled_order_items = wc_pb_get_bundled_order_items( $item, $order );
  1612.  
  1613. foreach ( $bundled_order_items as $bundled_item_key => $bundled_order_item ) {
  1614. if ( ! $parent_item_visible ) {
  1615. if ( ! $this->order_item_visible( true, $bundled_order_item ) ) {
  1616. $subtract += $bundled_order_item->get_quantity();
  1617. }
  1618. } else {
  1619. $subtract += $bundled_order_item->get_quantity();
  1620. }
  1621. }
  1622. }
  1623. }
  1624. }
  1625.  
  1626. return $count - $subtract;
  1627. }
  1628.  
  1629. /**
  1630. * Indent bundled items in emails.
  1631. *
  1632. * @param string $css
  1633. * @return string
  1634. */
  1635. public function email_styles( $css ) {
  1636. $css .= ' .bundled_table_item td:first-of-type { padding-left: 2.5em !important; } .bundled_table_item td { border-top: none; font-size: 0.875em; } #body_content table tr.bundled_table_item td ul.wc-item-meta { font-size: inherit; } ';
  1637. return $css;
  1638. }
  1639.  
  1640. /*
  1641. |--------------------------------------------------------------------------
  1642. | Archives.
  1643. |--------------------------------------------------------------------------
  1644. */
  1645.  
  1646. /**
  1647. * Used to fix QuickView support when:
  1648. * - ajax add-to-cart is active and
  1649. * - QuickView operates without a separate button.
  1650. * Since WC 2.5+ this is (almost) a relic.
  1651. *
  1652. * @param string $link
  1653. * @param WC_Product $product
  1654. * @return string
  1655. */
  1656. public function loop_add_to_cart_link( $link, $product ) {
  1657.  
  1658. if ( $product->is_type( 'bundle' ) ) {
  1659.  
  1660. if ( ! $product->is_in_stock() || $product->has_options() ) {
  1661. $link = str_replace( array( 'product_type_bundle', 'ajax_add_to_cart' ), array( 'product_type_bundle product_type_bundle_input_required', '' ), $link );
  1662. }
  1663. }
  1664.  
  1665. return $link;
  1666. }
  1667.  
  1668. /*
  1669. |--------------------------------------------------------------------------
  1670. | Other.
  1671. |--------------------------------------------------------------------------
  1672. */
  1673.  
  1674. /**
  1675. * Enhance price filter widget meta query to include results based on max '_wc_sw_max_price' meta.
  1676. *
  1677. * @param array $meta_query
  1678. * @param WC_Query $wc_query
  1679. * @return array
  1680. */
  1681. public function price_filter_query_params( $meta_query, $wc_query ) {
  1682.  
  1683. if ( isset( $meta_query[ 'price_filter' ] ) && isset( $meta_query[ 'price_filter' ][ 'price_filter' ] ) && ! isset( $meta_query[ 'price_filter' ][ 'sw_price_filter' ] ) ) {
  1684.  
  1685. $min = isset( $_GET[ 'min_price' ] ) ? floatval( $_GET[ 'min_price' ] ) : 0;
  1686. $max = isset( $_GET[ 'max_price' ] ) ? floatval( $_GET[ 'max_price' ] ) : 9999999999;
  1687.  
  1688. $price_meta_query = $meta_query[ 'price_filter' ];
  1689. $price_meta_query = array(
  1690. 'sw_price_filter' => true,
  1691. 'price_filter' => true,
  1692. 'relation' => 'OR',
  1693. $price_meta_query,
  1694. array(
  1695. 'relation' => 'AND',
  1696. array(
  1697. 'key' => '_price',
  1698. 'compare' => '<=',
  1699. 'type' => 'DECIMAL',
  1700. 'value' => $max
  1701. ),
  1702. array(
  1703. 'key' => '_wc_sw_max_price',
  1704. 'compare' => '>=',
  1705. 'type' => 'DECIMAL',
  1706. 'value' => $min
  1707. )
  1708. )
  1709. );
  1710.  
  1711. $meta_query[ 'price_filter' ] = $price_meta_query;
  1712. }
  1713.  
  1714. return $meta_query;
  1715. }
  1716.  
  1717. /*
  1718. |--------------------------------------------------------------------------
  1719. | Deprecated.
  1720. |--------------------------------------------------------------------------
  1721. */
  1722.  
  1723. public function order_table_item_title( $content, $order_item ) {
  1724. _deprecated_function( __METHOD__ . '()', '5.5.0', __CLASS__ . '::order_item_title()' );
  1725. return $this->order_item_title( $content, $order_item );
  1726. }
  1727. public function woo_bundles_loop_add_to_cart_link( $link, $product ) {
  1728. _deprecated_function( __METHOD__ . '()', '5.0.0', __CLASS__ . '::loop_add_to_cart_link()' );
  1729. return $this->loop_add_to_cart_link( $link, $product );
  1730. }
  1731. public function woo_bundles_in_cart_item_title( $content, $cart_item_values, $cart_item_key ) {
  1732. _deprecated_function( __METHOD__ . '()', '5.0.0', __CLASS__ . '::cart_item_title()' );
  1733. return $this->cart_item_title( $content, $cart_item_values, $cart_item_key );
  1734. }
  1735. public function woo_bundles_order_table_item_title( $content, $order_item ) {
  1736. _deprecated_function( __METHOD__ . '()', '5.0.0', __CLASS__ . '::order_item_title()' );
  1737. return $this->order_item_title( $content, $order_item );
  1738. }
  1739. public function woo_bundles_table_item_class( $classname, $values ) {
  1740. _deprecated_function( __METHOD__ . '()', '5.0.0', __CLASS__ . '::table_item_class()' );
  1741. return false !== strpos( $classname, 'cart_item' ) ? $this->cart_item_class( $classname, $values, false ) : $this->order_item_class( $classname, $values, false );
  1742. }
  1743. public function woo_bundles_frontend_scripts() {
  1744. _deprecated_function( __METHOD__ . '()', '5.0.0', __CLASS__ . '::frontend_scripts()' );
  1745. return $this->frontend_scripts();
  1746. }
  1747. public function woo_bundles_cart_contents_count( $count ) {
  1748. _deprecated_function( __METHOD__ . '()', '5.0.0', __CLASS__ . '::cart_contents_count()' );
  1749. return $this->cart_contents_count( $count );
  1750. }
  1751. public function woo_bundles_add_cart_widget_filters() {
  1752. _deprecated_function( __METHOD__ . '()', '5.0.0', __CLASS__ . '::add_cart_widget_filters()' );
  1753. return $this->add_cart_widget_filters();
  1754. }
  1755. public function woo_bundles_remove_cart_widget_filters() {
  1756. _deprecated_function( __METHOD__ . '()', '5.0.0', __CLASS__ . '::remove_cart_widget_filters()' );
  1757. return $this->remove_cart_widget_filters();
  1758. }
  1759. public function woo_bundles_order_item_visible( $visible, $order_item ) {
  1760. _deprecated_function( __METHOD__ . '()', '5.0.0', __CLASS__ . '::order_item_visible()' );
  1761. return $this->order_item_visible( $visible, $order_item );
  1762. }
  1763. public function woo_bundles_cart_item_visible( $visible, $cart_item, $cart_item_key ) {
  1764. _deprecated_function( __METHOD__ . '()', '5.0.0', __CLASS__ . '::cart_item_visible()' );
  1765. return $this->cart_item_visible( $visible, $cart_item, $cart_item_key );
  1766. }
  1767. public function woo_bundles_email_styles( $css ) {
  1768. _deprecated_function( __METHOD__ . '()', '5.0.0', __CLASS__ . '::email_styles()' );
  1769. return $this->email_styles( $css );
  1770. }
  1771. }
  1772.  
Advertisement
Add Comment
Please, Sign In to add comment