PluginProbe
Tiered Pricing Table for WooCommerce / 6.5.0
Tiered Pricing Table for WooCommerce v6.5.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 / PriceManager.php

PriceManager.php in Tiered Pricing Table for WooCommerce 6.5.0, at src/PriceManager.php

279 lines 10.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace TierPricingTable;
4
5 use WC_Product;
6 class PriceManager {
7 protected static $pricingRules = array();
8
9 public static function getFixedPriceRules( $productId, string $context = 'view' ) : array {
10 return self::getPriceRules( $productId, 'fixed', $context );
11 }
12
13 public static function getPercentagePriceRules( $productId, string $context = 'view' ) : array {
14 return self::getPriceRules( $productId, 'percentage', $context );
15 }
16
17 public static function getPriceRules( $productId, ?string $type = null, string $context = 'view' ) : array {
18 $type = ( $type ? $type : self::getPricingType( $productId, 'fixed', $context ) );
19 if ( 'fixed' === $type ) {
20 $rules = (array) get_post_meta( $productId, '_fixed_price_rules', true );
21 } else {
22 $rules = (array) get_post_meta( $productId, '_percentage_price_rules', true );
23 }
24 $rules = array_map( function ( $price ) {
25 return floatval( $price );
26 }, $rules );
27 $rules = ( !empty( $rules ) ? array_filter( $rules ) : array() );
28 ksort( $rules );
29 if ( 'edit' !== $context ) {
30 $rules = apply_filters(
31 'tiered_pricing_table/price/product_price_rules',
32 $rules,
33 $productId,
34 $type
35 );
36 }
37 return array_filter( $rules, function ( $quantity ) {
38 return intval( $quantity ) > 1;
39 }, ARRAY_FILTER_USE_KEY );
40 }
41
42 /**
43 * Get price by product quantity
44 *
45 * @param int $quantity
46 * @param int $productId
47 * @param ?string $context
48 * @param ?string $place
49 * @param bool $withTaxes
50 * @param ?PricingRule $pricingRule
51 * @param bool $roundPrice
52 *
53 * @return bool|float|int
54 */
55 public static function getPriceByRules(
56 $quantity,
57 $productId,
58 $context = 'view',
59 $place = 'shop',
60 bool $withTaxes = true,
61 ?PricingRule $pricingRule = null,
62 ?bool $roundPrice = null
63 ) {
64 $pricingRule = ( $pricingRule ? $pricingRule : self::getPricingRule( $productId ) );
65 $roundPrice = ( !is_null( $roundPrice ) ? $roundPrice : CalculationLogic::roundPrice() );
66 foreach ( array_reverse( $pricingRule->getRules(), true ) as $_amount => $price ) {
67 if ( $_amount <= $quantity ) {
68 if ( $pricingRule->isPercentage() ) {
69 $product = wc_get_product( $productId );
70 if ( $product ) {
71 $productPrice = self::getProductPriceWithPercentageDiscount( $product, $price, $context );
72 }
73 } else {
74 $productPrice = $price;
75 }
76 if ( 'view' === $context && $withTaxes ) {
77 $product = wc_get_product( $productId );
78 $productPrice = self::getPriceToDisplay( $productPrice, $product, $place );
79 }
80 break;
81 }
82 }
83 $productPrice = $productPrice ?? false;
84 if ( $productPrice && apply_filters( 'tiered_pricing_table/price/round_price', $roundPrice ) ) {
85 $roundPrecision = (int) apply_filters( 'tiered_pricing_table/price/round_precision', max( 2, wc_get_price_decimals() ) );
86 $productPrice = round( $productPrice, $roundPrecision );
87 }
88 if ( 'edit' !== $context ) {
89 return apply_filters(
90 'tiered_pricing_table/price/price_by_rules',
91 $productPrice,
92 $quantity,
93 $productId,
94 $context,
95 $place,
96 $pricingRule
97 );
98 }
99 return $productPrice;
100 }
101
102 /**
103 * Calculate displayed price depend on taxes
104 *
105 * @param float $price
106 * @param WC_Product $product
107 * @param ?string $displayContext
108 *
109 * @return ?float
110 */
111 public static function getPriceToDisplay( $price, WC_Product $product, ?string $displayContext = 'shop' ) : ?float {
112 if ( wc_tax_enabled() ) {
113 $price = wc_get_price_to_display( $product, array(
114 'price' => $price,
115 'qty' => 1,
116 'display_context' => $displayContext,
117 ) );
118 }
119 return floatval( $price );
120 }
121
122 /**
123 * Calculate price using percentage discount
124 *
125 * @param float $price
126 * @param float $discount
127 *
128 * @return bool|float
129 */
130 public static function getPriceByPercentDiscount( $price, $discount ) {
131 if ( $price > 0 && $discount <= 100 ) {
132 $discount_amount = $price / 100 * $discount;
133 return $price - $discount_amount;
134 }
135 return false;
136 }
137
138 public static function getProductPriceWithPercentageDiscount( WC_Product $product, $discount, $context = 'view' ) {
139 $discount = floatval( $discount );
140 $productPrice = ( CalculationLogic::calculateDiscountBasedOnRegularPrice() ? $product->get_regular_price( $context ) : $product->get_price( $context ) );
141 return self::getPriceByPercentDiscount( $productPrice, $discount );
142 }
143
144 public static function getPricingType( $productId, string $default = 'fixed', string $context = 'view' ) : string {
145 if ( !tpt_fs()->can_use_premium_code() ) {
146 return 'fixed';
147 }
148 $type = get_post_meta( $productId, '_tiered_price_rules_type', true );
149 $type = ( in_array( $type, array('fixed', 'percentage') ) ? $type : $default );
150 if ( 'edit' !== $context ) {
151 return apply_filters( 'tiered_pricing_table/price/type', $type, $productId );
152 }
153 return $type;
154 }
155
156 /**
157 * Update product pricing type
158 *
159 * @param int $productId
160 * @param string $type
161 */
162 public static function updatePriceRulesType( $productId, string $type ) {
163 if ( in_array( $type, array('percentage', 'fixed') ) ) {
164 update_post_meta( $productId, '_tiered_price_rules_type', $type );
165 }
166 }
167
168 /**
169 * Get product minimum quantity
170 *
171 * @param int $productId
172 * @param ?string $context
173 *
174 * @return int
175 */
176 public static function getProductQtyMin( $productId, ?string $context = 'view' ) : ?int {
177 return null;
178 }
179
180 /**
181 * Update product minimum quantity
182 *
183 * @param int $productId
184 * @param ?int $minimum
185 */
186 public static function updateProductMinimumQuantity( $productId, ?int $minimum ) {
187 if ( !$minimum ) {
188 delete_post_meta( $productId, '_tiered_price_minimum_qty' );
189 } else {
190 update_post_meta( $productId, '_tiered_price_minimum_qty', $minimum );
191 }
192 }
193
194 public static function calculateDiscount( $originalPrice, $currentPrice ) {
195 if ( $currentPrice >= $originalPrice ) {
196 return 0;
197 }
198 return 100 * ($originalPrice - $currentPrice) / $originalPrice;
199 }
200
201 /**
202 * Main function to get pricing information for a product.
203 *
204 * @param int $productId
205 * @param ?string $tieredPricingType - 'percentage' or 'fixed'. Leave null to use default.
206 *
207 * @return PricingRule
208 */
209 public static function getPricingRule( $productId, ?string $tieredPricingType = null ) : PricingRule {
210 /****************************************
211 *
212 * Object cache
213 *
214 ****************************************/
215 if ( array_key_exists( $productId, self::$pricingRules ) && !$tieredPricingType ) {
216 return self::$pricingRules[$productId];
217 }
218 /****************************************
219 *
220 * Initialize variables
221 *
222 ****************************************/
223 $product = null;
224 $pricingRule = new PricingRule($productId);
225 $tieredPricingType = ( $tieredPricingType ? $tieredPricingType : self::getPricingType( $productId ) );
226 /****************************************
227 *
228 * Set tiered pricing for the product
229 *
230 ****************************************/
231 $tieredPricingRules = self::getPriceRules( $productId, $tieredPricingType );
232 // If product does not have rules, check parent product
233 if ( empty( $tieredPricingRules ) ) {
234 $product = wc_get_product( $productId );
235 if ( $product && TierPricingTablePlugin::isVariationProductSupported( $product ) ) {
236 $tieredPricingType = self::getPricingType( $product->get_parent_id() );
237 $tieredPricingRules = self::getPriceRules( $product->get_parent_id(), $tieredPricingType );
238 if ( !empty( $tieredPricingRules ) ) {
239 $pricingRule->logPricingModification( 'Using parent product pricing rules' );
240 }
241 }
242 }
243 $pricingRule->setRules( $tieredPricingRules );
244 $pricingRule->setType( $tieredPricingType );
245 /****************************************
246 *
247 * Set minimum quantity for the product
248 *
249 ****************************************/
250 $minimum = self::getProductQtyMin( $productId );
251 // If product does not have minimum quantity, check parent product
252 if ( !$minimum ) {
253 $product = ( $product ? $product : wc_get_product( $productId ) );
254 if ( $product && TierPricingTablePlugin::isVariationProductSupported( $product ) ) {
255 $minimum = self::getProductQtyMin( $product->get_parent_id() );
256 if ( $minimum ) {
257 $pricingRule->logPricingModification( 'Using parent product minimum quantity' );
258 }
259 }
260 }
261 $pricingRule->setMinimum( $minimum );
262 /*****************************************
263 *
264 * Services that modify pricing rule
265 *
266 * @hooked QuantityManager - 1: Added maximum and quantity step information.
267 * @hooked CategoryTierAddon - 10: Filter with category-based rules
268 * @hooked RoleBasedPricingAddon - 20: Filter with role-based rules
269 * @hooked RoleBasedPricingAddon - 25: Filter with customer-based rules
270 * @hooked GlobalPricingService - 30: Filter with global rules
271 *
272 *****************************************/
273 $pricingRule = apply_filters( 'tiered_pricing_table/price/pricing_rule', $pricingRule, $productId );
274 self::$pricingRules[$productId] = $pricingRule;
275 return $pricingRule;
276 }
277
278 }
279