PluginProbe
Tiered Pricing Table for WooCommerce / trunk
Tiered Pricing Table for WooCommerce vtrunk
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
tier-pricing-table / src / Addons / AdvancedQuantityOptions / QuantityManager.php

QuantityManager.php in Tiered Pricing Table for WooCommerce trunk, at src/Addons/AdvancedQuantityOptions/QuantityManager.php

269 lines 8.0 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php namespace TierPricingTable\Addons\AdvancedQuantityOptions;
2
3 use TierPricingTable\PriceManager;
4 use TierPricingTable\PricingRule;
5 use TierPricingTable\TierPricingTablePlugin;
6 use WC_Product;
7
8 class QuantityManager {
9
10 public function __construct() {
11
12 add_filter( 'tiered_pricing_table/tiered_pricing/last_tier_postfix',
13 function ( $postfix, $quantity, PricingRule $pricingRule ) {
14
15 if ( $pricingRule->data['maximum_quantity'] && $pricingRule->data['maximum_quantity'] <= $quantity ) {
16 return '';
17 }
18
19 return $postfix;
20 }, 10, 3 );
21
22 add_filter( 'tiered_pricing_table/price/pricing_rule', function ( PricingRule $pricingRule, $productId ) {
23 $pricingRule->data['maximum_quantity'] = DataProvider::getMaximumQuantity( $productId );
24 $pricingRule->data['group_of_quantity'] = DataProvider::getGroupOfQuantity( $productId );
25
26 return $pricingRule;
27 }, 1, 2 );
28
29 add_action( 'woocommerce_before_calculate_totals', function ( \WC_Cart $cart ) {
30
31 foreach ( $cart->get_cart_contents() as $cartItemKey => $cartItem ) {
32
33 if ( $cartItem['data'] instanceof WC_Product ) {
34
35 $productId = ! empty( $cartItem['variation_id'] ) ? $cartItem['variation_id'] : $cartItem['product_id'];
36
37 $pricingRule = PriceManager::getPricingRule( $productId );
38 $max = $pricingRule->data['maximum_quantity'] ?? null;
39 $groupOf = $pricingRule->data['group_of_quantity'] ?? null;
40
41 $cartItemQuantity = $this->getProductCartQuantity( $productId );
42
43 if ( $max ) {
44
45 $max = max( $groupOf, $max );
46
47 if ( $this->getProductCartQuantity( $productId ) > $max ) {
48 $cart->cart_contents[ $cartItemKey ]['quantity'] = $max;
49 // translators: %1$s: item name, %2$s: minimum quantity
50 wc_add_notice( sprintf( __( 'Maximum quantity for the %1$s is %2$d', 'tier-pricing-table' ),
51 $cartItem['data']->get_name(), $max ), 'error' );
52 }
53 }
54
55 if ( $groupOf ) {
56
57 if ( 0 !== $cartItemQuantity % $groupOf ) {
58 // translators: %s: quantity step
59 wc_add_notice( sprintf( __( 'Order quantity must be multiple of %s', 'tier-pricing-table' ),
60 $groupOf ), 'error' );
61
62 $cart->cart_contents[ $cartItemKey ]['quantity'] = ceil( $cartItemQuantity / $groupOf ) * $groupOf;
63 }
64 }
65 }
66 }
67 }, 10, 1 );
68
69 add_filter( 'woocommerce_quantity_input_args', function ( $args, $product ) {
70
71 if ( $product instanceof WC_Product && TierPricingTablePlugin::isSimpleProductSupported( $product ) ) {
72
73 $pricingRule = PriceManager::getPricingRule( $product->get_id() );
74
75 $max = $pricingRule->data['maximum_quantity'] ?? null;
76 $groupOf = $pricingRule->data['group_of_quantity'] ?? null;
77
78 if ( $max ) {
79
80 // Subtract what is already in the cart ONLY for the classic product-page input, where
81 // the field means "how many more can be added". The Store API reads this filter's
82 // max_value as the ABSOLUTE cart maximum (QuantityLimits::get_add_to_cart_limits), so
83 // subtracting there double-counts the cart and caps customers at half the real limit.
84 if ( ! is_cart() && ! is_checkout() && ! WC()->is_rest_api_request() ) {
85 $max = max( 1, $max - $this->getProductCartQuantity( $product->get_id() ) );
86 }
87
88 $max = max( $groupOf, $max );
89
90 $args['max_value'] = $max;
91 }
92
93 if ( $groupOf ) {
94 $args['step'] = $groupOf;
95 $args['min_value'] = max( $args['min_value'] ?? 1, $groupOf );
96 $args['value'] = max( $args['value'] ?? 1, $groupOf );
97 }
98 }
99
100 return $args;
101 }, 9999999, 2 );
102
103 add_filter( 'woocommerce_add_to_cart_validation', function ( $passed, $_productId, $qty, $variationId = null ) {
104
105 $productId = $variationId ? $variationId : $_productId;
106
107 // Do not show additional notices if there are already notices
108 if ( ! $passed ) {
109 return false;
110 }
111
112 $pricingRule = PriceManager::getPricingRule( $productId );
113
114 $max = $pricingRule->data['maximum_quantity'] ?? null;
115 $groupOf = $pricingRule->data['group_of_quantity'] ?? null;
116
117 if ( $max ) {
118
119 $max = max( $groupOf, $max );
120
121 if ( $qty + $this->getProductCartQuantity( $_productId ) > $max ) {
122
123 // translators: %s: maximum quantity
124 wc_add_notice( sprintf( __( 'Maximum order quantity for the product is %s', 'tier-pricing-table' ),
125 $max ), 'error' );
126
127 return false;
128 }
129 }
130
131 if ( $groupOf ) {
132
133 if ( 0 !== $qty % $groupOf ) {
134 // translators: %s: quantity step
135 wc_add_notice( sprintf( __( 'Order quantity must be multiple of %s', 'tier-pricing-table' ),
136 $groupOf ), 'error' );
137
138 return false;
139 }
140 }
141
142 return $passed;
143
144 }, 10, 4 );
145
146 add_action( 'wp_head', function () {
147 if ( is_product() ) {
148 ?>
149 <script>
150 jQuery(document).ready(function () {
151
152 let $quantity = jQuery('.single_variation_wrap').find('[name=quantity]');
153
154 jQuery(document).on('found_variation', function (e, variation) {
155
156 if (variation.step) {
157 $quantity.attr('step', variation.step);
158 $quantity.data('step', variation.step);
159 } else {
160 $quantity.attr('step', 1);
161 $quantity.data('step', 1);
162 }
163
164 if (variation.max_qty) {
165 $quantity.attr('max', variation.max_qty);
166 $quantity.data('max', variation.max_qty);
167 } else {
168 $quantity.removeAttr('max');
169 }
170 });
171
172 jQuery(document).on('reset_data', function () {
173 // Do not remove step attr - it can be used for some themes for +\- buttons
174 $quantity.attr('step', 1);
175 $quantity.data('step', 1);
176
177 $quantity.removeAttr('max');
178 });
179 });
180 </script>
181 <?php
182 }
183 } );
184
185 add_filter( 'woocommerce_update_cart_validation', function ( $passed, $cart_item_key, $values, $quantity ) {
186 $product = $values['data'] ?? null;
187
188 if ( ! ( $product instanceof WC_Product ) ) {
189 return $passed;
190 }
191
192 $pricingRule = PriceManager::getPricingRule( $product->get_id() );
193
194 $max = $pricingRule->data['maximum_quantity'] ? intval( $pricingRule->data['maximum_quantity'] ) : null;
195 $groupOf = $pricingRule->data['group_of_quantity'] ? intval( $pricingRule->data['group_of_quantity'] ) : null;
196
197 if ( $max ) {
198
199 if ( $quantity > $max ) {
200
201 // translators: %s: maximum quantity
202 wc_add_notice( sprintf( __( 'Maximum order quantity for the product is %s', 'tier-pricing-table' ),
203 $max ), 'error' );
204
205 return false;
206 }
207 }
208
209 if ( $groupOf ) {
210
211 if ( 0 !== $quantity % $groupOf ) {
212
213 // translators: %s: quantity step
214 wc_add_notice( sprintf( __( 'Order quantity must be multiple of %s', 'tier-pricing-table' ),
215 $groupOf ), 'error' );
216
217 return false;
218 }
219 }
220
221 return $passed;
222
223 }, 10, 4 );
224
225 add_filter( 'woocommerce_available_variation', function ( $variation ) {
226
227 $pricingRule = PriceManager::getPricingRule( $variation['variation_id'] );
228
229 $max = $pricingRule->data['maximum_quantity'] ?? null;
230 $groupOf = $pricingRule->data['group_of_quantity'] ?? null;
231
232 if ( $max ) {
233 $max = max( 1, $max - $this->getProductCartQuantity( $variation['variation_id'], true ) );
234
235 if ( $groupOf ) {
236 $max = max( $groupOf, $max );
237 }
238
239 $variation['max_qty'] = $max;
240 }
241
242 if ( $groupOf ) {
243 $variation['step'] = $groupOf;
244 $variation['min_qty'] = max( $variation['min_qty'], $groupOf );
245 $variation['qty_value'] = max( $variation['min_qty'], $groupOf );
246 }
247
248 return $variation;
249 }, 999 );
250 }
251
252 public function getProductCartQuantity( $productId, $isVariation = false ) {
253 $qty = 0;
254
255 if ( is_array( wc()->cart->cart_contents ) ) {
256 foreach ( wc()->cart->cart_contents as $cart_content ) {
257
258 $compare = $isVariation ? ( $cart_content['variation_id'] ?? false ) : $cart_content['product_id'];
259
260 if ( $compare == $productId ) {
261 $qty += $cart_content['quantity'];
262 }
263
264 }
265 }
266
267 return $qty;
268 }
269 }