Woocommerce – Problem sorting and filtering products with different tax rates by price [closed]

Wasn’t able to find any solution to my problem so I made a simple plugin:

<?php
/**
 * Plugin Name: calisia-sort-and-filter
 * Author: Tomasz Boroń
 */

//order by; add new options and remove defaults
add_filter( 'woocommerce_default_catalog_orderby_options', 'calisia_sort_and_filter::add_new_postmeta_orderby' );
add_filter( 'woocommerce_catalog_orderby', 'calisia_sort_and_filter::add_new_postmeta_orderby' );
//order by; arguments
add_filter( 'woocommerce_get_catalog_ordering_args', 'calisia_sort_and_filter::add_postmeta_ordering_args' );
//price filtering
add_action('woocommerce_product_query', 'calisia_sort_and_filter::min_max_price_handler');
//save meta _price_with_tax on every product update
add_action( 'woocommerce_update_product', 'calisia_sort_and_filter::product_save', 10, 1 );
//set meta _price_with_tax for all existing products
//to run: create new page with slug "calisia-add-price-meta" and visit it
add_action( 'get_header', 'calisia_sort_and_filter::add_meta_price_to_all_products' );

class calisia_sort_and_filter{

    //NEW ORDER BY OPTIONS, REMOVING DEFAULTS
    public static function add_new_postmeta_orderby( $sortby ) {
    
        // Adjust the text as desired
        $sortby['price_with_tax_asc'] = __( 'Sort by price: low to high', 'woocommerce' );
        $sortby['price_with_tax_desc'] = __( 'Sort by price: high to low', 'woocommerce' );
    
        //remove default price order by
        unset($sortby['price']);
        unset($sortby['price-desc']);
    
    
        return $sortby;
    }

    //ARGUMENTS FOR NEW ORDER BY OPTIONS
    public static function add_postmeta_ordering_args( $sort_args ) {
        
        $orderby_value = isset( $_GET['orderby'] ) ? wc_clean( $_GET['orderby'] ) : apply_filters( 'woocommerce_default_catalog_orderby', get_option( 'woocommerce_default_catalog_orderby' ) );
        switch( $orderby_value ) {
        
            // Name your sortby key whatever you'd like; must correspond to the $sortby in the next function
            case 'price_with_tax_asc':
                $sort_args['orderby']  = 'meta_value_num'; //meta_value for string
                // Sort by meta_value because we're using alphabetic sorting
                $sort_args['order']    = 'asc';
                $sort_args['meta_key'] = '_price_with_tax';
                // use the meta key you've set for your custom field, i.e., something like "location" or "_wholesale_price"
                break;
                
            case 'price_with_tax_desc':
                $sort_args['orderby']  = 'meta_value_num'; //meta_value for string
                // Sort by meta_value because we're using alphabetic sorting
                $sort_args['order']    = 'desc';
                $sort_args['meta_key'] = '_price_with_tax';
                // use the meta key you've set for your custom field, i.e., something like "location" or "_wholesale_price"
                break;
            
        }
        
        return $sort_args;
    }

    //PRICE FILTERING
    public static function min_max_price_handler($q) {
        global $wpdb, $wp_query;

        if (! $wp_query->is_main_query() || ( ! isset($_GET['max_price']) && ! isset($_GET['min_price']))) {
            return;
        }

        // Remove default Woocommerce min/max price request handler
        remove_filter('posts_clauses', [WC()->query, 'price_filter_post_clauses'], 10);

        $current_min_price = isset($_GET['min_price']) ? floatval(wp_unslash($_GET['min_price'])) : 0;
        $current_max_price = isset($_GET['max_price']) ? floatval(wp_unslash($_GET['max_price'])) : PHP_INT_MAX;

        $sql = "SELECT DISTINCT post_id FROM wp_postmeta WHERE meta_key = '_price_with_tax' AND meta_value >= %f AND meta_value <= %f";

        $results = $wpdb->get_results(
            $wpdb->prepare(
                $sql,
                $current_min_price,
                $current_max_price
            ),
            ARRAY_A
        );

        $results = array_column($results, 'post_id');

        if (is_array($results)) {
            $q->set('post__in', $results);
        }
    }

    public static function product_save( $product_id ) {
        $product = wc_get_product( $product_id );
        $price_incl_tax = wc_get_price_including_tax($product);
        update_post_meta( $product->get_id(), '_price_with_tax', $price_incl_tax );
    }

    public static function add_meta_price_to_all_products(){
        if (!is_page('calisia-add-price-meta'))
            return;
    
    
        if(!current_user_can('administrator'))
            return;
    
        global $post;
    
    
        // fetch all products
        $args = array(
            'post_type' => 'product',
            'posts_per_page' => -1
        );
        $products = new WP_Query( $args );
    
    
        $_pf = new WC_Product_Factory();
    
        if ( $products->have_posts() ){
            while ( $products->have_posts() ){
                $products->the_post();
    
    
               //SAVE
                $product = $_pf->get_product($post->ID);
                $price_incl_tax = wc_get_price_including_tax($product);
                update_post_meta( $post->ID, '_price_with_tax', $price_incl_tax );
                echo "<br>Product id:" . $post->ID . " total price:" . $price_incl_tax;
    
    
                //SHOW
                /*
                $product_attr = get_post_meta( $post->ID, '_price_with_tax' );
                // displaying the array of values (just to test and to see output)
                echo var_dump( $product_attr[0] );*/
            }
        }
    
        wp_die();
    }
}

How it works?
It adds extra meta value for every existing and new product, called “_price_with_tax”. Value of that meta field is used to filter and sort by price.

Usage:

  1. Install and activate
  2. Create page with slug “calisia-add-price-meta” and visit it as admin (this will create meta fields for all existing products)
  3. Filtering and sorting by price should work as expected now.

Sources:
https://www.skyverge.com/blog/sort-woocommerce-products-custom-fields/
https://stackoverflow.com/questions/65360345/override-standard-request-processing-for-min-and-max-price-in-woocommerce-filter