Untitled

 avatar
unknown
plain_text
a month ago
2.6 kB
7
Indexable
/**
 * WooCommerce - Show In-Stock Products First While Maintaining User Sort Order
 * 
 * This code will:
 * 1. Put in-stock products first, followed by out-of-stock products
 * 2. Maintain the user's selected sort order (price, popularity, date, etc.)
 * 3. Work on main product listings, category pages, and shop-specific product pages
 */

add_filter('woocommerce_get_catalog_ordering_args', 'custom_stock_status_sort', 9999);
function custom_stock_status_sort($args) {
    // First, create a meta query for the stock status
    $args['meta_query']['stock_status'] = array(
        'key' => '_stock_status',
    );
    
    // We need to preserve the existing orderby parameters
    $orderby_value = isset($args['orderby']) ? $args['orderby'] : 'menu_order';
    
    // If it's an array, we'll work with it differently
    if (is_array($orderby_value)) {
        // Add stock status as first ordering parameter
        $new_args = array(
            'stock_status' => 'ASC', // In-stock first (instock comes before outofstock alphabetically)
        );
        
        // Then add all existing orderby parameters
        foreach ($orderby_value as $key => $value) {
            $new_args[$key] = $value;
        }
        
        $args['orderby'] = $new_args;
    } else {
        // For string-based orderby
        // Stock status first, then the user-selected sort
        $args['orderby'] = array(
            'stock_status' => 'ASC', // In-stock first
            $orderby_value => $args['order'], // Preserve existing sort order
        );
    }
    
    return $args;
}

// Also apply this to shortcodes like [products]
add_filter('woocommerce_shortcode_products_query', 'custom_stock_status_sort', 9999);

// For store-specific product pages
add_filter('posts_clauses', 'custom_posts_clauses_sort_by_stock', 10, 2);
function custom_posts_clauses_sort_by_stock($clauses, $wp_query) {
    global $wpdb;
    
    // Only apply to WooCommerce product queries on frontend
    if (is_admin() || !$wp_query->is_main_query() || 
        !is_woocommerce() || !is_shop() && !is_product_category() && !is_product_tag()) {
        return $clauses;
    }
    
    // Join the postmeta table to get stock status
    $clauses['join'] .= " LEFT JOIN {$wpdb->postmeta} as stock_status_meta ON ({$wpdb->posts}.ID = stock_status_meta.post_id AND stock_status_meta.meta_key = '_stock_status') ";
    
    // Add the stock status to the ORDER BY clause, keeping the original ordering
    $clauses['orderby'] = "stock_status_meta.meta_value ASC, " . $clauses['orderby'];
    
    return $clauses;
}
Editor is loading...
Leave a Comment