PluginProbe
Filter Everything — WordPress & WooCommerce Filters / 1.9.7
Filter Everything — WordPress & WooCommerce Filters v1.9.7
1.9.7 1.9.6 1.9.5 1.9.4 1.9.3 1.9.2.2 1.9.2.1 trunk 1.2.1 1.2.3 1.2.4 1.2.5 1.3.0 1.3.1 1.3.2 1.4.1 1.4.4 1.4.5 1.4.8 1.4.9 1.5.0 1.5.1 1.6.0 1.6.1 1.6.2 All 52 releases
← All changes | src/wpc-third-party.php +958 -38 1.6.11.9.7 View file →
@@ -1,8 +1,8 @@
1 1 <?php
2 2
3 -if ( ! defined('WPINC') ) {
4 - wp_die();
3 +if ( ! defined('ABSPATH') ) {
4 + exit;
5 5 }
6 6
7 7 function flrt_is_woocommerce()
8 8 {
@@ -11,8 +11,16 @@
11 11 }
12 12 return false;
13 13 }
14 14
15 +function flrt_is_acf()
16 +{
17 + if( class_exists( 'ACF' ) ){
18 + return true;
19 + }
20 + return false;
21 +}
22 +
15 23 function flrt_get_mobile_width(){
16 24 return apply_filters( 'wpc_mobile_width', 768 );
17 25 }
18 26
@@ -24,9 +32,9 @@
24 32
25 33 function flrt_wp(){
26 34 $theme_dependencies = flrt_get_theme_dependencies();
27 35
28 - if( flrt_get_option('show_bottom_widget') === 'on' ) {
36 + if( flrt_get_option('mobile_filter_settings') === 'show_bottom_widget' ){
29 37
30 38 if( flrt_get_experimental_option('disable_buttons') !== 'on' ) {
31 39
32 40 if (flrt_is_woocommerce()) { // It means WooCommerce installed
@@ -36,9 +44,11 @@
36 44 add_action('woocommerce_no_products_found', 'flrt_filters_button', 5);
37 45 }else{
38 46 if (isset($theme_dependencies['button_hook']) && is_array($theme_dependencies['button_hook'])) {
39 47 foreach ($theme_dependencies['button_hook'] as $button_hook) {
40 - add_action($button_hook, 'flrt_filters_button', 15);
48 + add_action($button_hook, function() use ($button_hook) {
49 + flrt_filters_button(0, '', $button_hook);
50 + }, 15);
41 51 }
42 52 }
43 53 }
44 54
@@ -44,9 +54,11 @@
44 54
45 55 } else {
46 56 if (isset($theme_dependencies['button_hook']) && is_array($theme_dependencies['button_hook'])) {
47 57 foreach ($theme_dependencies['button_hook'] as $button_hook) {
48 - add_action($button_hook, 'flrt_filters_button', 15);
58 + add_action($button_hook, function() use ($button_hook) {
59 + flrt_filters_button(0, '', $button_hook);
60 + }, 15);
49 61 }
50 62 }
51 63 }
52 64 }
@@ -150,8 +162,15 @@
150 162 'primary_color' => '#0073aa',
151 163 'button_hook' => '',
152 164 'chips_hook' => ''
153 165 ),
166 + 'twentytwentyfive' => array(
167 + 'posts_container' => '#wp--skip-link--target',
168 + 'sidebar_container' => '',
169 + 'primary_color' => '#0073aa',
170 + 'button_hook' => '',
171 + 'chips_hook' => ''
172 + ),
154 173 'twentytwenty' => array(
155 174 'posts_container' => '#site-content',
156 175 'sidebar_container' => '',
157 176 'primary_color' => '#cd2653',
@@ -312,15 +331,8 @@
312 331 'primary_color' => '',
313 332 'button_hook' => '',
314 333 'chips_hook' => ''
315 334 ),
316 - 'divi' => array(
317 - 'posts_container' => '#primary',
318 - 'sidebar_container' => '#secondary',
319 - 'primary_color' => '',
320 - 'button_hook' => '',
321 - 'chips_hook' => ''
322 - ),
323 335 'woodmart' => array(
324 336 'posts_container' => '.site-content',
325 337 'sidebar_container' => '#secondary',
326 338 'primary_color' => '#83b735',
@@ -325,9 +337,24 @@
325 337 'sidebar_container' => '#secondary',
326 338 'primary_color' => '#83b735',
327 339 'button_hook' => '',
328 340 'chips_hook' => array( 'woodmart_shop_filters_area', 'woodmart_main_loop')
329 - )
341 + ),
342 +
343 + 'bricks' => array(
344 + 'posts_container' => '.brxe-container',
345 + 'sidebar_container' => '',
346 + 'primary_color' => '',
347 + 'button_hook' => array('bricks_after_header'),
348 + 'chips_hook' => ''
349 + ),
350 + 'bb-theme' => array(
351 + 'posts_container' => '#fl-main-content',
352 + 'sidebar_container' => '',
353 + 'primary_color' => '',
354 + 'button_hook' => array('fl_content_open'),
355 + 'chips_hook' => ''
356 + ),
330 357 );
331 358
332 359 $theme_dependencies = apply_filters( 'wpc_theme_dependencies', $theme_dependencies );
333 360
@@ -377,32 +404,18 @@
377 404 add_filter('wpc_theme_posts_container', 'flrt_set_posts_container');
378 405
379 406 // Set correct theme color
380 407 add_filter('wpc_theme_color', 'flrt_set_theme_color');
408 +
409 + //
410 + if( flrt_is_acf() ) {
411 + add_filter( 'wpc_pre_save_filter', 'flrt_maybe_acf_field' );
412 + add_filter( 'wpc_default_sorting_terms', 'flrt_acf_terms_order', 10, 2 );
413 + }
381 414 }
382 415 }
383 416 add_action('init', 'flrt_init');
384 417
385 -/**
386 - * @todo check the problem with Elementor archive template and different posts queries
387 - * Different post types, custom and predefined category or custom term
388 - */
389 -//add_filter( 'elementor/theme/posts_archive/query_posts/query_vars', 'flrt_fix_elementor_query_args' );
390 -//add_filter( 'elementor/query/get_query_args/current_query', 'flrt_fix_elementor_query_args' );
391 -function flrt_fix_elementor_query_args( $query_args ){
392 - $wpManager = \FilterEverything\Filter\Container::instance()->getWpManager();
393 - if( ! $wpManager->getQueryVar( 'allowed_filter_page' ) ){
394 - return $query_args;
395 - }
396 -
397 - if( isset( $query_args['taxonomy'] ) ){
398 - unset( $query_args['taxonomy'] );
399 - unset( $query_args['term'] );
400 - }
401 -
402 - return $query_args;
403 -}
404 -
405 418 function flrt_wpml_active(){
406 419 if( defined('WPML_PLUGIN_BASENAME') ){
407 420 return true;
408 421 }
@@ -412,10 +425,10 @@
412 425 add_action( 'elementor/editor/before_enqueue_scripts', 'flrt_include_elementor_script' );
413 426 function flrt_include_elementor_script(){
414 427 $suffix = ( defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ) ? '' : '.min';
415 428 $ver = ( defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ) ? rand(0, 1000) : FLRT_PLUGIN_VER;
416 - wp_enqueue_script('wpc-widgets', FLRT_PLUGIN_URL . 'assets/js/wpc-widgets' . $suffix . '.js', ['jquery', 'jquery-ui-sortable'], $ver, true );
417 - wp_enqueue_style('wpc-widgets', FLRT_PLUGIN_URL . 'assets/css/wpc-widgets' . $suffix . '.css', [], $ver );
429 + wp_enqueue_script('wpc-widgets', FLRT_PLUGIN_DIR_URL . 'assets/js/wpc-widgets' . $suffix . '.js', ['jquery', 'jquery-ui-sortable'], $ver, true );
430 + wp_enqueue_style('wpc-widgets', FLRT_PLUGIN_DIR_URL . 'assets/css/wpc-widgets' . $suffix . '.css', [], $ver );
418 431
419 432 $l10n = array(
420 433 'wpcItemNum' => esc_html__( 'Item #', 'filter-everything')
421 434 );
@@ -437,9 +450,9 @@
437 450 return $post_id;
438 451 }
439 452
440 453 function flrt_pll_pro_active(){
441 - if( defined('POLYLANG_PRO') ){
454 + if ( defined('POLYLANG_PRO') ) {
442 455 return true;
443 456 }
444 457 return false;
445 458 }
@@ -453,10 +466,917 @@
453 466 }
454 467
455 468 function flrt_add_cpt_to_pll( $post_types, $is_settings ) {
456 469 if ( $is_settings ) {
457 - unset( $post_types[ FLRT_FILTERS_SET_POST_TYPE ] );
470 + unset( $post_types[ FLRT_FILTERS_SET_POST_TYPE ], $post_types[ FLRT_FILTERS_SET_POST_TYPE ] );
458 471 } else {
459 472 $post_types[ FLRT_FILTERS_SET_POST_TYPE ] = FLRT_FILTERS_SET_POST_TYPE;
473 + if( defined('FLRT_FILTERS_PRO') && FLRT_FILTERS_PRO ) {
474 + $post_types[ FLRT_SEO_RULES_POST_TYPE ] = FLRT_SEO_RULES_POST_TYPE;
475 + }
460 476 }
461 477 return $post_types;
462 -}
478 +}
479 +
480 +/**
481 + * Adds compatibility the Price filter with multi-currency plugins WOOCS and CURCY
482 + * @since 1.7.12
483 + */
484 +add_action('init', 'flrt_add_currencies_support');
485 +function flrt_add_currencies_support() {
486 + if ( flrt_is_woocommerce() ) {
487 + // For the FOX - Currency Switcher Professional for WooCommerce
488 + if ( defined( 'WOOCS_PLUGIN_NAME' ) && WOOCS_PLUGIN_NAME ) {
489 + // Converts values into selected currency. Visible in the range slider form
490 + add_filter( 'wpc_set_num_shift', 'flrt_set_woocs_shift', 10, 2 );
491 + function flrt_set_woocs_shift( $value, $entity_name ) {
492 + global $WOOCS;
493 +
494 + if ( $entity_name === '_price' ) {
495 + if ( property_exists( $WOOCS, 'default_currency' ) && property_exists( $WOOCS, 'current_currency' ) ) {
496 + if ( ! $WOOCS->default_currency || ! $WOOCS->current_currency ) {
497 + return $value;
498 + }
499 +
500 + if ( $WOOCS->default_currency !== $WOOCS->current_currency && method_exists( $WOOCS, 'convert_from_to_currency' ) ) {
501 + $value = $WOOCS->convert_from_to_currency( $value, $WOOCS->default_currency, $WOOCS->current_currency );
502 + }
503 + }
504 + }
505 +
506 + return $value;
507 + }
508 +
509 + // Converts values back to default currency for WP_Query
510 + add_filter( 'wpc_unset_num_shift', 'flrt_unset_woocs_shift', 10, 2 );
511 + function flrt_unset_woocs_shift( $value, $entity_name ) {
512 + global $WOOCS;
513 +
514 + if ( $entity_name === '_price' ) {
515 + if ( property_exists( $WOOCS, 'default_currency' ) && property_exists( $WOOCS, 'current_currency' ) ) {
516 + if ( ! $WOOCS->default_currency || ! $WOOCS->current_currency ) {
517 + return $value;
518 + }
519 +
520 + $precision = 2;
521 + if( method_exists( $WOOCS, 'get_currency_price_num_decimals' ) ) {
522 + $precision = $WOOCS->get_currency_price_num_decimals( $WOOCS->current_currency, $WOOCS->price_num_decimals );
523 + }
524 +
525 + if ( $WOOCS->default_currency !== $WOOCS->current_currency && method_exists( $WOOCS, 'convert_from_to_currency' ) ) {
526 + $value = $WOOCS->convert_from_to_currency( $value, $WOOCS->current_currency, $WOOCS->default_currency );
527 + $value = round( $value, $precision );
528 + }
529 + }
530 + }
531 +
532 + return $value;
533 + }
534 + }
535 +
536 + // For the CURCY - Multi Currency for WooCommerce
537 + if ( defined( 'WOOMULTI_CURRENCY_F_VERSION' ) && WOOMULTI_CURRENCY_F_VERSION ) {
538 + // Converts values into selected currency. Visible in the range slider form
539 + add_filter( 'wpc_set_num_shift', 'flrt_set_curcy_shift', 10, 2 );
540 + function flrt_set_curcy_shift( $value, $entity_name ) {
541 +
542 + if ( $entity_name === '_price' ) {
543 + if ( method_exists( 'WOOMULTI_CURRENCY_F_Data', 'get_ins' ) && function_exists('wmc_get_price' ) ) {
544 + $settings = WOOMULTI_CURRENCY_F_Data::get_ins();
545 +
546 + if ( ! method_exists( $settings, 'get_current_currency' ) || ! method_exists( $settings, 'get_default_currency' ) ) {
547 + return $value;
548 + }
549 +
550 + $currency = $settings->get_current_currency();
551 + $default_currency = $settings->get_default_currency();
552 +
553 + if ( $currency !== $default_currency ) {
554 + $value = wmc_get_price( $value, $currency );
555 + }
556 + }
557 + }
558 +
559 + return $value;
560 + }
561 +
562 + // Converts values back to default currency for WP_Query
563 + add_filter( 'wpc_unset_num_shift', 'flrt_unset_curcy_shift', 10, 2 );
564 + function flrt_unset_curcy_shift( $value, $entity_name ) {
565 +
566 + if ( $entity_name === '_price' ) {
567 + if ( method_exists( 'WOOMULTI_CURRENCY_F_Data', 'get_ins' ) && function_exists('wmc_revert_price' ) ) {
568 + $settings = WOOMULTI_CURRENCY_F_Data::get_ins();
569 +
570 + if ( ! method_exists( $settings, 'get_current_currency' ) || ! method_exists( $settings, 'get_default_currency' ) ) {
571 + return $value;
572 + }
573 +
574 + $currency = $settings->get_current_currency();
575 + $default_currency = $settings->get_default_currency();
576 +
577 + if ( $currency !== $default_currency ) {
578 + $value = wmc_revert_price( $value );
579 + }
580 + }
581 + }
582 +
583 + return $value;
584 + }
585 + }
586 + }
587 +}
588 +
589 +/**
590 + * Removes WooCommerce Product Query post clauses for the price filter
591 + * @since 1.7.12
592 + */
593 +function flrt_remove_product_query_post_clauses( $wp_query, $WC_query ) {
594 + $wpManager = \FilterEverything\Filter\Container::instance()->getWpManager();
595 +
596 + if ( $wpManager->getQueryVar( 'wpc_is_filter_request' ) ) {
597 + remove_filter('posts_clauses', array( $WC_query, 'product_query_post_clauses' ), 10, 2);
598 + }
599 +
600 + return $wp_query;
601 +}
602 +
603 +add_filter('wpc_check_broken_filter', function ($is_broken, $query) {
604 + $detector_class = 'FilterEverything\\Filter\\WP_Query_Source_Detector';
605 + $is_allowed_method = 'is_allowed';
606 + $source_var = 'flrt_detected_source';
607 +
608 + if (defined('FLRT_FILTERS_PRO')) {
609 + if (defined('FLRT_PRO_BUILDER_KEY')) {
610 + $builder_key = apply_filters('wpc_builder_key_pro', $query->get($source_var), constant('FLRT_PRO_BUILDER_KEY'));
611 +
612 + if ($detector_class::$is_allowed_method($builder_key)) {
613 + return false;
614 + }
615 + }
616 + }
617 +
618 + if (!defined('FLRT_FILTERS_PRO')) {
619 + $builder_key = apply_filters('wpc_builder_key', $query->get($source_var), $detector_class::$builder_key);
620 +
621 + if ($detector_class::$is_allowed_method($builder_key)) {
622 + return false;
623 + }
624 + }
625 +
626 + return true;
627 +}, 10, 2);
628 +
629 +function flrt_is_dokan() {
630 + return function_exists('dokan');
631 +}
632 +
633 +function flrt_maybe_acf_field( $filter ){
634 + if( $filter['entity'] === 'post_meta' ) {
635 + global $wpdb;
636 + // Try to check if this is ACF field
637 + $sql[] = "SELECT {$wpdb->posts}.ID FROM {$wpdb->posts}";
638 + $sql[] = "WHERE {$wpdb->posts}.post_excerpt = %s";
639 + $sql[] = "AND {$wpdb->posts}.post_type = %s";
640 + $sql[] = "ORDER BY {$wpdb->posts}.ID ASC";
641 +
642 + $sql = implode(' ', $sql );
643 + $sql = $wpdb->prepare( $sql, $filter['e_name'], 'acf-field' );
644 + $results = $wpdb->get_results( $sql, ARRAY_A );
645 +
646 + if ( ! empty( $results ) ) {
647 + $ids = [];
648 + foreach ( $results as $single_result ) {
649 + if( isset( $single_result['ID'] ) ){
650 + $ids[] = $single_result['ID'];
651 + }
652 + }
653 + $acf_field_ids = implode( ',', $ids );
654 +
655 + if( ! empty( $acf_field_ids ) ){
656 + $filter['acf_fields'] = $acf_field_ids;
657 + }
658 + }
659 + }
660 +
661 + return $filter;
662 +}
663 +
664 +function flrt_acf_terms_order( $entity_items, $filter ){
665 +
666 + if( isset( $filter['acf_fields'] ) && $filter['acf_fields'] !== '' ) {
667 + global $wpdb;
668 + // Here we have to get ACF fields by their IDs and sort terms in according to
669 + // the order in the field.
670 + $sql = [];
671 + $acf_field_ids = preg_replace( '/^[\d]\,/', '', $filter['acf_fields'] );
672 + $sql[] = "SELECT {$wpdb->posts}.post_content FROM {$wpdb->posts}";
673 + $sql[] = "WHERE {$wpdb->posts}.ID IN( {$acf_field_ids} )";
674 + $sql[] = "ORDER BY {$wpdb->posts}.ID ASC";
675 + $sql = implode(' ', $sql );
676 +
677 + $results = $wpdb->get_results( $sql, ARRAY_A );
678 +
679 + if( empty( $results ) ) {
680 + return $entity_items;
681 + }
682 +
683 + $field_terms = [];
684 + foreach ( $results as $acf_field ){
685 + if( isset( $acf_field['post_content'] ) ) {
686 + $field_options = maybe_unserialize( $acf_field['post_content'] );
687 +
688 + if( isset( $field_options['choices'] ) && is_array( $field_options['choices'] ) ){
689 + foreach ( $field_options['choices'] as $value => $label ){
690 + if( ! isset( $field_terms[$value] ) ) {
691 + $field_terms[$value] = $label;
692 + }
693 + }
694 + }
695 + }
696 + }
697 +
698 + $current_items = $entity_items;
699 + $sorted_items = [];
700 +
701 + foreach ( $field_terms as $tslug => $tvalue ) {
702 + $tslug = sanitize_title( $tslug );
703 +
704 + if( isset( $current_items[ $tslug ] ) ) {
705 + $term_object = $current_items[ $tslug ];
706 + $term_object->name = $tvalue;
707 + $sorted_items[ $tslug ] = $term_object;
708 + unset( $current_items[ $tslug ] );
709 + }
710 + }
711 +
712 + if( ! empty( $current_items ) ){
713 + foreach ( $current_items as $slug => $item ){
714 + $sorted_items[$slug] = $item;
715 + }
716 + }
717 + $entity_items = $sorted_items;
718 + }
719 +
720 + return $entity_items;
721 +}
722 +
723 +/**
724 + * Adds correct pagination URLs to the Load more/Infinite scroll button for Elementor posts block
725 + */
726 +add_filter( 'elementor/widget/render_content', 'flrt_elementor_load_more_anchor', 10, 2 );
727 +function flrt_elementor_load_more_anchor( $widget_content, $module ){
728 + // Nothing is needed if there is no Filter request
729 + if( ! flrt_is_filter_request() ){
730 + return $widget_content;
731 + }
732 +
733 + if( $module instanceof ElementorPro\Modules\Posts\Widgets\Posts ){
734 + global $wp_rewrite;
735 +
736 + $urlManager = \FilterEverything\Filter\Container::instance()->getUrlManager();
737 + $current_page = $module->get_current_page();
738 + $next_page = intval( $current_page ) + 1;
739 + $data_next_page = $module->get_wp_link_page( $next_page );
740 + $rewrite = $wp_rewrite->wp_rewrite_rules();
741 +
742 + /*
743 + * Loop widgets (Loop Grid/Loop Carousel) paginate with a widget-scoped
744 + * query arg (?e-page-<widget id>=N) instead of /page/N/, so the
745 + * path-based base replacement below never matches. Swap the base for
746 + * the filtered URL directly and carry the pagination args over.
747 + */
748 + $next_page_args = array();
749 + $next_url_parts = parse_url( $data_next_page );
750 + if ( isset( $next_url_parts['query'] ) ) {
751 + parse_str( $next_url_parts['query'], $next_page_args );
752 + }
753 +
754 + $e_page_args = array();
755 + foreach ( $next_page_args as $arg_key => $arg_value ) {
756 + if ( strpos( $arg_key, 'e-page-' ) === 0 ) {
757 + $e_page_args[ $arg_key ] = $arg_value;
758 + }
759 + }
760 +
761 + if ( ! empty( $e_page_args ) ) {
762 + // The current request may already contain pagination args (page 2+)
763 + $data_next_page = remove_query_arg( array_keys( $e_page_args ), $urlManager->getFormActionOrFullPageUrl( true ) );
764 + foreach ( $e_page_args as $arg_key => $arg_value ) {
765 + $data_next_page = flrt_add_query_arg( $arg_key, $arg_value, $data_next_page );
766 + }
767 + } else if ( defined('FLRT_PERMALINKS_ENABLED') && FLRT_PERMALINKS_ENABLED ) {
768 + // This is ok when permalinks are enabled.
769 + $data_next_page = str_replace( $urlManager->removePaginationBase( $data_next_page ), $urlManager->getFormActionOrFullPageUrl(), $data_next_page );
770 + $uri_components = explode( "?", $urlManager->getFormActionOrFullPageUrl( true ) );
771 + if( isset( $uri_components[1] ) ){
772 + $data_next_page = $data_next_page . '?'.$uri_components[1];
773 + }
774 + } else if ( ! FLRT_PERMALINKS_ENABLED && ! empty( $rewrite ) ) {
775 + // WordPress permalinks are Enabled, but Filter Everything permalinks are Disabled
776 + $uri_components = explode( "?", $urlManager->getFormActionOrFullPageUrl( true ) );
777 + // If URI part after ? exists
778 + if( isset( $uri_components[1] ) ){
779 + $data_next_page = $data_next_page . '?'.$uri_components[1];
780 + }
781 + } else {
782 + // No permalinks at all
783 + $current_page_url = $urlManager->getFormActionOrFullPageUrl( true );
784 + $url_parts = parse_url( $data_next_page );
785 + if( isset( $url_parts['query'] ) ){
786 + parse_str( $url_parts['query'], $params );
787 + if( isset( $params['page'] ) && $params['page'] ) {
788 + $data_next_page = flrt_add_query_arg( 'page', $params['page'], $current_page_url );
789 + }
790 + }
791 + }
792 +
793 + /*
794 + * $data_next_page carries the GET part of the current request, and
795 + * getFormActionOrFullPageUrl() hands it back URL-DECODED (parse_str()
796 + * + build_query(), which does not re-encode). Printed raw, a request
797 + * like ?x="><script>… closed the attribute and injected markup —
798 + * reflected XSS, reported by Wordfence (CVE-2026-87869). esc_url()
799 + * drops the characters that can break out of the attribute and
800 + * re-encodes the ampersands for the HTML context.
801 + * A callback instead of a replacement string: in a string "$1" or
802 + * "\1" coming from the URL would be read as a backreference.
803 + */
804 + $next_page_attr = 'data-next-page="' . esc_url( $data_next_page ) . '"';
805 + $widget_content = preg_replace_callback(
806 + '%data-next-page\="[^"]+"%',
807 + function () use ( $next_page_attr ) {
808 + return $next_page_attr;
809 + },
810 + $widget_content
811 + );
812 + }
813 +
814 + return $widget_content;
815 +}
816 +
817 +add_filter( 'wpc_remove_pagination_base', 'flrt_remove_pagination_base' );
818 +function flrt_remove_pagination_base( $url ){
819 + global $wp_rewrite;
820 +
821 + $rewrite = $wp_rewrite->wp_rewrite_rules();
822 + $url = ( ! empty( $rewrite ) ) ? user_trailingslashit( $url ) : rtrim( $url, '/' ) . '/';
823 +
824 + return $url;
825 +}
826 +
827 +function flrt_is_woo_discount_rules()
828 +{
829 + $check_woo_discount_rules = apply_filters('flrt_woo_discount_rules_enabled', true);
830 + if(!$check_woo_discount_rules) return false;
831 + if( flrt_is_woocommerce() &&
832 + class_exists('Wdr\App\Helpers\Woocommerce') &&
833 + class_exists('Wdr\App\Controllers\Base') &&
834 + class_exists('Wdr\App\Helpers\Rule') &&
835 + class_exists('Wdr\App\Controllers\ManageDiscount') &&
836 + class_exists('Wdr\App\Controllers\DiscountCalculator') &&
837 + class_exists('Wdr\App\Models\DBTable')
838 + )
839 + {
840 + $tb_table = new Wdr\App\Models\DBTable();
841 + $wdr_rules = $tb_table::getRules();
842 + if(!empty($wdr_rules)){
843 + $discount_types = [];
844 + foreach ($wdr_rules as $rule){
845 + $discount_types[] = $rule->discount_type;
846 + }
847 + $allowed_discount_types = ['wdr_simple_discount', 'wdr_bulk_discount', 'wdr_set_discount'];
848 + if(!empty(array_intersect($allowed_discount_types, $discount_types))){
849 + return true;
850 + }
851 + }
852 + }
853 + return false;
854 +}
855 +
856 +function flrt_is_elementor_active()
857 +{
858 + return did_action( 'elementor/loaded' );
859 +}
860 +
861 +if ( flrt_is_elementor_active() ) {
862 + function wpc_add_elementor_widget_categories( $elements_manager ) {
863 + $pro_text = (defined('FLRT_FILTERS_PRO') && FLRT_FILTERS_PRO)
864 + ? ' ' .esc_html__('PRO', 'filter-everything')
865 + : '';
866 +
867 + $elements_manager->add_category(
868 + 'filter-everything',
869 + [
870 + 'title' => esc_html__( 'Filter Everything', 'filter-everything' ) . $pro_text,
871 + 'icon' => 'fa-solid fa-filter',
872 + ]
873 + );
874 + }
875 + add_action( 'elementor/elements/categories_registered', 'wpc_add_elementor_widget_categories' );
876 +
877 + function wpc_register_elementor_widget( $widgets_manager ) {
878 +
879 + flrt_include('src/Frontend/Builders/ElementorWidgets/ChipsElementorWidget.php');
880 + flrt_include('src/Frontend/Builders/ElementorWidgets/FiltersElementorWidget.php');
881 + flrt_include('src/Frontend/Builders/ElementorWidgets/SortingElementorWidget.php');
882 +
883 + $widgets_manager->register( new \FilterEverything\Filter\ChipsElementorWidget() );
884 + $widgets_manager->register( new \FilterEverything\Filter\FiltersElementorWidget() );
885 + $widgets_manager->register( new \FilterEverything\Filter\SortingElementorWidget() );
886 +
887 + }
888 + add_action( 'elementor/widgets/register', 'wpc_register_elementor_widget' );
889 +
890 + add_action( 'elementor/editor/after_enqueue_styles', function() {
891 + wp_enqueue_style(
892 + 'filter-everything-elementor',
893 + FLRT_PLUGIN_DIR_URL . 'assets/css/elementor-icon.css'
894 + );
895 + $css = '
896 + .wpc-fe-icon {
897 + background: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB2ZXJzaW9uPSIxLjEiIGVuYWJsZS1iYWNrZ3JvdW5kPSJuZXcgMCAwIDUzIDUzIiBpZD0iTGF5ZXJfMSIgeD0iMHB4IiB5PSIwcHgiIHZpZXdCb3g9IjAgMCA1MyA1MyIgc3R5bGU9ImVuYWJsZS1iYWNrZ3JvdW5kOm5ldyAwIDAgNTMgNTM7IiB4bWw6c3BhY2U9InByZXNlcnZlIj4NCiAgICAgICAgICAgICAgIDxzdHlsZSB0eXBlPSJ0ZXh0L2NzcyI+DQogICAgICAgICAgICAgICAgLnN0MHtkaXNwbGF5Om5vbmU7fQ0KICAgICAgICAgICAgICAgIC5zdDF7ZGlzcGxheTppbmxpbmU7fQ0KICAgICAgICAgICAgICAgIC5zdDN7ZmlsbDojZmZmZmZmO30NCiAgICAgICAgICAgICAgICAuc3Q0e2Rpc3BsYXk6bm9uZTtmaWxsOiNmZmZmZmY7fQ0KICAgICAgICAgICAgICAgIC5zdDV7ZmlsbDpub25lO2ZpbGwtb3BhY2l0eTowO3N0cm9rZTojZmZmZmZmO3N0cm9rZS13aWR0aDozO3N0cm9rZS1taXRlcmxpbWl0OjEwO30NCiAgICAgICAgICAgICAgICAuc3Q2e2ZpbGw6bm9uZTtmaWxsLW9wYWNpdHk6MDtzdHJva2U6I2ZmZmZmZjtzdHJva2Utd2lkdGg6MjtzdHJva2UtbWl0ZXJsaW1pdDoxMDt9DQogICAgICAgICAgICAgICA8L3N0eWxlPg0KICAgICAgICAgICAgICAgPGcgaWQ9IkxheWVyXzJfMDAwMDAwNDc3NzA3MTk3MTAxMTA3NDIyMzAwMDAwMDM5MjM5NTE2MjYxNDg4NDk1NTdfIiBjbGFzcz0ic3QwIj4NCiAgICAgICAgICAgICAgICA8cmVjdCB4PSIwIiB5PSIwIiBjbGFzcz0ic3QxIiB3aWR0aD0iNTMuMSIgaGVpZ2h0PSI1My4xIi8+DQogICAgICAgICAgICAgICA8L2c+DQogICAgICAgICAgICAgICA8ZyBpZD0iTGF5ZXJfMV8wMDAwMDE2MjMzMzEwMzI2NTgwNjk4MTUzMDAwMDAxNzE0NjYyNDI0NzU5MTY3NDU1Nl8iPg0KICAgICAgICAgICAgICAgIDxnPg0KICAgICAgICAgICAgICAgICAgIDxkZWZzPg0KICAgICAgICAgICAgICAgICAgICAgIDxwYXRoIGlkPSJTVkdJRF8xXyIgZD0iTTAsMGg1M3Y1M0gwVjB6IE0yMy4zLDM3LjJjMS40LDAsMi41LTEuMSwyLjUtMi41cy0xLjEtMi41LTIuNS0yLjVzLTIuNSwxLjEtMi41LDIuNSAgICAgQzIwLjgsMzYuMSwyMS45LDM3LjIsMjMuMywzNy4yeiBNMzMuNCwyNy4yYzEuNCwwLDIuNS0xLjEsMi41LTIuNXMtMS4xLTIuNS0yLjUtMi41cy0yLjUsMS4xLTIuNSwyLjVTMzIsMjcuMiwzMy40LDI3LjJ6ICAgICAgTTIzLDIyLjhjMS42LDAsMi45LTEuMywyLjktMi45UzI0LjYsMTcsMjMsMTdzLTIuOSwxLjMtMi45LDIuOUMyMC4yLDIxLjUsMjEuNSwyMi44LDIzLDIyLjh6Ii8+DQogICAgICAgICAgICAgICAgICAgPC9kZWZzPg0KICAgICAgICAgICAgICAgICAgIDxjbGlwUGF0aCBpZD0iU1ZHSURfMDAwMDAxMTI2MDgzNDA4MDQyNDU0NDI0NjAwMDAwMTM5ODYyMTkxNzgxOTkwODYyNDRfIj4NCiAgICAgICAgICAgICAgICAgICAgICA8dXNlIHhsaW5rOmhyZWY9IiNTVkdJRF8xXyIgc3R5bGU9Im92ZXJmbG93OnZpc2libGU7Ii8+DQogICAgICAgICAgICAgICAgICAgPC9jbGlwUGF0aD4NCiAgICAgICAgICAgICAgICAgICA8ZyBpZD0iQmFyc0NsaXBwZWQiIHN0eWxlPSJjbGlwLXBhdGg6dXJsKCNTVkdJRF8wMDAwMDExMjYwODM0MDgwNDI0NTQ0MjQ2MDAwMDAxMzk4NjIxOTE3ODE5OTA4NjI0NF8pOyI+DQogICAgICAgICAgICAgICAgICAgICAgPHBhdGggY2xhc3M9InN0MyIgZD0iTTM5LjksMzEuNUwxOCwzNy4zYy0wLjYsMC4yLTEuMi0wLjItMS40LTAuOGMtMC4yLTAuNiwwLjItMS4yLDAuOC0xLjRsMjEuOS01LjljMC42LTAuMiwxLjIsMC4yLDEuNCwwLjggICAgIEM0MC44LDMwLjcsNDAuNSwzMS4zLDM5LjksMzEuNXoiLz4NCiAgICAgICAgICAgICAgICAgICAgICA8cGF0aCBjbGFzcz0ic3QzIiBkPSJNMzguMSwyNC42bC0yMS45LDUuOWMtMC42LDAuMi0xLjItMC4yLTEuNC0wLjhjLTAuMi0wLjYsMC4yLTEuMiwwLjgtMS40bDIxLjktNS45YzAuNi0wLjIsMS4yLDAuMiwxLjQsMC44ICAgICBDMzksMjMuOCwzOC43LDI0LjUsMzguMSwyNC42eiIvPg0KICAgICAgICAgICAgICAgICAgICAgIDxwYXRoIGNsYXNzPSJzdDMiIGQ9Ik0zNi4yLDE3LjlsLTIxLjksNS45Yy0wLjYsMC4yLTEuMi0wLjItMS40LTAuOGMtMC4yLTAuNiwwLjItMS4yLDAuOC0xLjRsMjEuOS01LjljMC42LTAuMiwxLjIsMC4yLDEuNCwwLjggICAgIEMzNy4yLDE3LjEsMzYuOCwxNy43LDM2LjIsMTcuOXoiLz4NCiAgICAgICAgICAgICAgICAgICA8L2c+DQogICAgICAgICAgICAgICAgPC9nPg0KICAgICAgICAgICAgICAgIDxwYXRoIGNsYXNzPSJzdDQiIGQ9Ik0yMy4zLDM3LjJjMS40LDAsMi41LTEuMSwyLjUtMi41cy0xLjEtMi41LTIuNS0yLjVzLTIuNSwxLjEtMi41LDIuNUMyMC44LDM2LjEsMjEuOSwzNy4yLDIzLjMsMzcuMnoiLz4NCiAgICAgICAgICAgICAgICA8cGF0aCBjbGFzcz0ic3Q0IiBkPSJNMzMuNCwyNy4yYzEuNCwwLDIuNS0xLjEsMi41LTIuNXMtMS4xLTIuNS0yLjUtMi41cy0yLjUsMS4xLTIuNSwyLjVTMzIsMjcuMiwzMy40LDI3LjJ6Ii8+DQogICAgICAgICAgICAgICAgPHBhdGggY2xhc3M9InN0NCIgZD0iTTIzLDIyLjhjMS42LDAsMi45LTEuMywyLjktMi45UzI0LjYsMTcsMjMsMTdzLTIuOSwxLjMtMi45LDIuOUMyMC4yLDIxLjUsMjEuNSwyMi44LDIzLDIyLjh6Ii8+DQogICAgICAgICAgICAgICAgPHBhdGggY2xhc3M9InN0NCIgZD0iTTIzLjksMzguMmMtMS45LDAuNS0zLjgtMC42LTQuMy0yLjVjLTAuNS0xLjksMC42LTMuOCwyLjUtNC4zczMuOCwwLjYsNC4zLDIuNUMyNi45LDM1LjgsMjUuOCwzNy43LDIzLjksMzguMiAgIHogTTIyLjYsMzMuMmMtMC45LDAuMi0xLjQsMS4xLTEuMSwyYzAuMiwwLjksMS4xLDEuNCwyLDEuMWMwLjktMC4yLDEuNC0xLjEsMS4xLTJDMjQuMywzMy41LDIzLjQsMzMsMjIuNiwzMy4yeiIvPg0KICAgICAgICAgICAgICAgIDxwYXRoIGNsYXNzPSJzdDQiIGQ9Ik0zNC4xLDI4LjJjLTEuOSwwLjUtMy44LTAuNi00LjMtMi41czAuNi0zLjgsMi41LTQuM2MxLjktMC41LDMuOCwwLjYsNC4zLDIuNUMzNy4xLDI1LjgsMzYsMjcuNywzNC4xLDI4LjJ6ICAgIE0zMi44LDIzLjJjLTAuOSwwLjItMS40LDEuMS0xLjEsMmMwLjIsMC45LDEuMSwxLjQsMiwxLjFjMC45LTAuMiwxLjQtMS4xLDEuMS0yQzM0LjUsMjMuNSwzMy42LDIzLDMyLjgsMjMuMnoiLz4NCiAgICAgICAgICAgICAgICA8cGF0aCBjbGFzcz0ic3Q0IiBkPSJNMjQuMiwyMy41Yy0xLjksMC41LTMuOC0wLjYtNC4zLTIuNXMwLjYtMy44LDIuNS00LjNzMy44LDAuNiw0LjMsMi41UzI2LjEsMjMsMjQuMiwyMy41eiBNMjIuOSwxOC42ICAgYy0wLjksMC4yLTEuNCwxLjEtMS4xLDJjMC4yLDAuOSwxLjEsMS40LDIsMS4xYzAuOS0wLjIsMS40LTEuMSwxLjEtMkMyNC43LDE4LjgsMjMuOCwxOC4zLDIyLjksMTguNnoiLz4NCiAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICA8cGF0aCBjbGFzcz0ic3Q1IiBmaWxsLW9wYWNpdHk9IjAiIGQ9Ik0yNi41LDUxLjVjMTMuOCwwLDI1LTExLjIsMjUtMjVzLTExLjItMjUtMjUtMjVzLTI1LDExLjItMjUsMjVTMTIuNyw1MS41LDI2LjUsNTEuNXoiLz4NCiAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICA8cGF0aCBjbGFzcz0ic3Q0IiBkPSJNMzMuMywyMWgxMGMwLjQsMCwwLjgtMC4zLDAuOC0wLjhzLTAuMy0wLjgtMC44LTAuOGgtMTBDMzMuMywyMC4yLDMzLjMsMjAuMiwzMy4zLDIxeiIvPg0KICAgICAgICAgICAgICAgPC9nPg0KICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICA8Y2lyY2xlIGNsYXNzPSJzdDYiIGZpbGwtb3BhY2l0eT0iMCIgY3g9IjIzLjMiIGN5PSIyMC4xIiByPSIyLjUiLz4NCiAgICAgICAgICAgICAgIDxjaXJjbGUgY2xhc3M9InN0NiIgZmlsbC1vcGFjaXR5PSIwIiBjeD0iMzMuMiIgY3k9IjI0LjgiIHI9IjIuNSIvPg0KICAgICAgICAgICAgICAgPGNpcmNsZSBjbGFzcz0ic3Q2IiBmaWxsLW9wYWNpdHk9IjAiIGN4PSIyMyIgY3k9IjM0LjgiIHI9IjIuNSIvPg0KICAgICAgICAgICAgICAgPC9zdmc+) no-repeat;
898 + background-size: auto;
899 + background-size: contain;
900 + display: inline-block;
901 + width: 28px;
902 + height: 28px;
903 + margin-bottom: -5px;
904 + }
905 +
906 + .elementor-navigator__element-widget .wpc-fe-icon {
907 + width: 15px;
908 + height: 15px;
909 + margin-bottom: 0px;
910 + }';
911 + wp_add_inline_style( 'filter-everything-elementor', $css );
912 + });
913 +
914 + add_filter('elementor/document/wrapper_attributes', function($attributes) {
915 + $attributes['wpc-filter-elementor-widget'] = true;
916 + return $attributes;
917 + });
918 +
919 + add_action( 'wp_footer', function() {
920 + if ( ! defined( 'ELEMENTOR_VERSION' ) ) {
921 + return;
922 + }
923 + if( flrt_get_option('mobile_filter_settings') === 'show_bottom_widget' ){
924 + if( flrt_get_experimental_option('disable_buttons') !== 'on' ) {
925 +
926 + ?>
927 +
928 + <script>
929 + jQuery(function($) {
930 + $(window).on('elementor/frontend/init', function() {
931 + elementorFrontend.hooks.addAction(
932 + 'frontend/element_ready/filter-everything-filters.default',
933 + function($scope) {
934 + let $el = $('[wpc-filter-elementor-widget="1"][data-elementor-type]:not([data-elementor-type="loop-item"])');
935 + if($el.length > 0){
936 + $el.before(`<?php flrt_filters_button() ?>`);
937 + }
938 + }
939 + );
940 + });
941 + });
942 + </script>
943 + <?php
944 + }
945 + }
946 + });
947 +}
948 +
949 +add_action('admin_enqueue_scripts', function () {
950 + $handle = 'filter-everything-menu-icon';
951 + wp_register_style($handle, false);
952 + wp_enqueue_style($handle);
953 +
954 +
955 + $css = <<<PHP_CSS
956 + #toplevel_page_edit-post_type-filter-set .wp-menu-image{
957 + content: '';
958 + background-repeat: no-repeat;
959 + background-position: center;
960 + background-size: 20px;
961 + background-image: url('data:image/svg+xml,%3C%3Fxml version="1.0" encoding="utf-8"%3F%3E%3C!-- --%3E%3Csvg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 53 53" style="enable-background:new 0 0 53 53;" xml:space="preserve"%3E%3Cstyle type="text/css"%3E .st0%7Bdisplay:none;%7D .st1%7Bdisplay:inline;%7D .st2%7Bclip-path:url(%23SVGID_00000142154616827085436530000012698217856111301567_);%7D .st3%7Bfill:%23a7aaad;%7D .st4%7Bdisplay:none;fill:%23FFFFFF;%7D .st5%7Bfill:none;stroke:%23a7aaad;stroke-width:3;stroke-miterlimit:10;%7D .st6%7Bfill:none;stroke:%23a7aaad;stroke-width:2;stroke-miterlimit:10;%7D%0A%3C/style%3E%3Cg id="Layer_2_00000047770719710110742230000003923951626148849557_" class="st0"%3E%3Crect class="st1" width="53.1" height="53.1"/%3E%3C/g%3E%3Cg id="Layer_1_00000162333103265806981530000017146624247591674556_"%3E%3Cg%3E%3Cg%3E%3Cdefs%3E%3Cpath id="SVGID_1_" d="M0,0h53v53H0V0z M23.3,37.2c1.4,0,2.5-1.1,2.5-2.5s-1.1-2.5-2.5-2.5s-2.5,1.1-2.5,2.5 C20.8,36.1,21.9,37.2,23.3,37.2z M33.4,27.2c1.4,0,2.5-1.1,2.5-2.5s-1.1-2.5-2.5-2.5s-2.5,1.1-2.5,2.5S32,27.2,33.4,27.2z M23,22.8c1.6,0,2.9-1.3,2.9-2.9S24.6,17,23,17s-2.9,1.3-2.9,2.9C20.2,21.5,21.5,22.8,23,22.8z"/%3E%3C/defs%3E%3CclipPath id="SVGID_00000111880200341027563210000003406718579453459379_"%3E%3Cuse xlink:href="%23SVGID_1_" style="overflow:visible;"/%3E%3C/clipPath%3E%3Cg id="BarsClipped" style="clip-path:url(%23SVGID_00000111880200341027563210000003406718579453459379_);"%3E%3Cpath class="st3" d="M39.9,31.5L18,37.3c-0.6,0.2-1.2-0.2-1.4-0.8c-0.2-0.6,0.2-1.2,0.8-1.4l21.9-5.9c0.6-0.2,1.2,0.2,1.4,0.8 C40.8,30.7,40.5,31.3,39.9,31.5z"/%3E%3Cpath class="st3" d="M38.1,24.6l-21.9,5.9c-0.6,0.2-1.2-0.2-1.4-0.8c-0.2-0.6,0.2-1.2,0.8-1.4l21.9-5.9c0.6-0.2,1.2,0.2,1.4,0.8 C39,23.8,38.7,24.5,38.1,24.6z"/%3E%3Cpath class="st3" d="M36.2,17.9l-21.9,5.9c-0.6,0.2-1.2-0.2-1.4-0.8c-0.2-0.6,0.2-1.2,0.8-1.4l21.9-5.9c0.6-0.2,1.2,0.2,1.4,0.8 C37.2,17.1,36.8,17.7,36.2,17.9z"/%3E%3C/g%3E%3C/g%3E%3C/g%3E%3Cpath class="st4" d="M23.3,37.2c1.4,0,2.5-1.1,2.5-2.5s-1.1-2.5-2.5-2.5s-2.5,1.1-2.5,2.5C20.8,36.1,21.9,37.2,23.3,37.2z"/%3E%3Cpath class="st4" d="M33.4,27.2c1.4,0,2.5-1.1,2.5-2.5s-1.1-2.5-2.5-2.5s-2.5,1.1-2.5,2.5S32,27.2,33.4,27.2z"/%3E%3Cpath class="st4" d="M23,22.8c1.6,0,2.9-1.3,2.9-2.9S24.6,17,23,17s-2.9,1.3-2.9,2.9C20.2,21.5,21.5,22.8,23,22.8z"/%3E%3Cpath class="st4" d="M23.9,38.2c-1.9,0.5-3.8-0.6-4.3-2.5c-0.5-1.9,0.6-3.8,2.5-4.3s3.8,0.6,4.3,2.5C26.9,35.8,25.8,37.7,23.9,38.2 z M22.6,33.2c-0.9,0.2-1.4,1.1-1.1,2c0.2,0.9,1.1,1.4,2,1.1c0.9-0.2,1.4-1.1,1.1-2C24.3,33.5,23.4,33,22.6,33.2z"/%3E%3Cpath class="st4" d="M34.1,28.2c-1.9,0.5-3.8-0.6-4.3-2.5s0.6-3.8,2.5-4.3c1.9-0.5,3.8,0.6,4.3,2.5C37.1,25.8,36,27.7,34.1,28.2z M32.8,23.2c-0.9,0.2-1.4,1.1-1.1,2c0.2,0.9,1.1,1.4,2,1.1c0.9-0.2,1.4-1.1,1.1-2C34.5,23.5,33.6,23,32.8,23.2z"/%3E%3Cpath class="st4" d="M24.2,23.5c-1.9,0.5-3.8-0.6-4.3-2.5s0.6-3.8,2.5-4.3s3.8,0.6,4.3,2.5S26.1,23,24.2,23.5z M22.9,18.6 c-0.9,0.2-1.4,1.1-1.1,2c0.2,0.9,1.1,1.4,2,1.1c0.9-0.2,1.4-1.1,1.1-2C24.7,18.8,23.8,18.3,22.9,18.6z"/%3E%3Cpath class="st5" d="M26.5,51.5c13.8,0,25-11.2,25-25s-11.2-25-25-25s-25,11.2-25,25S12.7,51.5,26.5,51.5z"/%3E%3Cpath class="st4" d="M33.3,21h10c0.4,0,0.8-0.3,0.8-0.8s-0.3-0.8-0.8-0.8h-10C33.3,20.2,33.3,20.2,33.3,21z"/%3E%3C/g%3E%3Ccircle class="st6" cx="23.3" cy="20.1" r="2.5"/%3E%3Ccircle class="st6" cx="33.2" cy="24.8" r="2.5"/%3E%3Ccircle class="st6" cx="23" cy="34.8" r="2.5"/%3E%3C/svg%3E');
962 + }
963 + #toplevel_page_edit-post_type-filter-set:hover .wp-menu-image{
964 + background-image: url('data:image/svg+xml,%3C%3Fxml version="1.0" encoding="utf-8"%3F%3E%3C!-- --%3E%3Csvg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 53 53" style="enable-background:new 0 0 53 53;" xml:space="preserve"%3E%3Cstyle type="text/css"%3E .st0%7Bdisplay:none;%7D .st1%7Bdisplay:inline;%7D .st2%7Bclip-path:url(%23SVGID_00000142154616827085436530000012698217856111301567_);%7D .st3%7Bfill:%2372AEE6;%7D .st4%7Bdisplay:none;fill:%23FFFFFF;%7D .st5%7Bfill:none;stroke:%2372AEE6;stroke-width:3;stroke-miterlimit:10;%7D .st6%7Bfill:none;stroke:%2372AEE6;stroke-width:2;stroke-miterlimit:10;%7D%0A%3C/style%3E%3Cg id="Layer_2_00000047770719710110742230000003923951626148849557_" class="st0"%3E%3Crect class="st1" width="53.1" height="53.1"/%3E%3C/g%3E%3Cg id="Layer_1_00000162333103265806981530000017146624247591674556_"%3E%3Cg%3E%3Cg%3E%3Cdefs%3E%3Cpath id="SVGID_1_" d="M0,0h53v53H0V0z M23.3,37.2c1.4,0,2.5-1.1,2.5-2.5s-1.1-2.5-2.5-2.5s-2.5,1.1-2.5,2.5 C20.8,36.1,21.9,37.2,23.3,37.2z M33.4,27.2c1.4,0,2.5-1.1,2.5-2.5s-1.1-2.5-2.5-2.5s-2.5,1.1-2.5,2.5S32,27.2,33.4,27.2z M23,22.8c1.6,0,2.9-1.3,2.9-2.9S24.6,17,23,17s-2.9,1.3-2.9,2.9C20.2,21.5,21.5,22.8,23,22.8z"/%3E%3C/defs%3E%3CclipPath id="SVGID_00000111880200341027563210000003406718579453459379_"%3E%3Cuse xlink:href="%23SVGID_1_" style="overflow:visible;"/%3E%3C/clipPath%3E%3Cg id="BarsClipped" style="clip-path:url(%23SVGID_00000111880200341027563210000003406718579453459379_);"%3E%3Cpath class="st3" d="M39.9,31.5L18,37.3c-0.6,0.2-1.2-0.2-1.4-0.8c-0.2-0.6,0.2-1.2,0.8-1.4l21.9-5.9c0.6-0.2,1.2,0.2,1.4,0.8 C40.8,30.7,40.5,31.3,39.9,31.5z"/%3E%3Cpath class="st3" d="M38.1,24.6l-21.9,5.9c-0.6,0.2-1.2-0.2-1.4-0.8c-0.2-0.6,0.2-1.2,0.8-1.4l21.9-5.9c0.6-0.2,1.2,0.2,1.4,0.8 C39,23.8,38.7,24.5,38.1,24.6z"/%3E%3Cpath class="st3" d="M36.2,17.9l-21.9,5.9c-0.6,0.2-1.2-0.2-1.4-0.8c-0.2-0.6,0.2-1.2,0.8-1.4l21.9-5.9c0.6-0.2,1.2,0.2,1.4,0.8 C37.2,17.1,36.8,17.7,36.2,17.9z"/%3E%3C/g%3E%3C/g%3E%3C/g%3E%3Cpath class="st4" d="M23.3,37.2c1.4,0,2.5-1.1,2.5-2.5s-1.1-2.5-2.5-2.5s-2.5,1.1-2.5,2.5C20.8,36.1,21.9,37.2,23.3,37.2z"/%3E%3Cpath class="st4" d="M33.4,27.2c1.4,0,2.5-1.1,2.5-2.5s-1.1-2.5-2.5-2.5s-2.5,1.1-2.5,2.5S32,27.2,33.4,27.2z"/%3E%3Cpath class="st4" d="M23,22.8c1.6,0,2.9-1.3,2.9-2.9S24.6,17,23,17s-2.9,1.3-2.9,2.9C20.2,21.5,21.5,22.8,23,22.8z"/%3E%3Cpath class="st4" d="M23.9,38.2c-1.9,0.5-3.8-0.6-4.3-2.5c-0.5-1.9,0.6-3.8,2.5-4.3s3.8,0.6,4.3,2.5C26.9,35.8,25.8,37.7,23.9,38.2 z M22.6,33.2c-0.9,0.2-1.4,1.1-1.1,2c0.2,0.9,1.1,1.4,2,1.1c0.9-0.2,1.4-1.1,1.1-2C24.3,33.5,23.4,33,22.6,33.2z"/%3E%3Cpath class="st4" d="M34.1,28.2c-1.9,0.5-3.8-0.6-4.3-2.5s0.6-3.8,2.5-4.3c1.9-0.5,3.8,0.6,4.3,2.5C37.1,25.8,36,27.7,34.1,28.2z M32.8,23.2c-0.9,0.2-1.4,1.1-1.1,2c0.2,0.9,1.1,1.4,2,1.1c0.9-0.2,1.4-1.1,1.1-2C34.5,23.5,33.6,23,32.8,23.2z"/%3E%3Cpath class="st4" d="M24.2,23.5c-1.9,0.5-3.8-0.6-4.3-2.5s0.6-3.8,2.5-4.3s3.8,0.6,4.3,2.5S26.1,23,24.2,23.5z M22.9,18.6 c-0.9,0.2-1.4,1.1-1.1,2c0.2,0.9,1.1,1.4,2,1.1c0.9-0.2,1.4-1.1,1.1-2C24.7,18.8,23.8,18.3,22.9,18.6z"/%3E%3Cpath class="st5" d="M26.5,51.5c13.8,0,25-11.2,25-25s-11.2-25-25-25s-25,11.2-25,25S12.7,51.5,26.5,51.5z"/%3E%3Cpath class="st4" d="M33.3,21h10c0.4,0,0.8-0.3,0.8-0.8s-0.3-0.8-0.8-0.8h-10C33.3,20.2,33.3,20.2,33.3,21z"/%3E%3C/g%3E%3Ccircle class="st6" cx="23.3" cy="20.1" r="2.5"/%3E%3Ccircle class="st6" cx="33.2" cy="24.8" r="2.5"/%3E%3Ccircle class="st6" cx="23" cy="34.8" r="2.5"/%3E%3C/svg%3E');
965 + }
966 + .wp-menu-open#toplevel_page_edit-post_type-filter-set .wp-menu-image {
967 + background-image: url('data:image/svg+xml,%3C%3Fxml version="1.0" encoding="utf-8"%3F%3E%3C!-- --%3E%3Csvg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 53 53" style="enable-background:new 0 0 53 53;" xml:space="preserve"%3E%3Cstyle type="text/css"%3E .st0%7Bdisplay:none;%7D .st1%7Bdisplay:inline;%7D .st2%7Bclip-path:url(%23SVGID_00000098199702249043298830000017010845528166695064_);%7D .st3%7Bfill:%23FFFFFF;%7D .st4%7Bdisplay:none;fill:%23FFFFFF;%7D .st5%7Bfill:none;stroke:%23FFFFFF;stroke-width:3;stroke-miterlimit:10;%7D .st6%7Bfill:none;stroke:%23FFFFFF;stroke-width:2;stroke-miterlimit:10;%7D%0A%3C/style%3E%3Cg id="Layer_2_00000047770719710110742230000003923951626148849557_" class="st0"%3E%3Crect x="0" y="0" class="st1" width="53.1" height="53.1"/%3E%3C/g%3E%3Cg id="Layer_1_00000162333103265806981530000017146624247591674556_"%3E%3Cg%3E%3Cdefs%3E%3Cpath id="SVGID_1_" d="M0,0h53v53H0V0z M23.3,37.2c1.4,0,2.5-1.1,2.5-2.5s-1.1-2.5-2.5-2.5s-2.5,1.1-2.5,2.5 C20.8,36.1,21.9,37.2,23.3,37.2z M33.4,27.2c1.4,0,2.5-1.1,2.5-2.5s-1.1-2.5-2.5-2.5s-2.5,1.1-2.5,2.5S32,27.2,33.4,27.2z M23,22.8c1.6,0,2.9-1.3,2.9-2.9S24.6,17,23,17s-2.9,1.3-2.9,2.9C20.2,21.5,21.5,22.8,23,22.8z"/%3E%3C/defs%3E%3CclipPath id="SVGID_00000112608340804245442460000013986219178199086244_"%3E%3Cuse xlink:href="%23SVGID_1_" style="overflow:visible;"/%3E%3C/clipPath%3E%3Cg id="BarsClipped" style="clip-path:url(%23SVGID_00000112608340804245442460000013986219178199086244_);"%3E%3Cpath class="st3" d="M39.9,31.5L18,37.3c-0.6,0.2-1.2-0.2-1.4-0.8c-0.2-0.6,0.2-1.2,0.8-1.4l21.9-5.9c0.6-0.2,1.2,0.2,1.4,0.8 C40.8,30.7,40.5,31.3,39.9,31.5z"/%3E%3Cpath class="st3" d="M38.1,24.6l-21.9,5.9c-0.6,0.2-1.2-0.2-1.4-0.8c-0.2-0.6,0.2-1.2,0.8-1.4l21.9-5.9c0.6-0.2,1.2,0.2,1.4,0.8 C39,23.8,38.7,24.5,38.1,24.6z"/%3E%3Cpath class="st3" d="M36.2,17.9l-21.9,5.9c-0.6,0.2-1.2-0.2-1.4-0.8c-0.2-0.6,0.2-1.2,0.8-1.4l21.9-5.9c0.6-0.2,1.2,0.2,1.4,0.8 C37.2,17.1,36.8,17.7,36.2,17.9z"/%3E%3C/g%3E%3C/g%3E%3Cpath class="st4" d="M23.3,37.2c1.4,0,2.5-1.1,2.5-2.5s-1.1-2.5-2.5-2.5s-2.5,1.1-2.5,2.5C20.8,36.1,21.9,37.2,23.3,37.2z"/%3E%3Cpath class="st4" d="M33.4,27.2c1.4,0,2.5-1.1,2.5-2.5s-1.1-2.5-2.5-2.5s-2.5,1.1-2.5,2.5S32,27.2,33.4,27.2z"/%3E%3Cpath class="st4" d="M23,22.8c1.6,0,2.9-1.3,2.9-2.9S24.6,17,23,17s-2.9,1.3-2.9,2.9C20.2,21.5,21.5,22.8,23,22.8z"/%3E%3Cpath class="st4" d="M23.9,38.2c-1.9,0.5-3.8-0.6-4.3-2.5c-0.5-1.9,0.6-3.8,2.5-4.3s3.8,0.6,4.3,2.5C26.9,35.8,25.8,37.7,23.9,38.2 z M22.6,33.2c-0.9,0.2-1.4,1.1-1.1,2c0.2,0.9,1.1,1.4,2,1.1c0.9-0.2,1.4-1.1,1.1-2C24.3,33.5,23.4,33,22.6,33.2z"/%3E%3Cpath class="st4" d="M34.1,28.2c-1.9,0.5-3.8-0.6-4.3-2.5s0.6-3.8,2.5-4.3c1.9-0.5,3.8,0.6,4.3,2.5C37.1,25.8,36,27.7,34.1,28.2z M32.8,23.2c-0.9,0.2-1.4,1.1-1.1,2c0.2,0.9,1.1,1.4,2,1.1c0.9-0.2,1.4-1.1,1.1-2C34.5,23.5,33.6,23,32.8,23.2z"/%3E%3Cpath class="st4" d="M24.2,23.5c-1.9,0.5-3.8-0.6-4.3-2.5s0.6-3.8,2.5-4.3s3.8,0.6,4.3,2.5S26.1,23,24.2,23.5z M22.9,18.6 c-0.9,0.2-1.4,1.1-1.1,2c0.2,0.9,1.1,1.4,2,1.1c0.9-0.2,1.4-1.1,1.1-2C24.7,18.8,23.8,18.3,22.9,18.6z"/%3E%3Cpath class="st5" d="M26.5,51.5c13.8,0,25-11.2,25-25s-11.2-25-25-25s-25,11.2-25,25S12.7,51.5,26.5,51.5z"/%3E%3Cpath class="st4" d="M33.3,21h10c0.4,0,0.8-0.3,0.8-0.8s-0.3-0.8-0.8-0.8h-10C33.3,20.2,33.3,20.2,33.3,21z"/%3E%3C/g%3E%3Ccircle class="st6" cx="23.3" cy="20.1" r="2.5"/%3E%3Ccircle class="st6" cx="33.2" cy="24.8" r="2.5"/%3E%3Ccircle class="st6" cx="23" cy="34.8" r="2.5"/%3E%3C/svg%3E');
968 + }
969 + PHP_CSS;
970 + wp_add_inline_style($handle, $css);
971 +});
972 +
973 +/**
974 + * Fix Elementor query arguments for filtered content
975 + *
976 + * This function adjusts Elementor's query arguments when dealing with
977 + * filtered content from Filter Everything Pro plugin. It ensures proper
978 + * handling of custom post types in Elementor queries.
979 + *
980 + * @param array $query_args The Elementor query arguments
981 + * @return array Modified query arguments
982 + */
983 +add_filter( 'elementor/query/get_query_args/current_query', 'flrt_fix_elementor_query_args' );
984 +function flrt_fix_elementor_query_args( $query_args ) {
985 + // Verify that we're dealing with a filtered query
986 + if ( ! isset( $query_args['flrt_filtered_query'] ) || !$query_args['flrt_filtered_query'] ) {
987 + return $query_args;
988 + }
989 +
990 + // Get post type from query args or current post
991 + $post_type = isset( $query_args['post_type'] ) ? $query_args['post_type'] : get_post_type();
992 +
993 + // Sanitize the post type
994 + if ( ! empty( $post_type ) ) {
995 + $post_type = sanitize_text_field( $post_type );
996 + }
997 +
998 + // Check if the post type is non-built-in
999 + $post_type_object = get_post_type_object( $post_type );
1000 +
1001 + if ( $post_type_object && !$post_type_object->_builtin ) {
1002 + // Remove taxonomy from query args if present
1003 + if ( isset( $query_args['taxonomy'] ) ) {
1004 + unset( $query_args['taxonomy'] );
1005 + }
1006 + }
1007 +
1008 + return $query_args;
1009 +}
1010 +
1011 +/**
1012 + * Fixes Elementor featured products price range query arguments.
1013 + *
1014 + * This function addresses an issue where Elementor's featured products widget
1015 + * incorrectly applies meta_key filtering when sorting by price, which can
1016 + * interfere with price range filtering functionality. It removes the meta_key
1017 + * from query arguments for featured products sorted by price.
1018 + *
1019 + *
1020 + * @param array $query_args Query arguments for Elementor widget.
1021 + * @param object $widget The Elementor widget instance.
1022 + * @return array Modified query arguments.
1023 + */
1024 +if ( flrt_is_elementor_active() ) {
1025 + add_filter( 'elementor/query/query_args', 'flrt_fix_elementor_featured_products_price_range', 10, 2 );
1026 +
1027 + function flrt_fix_elementor_featured_products_price_range( array $query_args, $widget ): array {
1028 + $is_featured = ( $query_args['post_type'] ?? '' ) === 'featured';
1029 + $is_price_order = ( $query_args['orderby'] ?? '' ) === 'price';
1030 +
1031 + if ( $is_featured && $is_price_order ) {
1032 + static $registered = false;
1033 +
1034 + if ( ! $registered ) {
1035 + add_filter( 'elementor/query/query_args', function ( array $query_args, $widget ): array {
1036 + unset( $query_args['meta_key'] );
1037 + return $query_args;
1038 + }, 11, 2 );
1039 +
1040 + $registered = true;
1041 + }
1042 + }
1043 +
1044 + return $query_args;
1045 + }
1046 +}
1047 +
1048 +
1049 +
1050 +function flrt_is_divi_theme()
1051 +{
1052 + if ( 'Divi' === wp_get_theme()->get('Name') || 'Divi' === wp_get_theme()->get_template() ) {
1053 + return true;
1054 + }
1055 + return false;
1056 +}
1057 +
1058 +if ( flrt_is_divi_theme() ) {
1059 +
1060 + function wpc_initialize_divi_custom_module() {
1061 + if (!class_exists('ET_Builder_Module')) {
1062 + return;
1063 + }
1064 +
1065 + flrt_include('src/Frontend/Builders/DiviWidgets/ChipsDiviWidget.php');
1066 + flrt_include('src/Frontend/Builders/DiviWidgets/FiltersDiviWidget.php');
1067 + flrt_include('src/Frontend/Builders/DiviWidgets/SortingDiviWidget.php');
1068 + }
1069 +
1070 + add_action('et_builder_ready', 'wpc_initialize_divi_custom_module');
1071 +
1072 + add_filter( 'et_builder_inner_content_class', function ($classes){
1073 + $classes[] = 'wpc-divi-inner-content';
1074 + return $classes;
1075 + }, 10 );
1076 +
1077 + if( flrt_get_option('mobile_filter_settings') === 'show_bottom_widget' ) {
1078 + if (flrt_get_experimental_option('disable_buttons') !== 'on') {
1079 + add_action('et_before_main_content', 'flrt_divi_filter_button');
1080 + }
1081 + }
1082 +}
1083 +
1084 +function flrt_divi_filter_button()
1085 +{
1086 + // et_before_main_content fires more than once per page when a Divi Theme
1087 + // Builder header layout is present (both header.php and
1088 + // theme-after-header.php do_action it), so nothing here may declare a
1089 + // function at runtime — the previous nested declaration fataled with
1090 + // "Cannot redeclare modify_specific_module" on the second call.
1091 + // Re-adding the same filter callback is a no-op in WordPress.
1092 + add_filter('et_module_process_display_conditions', 'flrt_divi_modify_specific_module', 10, 3);
1093 +}
1094 +
1095 +function flrt_divi_modify_specific_module($output, $render_slug, $module)
1096 +{
1097 + if ($module->slug === 'filter_everything') {
1098 + flrt_filters_button(0, '', 'et_before_main_content');
1099 + }
1100 + return $output;
1101 +}
1102 +/**
1103 + * Checks if the Breakdance plugin and its required classes/functions are active and exist.
1104 + *
1105 + * This function verifies the presence of the Breakdance plugin, along with specific
1106 + * classes and functions used by the plugin. It returns true only if all checks pass,
1107 + * indicating that Breakdance is properly installed and functional.
1108 + *
1109 + * @return bool True if Breakdance is active and its required components exist, false otherwise.
1110 + */
1111 +function flrt_check_breakdance() {
1112 + // is_plugin_active() lives in wp-admin/includes/plugin.php and is not loaded
1113 + // on the frontend, in WP-CLI or in cron. Fall back to the raw option list.
1114 + if ( ! function_exists( 'is_plugin_active' ) ) {
1115 + $active = (array) get_option( 'active_plugins', [] );
1116 + if ( is_multisite() ) {
1117 + $active = array_merge( $active, array_keys( (array) get_site_option( 'active_sitewide_plugins', [] ) ) );
1118 + }
1119 + if ( ! in_array( 'breakdance/plugin.php', $active, true ) ) {
1120 + return false;
1121 + }
1122 + } elseif ( ! is_plugin_active( 'breakdance/plugin.php' ) ) {
1123 + return false;
1124 + }
1125 +
1126 + if (!function_exists('Breakdance\Util\getDirectoryPathRelativeToPluginFolder')) {
1127 + return false;
1128 + }
1129 +
1130 + return true;
1131 +}
1132 +if(flrt_check_breakdance()){
1133 + function flrt_breakdance_custom_css() {
1134 + echo '<style>
1135 + .breakdance-add-panel__element{
1136 + background: #0A2D48;
1137 + }
1138 + </style>';
1139 + }
1140 + add_action('wp_head', 'flrt_breakdance_custom_css');
1141 + flrt_include('src/Frontend/Builders/breakdance/widgets/breakdance.php');
1142 +}
1143 +
1144 +/**
1145 + * Checks if Bricks Builder theme and its classes are ready to register custom elements.
1146 + *
1147 + * @return bool True if Bricks Builder theme is active and necessary classes exist, false otherwise.
1148 + */
1149 +function flrt_is_bricks_ready_for_elements() {
1150 + $theme = wp_get_theme();
1151 +
1152 + if (
1153 + $theme->get_stylesheet() !== 'bricks' &&
1154 + $theme->get_template() !== 'bricks'
1155 + ) {
1156 + return false;
1157 + }
1158 +
1159 + if ( ! class_exists( '\Bricks\Elements' ) ) {
1160 + return false;
1161 + }
1162 +
1163 + if ( ! method_exists( '\Bricks\Elements', 'register_element' ) ) {
1164 + return false;
1165 + }
1166 +
1167 + return true;
1168 +}
1169 +
1170 +/**
1171 + * Registers custom Bricks elements during WordPress initialization.
1172 + *
1173 + * This function checks if Bricks Builder is ready using flrt_is_bricks_ready_for_elements().
1174 + * If it is, it includes the ChipsBricksWidget.php file and registers the element using Bricks\Elements::register_element().
1175 + */
1176 +
1177 +add_action('init', 'flrt_init_bricks_widgets', 11);
1178 +
1179 +function flrt_init_bricks_widgets() {
1180 + if (flrt_is_bricks_ready_for_elements()) {
1181 + $element_files = [
1182 + FLRT_PLUGIN_DIR_PATH .'src/Frontend/Builders/bricks/ChipsBricksWidget.php',
1183 + FLRT_PLUGIN_DIR_PATH .'src/Frontend/Builders/bricks/FiltersBricksWidget.php',
1184 + FLRT_PLUGIN_DIR_PATH .'src/Frontend/Builders/bricks/SortingBricksWidget.php',
1185 + ];
1186 + foreach ($element_files as $file) {
1187 + \Bricks\Elements::register_element($file);
1188 + }
1189 +
1190 + add_filter( 'bricks/builder/i18n', function( $i18n ) {
1191 + $i18n['filter-everything'] = esc_html__( 'Filter Everything', 'filter-everything' );
1192 + return $i18n;
1193 + } );
1194 +
1195 + function flrt_bricks_custom_css() {
1196 + echo '<style>
1197 + .wpc-fe-icon {
1198 + background: var(--builder-color);
1199 + mask-image: url(' . flrt_get_icon_logo_svg_css() . ');
1200 + mask-repeat: no-repeat;
1201 + mask-size: contain;
1202 + display: inline-block;
1203 + width: 28px;
1204 + height: 28px;
1205 + margin-bottom: -5px;
1206 + }
1207 +
1208 + .bricks-add-element:focus .wpc-fe-icon, .bricks-add-element:hover .wpc-fe-icon {
1209 + background: var(--builder-color-accent);
1210 + }
1211 +
1212 + .structure-item .wpc-fe-icon {
1213 + width: 16px;
1214 + height: 16px;
1215 + margin-bottom: 0px;
1216 + }
1217 + </style>';
1218 + }
1219 + add_action('wp_head', 'flrt_bricks_custom_css');
1220 + }
1221 +}
1222 +
1223 +function wpc_beaver_builder_widgets_load() {
1224 + if ( class_exists( 'FLBuilder' ) ) {
1225 + flrt_include('src/Frontend/Builders/beaver/chips/ChipsBeaverWidget.php');
1226 + flrt_include('src/Frontend/Builders/beaver/filters/FiltersBeaverWidget.php');
1227 + flrt_include('src/Frontend/Builders/beaver/sorting/SortingBeaverWidget.php');
1228 + }
1229 +}
1230 +add_action( 'init', 'wpc_beaver_builder_widgets_load' );
1231 +
1232 +/**
1233 + * XStore theme — "Display variable products as single variations" compatibility.
1234 + *
1235 + * With that XStore option (variable_products_detach) the theme:
1236 + * 1. adds 'product_variation' to the shop query's post_type, hides variable
1237 + * parents via post__not_in and flags the query with single_variations_filter=yes;
1238 + * 2. on posts_clauses (priority 20) appends a TOP-LEVEL
1239 + * "OR ( post_type='product_variation' AND post_status='publish' AND … )"
1240 + * branch, re-implementing WooCommerce's own layered-nav filters for the
1241 + * detached variations (price, rating, brand, chosen attributes from $_GET).
1242 + *
1243 + * The theme knows nothing about Filter Everything, so on FE-filtered pages that
1244 + * OR branch let EVERY published variation into the results, past FE's term
1245 + * constraints — filtering visually "did nothing" (each alternative of a
1246 + * top-level OR must repeat the filter conditions).
1247 + *
1248 + * Fix: append FE's active filter constraints AFTER the theme's branch
1249 + * (priority 30). AND binds tighter than OR, so in
1250 + * <first alternative> OR ( <theme branch> ) AND ( <FE constraints> )
1251 + * the constraints apply to the variations branch only, leaving the first
1252 + * alternative (already filtered by FE the regular way) untouched.
1253 + */
1254 +function flrt_xstore_detached_variations_where( $clauses, $wp_query ) {
1255 + global $wpdb;
1256 +
1257 + if ( is_admin() || empty( $clauses['where'] ) ) {
1258 + return $clauses;
1259 + }
1260 +
1261 + // Only XStore "detached variations" queries that FE has actually filtered.
1262 + if ( $wp_query->get( 'single_variations_filter' ) !== 'yes' || ! $wp_query->get( 'flrt_filtered_query' ) ) {
1263 + return $clauses;
1264 + }
1265 +
1266 + // The theme adds its branch at priority 20 — bail if it is not there.
1267 + if ( strpos( $clauses['where'], "OR ({$wpdb->posts}.post_type = 'product_variation'" ) === false ) {
1268 + return $clauses;
1269 + }
1270 +
1271 + $wpManager = \FilterEverything\Filter\Container::instance()->getWpManager();
1272 + $queried_values = $wpManager->getQueryVar( 'queried_values' );
1273 +
1274 + if ( empty( $queried_values ) || ! is_array( $queried_values ) ) {
1275 + return $clauses;
1276 + }
1277 +
1278 + $conditions = [];
1279 +
1280 + foreach ( $queried_values as $queried ) {
1281 +
1282 + if ( ! isset( $queried['entity'], $queried['e_name'] ) ) {
1283 + continue;
1284 + }
1285 +
1286 + // Taxonomy filters: a variation matches when its PARENT product carries
1287 + // the term (variations have no term_relationships rows of their own).
1288 + if ( $queried['entity'] === 'taxonomy' && ! empty( $queried['values'] ) ) {
1289 + $tax = $queried['e_name'];
1290 + $and_logic = ( isset( $queried['logic'] ) && $queried['logic'] === 'and' );
1291 + $groups = []; // one ttid-group per condition: single for OR-logic, per-term for AND-logic
1292 + $slugs = [];
1293 +
1294 + foreach ( (array) $queried['values'] as $value_slug ) {
1295 + $term = get_term_by( 'slug', $value_slug, $tax );
1296 + if ( ! $term ) {
1297 + continue;
1298 + }
1299 + $slugs[] = esc_sql( $term->slug );
1300 +
1301 + $ttids = [ (int) $term->term_taxonomy_id ];
1302 + if ( is_taxonomy_hierarchical( $tax ) && ! $and_logic ) {
1303 + foreach ( get_term_children( $term->term_id, $tax ) as $child_id ) {
1304 + $child = get_term( $child_id, $tax );
1305 + if ( $child && ! is_wp_error( $child ) ) {
1306 + $ttids[] = (int) $child->term_taxonomy_id;
1307 + }
1308 + }
1309 + }
1310 +
1311 + if ( $and_logic ) {
1312 + $groups[] = $ttids; // every term required — own condition each
1313 + } elseif ( empty( $groups ) ) {
1314 + $groups[] = $ttids; // any term enough — collect into one IN()
1315 + } else {
1316 + $groups[0] = array_merge( $groups[0], $ttids );
1317 + }
1318 + }
1319 +
1320 + if ( empty( $groups ) ) {
1321 + continue;
1322 + }
1323 +
1324 + foreach ( $groups as $group_ttids ) {
1325 + $ttids_in = implode( ',', array_unique( $group_ttids ) );
1326 + $parent_has_term = "{$wpdb->posts}.post_parent IN ( SELECT object_id FROM {$wpdb->term_relationships} WHERE term_taxonomy_id IN ({$ttids_in}) )";
1327 +
1328 + if ( strpos( $tax, 'pa_' ) === 0 && ! $and_logic && ! empty( $slugs ) ) {
1329 + // Variation attributes: prefer the variation's own value —
1330 + // a variation with a DIFFERENT value must not ride in on its
1331 + // parent's term. Variations without own value ("Any …")
1332 + // fall back to the parent's term.
1333 + $meta_key = esc_sql( 'attribute_' . $tax );
1334 + $slugs_in = "'" . implode( "','", $slugs ) . "'";
1335 +
1336 + $conditions[] = "( {$wpdb->posts}.ID IN ( SELECT post_id FROM {$wpdb->postmeta} WHERE meta_key = '{$meta_key}' AND meta_value IN ({$slugs_in}) )"
1337 + . " OR ( {$parent_has_term}"
1338 + . " AND {$wpdb->posts}.ID NOT IN ( SELECT post_id FROM {$wpdb->postmeta} WHERE meta_key = '{$meta_key}' AND meta_value <> '' ) ) )";
1339 + } else {
1340 + $conditions[] = $parent_has_term;
1341 + }
1342 + }
1343 + }
1344 +
1345 + // Numeric meta filters (price and alike): variations carry their own value.
1346 + if ( $queried['entity'] === 'post_meta_num' && isset( $queried['values'] ) && is_array( $queried['values'] ) ) {
1347 + $meta_key = esc_sql( $queried['e_name'] );
1348 + $min = ( isset( $queried['values']['min'] ) && $queried['values']['min'] !== '' ) ? (float) $queried['values']['min'] : false;
1349 + $max = ( isset( $queried['values']['max'] ) && $queried['values']['max'] !== '' ) ? (float) $queried['values']['max'] : false;
1350 +
1351 + $range = [];
1352 + if ( $min !== false ) {
1353 + $range[] = "CAST(meta_value AS DECIMAL(15,6)) >= {$min}";
1354 + }
1355 + if ( $max !== false ) {
1356 + $range[] = "CAST(meta_value AS DECIMAL(15,6)) <= {$max}";
1357 + }
1358 +
1359 + if ( $range ) {
1360 + $conditions[] = "{$wpdb->posts}.ID IN ( SELECT post_id FROM {$wpdb->postmeta} WHERE meta_key = '{$meta_key}' AND " . implode( ' AND ', $range ) . " )";
1361 + }
1362 + }
1363 +
1364 + // Other filter entities (post_meta choices, author, post_date …) are not
1365 + // mirrored into the variations branch yet — they are rare on shop archives.
1366 + }
1367 +
1368 + if ( ! empty( $conditions ) ) {
1369 + $clauses['where'] .= ' AND ( ' . implode( ' ) AND ( ', $conditions ) . ' )';
1370 + }
1371 +
1372 + return $clauses;
1373 +}
1374 +add_filter( 'posts_clauses', 'flrt_xstore_detached_variations_where', 30, 2 );
1375 +
1376 +//@todo check this with PLL support
1377 +//function flrt_add_cpt_to_pll_tmp( $post_types, $is_settings ) {
1378 +// if ( $is_settings ) {
1379 +// $post_types[ FLRT_FILTERS_SET_POST_TYPE ] = FLRT_FILTERS_SET_POST_TYPE;
1380 +// }
1381 +// return $post_types;
1382 +//}