PluginProbe
Tiered Pricing Table for WooCommerce / 7.1.4
Tiered Pricing Table for WooCommerce v7.1.4
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 / Addons / MinQuantity / MinQuantity.php

MinQuantity.php in Tiered Pricing Table for WooCommerce 7.1.4, at src/Addons/MinQuantity/MinQuantity.php

282 lines 9.0 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php namespace TierPricingTable\Addons\MinQuantity;
2
3 use TierPricingTable\Addons\AbstractAddon;
4 use TierPricingTable\PriceManager;
5 use TierPricingTable\TierPricingTablePlugin;
6 use WC_Cart;
7 use WC_Product;
8
9 class MinQuantity extends AbstractAddon {
10
11 public function getName(): string {
12 return __( 'Minimum order quantity validation', 'tier-pricing-table' );
13 }
14
15 public function run() {
16
17 ( new StoreApiValidation() )->run();
18
19 add_action( 'woocommerce_before_calculate_totals', function ( WC_Cart $cart ) {
20 foreach ( $cart->get_cart_contents() as $cartItemKey => $cartItem ) {
21 if ( $cartItem['data'] instanceof WC_Product ) {
22
23 $productId = ! empty( $cartItem['variation_id'] ) ? $cartItem['variation_id'] : $cartItem['product_id'];
24
25 $pricingRule = PriceManager::getPricingRule( $productId );
26 $min = $pricingRule->getMinimum();
27
28 if ( ! $min ) {
29 continue;
30 }
31
32 $cartQty = ! empty( $cartItem['variation_id'] )
33 ? $this->getProductCartQuantity( $cartItem['variation_id'], 'variation', $cart )
34 : $this->getProductCartQuantity( $cartItem['product_id'], 'product', $cart );
35
36 if ( $cartQty < $min ) {
37 $cart->cart_contents[ $cartItemKey ]['quantity'] = $min;
38
39 // translators: %1$s: item name, %2$s: minimum quantity
40 wc_add_notice( sprintf( __( 'Minimum quantity for the %1$s is %2$d', 'tier-pricing-table' ),
41 $cartItem['data']->get_name(), $min ), 'error' );
42 }
43 }
44 }
45 } );
46
47 add_filter( 'woocommerce_quantity_input_args', function ( $args, $product = null ) {
48
49 if ( $product instanceof WC_Product && TierPricingTablePlugin::isSimpleProductSupported( $product ) ) {
50
51 if ( is_cart() && ! apply_filters( 'tiered_pricing_table/minimum_quantity/control_cart_quantity_field', true, $product ) ) {
52 return $args;
53 }
54
55 $pricingRule = PriceManager::getPricingRule( $product->get_id() );
56 $min = $pricingRule->getMinimum();
57
58 if ( ! $min ) {
59 return $args;
60 }
61
62 if ( is_cart() ) {
63 $args['min_value'] = $min;
64 } else {
65 $min = max( 1, $min - $this->getProductCartQuantity( $product->get_id() ) );
66 $args['min_value'] = $min;
67 }
68 }
69
70 return $args;
71 }, 9999, 2 );
72
73 add_filter( 'woocommerce_add_to_cart_validation', function ( $passed, $productId, $quantity, $variationId = 0 ) {
74 $productId = intval( $productId );
75 $quantity = intval( $quantity );
76
77 if ( $variationId ) {
78 $variationRule = PriceManager::getPricingRule( $variationId );
79 $varMin = $variationRule->getMinimum();
80 if ( $varMin ) {
81 $remainingMin = max( 1, $varMin - $this->getProductCartQuantity( $variationId, 'variation' ) );
82 if ( $quantity < $remainingMin ) {
83 wc_add_notice( sprintf( __( 'Minimum quantity for the product is %s', 'tier-pricing-table' ), $varMin ), 'error' );
84 return false;
85 }
86 }
87
88 $pricingRule = PriceManager::getPricingRule( $productId );
89 if ( $pricingRule->isMixAndMatchMinQuantity() ) {
90 return $passed;
91 }
92 } else {
93 $pricingRule = PriceManager::getPricingRule( $productId );
94 $min = $pricingRule->getMinimum();
95
96 if ( $min ) {
97 $cartQty = $this->getProductCartQuantity( $productId, 'product' );
98 $remainingMin = max( 1, $min - $cartQty );
99
100 if ( $quantity < $remainingMin ) {
101 // translators: %s: minimum quantity
102 wc_add_notice( sprintf( __( 'Minimum quantity for the product is %s', 'tier-pricing-table' ), $min ), 'error' );
103 return false;
104 }
105 }
106 }
107
108 return $passed;
109
110 }, 10, 4 );
111
112 add_filter( 'woocommerce_update_cart_validation', function ( $passed, $cart_item_key, $values, $quantity ) {
113
114 $product = $values['data'] ?? null;
115
116 if ( ! ( $product instanceof WC_Product ) ) {
117 return $passed;
118 }
119
120 $pricingRule = PriceManager::getPricingRule( $product->get_id() );
121
122 if ( ! $pricingRule->getMinimum() ) {
123 return $passed;
124 }
125
126 if ( $quantity && $quantity < $pricingRule->getMinimum() ) {
127
128 // translators: %s: minimum quantity
129 wc_add_notice( sprintf( __( 'Minimum quantity for the product is %s', 'tier-pricing-table' ),
130 $pricingRule->getMinimum() ), 'error' );
131
132 return false;
133 }
134
135 return $passed;
136
137 }, 10, 4 );
138
139 add_filter( 'woocommerce_available_variation', function ( $variation ) {
140 $pricingRule = PriceManager::getPricingRule( (int) $variation['variation_id'] );
141
142 $min = $pricingRule->getMinimum();
143
144 if ( ! $min ) {
145 return $variation;
146 }
147
148 $min = max( 1, $min - $this->getProductCartQuantity( (int) $variation['variation_id'], 'variation' ) );
149
150 $variation['min_qty'] = $min;
151 $variation['qty_value'] = $min;
152
153 return $variation;
154 } );
155
156 add_action( 'woocommerce_check_cart_items', function () {
157 $cart = wc()->cart;
158 if ( ! $cart ) {
159 return;
160 }
161
162 $parentQuantities = array();
163
164 foreach ( $cart->get_cart_contents() as $cartItem ) {
165 if ( $cartItem['data'] instanceof WC_Product ) {
166 $itemPricingRule = PriceManager::getPricingRule( $cartItem['data']->get_id() );
167 $itemMin = $itemPricingRule->getMinimum();
168 if ( $itemMin && $cartItem['quantity'] < $itemMin ) {
169 // translators: 1: Product name, 2: Minimum quantity.
170 wc_add_notice( sprintf( __( 'Minimum quantity for %1$s is %2$s.', 'tier-pricing-table' ),
171 $cartItem['data']->get_name(), $itemMin ), 'error' );
172 }
173
174 $parentId = $cartItem['data']->get_parent_id();
175 if ( $parentId ) {
176 if ( ! isset( $parentQuantities[ $parentId ] ) ) {
177 $parentQuantities[ $parentId ] = 0;
178 }
179 $parentQuantities[ $parentId ] += $cartItem['quantity'];
180 }
181 }
182 }
183
184 foreach ( $parentQuantities as $parentId => $qty ) {
185 $pricingRule = PriceManager::getPricingRule( $parentId );
186 if ( $pricingRule->isMixAndMatchMinQuantity() && $pricingRule->getMinimum() ) {
187 if ( $qty < $pricingRule->getMinimum() ) {
188 $product = wc_get_product( $parentId );
189 // translators: 1: Minimum quantity, 2: Product name.
190 wc_add_notice( sprintf( __( 'You need to order at least %1$s items of %2$s to meet the minimum order quantity.',
191 'tier-pricing-table' ), $pricingRule->getMinimum(),
192 $product ? $product->get_name() : '' ), 'error' );
193 }
194 }
195 }
196 } );
197
198 add_action( 'woocommerce_add_to_cart',
199 function ( $cart_item_key, $productId, $quantity, $variationId, $variation, $cartItemData ) {
200 if ( $variationId ) {
201 $parentPricingRule = PriceManager::getPricingRule( $productId );
202 if ( $parentPricingRule->isMixAndMatchMinQuantity() && $parentPricingRule->getMinimum() ) {
203 $cartQty = $this->getProductCartQuantity( $productId, 'product' );
204 $min = $parentPricingRule->getMinimum();
205 if ( $cartQty < $min ) {
206 $missing = $min - $cartQty;
207 $product = wc_get_product( $productId );
208 // translators: 1: Missing quantity, 2: Product name, 3: Minimum quantity.
209 wc_add_notice( sprintf( __( 'You need %1$s more items of %2$s to meet the minimum order quantity of %3$s.',
210 'tier-pricing-table' ), $missing, $product ? $product->get_name() : '', $min ),
211 'notice' );
212 }
213 }
214 }
215 }, 10, 6 );
216
217 add_action( 'wp_head', function () {
218
219 if ( ! is_product() ) {
220 return;
221 }
222
223 ?>
224 <script>
225 // Handle Minimum Quantities by Tiered Pricing Table
226 (function ($) {
227
228 $(document).on('found_variation', function (event, variation) {
229 if (typeof variation.qty_value !== "undefined") {
230 // update quantity field with a new minimum
231 $('form.cart').find('[name=quantity]').val(variation.qty_value)
232 }
233
234 if (typeof variation.min_qty !== "undefined") {
235 // update quantity field with a new minimum
236 $('form.cart').find('[name=quantity]').attr('min', variation.min_qty);
237 }
238 });
239
240 })(jQuery);
241 </script>
242 <?php
243 } );
244 }
245
246 protected function getProductCartQuantity( $productId, $type = 'product', $cart = null ) {
247 $qty = 0;
248
249 $cart = $cart ? $cart : wc()->cart;
250
251 if ( $cart && is_array( $cart->cart_contents ) ) {
252 foreach ( $cart->cart_contents as $cartItem ) {
253
254 if ( 'variation' === $type ) {
255 $compare = ! empty( $cartItem['variation_id'] ) ? $cartItem['variation_id'] : 0;
256 } else {
257 $compare = $cartItem['product_id'];
258 }
259
260 if ( $compare == $productId ) {
261 $qty += $cartItem['quantity'];
262 }
263 }
264 }
265
266 return apply_filters( 'tiered_pricing_table/minimum_quantity/item_quantity', $qty, $productId );
267 }
268
269 public function getDescription(): string {
270 return __( 'Enforce minimum order quantities for products based on tiered pricing rules.',
271 'tier-pricing-table' );
272 }
273
274 public function getIcon(): string {
275 return '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M7 18c-1.1 0-1.99.9-1.99 2S5.9 22 7 22s2-.9 2-2-.9-2-2-2zM1 2v2h2l3.6 7.59-1.35 2.45c-.16.28-.25.61-.25.96 0 1.1.9 2 2 2h12v-2H7.42c-.14 0-.25-.11-.25-.25l.03-.12.9-1.63h7.45c.75 0 1.41-.41 1.75-1.03l3.58-6.49c.08-.14.12-.31.12-.48 0-.55-.45-1-1-1H5.21l-.94-2H1zm16 16c-1.1 0-1.99.9-1.99 2s.89 2 1.99 2 2-.9 2-2-.9-2-2-2z"/></svg>';
276 }
277
278 public function getSlug(): string {
279 return 'minimum-quantity';
280 }
281 }
282