Filter by dimension? (Width, length, height filter)

This topic has 11 replies, 3 voices, and was last updated 5 months, 3 weeks ago ago by Luca Rossi

  • Avatar: Nancy
    Nancy
    Participant
    February 8, 2024 at 11:29

    Hello,
    Is there a way to implement a size/dimension filter, based on this data:
    https://prnt.sc/GBaDxURHM4dR

    I know we can create product attributes, but it’s double the work, and double the data. We have boxes and cake boards and a lot of other products that come in different sizes (not like L, M or S, but in CM’s). Maybe there is a snippet or something I can use to make it work, or a setting inside a filter widget?

    Thanks in advance,
    Nancy

    10 Answers
    Avatar: Rose Tyler
    Rose Tyler
    Support staff
    February 8, 2024 at 12:58

    Hello, Nancy,

    Thank you for reaching out to us with your query.

    Please be advised that the feature you are inquiring about is not available by default within our theme. The fields you have mentioned are part of the WooCommerce functionality. Therefore, we kindly suggest that you reach out to the WooCommerce plugin support team for further assistance – https://wordpress.org/support/plugin/woocommerce/

    Best regards,
    The 8Theme Team

    Avatar: Nancy
    Nancy
    Participant
    February 9, 2024 at 10:08

    Hello Rose Tyler!

    So there is not an xstore widget that can filter by dimension or another custom field (I believe _width can also be approached as a custom meta field)? As I said, a snippet for functions.php is also not a problem.

    Kind regards,
    Nancy

    Avatar: Justin
    Luca Rossi
    Support staff
    February 9, 2024 at 12:17

    Dear Nancy,

    We hope this message finds you well.

    It requires the customization to achieve. Please be advised that the customization you are inquiring about falls beyond the scope of the support we are able to provide. However, we would like to direct your attention to a plugin that may offer a solution to your needs. You can find more information about it at the following links:
    https://wordpress.org/support/topic/filtering-woos-dimension-field/
    https://woobewoo.com/documentation/filter-by-length-width-height-and-weight/
    https://toolset.com/course-lesson/creating-a-custom-search/

    We trust that this resource will be of assistance to you.

    Warm regards,
    The 8Theme Team

    Avatar: Nancy
    Nancy
    Participant
    February 18, 2024 at 15:40

    I was having the trouble with the plugins suggested that it redirected to the front page somehow everytime I tried to filter it. Annasta Woocommerce Product Filters works though! Maybe you can keep this in mind if someone wants the same thing 😉

    Avatar: Nancy
    Nancy
    Participant
    February 18, 2024 at 15:41

    Also, if you have any idea why only your plugin and annasta works correctly on my site, let me know.

    Avatar: Justin
    Luca Rossi
    Support staff
    February 19, 2024 at 06:01

    Dear Nancy,

    We hope this message finds you well.

    We would like to inform you that the size/dimension you have inquired about is not included as a standard option within our XStore theme. The specific fields you referenced are associated with the WooCommerce plugin’s capabilities. As such, we respectfully recommend that you contact the WooCommerce plugin support team for more detailed assistance. They can be reached at the following link: https://wordpress.org/support/plugin/woocommerce/ or annasta Woocommerce Product Filters plugin: https://annasta.net/plugins/annasta-woocommerce-product-filters/support/.

    Should you have any other questions or require additional information regarding our theme, please do not hesitate to reach out.

    Warm regards,

    The 8Theme Team

    Avatar: Nancy
    Nancy
    Participant
    July 11, 2024 at 10:28

    Well for now this is my third version. It works with the other filters, but only if the other filters are chosen first, and the dimension is chosen last. If you guys have any ideas on how to fix it so the order doesn’t matter, let me know

    class Custom_Dimensions_Filter_Widget extends WP_Widget {
        public function __construct() {
            parent::__construct(
                'custom_dimensions_filter',
                esc_html__('Custom Dimensions Filter', 'text_domain'),
                array('description' => esc_html__('A widget to filter products by custom dimensions', 'text_domain'))
            );
        }
    
        public function widget($args, $instance) {
            $title = apply_filters('widget_title', $instance['title']);
    
            if (is_shop() || is_product_category()) {
                $current_category = get_queried_object();
    
                // Check if there are products with dimensions in the current category
                if ($this->category_has_dimensions($current_category->term_id)) {
                    echo $args['before_widget'];
                    if (!empty($title)) {
                        echo $args['before_title'] . $title . $args['after_title'];
                    }
    
                    // Capture existing filter parameters
                    $existing_filters = $_GET;
    
                    // Generate filter links with existing parameters
                    $current_url = $this->get_current_page_url();
                    $width_options = $this->get_dimension_options('width', $current_category->term_id);
                    $length_options = $this->get_dimension_options('length', $current_category->term_id);
    
                    ?>
                    <form id="custom-filters" method="get">
                        <?php
                        foreach ($existing_filters as $key => $value) {
                            if (strpos($key, 'filter_') === 0) {
                                echo "<input type='hidden' name='$key' value='" . esc_attr($value) . "' />";
                            }
                        }
                        ?>
                        <select name="filter_width" id="filter_width">
                            <option value=""><?php _e('Select width in cm', 'text_domain'); ?></option>
                            <?php echo $width_options; ?>
                        </select>
                        <select name="filter_length" id="filter_length">
                            <option value=""><?php _e('Select length in cm', 'text_domain'); ?></option>
                            <?php echo $length_options; ?>
                        </select>
                    </form>
    
                    <script>
                    jQuery(function($) {
                        $('#filter_width, #filter_length').change(function() {
                            $('#custom-filters').submit();
                        });
                    });
                    </script>
                    <?php
    
                    echo $args['after_widget'];
                }
            }
        }
    
        public function form($instance) {
            $title = !empty($instance['title']) ? $instance['title'] : esc_html__('Filter by Dimensions', 'text_domain');
            ?>
            <p>
                <label for="<?php echo esc_attr($this->get_field_id('title')); ?>"><?php esc_attr_e('Title:', 'text_domain'); ?></label>
                <input class="widefat" id="<?php echo esc_attr($this->get_field_id('title')); ?>"
                       name="<?php echo esc_attr($this->get_field_name('title')); ?>" type="text"
                       value="<?php echo esc_attr($title); ?>">
            </p>
            <?php
        }
    
        private function get_current_page_url() {
            global $wp;
            return home_url(add_query_arg(array(), $wp->request));
        }
    
        private function get_dimension_options($dimension, $category_id) {
            $ranges = array('1-10', '11-20', '21-30', '31-40', '41-50'); // Adjusted ranges as per your requirement
            $options = '';
            foreach ($ranges as $range) {
                $selected_count = $this->count_products_with_filters($dimension, $range, $category_id);
                if ($selected_count > 0) {
                    $selected = isset($_GET["filter_$dimension"]) && $_GET["filter_$dimension"] == $range ? 'selected' : '';
                    $options .= '<option value="' . esc_attr($range) . '" ' . $selected . '>' . esc_html($range) . ' (' . $selected_count . ')</option>';
                }
            }
            return $options;
        }
    
        private function count_products_with_filters($dimension, $range, $category_id) {
            global $wpdb;
    
            $meta_key = '_' . $dimension;
            $meta_value = explode('-', $range);
    
            // Prepare meta query
            $meta_query = array(
                'relation' => 'AND',
                array(
                    'key' => $meta_key,
                    'value' => floatval($meta_value[0]),
                    'compare' => '>=',
                    'type' => 'DECIMAL(10,2)',
                ),
                array(
                    'key' => $meta_key,
                    'value' => floatval($meta_value[1]),
                    'compare' => '<=',
                    'type' => 'DECIMAL(10,2)',
                )
            );
    
            // Add taxonomy query
            $tax_query = array(
                array(
                    'taxonomy' => 'product_cat',
                    'field' => 'term_id',
                    'terms' => $category_id
                )
            );
    
            // Add color filter if selected
            if (isset($_GET['filter_kleur']) && !empty($_GET['filter_kleur'])) {
                $tax_query[] = array(
                    'taxonomy' => 'pa_kleur', // Replace with your taxonomy name
                    'field' => 'slug',
                    'terms' => sanitize_text_field($_GET['filter_kleur']),
                    'operator' => 'IN'
                );
            }
    
            // Count matching products
            $query = new WP_Query(array(
                'post_type' => 'product',
                'posts_per_page' => -1, // Count all posts
                'meta_query' => $meta_query,
                'tax_query' => $tax_query,
            ));
    
            return $query->found_posts;
        }
    
        private function category_has_dimensions($category_id) {
            global $wpdb;
            $meta_query = array('relation' => 'OR');
            $meta_keys = array('_width', '_length');
    
            foreach ($meta_keys as $meta_key) {
                $meta_query[] = array(
                    'key' => $meta_key,
                    'value' => 0,
                    'compare' => '>',
                    'type' => 'NUMERIC'
                );
            }
    
            $query = new WP_Query(array(
                'post_type' => 'product',
                'posts_per_page' => 1,
                'meta_query' => $meta_query,
                'tax_query' => array(
                    array(
                        'taxonomy' => 'product_cat',
                        'field' => 'term_id',
                        'terms' => $category_id
                    )
                )
            ));
    
            return $query->have_posts();
        }
    }
    
    // Register the widget
    function register_custom_dimensions_filter_widget() {
        register_widget('Custom_Dimensions_Filter_Widget');
    }
    add_action('widgets_init', 'register_custom_dimensions_filter_widget');
    
    // Add custom filter query logic
    function custom_filter_query($query) {
        if (!is_admin() && $query->is_main_query() && (is_shop() || is_product_category())) {
            $meta_query = array('relation' => 'AND');
            $filtering = false;
    
            // Handle width filter
            if (isset($_GET['filter_width']) && !empty($_GET['filter_width'])) {
                $width_range = explode('-', sanitize_text_field($_GET['filter_width']));
                if (count($width_range) == 2) {
                    $meta_query[] = array(
                        'key' => '_width',
                        'value' => array(floatval($width_range[0]), floatval($width_range[1])),
                        'compare' => 'BETWEEN',
                        'type' => 'DECIMAL(10,2)',
                    );
                    $filtering = true;
                }
            }
    
            // Handle length filter
            if (isset($_GET['filter_length']) && !empty($_GET['filter_length'])) {
                $length_range = explode('-', sanitize_text_field($_GET['filter_length']));
                if (count($length_range) == 2) {
                    $meta_query[] = array(
                        'key' => '_length',
                        'value' => array(floatval($length_range[0]), floatval($length_range[1])),
                        'compare' => 'BETWEEN',
                        'type' => 'DECIMAL(10,2)',
                    );
                    $filtering = true;
                }
            }
    
            // Add more custom filters here as needed
    
            // Only set the meta query if a filter is being applied
            if ($filtering) {
                $query->set('meta_query', $meta_query);
            }
        }
    }
    add_action('pre_get_posts', 'custom_filter_query');
    Avatar: Justin
    Luca Rossi
    Support staff
    July 11, 2024 at 11:48

    Dear Nancy,

    We regret to inform you that the issues arising from the custom codes fall outside the standard scope of our support services.

    Should you require personalized customization services, we kindly invite you to submit a request via our customization panel at: [https://www.8theme.com/account/#etheme_customization_panel](https://www.8theme.com/account/#etheme_customization_panel). This will enable you to engage directly with our team of technicians.

    Please note that customization services will incur additional charges. The exact amount will be determined after a detailed review of your request.

    Thank you for your understanding.

    Best Regards,
    The 8Theme Team

    Avatar: Nancy
    Nancy
    Participant
    July 12, 2024 at 12:12

    Ofcourse I understand. Maybe you just knew the trick to make it work 😉

    Avatar: Justin
    Luca Rossi
    Support staff
    July 13, 2024 at 08:13

    Hi @Nancy,

    The provided codes you sent are too complicated and it could take a lot times to research/debug.

    Thank you for your understanding.

    Best Regards,
    The 8Theme Team

  • Viewing 11 results - 1 through 11 (of 11 total)

The issue related to '‘Filter by dimension? (Width, length, height filter)’' has been successfully resolved, and the topic is now closed for further responses

We're using our own and third-party cookies to improve your experience and our website. Keep on browsing to accept our cookie policy.