Skip to content

Instantly share code, notes, and snippets.

@xlplugins
Created December 4, 2025 07:33
Show Gist options
  • Select an option

  • Save xlplugins/0a430f43365e08a030611f172b510a0d to your computer and use it in GitHub Desktop.

Select an option

Save xlplugins/0a430f43365e08a030611f172b510a0d to your computer and use it in GitHub Desktop.
Custom Quantity Increments for Specific Categories
if ( ! class_exists( 'Custom_WooCommerce_Quantity_Handler' ) ) {
/**
* Class Custom_WooCommerce_Quantity_Handler
*
* Handles custom quantity increments for WooCommerce products based on categories.
* Compatible with standard WooCommerce cart and FunnelKit Cart (slide cart).
*
* @since 1.0.0
*/
class Custom_WooCommerce_Quantity_Handler {
/**
* Categories that should use step of 1
* @var array
*/
private $special_categories = array( 'big-bags', 'small-bags' );
/**
* Default step for products not in special categories
* @var float
*/
private $default_step = 0.5;
/**
* Step for products in special categories
* @var int
*/
private $special_step = 1;
/**
* Minimum quantity allowed
* @var int
*/
private $min_quantity = 1;
/**
* Constructor
*/
public function __construct() {
// Set minimum quantity value
add_filter( 'woocommerce_quantity_input_min', array( $this, 'set_min_quantity' ) );
// Primary filter for FunnelKit Cart compatibility
add_filter( 'woocommerce_quantity_input_step', array( $this, 'set_quantity_step' ), 10, 2 );
// Secondary filter for standard cart compatibility
add_filter( 'woocommerce_quantity_input_args', array( $this, 'set_quantity_args' ), 10, 2 );
// Apply same logic in cart page
add_filter( 'woocommerce_cart_item_quantity', array( $this, 'set_cart_item_quantity' ), 10, 3 );
// Enable float quantities
$this->enable_float_quantities();
// Fix unit price calculation in orders
add_filter( 'woocommerce_order_amount_item_total', array( $this, 'fix_unit_price' ), 10, 5 );
}
/**
* Set minimum quantity
*
* @param int $val Current minimum value
* @return int Minimum quantity
*/
public function set_min_quantity( $val ) {
return $this->min_quantity;
}
/**
* Determine step value based on product category
*
* @param WC_Product|null $product Product object
* @return float Step value
*/
private function get_quantity_step( $product ) {
if ( ! $product ) {
return $this->default_step;
}
$product_id = $product->get_id();
// For variations, get the parent product ID
if ( $product->is_type( 'variation' ) ) {
$product_id = $product->get_parent_id();
}
// Check if product is in special categories
if ( has_term( $this->special_categories, 'product_cat', $product_id ) ) {
return $this->special_step;
}
return $this->default_step;
}
/**
* Set quantity step (Primary filter for FunnelKit Cart)
*
* @param float $val Current step value
* @param WC_Product $product Product object
* @return float Step value
*/
public function set_quantity_step( $val, $product ) {
return $this->get_quantity_step( $product );
}
/**
* Set quantity args (Secondary filter for standard cart)
*
* @param array $args Quantity input arguments
* @param WC_Product $product Product object
* @return array Modified arguments
*/
public function set_quantity_args( $args, $product ) {
$args['step'] = $this->get_quantity_step( $product );
return $args;
}
/**
* Set cart item quantity display
*
* @param string $product_quantity HTML for quantity input
* @param string $cart_item_key Cart item key
* @param array $cart_item Cart item data
* @return string Modified HTML
*/
public function set_cart_item_quantity( $product_quantity, $cart_item_key, $cart_item ) {
$product = $cart_item['data'];
$step = $this->get_quantity_step( $product );
$product_quantity = woocommerce_quantity_input( array(
'input_name' => "cart[{$cart_item_key}][qty]",
'input_value' => $cart_item['quantity'],
'max_value' => $product->get_max_purchase_quantity(),
'min_value' => $this->min_quantity,
'step' => $step,
), $product, false );
return $product_quantity;
}
/**
* Enable float quantities in WooCommerce
*/
private function enable_float_quantities() {
// Remove the WooCommerce filter that validates quantity as int
remove_filter( 'woocommerce_stock_amount', 'intval' );
// Add a filter that validates quantity as float
add_filter( 'woocommerce_stock_amount', 'floatval' );
}
/**
* Fix unit price calculation when showing on processed orders
*
* @param float $price Current price
* @param WC_Order $order Order object
* @param WC_Order_Item $item Order item
* @param bool $inc_tax Include tax
* @param bool $round Round the price
* @return float Fixed unit price
*/
public function fix_unit_price( $price, $order, $item, $inc_tax = false, $round = true ) {
$total_price = 0;
$total_qty = 0;
foreach ( $order->get_items() as $order_item_id => $order_item ) {
$qty = $order_item->get_quantity();
$total_qty += $qty;
$total_price += $order_item->get_total();
}
if ( $total_qty > 0 ) {
if ( $inc_tax ) {
$price = ( $total_price + $order->get_total_tax() ) / $total_qty;
} else {
$price = $total_price / $total_qty;
}
}
$price = $round ? round( $price, 2 ) : $price;
return $price;
}
}
// Initialize the class
new Custom_WooCommerce_Quantity_Handler();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment