PluginProbe
Tiered Pricing Table for WooCommerce / 8.0.2
Tiered Pricing Table for WooCommerce v8.0.2
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
← All changes | src/Addons/MinQuantity/MinQuantity.php +157 -95 6.5.0 → 8.0.2 View file →
@@ -6,160 +6,221 @@
6 6 use WC_Cart;
7 7 use WC_Product;
8 8
9 9 class MinQuantity extends AbstractAddon {
10 -
10 +
11 11 public function getName(): string {
12 12 return __( 'Minimum order quantity validation', 'tier-pricing-table' );
13 13 }
14 -
14 +
15 15 public function run() {
16 -
16 +
17 + ( new StoreApiValidation() )->run();
18 +
17 19 add_action( 'woocommerce_before_calculate_totals', function ( WC_Cart $cart ) {
18 20 foreach ( $cart->get_cart_contents() as $cartItemKey => $cartItem ) {
19 21 if ( $cartItem['data'] instanceof WC_Product ) {
20 -
22 +
21 23 $productId = ! empty( $cartItem['variation_id'] ) ? $cartItem['variation_id'] : $cartItem['product_id'];
22 -
24 +
23 25 $pricingRule = PriceManager::getPricingRule( $productId );
24 26 $min = $pricingRule->getMinimum();
25 -
27 +
26 28 if ( ! $min ) {
27 - return;
29 + continue;
28 30 }
29 -
30 - if ( $this->getProductCartQuantity( $cartItem['product_id'], 'product', $cart ) < $min ) {
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 ) {
31 37 $cart->cart_contents[ $cartItemKey ]['quantity'] = $min;
32 -
38 +
33 39 // translators: %1$s: item name, %2$s: minimum quantity
34 40 wc_add_notice( sprintf( __( 'Minimum quantity for the %1$s is %2$d', 'tier-pricing-table' ),
35 - $cartItem['data']->get_name(), $min ), 'error' );
41 + $cartItem['data']->get_name(), $min ), 'error' );
36 42 }
37 43 }
38 44 }
39 45 } );
40 -
46 +
41 47 add_filter( 'woocommerce_quantity_input_args', function ( $args, $product = null ) {
42 -
48 +
43 49 if ( $product instanceof WC_Product && TierPricingTablePlugin::isSimpleProductSupported( $product ) ) {
44 - $pricingRule = PriceManager::getPricingRule( $product->get_id() );
45 - $min = $pricingRule->getMinimum();
46 50
47 - if ( ! $min ) {
51 + if ( is_cart() && ! apply_filters( 'tiered_pricing_table/minimum_quantity/control_cart_quantity_field', true, $product ) ) {
48 52 return $args;
49 53 }
50 -
51 - $min = max( 1, $min - $this->getProductCartQuantity( $product->get_id() ) );
52 - $args['min_value'] = $min;
53 - }
54 -
55 - return $args;
56 - }, 9999, 2 );
57 -
58 - // Quantity field in the cart
59 - add_filter( 'woocommerce_quantity_input_args', function ( $args, ?WC_Product $product ) {
60 -
61 - if ( ! apply_filters( 'tiered_pricing_table/minimum_quantity/control_cart_quantity_field', true,
62 - $product ) ) {
63 - return $args;
64 - }
65 -
66 - if ( ! is_cart() ) {
67 - return $args;
68 - }
69 -
70 - if ( $product instanceof WC_Product && TierPricingTablePlugin::isSimpleProductSupported( $product ) ) {
54 +
71 55 $pricingRule = PriceManager::getPricingRule( $product->get_id() );
72 56 $min = $pricingRule->getMinimum();
73 -
57 +
74 58 if ( ! $min ) {
75 59 return $args;
76 60 }
77 -
78 - $args['min_value'] = $pricingRule->getMinimum();
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 + }
79 68 }
80 -
69 +
81 70 return $args;
82 - }, 10, 3 );
83 -
84 - add_filter( 'woocommerce_add_to_cart_validation', function ( $passed, $productId, $quantity ) {
71 + }, 9999, 2 );
72 +
73 + add_filter( 'woocommerce_add_to_cart_validation', function ( $passed, $productId, $quantity, $variationId = 0 ) {
85 74 $productId = intval( $productId );
86 75 $quantity = intval( $quantity );
87 -
88 - $pricingRule = PriceManager::getPricingRule( $productId );
89 - $min = $pricingRule->getMinimum();
90 -
91 - if ( ! $min ) {
92 - return $passed;
93 - }
94 -
95 - $min = max( 1, $min - $this->getProductCartQuantity( $productId ) );
96 -
97 - if ( $quantity < $min ) {
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 + }
98 87
99 - // translators: %s: minimum quantity
100 - wc_add_notice( sprintf( __( 'Minimum quantity for the product is %s', 'tier-pricing-table' ), $min ),
101 - 'error' );
88 + $pricingRule = PriceManager::getPricingRule( $productId );
89 + if ( $pricingRule->isMixAndMatchMinQuantity() ) {
90 + return $passed;
91 + }
92 + } else {
93 + $pricingRule = PriceManager::getPricingRule( $productId );
94 + $min = $pricingRule->getMinimum();
102 95
103 - return false;
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 + }
104 106 }
105 -
107 +
106 108 return $passed;
107 -
108 - }, 10, 3 );
109 -
109 +
110 + }, 10, 4 );
111 +
110 112 add_filter( 'woocommerce_update_cart_validation', function ( $passed, $cart_item_key, $values, $quantity ) {
111 -
113 +
112 114 $product = $values['data'] ?? null;
113 -
115 +
114 116 if ( ! ( $product instanceof WC_Product ) ) {
115 117 return $passed;
116 118 }
117 -
119 +
118 120 $pricingRule = PriceManager::getPricingRule( $product->get_id() );
119 -
121 +
120 122 if ( ! $pricingRule->getMinimum() ) {
121 123 return $passed;
122 124 }
123 -
124 - $min = max( 1, $pricingRule->getMinimum() - $this->getProductCartQuantity( $values['product_id'] ) );
125 -
125 +
126 126 if ( $quantity && $quantity < $pricingRule->getMinimum() ) {
127 -
127 +
128 128 // translators: %s: minimum quantity
129 - wc_add_notice( sprintf( __( 'Minimum quantity for the product is %s', 'tier-pricing-table' ), $pricingRule->getMinimum() ),
130 - 'error' );
131 -
129 + wc_add_notice( sprintf( __( 'Minimum quantity for the product is %s', 'tier-pricing-table' ),
130 + $pricingRule->getMinimum() ), 'error' );
131 +
132 132 return false;
133 133 }
134 -
134 +
135 135 return $passed;
136 -
136 +
137 137 }, 10, 4 );
138 -
138 +
139 139 add_filter( 'woocommerce_available_variation', function ( $variation ) {
140 140 $pricingRule = PriceManager::getPricingRule( (int) $variation['variation_id'] );
141 -
141 +
142 142 $min = $pricingRule->getMinimum();
143 -
143 +
144 144 if ( ! $min ) {
145 145 return $variation;
146 146 }
147 -
147 +
148 148 $min = max( 1, $min - $this->getProductCartQuantity( (int) $variation['variation_id'], 'variation' ) );
149 -
149 +
150 150 $variation['min_qty'] = $min;
151 151 $variation['qty_value'] = $min;
152 -
152 +
153 153 return $variation;
154 154 } );
155 -
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 +
156 217 add_action( 'wp_head', function () {
157 -
218 +
158 219 if ( ! is_product() ) {
159 220 return;
160 221 }
161 -
222 +
162 223 ?>
163 224 <script>
164 225 // Handle Minimum Quantities by Tiered Pricing Table
165 226 (function ($) {
@@ -180,40 +241,41 @@
180 241 </script>
181 242 <?php
182 243 } );
183 244 }
184 -
245 +
185 246 protected function getProductCartQuantity( $productId, $type = 'product', $cart = null ) {
186 247 $qty = 0;
187 -
248 +
188 249 $cart = $cart ? $cart : wc()->cart;
189 -
250 +
190 251 if ( $cart && is_array( $cart->cart_contents ) ) {
191 252 foreach ( $cart->cart_contents as $cartItem ) {
192 -
253 +
193 254 if ( 'variation' === $type ) {
194 255 $compare = ! empty( $cartItem['variation_id'] ) ? $cartItem['variation_id'] : 0;
195 256 } else {
196 257 $compare = $cartItem['product_id'];
197 258 }
198 -
259 +
199 260 if ( $compare == $productId ) {
200 261 $qty += $cartItem['quantity'];
201 262 }
202 263 }
203 264 }
204 -
265 +
205 266 return apply_filters( 'tiered_pricing_table/minimum_quantity/item_quantity', $qty, $productId );
206 267 }
207 -
268 +
208 269 public function getDescription(): string {
209 - return __( 'Enforce minimum order quantities for products based on tiered pricing rules.', 'tier-pricing-table' );
270 + return __( 'Enforce minimum order quantities for products based on tiered pricing rules.',
271 + 'tier-pricing-table' );
210 272 }
211 -
273 +
212 274 public function getIcon(): string {
213 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>';
214 276 }
215 -
277 +
216 278 public function getSlug(): string {
217 279 return 'minimum-quantity';
218 280 }
219 281 }