run(); add_action( 'woocommerce_before_calculate_totals', function ( WC_Cart $cart ) { foreach ( $cart->get_cart_contents() as $cartItemKey => $cartItem ) { if ( $cartItem['data'] instanceof WC_Product ) { $productId = ! empty( $cartItem['variation_id'] ) ? $cartItem['variation_id'] : $cartItem['product_id']; $pricingRule = PriceManager::getPricingRule( $productId ); $min = $pricingRule->getMinimum(); if ( ! $min ) { continue; } $cartQty = ! empty( $cartItem['variation_id'] ) ? $this->getProductCartQuantity( $cartItem['variation_id'], 'variation', $cart ) : $this->getProductCartQuantity( $cartItem['product_id'], 'product', $cart ); if ( $cartQty < $min ) { $cart->cart_contents[ $cartItemKey ]['quantity'] = $min; // translators: %1$s: item name, %2$s: minimum quantity wc_add_notice( sprintf( __( 'Minimum quantity for the %1$s is %2$d', 'tier-pricing-table' ), $cartItem['data']->get_name(), $min ), 'error' ); } } } } ); add_filter( 'woocommerce_quantity_input_args', function ( $args, $product = null ) { if ( $product instanceof WC_Product && TierPricingTablePlugin::isSimpleProductSupported( $product ) ) { if ( is_cart() && ! apply_filters( 'tiered_pricing_table/minimum_quantity/control_cart_quantity_field', true, $product ) ) { return $args; } $pricingRule = PriceManager::getPricingRule( $product->get_id() ); $min = $pricingRule->getMinimum(); if ( ! $min ) { return $args; } if ( is_cart() ) { $args['min_value'] = $min; } else { $min = max( 1, $min - $this->getProductCartQuantity( $product->get_id() ) ); $args['min_value'] = $min; } } return $args; }, 9999, 2 ); add_filter( 'woocommerce_add_to_cart_validation', function ( $passed, $productId, $quantity, $variationId = 0 ) { $productId = intval( $productId ); $quantity = intval( $quantity ); if ( $variationId ) { $variationRule = PriceManager::getPricingRule( $variationId ); $varMin = $variationRule->getMinimum(); if ( $varMin ) { $remainingMin = max( 1, $varMin - $this->getProductCartQuantity( $variationId, 'variation' ) ); if ( $quantity < $remainingMin ) { wc_add_notice( sprintf( __( 'Minimum quantity for the product is %s', 'tier-pricing-table' ), $varMin ), 'error' ); return false; } } $pricingRule = PriceManager::getPricingRule( $productId ); if ( $pricingRule->isMixAndMatchMinQuantity() ) { return $passed; } } else { $pricingRule = PriceManager::getPricingRule( $productId ); $min = $pricingRule->getMinimum(); if ( $min ) { $cartQty = $this->getProductCartQuantity( $productId, 'product' ); $remainingMin = max( 1, $min - $cartQty ); if ( $quantity < $remainingMin ) { // translators: %s: minimum quantity wc_add_notice( sprintf( __( 'Minimum quantity for the product is %s', 'tier-pricing-table' ), $min ), 'error' ); return false; } } } return $passed; }, 10, 4 ); add_filter( 'woocommerce_update_cart_validation', function ( $passed, $cart_item_key, $values, $quantity ) { $product = $values['data'] ?? null; if ( ! ( $product instanceof WC_Product ) ) { return $passed; } $pricingRule = PriceManager::getPricingRule( $product->get_id() ); if ( ! $pricingRule->getMinimum() ) { return $passed; } if ( $quantity && $quantity < $pricingRule->getMinimum() ) { // translators: %s: minimum quantity wc_add_notice( sprintf( __( 'Minimum quantity for the product is %s', 'tier-pricing-table' ), $pricingRule->getMinimum() ), 'error' ); return false; } return $passed; }, 10, 4 ); add_filter( 'woocommerce_available_variation', function ( $variation ) { $pricingRule = PriceManager::getPricingRule( (int) $variation['variation_id'] ); $min = $pricingRule->getMinimum(); if ( ! $min ) { return $variation; } $min = max( 1, $min - $this->getProductCartQuantity( (int) $variation['variation_id'], 'variation' ) ); $variation['min_qty'] = $min; $variation['qty_value'] = $min; return $variation; } ); add_action( 'woocommerce_check_cart_items', function () { $cart = wc()->cart; if ( ! $cart ) { return; } $parentQuantities = array(); foreach ( $cart->get_cart_contents() as $cartItem ) { if ( $cartItem['data'] instanceof WC_Product ) { $itemPricingRule = PriceManager::getPricingRule( $cartItem['data']->get_id() ); $itemMin = $itemPricingRule->getMinimum(); if ( $itemMin && $cartItem['quantity'] < $itemMin ) { // translators: 1: Product name, 2: Minimum quantity. wc_add_notice( sprintf( __( 'Minimum quantity for %1$s is %2$s.', 'tier-pricing-table' ), $cartItem['data']->get_name(), $itemMin ), 'error' ); } $parentId = $cartItem['data']->get_parent_id(); if ( $parentId ) { if ( ! isset( $parentQuantities[ $parentId ] ) ) { $parentQuantities[ $parentId ] = 0; } $parentQuantities[ $parentId ] += $cartItem['quantity']; } } } foreach ( $parentQuantities as $parentId => $qty ) { $pricingRule = PriceManager::getPricingRule( $parentId ); if ( $pricingRule->isMixAndMatchMinQuantity() && $pricingRule->getMinimum() ) { if ( $qty < $pricingRule->getMinimum() ) { $product = wc_get_product( $parentId ); // translators: 1: Minimum quantity, 2: Product name. wc_add_notice( sprintf( __( 'You need to order at least %1$s items of %2$s to meet the minimum order quantity.', 'tier-pricing-table' ), $pricingRule->getMinimum(), $product ? $product->get_name() : '' ), 'error' ); } } } } ); add_action( 'woocommerce_add_to_cart', function ( $cart_item_key, $productId, $quantity, $variationId, $variation, $cartItemData ) { if ( $variationId ) { $parentPricingRule = PriceManager::getPricingRule( $productId ); if ( $parentPricingRule->isMixAndMatchMinQuantity() && $parentPricingRule->getMinimum() ) { $cartQty = $this->getProductCartQuantity( $productId, 'product' ); $min = $parentPricingRule->getMinimum(); if ( $cartQty < $min ) { $missing = $min - $cartQty; $product = wc_get_product( $productId ); // translators: 1: Missing quantity, 2: Product name, 3: Minimum quantity. wc_add_notice( sprintf( __( 'You need %1$s more items of %2$s to meet the minimum order quantity of %3$s.', 'tier-pricing-table' ), $missing, $product ? $product->get_name() : '', $min ), 'notice' ); } } } }, 10, 6 ); add_action( 'wp_head', function () { if ( ! is_product() ) { return; } ?> cart; if ( $cart && is_array( $cart->cart_contents ) ) { foreach ( $cart->cart_contents as $cartItem ) { if ( 'variation' === $type ) { $compare = ! empty( $cartItem['variation_id'] ) ? $cartItem['variation_id'] : 0; } else { $compare = $cartItem['product_id']; } if ( $compare == $productId ) { $qty += $cartItem['quantity']; } } } return apply_filters( 'tiered_pricing_table/minimum_quantity/item_quantity', $qty, $productId ); } public function getDescription(): string { return __( 'Enforce minimum order quantities for products based on tiered pricing rules.', 'tier-pricing-table' ); } public function getIcon(): string { return ''; } public function getSlug(): string { return 'minimum-quantity'; } }