PluginProbe
Tiered Pricing Table for WooCommerce / 6.1.0
Tiered Pricing Table for WooCommerce v6.1.0
8.0.2 7.1.7 7.1.5 7.1.4 7.1.1 6.5.0 6.4.0 6.1.0 trunk 1.0 1.1 2.0 2.0.1 2.0.2 2.1 2.1.1 2.1.2 2.2.0 2.2.1 2.2.2 2.2.3 2.3.0 2.3.1 2.3.2 2.3.3 All 91 releases
tier-pricing-table / src / Services / TieredPricingCartService.php

TieredPricingCartService.php in Tiered Pricing Table for WooCommerce 6.1.0, at src/Services/TieredPricingCartService.php

220 lines 8.7 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace TierPricingTable\Services;
4
5 /*
6 * Class TieredPricingCartService
7 *
8 * Service modifies product's price in the cart based on quantity and tiered pricing rules
9 *
10 * @package TierPricingTable\Services
11 */
12 use TierPricingTable\CalculationLogic;
13 use TierPricingTable\Core\ServiceContainerTrait;
14 use TierPricingTable\PriceManager;
15 use TierPricingTable\Settings\Sections\GeneralSection\Subsections\CartOptionsSubsection;
16 use WC_Product;
17 use WC_Cart;
18 class TieredPricingCartService {
19 use ServiceContainerTrait;
20 protected $originalPrices = [];
21
22 public function __construct() {
23 add_action(
24 'woocommerce_before_calculate_totals',
25 array($this, 'calculateTieredPricingInCart'),
26 99999,
27 3
28 );
29 add_action(
30 'woocommerce_before_mini_cart_contents',
31 array($this, 'triggerMiniCartUpdate'),
32 9999,
33 3
34 );
35 add_filter(
36 'woocommerce_cart_item_price',
37 array($this, 'calculateCartItemPrice'),
38 999,
39 2
40 );
41 add_filter(
42 'woocommerce_cart_item_subtotal',
43 array($this, 'modifyCartItemSubtotal'),
44 999,
45 3
46 );
47 }
48
49 public function modifyCartItemSubtotal( $subtotal, $cartItem, $cartItemKey ) {
50 $newPrice = $this->getCartItemPrice( $cartItem, $cartItemKey );
51 if ( false === $newPrice ) {
52 return $subtotal;
53 }
54 $recalculateCartItemSubtotal = apply_filters(
55 'tiered_pricing_table/cart/recalculate_cart_item_subtotal',
56 true,
57 $cartItem,
58 $cartItemKey,
59 $subtotal
60 );
61 if ( !$recalculateCartItemSubtotal ) {
62 return $subtotal;
63 }
64 $considerSalePriceAsDiscount = $this->getContainer()->getSettings()->get( 'consider_sale_price_as_discount_in_cart', 'no' ) === 'yes';
65 $considerSalePriceAsDiscount = apply_filters(
66 'tiered_pricing_table/cart/subtotal/consider_sale_price_as_discount',
67 $considerSalePriceAsDiscount,
68 $cartItem,
69 $cartItemKey
70 );
71 // Reset product instance because prices is already modified in the "woocommerce_before_calculate_totals" hook.
72 // We will not be able to get the original price
73 $product = wc_get_product( $cartItem['data']->get_id() );
74 if ( $product->is_taxable() ) {
75 if ( wc()->cart->display_prices_including_tax() ) {
76 $originalCartItemPrice = wc_get_price_including_tax( $product, array(
77 'qty' => $cartItem['quantity'],
78 'price' => ( $considerSalePriceAsDiscount ? $product->get_regular_price() : $product->get_price() ),
79 ) );
80 $newCartItemPrice = wc_get_price_including_tax( $product, array(
81 'qty' => $cartItem['quantity'],
82 'price' => $newPrice,
83 ) );
84 $originalProductSubtotal = wc_price( $originalCartItemPrice );
85 $newProductSubtotal = wc_price( $newCartItemPrice );
86 if ( !wc_prices_include_tax() && wc()->cart->get_subtotal_tax() > 0 ) {
87 $newProductSubtotal .= ' <small class="tax_label">' . WC()->countries->inc_tax_or_vat() . '</small>';
88 }
89 } else {
90 $originalCartItemPrice = wc_get_price_excluding_tax( $product, array(
91 'qty' => $cartItem['quantity'],
92 'price' => ( $considerSalePriceAsDiscount ? $product->get_regular_price() : $product->get_price() ),
93 ) );
94 $newCartItemPrice = wc_get_price_excluding_tax( $product, array(
95 'qty' => $cartItem['quantity'],
96 'price' => $newPrice,
97 ) );
98 $originalProductSubtotal = wc_price( $originalCartItemPrice );
99 $newProductSubtotal = wc_price( $newCartItemPrice );
100 if ( wc_prices_include_tax() && wc()->cart->get_subtotal_tax() > 0 ) {
101 $newProductSubtotal .= ' <small class="tax_label">' . WC()->countries->ex_tax_or_vat() . '</small>';
102 }
103 }
104 } else {
105 $_originalItemPrice = ( $considerSalePriceAsDiscount ? $product->get_regular_price() : $product->get_price() );
106 $originalCartItemPrice = (float) $_originalItemPrice * (float) $cartItem['quantity'];
107 $newCartItemPrice = (float) $newPrice * (float) $cartItem['quantity'];
108 $originalProductSubtotal = wc_price( $originalCartItemPrice );
109 $newProductSubtotal = wc_price( $newCartItemPrice );
110 }
111 return $newProductSubtotal;
112 }
113
114 public function getCartItemPrice( $cartItem, $cartItemKey, $cart = null ) {
115 $cart = ( $cart instanceof WC_Cart ? $cart : wc()->cart );
116 if ( !$cart instanceof WC_Cart ) {
117 return false;
118 }
119 $calculateTieredPriceForItem = apply_filters(
120 'tiered_pricing_table/cart/need_price_recalculation',
121 true,
122 $cartItem,
123 $cart
124 );
125 if ( !$calculateTieredPriceForItem ) {
126 return false;
127 }
128 if ( empty( $cartItem['data'] ) || !$cartItem['data'] instanceof WC_Product ) {
129 return false;
130 }
131 $pricingRule = PriceManager::getPricingRule( $cartItem['data']->get_id() );
132 $totalQuantity = $this->getTotalProductCount( $cartItem );
133 $newPrice = $pricingRule->getTierPrice( $totalQuantity, false, 'cart' );
134 return apply_filters(
135 'tiered_pricing_table/cart/product_cart_price',
136 $newPrice,
137 $cartItem,
138 $cartItemKey,
139 $totalQuantity
140 );
141 }
142
143 /**
144 * Calculate price by quantity rules
145 *
146 * @param WC_Cart $cart
147 */
148 public function calculateTieredPricingInCart( WC_Cart $cart ) {
149 if ( !empty( $cart->get_cart_contents() ) ) {
150 foreach ( $cart->get_cart_contents() as $key => $cartItem ) {
151 $newPrice = $this->getCartItemPrice( $cartItem, $key, $cart );
152 if ( false !== $newPrice ) {
153 if ( !isset( $this->originalPrices[$key] ) ) {
154 $this->originalPrices[$key] = $cartItem['data']->get_price();
155 }
156 $cartItem['data']->set_price( $newPrice );
157 $cartItem['data']->add_meta_data( 'tiered_pricing_cart_price_calculated', 'yes' );
158 } else {
159 if ( isset( $this->originalPrices[$key] ) ) {
160 $cartItem['data']->set_price( $this->originalPrices[$key] );
161 }
162 }
163 // Update tiered pricing data
164 $cart->cart_contents[$key]['tiered_pricing_data'] = array(
165 'total_item_quantity' => $this->getTotalProductCount( $cartItem ),
166 );
167 }
168 }
169 }
170
171 /**
172 * Calculate price in mini cart
173 *
174 * @param string $price
175 * @param array $cartItem
176 *
177 * @return string
178 */
179 public function calculateCartItemPrice( $price, $cartItem ) {
180 $calculateTieredPriceForItem = apply_filters( 'tiered_pricing_table/cart/need_price_recalculation/item', true, $cartItem );
181 if ( $cartItem['data'] instanceof WC_Product && $calculateTieredPriceForItem ) {
182 $product = wc_get_product( $cartItem['data']->get_id() );
183 $pricingRule = PriceManager::getPricingRule( $cartItem['data']->get_id() );
184 $newPrice = $pricingRule->getTierPrice( $this->getTotalProductCount( $cartItem ), true, 'cart' );
185 $newPrice = apply_filters( 'tiered_pricing_table/cart/product_cart_price/item', $newPrice, $cartItem );
186 if ( false !== $newPrice ) {
187 return wc_price( $newPrice );
188 }
189 }
190 return $price;
191 }
192
193 public function triggerMiniCartUpdate() {
194 $cart = wc()->cart;
195 $cart->calculate_totals();
196 }
197
198 /**
199 * Get total product count depends on user's settings
200 *
201 * @param ?array $cartItem
202 *
203 * @return int
204 */
205 public function getTotalProductCount( ?array $cartItem ) : int {
206 if ( CalculationLogic::considerProductVariationAsOneProduct() ) {
207 $count = 0;
208 foreach ( wc()->cart->cart_contents as $cart_content ) {
209 if ( $cart_content['product_id'] == $cartItem['product_id'] ) {
210 $count += $cart_content['quantity'];
211 }
212 }
213 } else {
214 $count = $cartItem['quantity'];
215 }
216 return (int) apply_filters( 'tiered_pricing_table/cart/total_product_count', $count, $cartItem );
217 }
218
219 }
220