PluginProbe
Tiered Pricing Table for WooCommerce / 2.3.0
Tiered Pricing Table for WooCommerce v2.3.0
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 2.3.4 All 90 releases
← All changes | src/PriceManager.php +138 -244 trunk2.3.0 View file →
@@ -1,297 +1,191 @@
1 1 <?php
2 2
3 3 namespace TierPricingTable;
4 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 );
5 +class PriceManager
6 +{
7 + /**
8 + * Return fixed price rules or empty array if not exist rules
9 + *
10 + * @param $product_id
11 + *
12 + * @return array
13 + */
14 + public static function getFixedPriceRules( $product_id )
15 + {
16 + return self::getPriceRules( $product_id, 'fixed' );
11 17 }
12 -
13 - public static function getPercentagePriceRules( $productId, string $context = 'view' ) : array {
14 - return self::getPriceRules( $productId, 'percentage', $context );
18 +
19 + /**
20 + * Return percentage price rules or empty array if not exist rules
21 + *
22 + * @param $product_id
23 + *
24 + * @return array
25 + */
26 + public static function getPercentagePriceRules( $product_id )
27 + {
28 + return self::getPriceRules( $product_id, 'percentage' );
15 29 }
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 );
30 +
31 + /**
32 + * Get product pricing rules
33 + *
34 + * @param int $product_id
35 + * @param bool $type
36 + *
37 + * @return array
38 + */
39 + public static function getPriceRules( $product_id, $type = false )
40 + {
41 + $type = ( $type ? $type : self::getPricingType( $product_id ) );
42 +
43 + if ( $type === 'fixed' ) {
44 + $rules = get_post_meta( $product_id, '_fixed_price_rules', true );
21 45 } else {
22 - $rules = (array) get_post_meta( $productId, '_percentage_price_rules', true );
46 + $rules = get_post_meta( $product_id, '_percentage_price_rules', true );
23 47 }
24 - $rules = array_map( function ( $price ) {
25 - return floatval( $price );
26 - }, $rules );
27 - $rules = ( !empty( $rules ) ? array_filter( $rules ) : array() );
48 +
49 + $rules = ( !empty($rules) ? $rules : [] );
28 50 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 );
51 + return apply_filters(
52 + 'tier_pricing_table/price/product_price_rules',
53 + $rules,
54 + $product_id,
55 + $type
56 + );
40 57 }
41 -
58 +
42 59 /**
43 60 * Get price by product quantity
44 61 *
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
62 + * @param int $quantity
63 + * @param int $product_id
52 64 *
53 65 * @return bool|float|int
54 66 */
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;
67 + public static function getPriceByRules( $quantity, $product_id )
68 + {
69 + $rules = self::getPriceRules( $product_id );
70 + $type = self::getPricingType( $product_id );
71 + if ( $type === 'fixed' ) {
72 + foreach ( array_reverse( $rules, true ) as $_amount => $price ) {
73 +
74 + if ( $_amount <= $quantity ) {
75 + $product_price = wc_get_price_to_display( wc_get_product( $product_id ), [
76 + 'price' => $price,
77 + 'qty' => 1,
78 + ] );
79 + break;
75 80 }
76 - if ( 'view' === $context && $withTaxes ) {
77 - $product = wc_get_product( $productId );
78 - $productPrice = self::getPriceToDisplay( $productPrice, $product, $place );
81 +
82 + }
83 + }
84 +
85 + if ( $type === 'percentage' ) {
86 + $product = wc_get_product( $product_id );
87 + foreach ( array_reverse( $rules, true ) as $_amount => $percentDiscount ) {
88 +
89 + if ( $_amount <= $quantity ) {
90 + $product_price = wc_get_price_to_display( $product, [
91 + 'price' => self::getPriceByPercentDiscount( $product->get_price(), $percentDiscount ),
92 + 'qty' => 1,
93 + ] );
94 + break;
79 95 }
80 - break;
96 +
81 97 }
82 98 }
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;
99 +
100 + $product_price = ( isset( $product_price ) ? $product_price : false );
101 + return apply_filters(
102 + 'tier_pricing_table/price/price_by_rules',
103 + $product_price,
104 + $quantity,
105 + $product_id
106 + );
100 107 }
101 -
108 +
102 109 /**
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 110 * Calculate price using percentage discount
124 111 *
125 - * @param float $price
126 - * @param float $discount
112 + * @param float|int $price
113 + * @param float|int $discount
127 114 *
128 - * @return bool|float
115 + * @return bool|float|int
129 116 */
130 - public static function getPriceByPercentDiscount( $price, $discount ) {
117 + public static function getPriceByPercentDiscount( $price, $discount )
118 + {
119 +
131 120 if ( $price > 0 && $discount <= 100 ) {
132 121 $discount_amount = $price / 100 * $discount;
133 122 return $price - $discount_amount;
134 123 }
124 +
135 125 return false;
136 126 }
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 -
127 +
156 128 /**
157 - * Update product pricing type
129 + * Get pricing type of product. Available: fixed or percentage
158 130 *
159 - * @param int $productId
160 - * @param string $type
131 + * @param int $product_id
132 + *
133 + * @param string $default
134 + *
135 + * @return string
161 136 */
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 - }
137 + public static function getPricingType( $product_id, $default = 'fixed' )
138 + {
139 + return 'fixed';
166 140 }
167 -
141 +
168 142 /**
169 - * Get product minimum quantity
143 + * Update price rules
170 144 *
171 - * @param int $productId
172 - * @param ?string $context
173 - *
174 - * @return int
145 + * @param array $amounts
146 + * @param array $prices
147 + * @param int $post_id
175 148 */
176 - public static function getProductQtyMin( $productId, ?string $context = 'view' ) : ?int {
177 - return null;
178 - }
179 -
180 - public static function isProductMixAndMatch( $productId ) {
181 - $mixAndMatch = get_post_meta( $productId, '_tiered_price_mix_and_match_minimum', true );
182 - if ( '' !== $mixAndMatch ) {
183 - return 'yes' === $mixAndMatch;
184 - }
185 - $product = wc_get_product( $productId );
186 - if ( $product && $product->is_type( 'variation' ) ) {
187 - $parentMixAndMatch = get_post_meta( $product->get_parent_id(), '_tiered_price_mix_and_match_minimum', true );
188 - if ( '' !== $parentMixAndMatch ) {
189 - return 'yes' === $parentMixAndMatch;
149 + public static function updateFixedPriceRules( $amounts, $prices, $post_id )
150 + {
151 + $rules = [];
152 + foreach ( $amounts as $key => $amount ) {
153 + if ( !empty($amount) && !empty($prices[$key]) && !key_exists( $amount, $rules ) ) {
154 + $rules[$amount] = wc_format_decimal( $prices[$key] );
190 155 }
191 156 }
192 - return CalculationLogic::isMixAndMatchMinimumEnabled();
157 + update_post_meta( $post_id, '_fixed_price_rules', $rules );
193 158 }
194 -
159 +
195 160 /**
196 - * Update product minimum quantity
161 + * Update price rules
197 162 *
198 - * @param int $productId
199 - * @param ?int $minimum
163 + * @param array $amounts
164 + * @param array $percents
165 + * @param int $post_id
200 166 */
201 - public static function updateProductMinimumQuantity( $productId, ?int $minimum ) {
202 - if ( !$minimum ) {
203 - delete_post_meta( $productId, '_tiered_price_minimum_qty' );
204 - } else {
205 - update_post_meta( $productId, '_tiered_price_minimum_qty', $minimum );
167 + public static function updatePercentagePriceRules( $amounts, $percents, $post_id )
168 + {
169 + $rules = [];
170 + foreach ( $amounts as $key => $amount ) {
171 + if ( !empty($amount) && !empty($percents[$key]) && !key_exists( $amount, $rules ) && $percents[$key] < 99 ) {
172 + $rules[$amount] = $percents[$key];
173 + }
206 174 }
175 + update_post_meta( $post_id, '_percentage_price_rules', $rules );
207 176 }
208 -
209 - public static function calculateDiscount( $originalPrice, $currentPrice ) {
210 - if ( $currentPrice >= $originalPrice ) {
211 - return 0;
212 - }
213 - return 100 * ($originalPrice - $currentPrice) / $originalPrice;
214 - }
215 -
177 +
216 178 /**
217 - * Main function to get pricing information for a product.
179 + * Update product pricing type
218 180 *
219 - * @param int $productId
220 - * @param ?string $tieredPricingType - 'percentage' or 'fixed'. Leave null to use default.
221 - *
222 - * @return PricingRule
181 + * @param int $post_id
182 + * @param string $type
223 183 */
224 - public static function getPricingRule( $productId, ?string $tieredPricingType = null ) : PricingRule {
225 - /****************************************
226 - *
227 - * Object cache
228 - *
229 - ****************************************/
230 - if ( array_key_exists( $productId, self::$pricingRules ) && !$tieredPricingType ) {
231 - return self::$pricingRules[$productId];
184 + public static function updatePriceRulesType( $post_id, $type )
185 + {
186 + if ( in_array( $type, [ 'percentage', 'fixed' ] ) ) {
187 + update_post_meta( $post_id, '_tiered_price_rules_type', $type );
232 188 }
233 - /****************************************
234 - *
235 - * Initialize variables
236 - *
237 - ****************************************/
238 - $product = null;
239 - $pricingRule = new PricingRule($productId);
240 - $tieredPricingType = ( $tieredPricingType ? $tieredPricingType : self::getPricingType( $productId ) );
241 - /****************************************
242 - *
243 - * Set tiered pricing for the product
244 - *
245 - ****************************************/
246 - $tieredPricingRules = self::getPriceRules( $productId, $tieredPricingType );
247 - // If product does not have rules, check parent product
248 - if ( empty( $tieredPricingRules ) ) {
249 - $product = wc_get_product( $productId );
250 - if ( $product && TierPricingTablePlugin::isVariationProductSupported( $product ) ) {
251 - $tieredPricingType = self::getPricingType( $product->get_parent_id() );
252 - $tieredPricingRules = self::getPriceRules( $product->get_parent_id(), $tieredPricingType );
253 - if ( !empty( $tieredPricingRules ) ) {
254 - $pricingRule->logPricingModification( 'Using parent product pricing rules' );
255 - }
256 - }
257 - }
258 - $pricingRule->setRules( $tieredPricingRules );
259 - $pricingRule->setType( $tieredPricingType );
260 - /****************************************
261 - *
262 - * Set minimum quantity for the product
263 - *
264 - ****************************************/
265 - $minimum = self::getProductQtyMin( $productId );
266 - $isMixAndMatch = self::isProductMixAndMatch( $productId );
267 - // If product does not have minimum quantity, check parent product
268 - if ( !$minimum ) {
269 - if ( $product && TierPricingTablePlugin::isVariationProductSupported( $product ) ) {
270 - $parentIsMixAndMatch = $isMixAndMatch;
271 - if ( !$parentIsMixAndMatch ) {
272 - $minimum = self::getProductQtyMin( $product->get_parent_id() );
273 - if ( $minimum ) {
274 - $pricingRule->logPricingModification( 'Using parent product minimum quantity' );
275 - }
276 - }
277 - }
278 - }
279 - $pricingRule->setMinimum( $minimum );
280 - $pricingRule->setMixAndMatchMinQuantity( $isMixAndMatch );
281 - /*****************************************
282 - *
283 - * Services that modify pricing rule
284 - *
285 - * @hooked QuantityManager - 1: Added maximum and quantity step information.
286 - * @hooked CategoryTierAddon - 10: Filter with category-based rules
287 - * @hooked RoleBasedPricingAddon - 20: Filter with role-based rules
288 - * @hooked RoleBasedPricingAddon - 25: Filter with customer-based rules
289 - * @hooked GlobalPricingService - 30: Filter with global rules
290 - *
291 - *****************************************/
292 - $pricingRule = apply_filters( 'tiered_pricing_table/price/pricing_rule', $pricingRule, $productId );
293 - self::$pricingRules[$productId] = $pricingRule;
294 - return $pricingRule;
295 189 }
296 190
297 -}
191 +}