PluginProbe
ShopBuilder – WooCommerce Builder For Elementor / 2.6.3
ShopBuilder – WooCommerce Builder For Elementor v2.6.3
3.4.2 3.4.1 3.4.0 2.0.1 2.0.2 2.0.3 2.1.0 2.1.1 2.1.10 2.1.11 2.1.12 2.1.13 2.1.14 2.1.15 2.1.2 2.1.3 2.1.4 2.1.5 2.1.6 2.1.7 2.1.8 2.1.9 2.2.0 2.2.1 2.2.2 All 63 releases
← All changes | app/Elementor/Helper/RenderHelpers.php +860 -34 2.1.42.6.3 View file →
@@ -8,10 +8,14 @@
8 8 */
9 9
10 10 namespace RadiusTheme\SB\Elementor\Helper;
11 11
12 +use Elementor\Plugin;
13 +use RadiusTheme\SB\Helpers\Cache;
14 +use RadiusTheme\SB\Helpers\Fns;
12 15 use RadiusTheme\SB\Helpers\BuilderFns;
13 -use RadiusTheme\SB\Helpers\Fns;
16 +use WC_Product_Query;
17 +use WP_Term;
14 18
15 19 // Do not allow directly accessing this file.
16 20 if ( ! defined( 'ABSPATH' ) ) {
17 21 exit( 'This script cannot be accessed directly.' );
@@ -21,8 +25,12 @@
21 25 * BuilderFns class
22 26 */
23 27 class RenderHelpers {
24 28 /**
29 + * @var array
30 + */
31 + private static $cache = [];
32 + /**
25 33 * Get data.
26 34 *
27 35 * @param array|string $haystack The array or string to search for the value.
28 36 * @param string $needle The key to look for in the array or the string itself.
@@ -178,8 +186,9 @@
178 186 'out_of_stock_badge_text' => self::get_data( $meta, 'stock_badges_text', esc_html__( 'Out of Stock', 'shopbuilder' ) ),
179 187 'badge_position' => self::get_data( $meta, 'badges_position', 'top' ),
180 188 'badge_alignment' => self::get_data( $meta, 'badges_alignment', 'left' ),
181 189 'badge_preset' => self::get_data( $meta, 'custom_badge_preset', 'preset-1' ),
190 + 'enable_badges_module' => self::get_data( $meta, 'enable_badges_module', '' ),
182 191
183 192 // Link.
184 193 'image_link' => ! empty( $meta['image_link'] ),
185 194 'title_link' => ! empty( $meta['title_link'] ),
@@ -195,8 +204,9 @@
195 204 'auto_play' => ! empty( $meta['slide_autoplay'] ),
196 205 'stop_on_hover' => ! empty( $meta['pause_hover'] ),
197 206 'slider_nav' => ! empty( $meta['slider_nav'] ),
198 207 'slider_dot' => ! empty( $meta['slider_pagi'] ),
208 + 'slider_dynamic_dot' => ! empty( $meta['slider_dynamic_pagi'] ),
199 209 'loop' => ! empty( $meta['slider_loop'] ),
200 210 'lazy_load' => ! empty( $meta['slider_lazy_load'] ),
201 211 'auto_height' => ! empty( $meta['slider_auto_height'] ),
202 212 'speed' => self::get_data( $meta, 'slide_speed', 2000 ),
@@ -407,13 +417,23 @@
407 417 * @return int
408 418 */
409 419 public static function default_columns( $layout ) {
410 420 switch ( $layout ) {
421 + case 'rtsb-post-grid-layout1':
422 + case 'rtsb-post-grid-layout2':
423 + case 'rtsb-post-grid-layout3':
424 + case 'rtsb-team-layout1':
425 + case 'rtsb-team-layout2':
426 + case 'rtsb-testimonial-layout2':
411 427 case 'grid-layout2':
412 428 case 'slider-layout2':
429 + case 'rtsb-coupon-layout1':
430 + case 'rtsb-coupon-layout2':
431 + case 'rtsb-coupon-layout3':
413 432 $columns = 3;
414 433 break;
415 -
434 + case 'rtsb-post-list-layout1':
435 + case 'rtsb-post-list-layout2':
416 436 case 'list-layout1':
417 437 case 'list-layout2':
418 438 case 'list-layout3':
419 439 case 'list-layout7':
@@ -419,9 +439,13 @@
419 439 case 'list-layout7':
420 440 case 'list-layout5':
421 441 $columns = 1;
422 442 break;
423 -
443 + case 'rtsb-team-layout4':
444 + case 'rtsb-testimonial-layout1':
445 + case 'rtsb-testimonial-layout3':
446 + case 'rtsb-testimonial-layout4':
447 + case 'rtsb-testimonial-layout5':
424 448 case 'list-layout4':
425 449 case 'list-layout6':
426 450 case 'slider-layout5':
427 451 case 'slider-layout8':
@@ -426,10 +450,12 @@
426 450 case 'slider-layout5':
427 451 case 'slider-layout8':
428 452 $columns = 2;
429 453 break;
430 -
454 + case 'rtsb-logo-layout1':
455 + case 'rtsb-logo-layout2':
431 456 case 'grid-layout6':
457 + case 'grid-layout9':
432 458 $columns = 5;
433 459 break;
434 460
435 461 case 'category-layout1':
@@ -470,9 +496,10 @@
470 496 public static function prepare_container_classes( $metas = [], $settings = [], $custom_class = '' ) {
471 497 $classes = 'rtsb-elementor-container products rtsb-pos-r ';
472 498 $classes .= $custom_class;
473 499
474 - $layout = $metas['layout'];
500 + $raw_layout = esc_html( $metas['layout'] );
501 + $layout = self::filter_layout( $raw_layout );
475 502 $is_cat = preg_match( '/category/', $layout );
476 503 $cart_txt_class = '';
477 504
478 505 $animation = $metas['hover_animation'];
@@ -532,8 +559,51 @@
532 559 return apply_filters( 'rtsb/product/container/class', $classes, $settings );
533 560 }
534 561
535 562 /**
563 + * Function to filter and validate the layout against allowed patterns.
564 + *
565 + * @param string $layout The layout string to be filtered.
566 + * @param string $template The template to be checked.
567 + *
568 + * @return string
569 + */
570 + public static function filter_layout( $layout, $template = '' ) {
571 + $allowed_patterns = apply_filters( 'rtsb/elementor/custom_layout', [ 'grid', 'list', 'slider', 'category', 'toyup', 'zilly', 'rtsb' ] );
572 + $layout_part = explode( '-', $layout );
573 + $default = 'grid-layout1';
574 +
575 + if ( empty( $layout_part[0] ) ) {
576 + return $default;
577 + }
578 +
579 + if ( in_array( $layout_part[0], $allowed_patterns, true ) ) {
580 + return $layout;
581 + } else {
582 + if ( ! empty( $template ) ) {
583 + $grid = preg_match( '/grid/', $template );
584 + $list = preg_match( '/list/', $template );
585 + $slider = preg_match( '/slider/', $template );
586 + $category = preg_match( '/category/', $template );
587 +
588 + if ( $grid ) {
589 + return $default;
590 + } elseif ( $list ) {
591 + return 'list-layout1';
592 + } elseif ( $slider ) {
593 + return 'slider-layout1';
594 + } elseif ( $category ) {
595 + return 'category-layout1';
596 + } else {
597 + return $default;
598 + }
599 + } else {
600 + return $default;
601 + }
602 + }
603 + }
604 +
605 + /**
536 606 * Row classes
537 607 *
538 608 * @param array $settings Settings array.
539 609 *
@@ -543,9 +613,10 @@
543 613 $masonry_class = null;
544 614 $classes = 'rtsb-row rtsb-content-loader element-loading';
545 615 $loader_class = ' rtsb-pre-loader';
546 616
547 - $layout = $settings['layout'];
617 + $raw_layout = esc_html( $settings['layout'] );
618 + $layout = self::filter_layout( $raw_layout );
548 619 $grid_type = $settings['grid_type'];
549 620 $is_carousel = preg_match( '/slider/', $layout );
550 621
551 622 if ( preg_match( '/category/', $layout ) && ! empty( $settings['active_cat_slider'] ) ) {
@@ -551,12 +622,14 @@
551 622 if ( preg_match( '/category/', $layout ) && ! empty( $settings['active_cat_slider'] ) ) {
552 623 $classes .= ' rtsb-slider-layout';
553 624 }
554 625
555 - if ( 'even' === $grid_type ) {
556 - $masonry_class = ' rtsb-even';
626 + if ( 'equal' === $grid_type ) {
627 + $masonry_class = ' rtsb-equal';
557 628 } elseif ( 'masonry' === $grid_type ) {
558 629 $masonry_class = ' rtsb-masonry';
630 + } else {
631 + $masonry_class = ' rtsb-even';
559 632 }
560 633
561 634 if ( ! rtsb()->has_pro() || $is_carousel ) {
562 635 $masonry_class = ' rtsb-even';
@@ -561,8 +634,19 @@
561 634 if ( ! rtsb()->has_pro() || $is_carousel ) {
562 635 $masonry_class = ' rtsb-even';
563 636 }
564 637
638 + if ( $is_carousel && ! empty( $settings['raw_settings']['always_show_nav'] ) ) {
639 + $classes .= ' always-show-nav';
640 + }
641 +
642 + if ( ! empty( $settings['raw_settings']['inner_slider_always_show_nav'] ) ) {
643 + $classes .= ' inner-slider-always-show-nav';
644 + }
645 + if ( empty( $settings['raw_settings']['cols_mobile'] ) ) {
646 + $classes .= ' rtsb-mobile-flex-row';
647 + }
648 +
565 649 $classes .= ' rtsb-' . $layout . $masonry_class . $loader_class;
566 650
567 651 return apply_filters( 'rtsb/elementor/row/classes', $classes, $settings );
568 652 }
@@ -569,13 +653,13 @@
569 653
570 654 /**
571 655 * Prepare pagination attributes.
572 656 *
573 - * @param string $layout The layout type.
657 + * @param string $layout The layout type.
574 658 * @param bool $has_filters Whether the widget has filters.
575 - * @param string $template The template name.
576 - * @param array $settings The widget settings.
577 - * @param bool $ajax Whether to enable AJAX pagination.
659 + * @param string $template The template name.
660 + * @param array $settings The widget settings.
661 + * @param bool $ajax Whether to enable AJAX pagination.
578 662 *
579 663 * @return string
580 664 */
581 665 public static function prepare_pagination_attr( $layout, $has_filters, $template, $settings, $ajax ) {
@@ -587,9 +671,9 @@
587 671 } elseif ( $is_cat ) {
588 672 return '';
589 673 } else {
590 674 $ajax_pagination = ! empty( $settings['show_pagination'] ) && 'pagination' !== $settings['pagination_type'];
591 - $page = Fns::product_filters_has_ajax( 'shop' ) || Fns::product_filters_has_ajax( 'archive' );
675 + $page = Fns::product_filters_has_ajax( apply_filters( 'rtsb/builder/set/current/page/type', '' ) );
592 676 $condition = rtsb()->has_pro() && $ajax && ( $ajax_pagination || $has_filters || $page );
593 677
594 678 return $condition ? self::pagination_data( $settings, $template ) : '';
595 679 }
@@ -617,15 +701,16 @@
617 701 *
618 702 * @return array
619 703 */
620 704 public static function slider_data( array $meta, $settings = [] ) {
621 - $has_dots = $meta['slider_dot'] ? ' has-dot' : ' no-dot';
622 - $has_dots .= $meta['slider_nav'] ? ' has-nav' : ' no-nav';
623 - $d_col = 0 === $meta['d_cols'] ? self::default_columns( $meta['layout'] ) : $meta['d_cols'];
624 - $t_col = 0 === $meta['t_cols'] ? 2 : $meta['t_cols'];
625 - $m_col = 0 === $meta['m_cols'] ? 1 : $meta['m_cols'];
705 + $has_dots = $meta['slider_dot'] ? ' has-dot' : ' no-dot';
706 + $has_dots .= $meta['slider_nav'] ? ' has-nav' : ' no-nav';
707 + $has_dynamic_dots = $meta['slider_dynamic_dot'] ? true : false;
708 + $d_col = 0 === $meta['d_cols'] ? self::default_columns( $meta['layout'] ) : $meta['d_cols'];
709 + $t_col = 0 === $meta['t_cols'] ? 2 : $meta['t_cols'];
710 + $m_col = 0 === $meta['m_cols'] ? 1 : $meta['m_cols'];
626 711
627 - if ( \Elementor\Plugin::$instance->breakpoints->has_custom_breakpoints() ) {
712 + if ( Plugin::$instance->breakpoints->has_custom_breakpoints() ) {
628 713 // Widescreen.
629 714 $w_col = self::get_data( $settings, 'cols_widescreen' );
630 715 $w_col = 0 === $w_col ? self::default_columns( $meta['layout'] ) : $w_col;
631 716 $w_group = self::get_data( $settings, 'cols_group_widescreen', 1 );
@@ -657,9 +742,9 @@
657 742 0 => [
658 743 'slidesPerView' => absint( $m_col ),
659 744 'slidesPerGroup' => absint( $meta['m_group'] ),
660 745 'pagination' => [
661 - 'dynamicBullets' => true,
746 + 'dynamicBullets' => $has_dynamic_dots,
662 747 ],
663 748 ],
664 749 ];
665 750
@@ -684,16 +769,16 @@
684 769 }
685 770
686 771 foreach ( $el_breakpoints as $el_breakpoint => $value ) {
687 772 $breakpoint_value = ! empty( $value['value'] ) ? $value['value'] : $value['default_value'];
688 - $dynamic_bullets = false;
773 + $dynamic_bullets = $has_dynamic_dots;
689 774 $slides_per_view = $d_col;
690 775 $slides_per_group = $meta['d_group'];
691 776
692 777 switch ( $el_breakpoint ) {
693 778 case 'widescreen':
694 - $slides_per_view = $w_col;
695 - $slides_per_group = $w_group;
779 + $slides_per_view = $w_col;
780 + $slides_per_group = $w_group;
696 781
697 782 break;
698 783
699 784 case 'laptop':
@@ -702,10 +787,10 @@
702 787
703 788 break;
704 789
705 790 case 'tablet_extra':
706 - $slides_per_view = $l_col;
707 - $slides_per_group = $l_group;
791 + $slides_per_view = $l_col;
792 + $slides_per_group = $l_group;
708 793
709 794 if ( empty( $el_breakpoints['laptop'] ) ) {
710 795 $slides_per_view = $d_col;
711 796 $slides_per_group = $meta['d_group'];
@@ -730,11 +815,11 @@
730 815
731 816 break;
732 817
733 818 case 'mobile_extra':
734 - $slides_per_view = $t_col;
735 - $slides_per_group = $meta['t_group'];
736 - $dynamic_bullets = true;
819 + $slides_per_view = $t_col;
820 + $slides_per_group = $meta['t_group'];
821 + $dynamic_bullets = $has_dynamic_dots;
737 822
738 823 break;
739 824
740 825 case 'mobile':
@@ -739,9 +824,9 @@
739 824
740 825 case 'mobile':
741 826 $slides_per_view = $t_col;
742 827 $slides_per_group = $meta['t_group'];
743 - $dynamic_bullets = true;
828 + $dynamic_bullets = $has_dynamic_dots;
744 829
745 830 if ( ! empty( $el_breakpoints['mobile_extra'] ) ) {
746 831 $slides_per_view = $me_col;
747 832 $slides_per_group = $me_group;
@@ -767,9 +852,9 @@
767 852 0 => [
768 853 'slidesPerView' => absint( $m_col ),
769 854 'slidesPerGroup' => absint( $meta['m_group'] ),
770 855 'pagination' => [
771 - 'dynamicBullets' => true,
856 + 'dynamicBullets' => $has_dynamic_dots,
772 857 ],
773 858 ],
774 859 768 => [
775 860 'slidesPerView' => absint( $t_col ),
@@ -774,9 +859,9 @@
774 859 768 => [
775 860 'slidesPerView' => absint( $t_col ),
776 861 'slidesPerGroup' => absint( $meta['t_group'] ),
777 862 'pagination' => [
778 - 'dynamicBullets' => false,
863 + 'dynamicBullets' => $has_dynamic_dots,
779 864 ],
780 865 ],
781 866 1025 => [
782 867 'slidesPerView' => absint( $d_col ),
@@ -781,9 +866,9 @@
781 866 1025 => [
782 867 'slidesPerView' => absint( $d_col ),
783 868 'slidesPerGroup' => absint( $meta['d_group'] ),
784 869 'pagination' => [
785 - 'dynamicBullets' => false,
870 + 'dynamicBullets' => $has_dynamic_dots,
786 871 ],
787 872 ],
788 873 ];
789 874 }
@@ -876,10 +961,11 @@
876 961 *
877 962 * @return void
878 963 */
879 964 public static function register_scripts( $scripts ) {
880 - $caro = false;
881 - $script = [];
965 + $caro = false;
966 + $masonry = false;
967 + $script = [];
882 968
883 969 $script[] = 'jquery';
884 970
885 971 foreach ( $scripts as $sc => $value ) {
@@ -886,8 +972,12 @@
886 972 if ( ! empty( $sc ) ) {
887 973 if ( 'isCarousel' === $sc ) {
888 974 $caro = $value;
889 975 }
976 +
977 + if ( 'isMasonry' === $sc ) {
978 + $masonry = $value;
979 + }
890 980 }
891 981 }
892 982
893 983 if ( count( $scripts ) ) {
@@ -897,8 +987,12 @@
897 987 if ( $caro ) {
898 988 $script[] = 'swiper';
899 989 }
900 990
991 + if ( $masonry ) {
992 + $script[] = 'masonry';
993 + }
994 +
901 995 $script[] = 'rtsb-imagesloaded';
902 996 $script[] = 'rtsb-public';
903 997
904 998 foreach ( $script as $sc ) {
@@ -943,6 +1037,738 @@
943 1037 $products_col = absint( get_option( 'woocommerce_catalog_columns', 4 ) );
944 1038 $products_per_page = apply_filters( 'rtsb/elementor/archive/products_per_page', $products_row * $products_col );
945 1039
946 1040 return ! empty( $products_per_page ) ? $products_per_page : 12;
1041 + }
1042 + /**
1043 + * Render Filters View.
1044 + *
1045 + * @param array $templates Template name.
1046 + * @param array $settings Control settings.
1047 + *
1048 + * @return string
1049 + */
1050 + public static function filters_view( $templates, $settings ) {
1051 + global $wp;
1052 + $filters = [];
1053 + $html = null;
1054 + $reset = ! empty( $settings['reset_btn'] );
1055 + $reset_mode = 'show' === $settings['reset_btn_behavior'] ? ' show-reset' : ' ondemand-reset';
1056 + $reset_text = ! empty( $settings['reset_btn_text'] ) ? $settings['reset_btn_text'] : esc_html__( 'Reset Filter', 'shopbuilder' );
1057 + $scroll_mode = ! empty( $settings['enable_scroll'] ) ? ' has-scroll' : ' no-scroll';
1058 + $scroll_height = ! empty( $settings['enable_scroll'] ) ? $settings['scroll_height']['size'] : 300;
1059 +
1060 + $scroll_attr = '';
1061 +
1062 + if ( ! empty( $settings['enable_scroll'] ) ) {
1063 + $scroll_attr = ' style="--rtsb-filter-scroll-height: ' . absint( $scroll_height ) . 'px;"';
1064 + }
1065 +
1066 + foreach ( $settings['filter_types'] as $key => $item ) {
1067 + if ( ! defined( 'RTWPVS_PLUGIN_FILE' ) && in_array( $item['input_type_all'], [ 'color', 'button', 'image' ], true ) ) {
1068 + $item['input_type_all'] = 'checkbox';
1069 + }
1070 + $filters[] = [
1071 + 'filter_title' => $item['filter_title'],
1072 + 'filter_items' => $item['filter_items'],
1073 + 'filter_attr' => $item['filter_attr'],
1074 + 'input_type' => 'product_attr' === $item['filter_items'] ? $item['input_type_all'] : $item['input_type'],
1075 + ];
1076 +
1077 + if ( 'rating_filter' === $item['filter_items'] ) {
1078 + $filters[ $key ]['template'] = $templates['rating'];
1079 + } elseif ( 'price_filter' === $item['filter_items'] ) {
1080 +
1081 + $filters[ $key ]['input_type'] = 'slider';
1082 + $filters[ $key ]['template'] = $templates['price'];
1083 + } else {
1084 + $filters[ $key ]['template'] = 'product_attr' === $item['filter_items'] ? $templates[ $item['input_type_all'] ] : $templates[ $item['input_type'] ];
1085 + }
1086 + }
1087 +
1088 + if ( '' === get_option( 'permalink_structure' ) ) {
1089 + $form_action = remove_query_arg( [ 'page', 'paged', 'product-page' ], add_query_arg( $wp->query_string, '', home_url( $wp->request ) ) );
1090 + } else {
1091 + $form_action = preg_replace( '%\/page/[0-9]+%', '', home_url( trailingslashit( $wp->request ) ) );
1092 + }
1093 + $args = [
1094 + 'filters' => $filters,
1095 + 'scroll_mode' => $scroll_mode,
1096 + 'reset_mode' => $reset_mode,
1097 + 'reset' => $reset,
1098 + 'scroll_attr' => $scroll_attr,
1099 + 'reset_text' => $reset_text,
1100 + 'settings' => $settings,
1101 + 'form_action' => $form_action,
1102 + ];
1103 +
1104 + $html .= '<div class="rtsb-default-archive-filters">';
1105 +
1106 + $html .= Fns::load_template( $templates['layout'], $args, true );
1107 + $html .= '</div>';
1108 + return $html;
1109 + }
1110 + /**
1111 + * Get taxonomy type.
1112 + *
1113 + * @param string $tax_type Taxonomy type.
1114 + * @param string $attr_type Attribute type.
1115 + *
1116 + * @return string
1117 + */
1118 + public static function get_product_filters_tax_type( $tax_type, $attr_type = '' ) {
1119 + if ( 'product_attr' !== $tax_type ) {
1120 + return $tax_type;
1121 + }
1122 +
1123 + if ( empty( $attr_type ) ) {
1124 + return $tax_type;
1125 + }
1126 +
1127 + return $attr_type;
1128 + }
1129 + /**
1130 + * Get attribute terms.
1131 + *
1132 + * @param string $tax Taxonomy type.
1133 + * @return int[]|string|string[]|\WP_Error|\WP_Term[]
1134 + */
1135 + public static function get_product_filters_attribute_terms( $tax ) {
1136 + $cache_key = 'get_default_filter_attribute_terms_' . $tax;
1137 + if ( isset( self::$cache[ $cache_key ] ) ) {
1138 + return self::$cache[ $cache_key ];
1139 + }
1140 +
1141 + $attributes = wc_get_attribute_taxonomies();
1142 + $att_name = str_replace( 'pa_', '', $tax );
1143 + $exist = array_search( $att_name, array_column( $attributes, 'attribute_name' ), true );
1144 + if ( false === $exist ) {
1145 + self::$cache[ $cache_key ] = [];
1146 + return self::$cache[ $cache_key ];
1147 + }
1148 + $attribute = $tax;
1149 +
1150 + if ( ! is_shop() && is_product_taxonomy() ) {
1151 + $term = get_queried_object();
1152 +
1153 + if ( ! $term instanceof WP_Term ) {
1154 + return [];
1155 + }
1156 +
1157 + $args = [
1158 + 'status' => 'publish',
1159 + 'limit' => -1,
1160 + 'return' => 'ids',
1161 + ];
1162 +
1163 + if ( 'product_cat' === $term->taxonomy ) {
1164 + $args['category'] = [ $term->slug ];
1165 + }
1166 +
1167 + if ( 'product_tag' === $term->taxonomy ) {
1168 + $args['tag'] = [ $term->slug ];
1169 + }
1170 +
1171 + if ( strpos( $term->taxonomy, 'pa_' ) !== false ) {
1172 + $args['tax_query'] = [ // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_tax_query
1173 + [
1174 + 'taxonomy' => $term->taxonomy,
1175 + 'field' => 'term_id',
1176 + 'terms' => $term->term_id,
1177 + 'operator' => 'IN',
1178 + ],
1179 + ];
1180 + }
1181 +
1182 + $query = new WC_Product_Query( $args );
1183 + $products = $query->get_products();
1184 + $attr_terms = [];
1185 +
1186 + foreach ( $products as $product_id ) {
1187 + $product_attr = wp_get_post_terms( $product_id, $attribute );
1188 +
1189 + foreach ( $product_attr as $attr ) {
1190 + $attr_terms[] = $attr;
1191 + }
1192 + }
1193 + self::$cache[ $cache_key ] = self::filter_products_array_unique( $attr_terms );
1194 + return self::$cache[ $cache_key ];
1195 + } else {
1196 + self::$cache[ $cache_key ] = get_terms(
1197 + [
1198 + 'taxonomy' => $attribute,
1199 + 'hide_empty' => false,
1200 + ]
1201 + );
1202 + return self::$cache[ $cache_key ];
1203 + }
1204 + }
1205 + /**
1206 + * Remove duplicate values from an array.
1207 + *
1208 + * @param array $array The input array.
1209 + * @param bool $keep_key_assoc Whether to keep the key associations after removing duplicates.
1210 + * @return array The array with duplicates removed.
1211 + */
1212 + public static function filter_products_array_unique( $array, $keep_key_assoc = false ) {
1213 + $duplicate_keys = [];
1214 + $tmp = [];
1215 +
1216 + foreach ( $array as $key => $val ) {
1217 + // convert objects to arrays, in_array() does not support objects.
1218 + if ( is_object( $val ) ) {
1219 + $val = (array) $val;
1220 + }
1221 +
1222 + if ( ! in_array( $val, $tmp, true ) ) {
1223 + $tmp[] = $val;
1224 + } else {
1225 + $duplicate_keys[] = $key;
1226 + }
1227 + }
1228 +
1229 + foreach ( $duplicate_keys as $key ) {
1230 + unset( $array[ $key ] );
1231 + }
1232 +
1233 + return $keep_key_assoc ? $array : array_values( $array );
1234 + }
1235 + /**
1236 + * Retrieve product categories (including hierarchical support)
1237 + *
1238 + * @param string $taxonomy Taxonomy name.
1239 + * @return int[]|string|string[]|\WP_Error|\WP_Term[]
1240 + */
1241 + public static function get_products( $taxonomy ) {
1242 + $args = [
1243 + 'taxonomy' => esc_html( $taxonomy ),
1244 + 'hide_empty' => false,
1245 + 'pad_counts' => true,
1246 + 'hierarchical' => true,
1247 + ];
1248 +
1249 + $cache_key = 'rtsb_get_terms_filter_products' . $taxonomy;
1250 + $taxonomy_terms = wp_cache_get( $cache_key, 'shopbuilder' );
1251 +
1252 + if ( false === $taxonomy_terms ) {
1253 + $queried_object = get_queried_object();
1254 +
1255 + if ( 'archive' === apply_filters( 'rtsb/builder/set/current/page/type', '' ) && $queried_object instanceof WP_Term && $queried_object->taxonomy === $taxonomy ) {
1256 + $term_id = $queried_object->term_id;
1257 + $taxonomy = $queried_object->taxonomy;
1258 + $archive_cache_key = 'rtsb_get_terms_filter_products_' . $taxonomy . $term_id;
1259 + $taxonomy_terms = wp_cache_get( $archive_cache_key, 'shopbuilder' );
1260 + if ( false === $taxonomy_terms ) {
1261 + $taxonomy_terms = [ $queried_object ];
1262 + $child_args = [
1263 + 'taxonomy' => $taxonomy,
1264 + 'child_of' => $term_id,
1265 + 'hide_empty' => false,
1266 + ];
1267 +
1268 + $child_terms = get_terms( $child_args );
1269 +
1270 + if ( ! empty( $child_terms ) ) {
1271 + $taxonomy_terms = array_merge( $taxonomy_terms, $child_terms );
1272 + }
1273 +
1274 + wp_cache_set( $archive_cache_key, $taxonomy_terms, 'shopbuilder' );
1275 + Cache::set_data_cache_key( $archive_cache_key );
1276 + }
1277 + } else {
1278 + $taxonomy_terms = get_terms( $args );
1279 + }
1280 +
1281 + wp_cache_set( $cache_key, $taxonomy_terms, 'shopbuilder' );
1282 + Cache::set_data_cache_key( $cache_key );
1283 + }
1284 +
1285 + return $taxonomy_terms;
1286 + }
1287 + /**
1288 + * Generates an error message block.
1289 + *
1290 + * @param array $title The title array of the error message block.
1291 + * @param string $wrapper Additional CSS class for the wrapper div.
1292 + *
1293 + * @return string The HTML representation of the error message block.
1294 + */
1295 + public static function filter_error_message( $title, $wrapper ) {
1296 + $html = '<div class="rtsb-product-default-filters ' . esc_attr( $wrapper ) . '">';
1297 + $html .= self::get_default_filter_title( $title );
1298 + $html .= '<div class="default-filter-content">';
1299 + $html .= '<p class="no-filter">' . esc_html__( 'Nothing found.', 'shopbuilder' ) . '</p>';
1300 + $html .= '</div>';
1301 + $html .= '</div>';
1302 +
1303 + return $html;
1304 + }
1305 + /**
1306 + * Get filter title.
1307 + *
1308 + * @param array $title Filter title.
1309 + * @return string
1310 + */
1311 + public static function get_default_filter_title( $title ) {
1312 + $html = '';
1313 +
1314 + if ( empty( $title['title'] ) ) {
1315 + return $html;
1316 + }
1317 +
1318 + $html .= '<div class="default-filter-title-wrapper">';
1319 +
1320 + $html .= '<h3 class="widget-title rtsb-d-flex rtsb-align-items-center"><span class="title">' . $title['title'] . '</span></h3>';
1321 +
1322 + $html .= '</div>';
1323 +
1324 + return apply_filters( 'rtsb/elementor/default/filter/title', $html, $title );
1325 + }
1326 + /**
1327 + * Recursive function to generate the filter list with hierarchy.
1328 + *
1329 + * @param array $data Array of required data.
1330 + * @param string $input Type of input field for the filter (e.g., checkbox).
1331 + * @param array $additional_data Data for additional filtering.
1332 + * @param int $parent ID of the parent term (default: 0).
1333 + *
1334 + * @return string The generated HTML for the product filter list.
1335 + */
1336 + public static function get_product_default_filter_list_html( $data, $input = 'checkbox', $additional_data = [], $parent = 0 ) {
1337 +
1338 + $html = '';
1339 + $default_tax = [];
1340 + $is_attribute = ! empty( $data['is_attribute'] );
1341 + $active_option = isset( $_GET[ $additional_data['taxonomy'] ] ) ? explode( ',', wc_clean( wp_unslash( $_GET[ $additional_data['taxonomy'] ] ) ) ) : []; // phpcs:ignore WordPress.Security.NonceVerification.Recommended, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
1342 + $counter = 0;
1343 +
1344 + if ( $is_attribute ) {
1345 + list(
1346 + 'filter_name' => $filter_name,
1347 + 'base_link' => $base_link
1348 + ) = self::get_product_filters_attribute_term_info( $additional_data['taxonomy'] );
1349 + }
1350 +
1351 + $html .= '<ul class="product-default-filters input-type-' . esc_attr( $input ) . '">';
1352 +
1353 + foreach ( $data['taxonomy'] as $tax ) {
1354 + if ( $tax->parent !== $parent ) {
1355 + continue;
1356 + }
1357 +
1358 + if ( $is_attribute ) {
1359 + $tax_link = remove_query_arg( $filter_name, $base_link );
1360 + $tax_link = add_query_arg( $filter_name, $tax->slug, $tax_link );
1361 + $active_option = isset( $_GET[ $filter_name ] ) ? explode( ',', sanitize_text_field( wp_unslash( $_GET[ $filter_name ] ) ) ) : []; // phpcs:ignore WordPress.Security.NonceVerification.Recommended
1362 + } else {
1363 + $tax_link = get_term_link( $tax );
1364 + }
1365 +
1366 + $unique_id = substr( uniqid(), -4 );
1367 +
1368 + $active_tax = in_array( $tax->slug, $active_option, true ) ? ' checked' : '';
1369 + $active_tax_parent = in_array( $tax->slug, $active_option, true ) ? ' active' : '';
1370 + $term_children = 'product_cat' === $tax->taxonomy ? get_term_children( $tax->term_id, $tax->taxonomy ) : [];
1371 + $taxonomy = $tax->taxonomy;
1372 + $product_count = $tax->count;
1373 +
1374 + // Show count.
1375 + if ( 'archive' === apply_filters( 'rtsb/builder/set/current/page/type', '' ) && ! empty( $data['count_display'] ) && 'block' === $data['count_display'] ) {
1376 + $product_count = self::count_tax_data( $tax, $tax->count );
1377 + }
1378 +
1379 + // Show Empty Categories.
1380 + if ( empty( $data['show_empty_terms'] ) && 0 === $product_count ) {
1381 + continue;
1382 + }
1383 +
1384 + $html .= '<li class="rtsb-default-filter-term-item term-item-' . absint( $tax->term_id ) . esc_attr( $term_children ? ' term-has-children' : '' ) . ( ! $data['show_child'] ? ' child-terms-hidden' : '' ) . '">
1385 + <div class="rtsb-default-filter-group' . esc_attr( $active_tax_parent ) . '">
1386 + <input type="' . esc_attr( $input ) . '" class="rtsb-default-filter-trigger rtsb-' . esc_attr( $input . '-filter rtsb-term-' . $tax->slug . $active_tax ) . '" name="rtsb-filter-' . esc_attr( $taxonomy ) . '[]" id="rtsb-default-term-filter-' . $unique_id . absint( $tax->term_id ) . '" value="' . esc_attr( $tax->slug ) . '" ' . esc_attr( $active_tax ) . '>
1387 + <label class="rtsb-default-' . esc_attr( $input ) . '-filter-label" for="rtsb-default-term-filter-' . $unique_id . absint( $tax->term_id ) . '">
1388 + <span class="name">' . esc_html( $tax->name ) . '</span>
1389 + </label>
1390 + <div class="rtsb-product-count">(' . esc_html( $product_count ) . ')</div>
1391 + ' . ( ! empty( $term_children ) && $data['show_child'] ? '<i class="rtsb-plus-icon"></i>' : '' ) . '
1392 + </div>';
1393 +
1394 + // Show Sub-categories.
1395 + if ( $data['show_child'] ) {
1396 + $children = self::get_product_default_filter_list_html( $data, $input, $additional_data, $tax->term_id );
1397 +
1398 + if ( ! empty( $children ) ) {
1399 + $html .= '<div class="filter-child">' . $children . '</div>';
1400 + }
1401 + }
1402 +
1403 + $counter++;
1404 +
1405 + $html .= '</li>';
1406 + }
1407 +
1408 + $html .= '</ul>';
1409 +
1410 + // Check if the output contains any child elements.
1411 + $has_children = strpos( $html, '<li class="rtsb-default-filter-term-item' ) !== false;
1412 +
1413 + if ( ! $has_children ) {
1414 + // Remove the outer <ul> if there are no child elements.
1415 + $html = '';
1416 + }
1417 + return $html;
1418 + }
1419 + /**
1420 + * Get attribute term info.
1421 + *
1422 + * @param string $tax Taxonomy type.
1423 + * @return array
1424 + */
1425 + public static function get_product_filters_attribute_term_info( $tax ) {
1426 + $result = [];
1427 + $attributes = wc_get_attribute_taxonomies();
1428 +
1429 + foreach ( $attributes as $attr ) {
1430 + if ( str_replace( 'pa_', '', $tax ) === $attr->attribute_name ) {
1431 + $term_type = $attr->attribute_type;
1432 + $attribute_slug = $attr->attribute_name;
1433 + $attribute = wc_attribute_taxonomy_name( $attr->attribute_name );
1434 + break;
1435 + }
1436 + }
1437 +
1438 + $filter_name = 'filter_' . wc_attribute_taxonomy_slug( $attribute_slug );
1439 +
1440 + $result['attribute'] = $attribute ?? '';
1441 + $result['term_type'] = $term_type ?? '';
1442 + $result['attribute_slug'] = $attribute_slug ?? '';
1443 + $result['filter_name'] = $filter_name;
1444 + $result['base_link'] = self::get_base_url();
1445 +
1446 + return $result;
1447 + }
1448 + /**
1449 + * Get base URL.
1450 + *
1451 + * @return string|null
1452 + */
1453 + public static function get_base_url() {
1454 + global $wp;
1455 + return home_url( add_query_arg( [], $wp->request ) );
1456 + }
1457 + /**
1458 + * Count the number of occurrences for a specific term in a taxonomy for the current queried object.
1459 + *
1460 + * @param object|array $tax The term object for the taxonomy.
1461 + * @param int $count The initial count value.
1462 + *
1463 + * @return int The updated count value.
1464 + */
1465 + public static function count_tax_data( $tax, $count ) {
1466 + $page = get_queried_object();
1467 +
1468 + if ( is_array( $tax ) && strpos( $tax['taxonomy'], 'attribute_' ) !== false ) {
1469 + $taxonomy = str_replace( 'attribute_', '', $tax['taxonomy'] );
1470 + $term_id = $tax['term_id'];
1471 + } else {
1472 + $taxonomy = $tax->taxonomy;
1473 + $term_id = $tax->term_id;
1474 + }
1475 +
1476 + if ( strpos( $page->taxonomy, 'pa_' ) !== false ) {
1477 + $args['status'] = 'publish';
1478 + $args['limit'] = -1;
1479 + $args['return'] = 'ids';
1480 + $args['tax_query'] = [ // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_tax_query
1481 + 'relation' => 'AND',
1482 + [
1483 + 'taxonomy' => $page->taxonomy,
1484 + 'field' => 'term_id',
1485 + 'terms' => $page->term_id,
1486 + 'operator' => 'IN',
1487 + ],
1488 + [
1489 + 'taxonomy' => $tax->taxonomy,
1490 + 'field' => 'term_id',
1491 + 'terms' => $tax->term_id,
1492 + 'operator' => 'IN',
1493 + ],
1494 + ];
1495 +
1496 + $query = new WC_Product_Query( $args );
1497 + $products = $query->get_products();
1498 +
1499 + return count( $products );
1500 + }
1501 +
1502 + if ( $taxonomy !== $page->taxonomy ) {
1503 + $args = [
1504 + 'limit' => -1,
1505 + 'return' => 'ids',
1506 + 'status' => 'publish',
1507 + 'tax_query' => [ // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_tax_query
1508 + [
1509 + 'taxonomy' => $taxonomy,
1510 + 'field' => 'term_id',
1511 + 'terms' => $term_id,
1512 + ],
1513 + ],
1514 + ];
1515 +
1516 + if ( 'product_cat' === $page->taxonomy ) {
1517 + $args['category'] = [ $page->slug ];
1518 + }
1519 +
1520 + if ( 'product_tag' === $page->taxonomy ) {
1521 + $args['tag'] = [ $page->slug ];
1522 + }
1523 +
1524 + $query = new WC_Product_Query( $args );
1525 + $products = $query->get_products();
1526 +
1527 + $count = count( $products );
1528 + }
1529 +
1530 + return $count;
1531 + }
1532 + /**
1533 + * Get filter HTML.
1534 + *
1535 + * @param string $filter_type Filter type.
1536 + * @param array $options Options.
1537 + * @param array $additional_data Data for additional filtering.
1538 + * @param string $input Input type.
1539 + *
1540 + * @return string The generated HTML for the attribute filter list.
1541 + */
1542 + public static function get_default_filter_html( $filter_type, $options, $additional_data = [], $input = 'checkbox' ) {
1543 + $html = '<ul class="product-filters input-type-' . esc_attr( $input ) . '" ';
1544 + $active_option = isset( $_GET[ $filter_type ] ) ? explode( ',', wc_clean( wp_unslash( $_GET[ $filter_type ] ) ) ) : []; // phpcs:ignore WordPress.Security.NonceVerification.Recommended, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
1545 + $option_link = self::get_base_url() . '/' . $filter_type . '/';
1546 +
1547 + foreach ( $options as $option => $option_name ) {
1548 + $unique_id = substr( uniqid(), -6 );
1549 + $active_tax = in_array( $option, $active_option, true ) ? ' checked' : '';
1550 + $active_group = in_array( $option, $active_option, true ) ? ' active' : '';
1551 +
1552 + $html .= '
1553 + <li class="rtsb-term-item">
1554 + <div class="rtsb-default-filter-group' . esc_attr( $active_group ) . '">
1555 + <input type="' . esc_attr( $input ) . '" class="rtsb-default-filter-trigger rtsb-' . esc_attr( $input ) . '-filter rtsb-term-' . esc_attr( $option ) . esc_attr( $active_tax ) . '" name="rtsb-filter-' . esc_attr( $filter_type ) . '[]" id="rtsb-term-default-filter-' . $unique_id . '" value="' . esc_attr( $option ) . '" ' . $active_tax . '>
1556 + <label class="rtsb-default-' . esc_attr( $input ) . '-filter-label" for="rtsb-term-default-filter-' . $unique_id . '">
1557 + <span class="name">' . esc_html( $option_name ) . '</span>
1558 + </label>
1559 + </div>
1560 + </li>';
1561 + }
1562 +
1563 + $html .= '</ul>';
1564 +
1565 + return $html;
1566 + }
1567 + /**
1568 + * Get the count of products with a specific star rating.
1569 + *
1570 + * @param int $star_rating The star rating value.
1571 + *
1572 + * @return int
1573 + */
1574 + public static function get_product_rating_count( $star_rating ) {
1575 + $args = [
1576 + 'status' => 'publish',
1577 + 'limit' => -1,
1578 + 'product_rating' => sprintf( '%.1f', $star_rating ),
1579 + ];
1580 +
1581 + if ( is_product_taxonomy() ) {
1582 + $term = get_queried_object();
1583 + $term_type = 'product_cat' === $term->taxonomy ? 'product_category_id' : 'product_tag_id';
1584 +
1585 + if ( $term instanceof WP_Term ) {
1586 + $args[ $term_type ] = [ $term->term_id ];
1587 + }
1588 + }
1589 +
1590 + $query = new WC_Product_Query( $args );
1591 + $products = $query->get_products();
1592 +
1593 + return count( $products );
1594 + }
1595 + /**
1596 + * Get attribute filter HTML.
1597 + *
1598 + * @param array $data Array of required data.
1599 + * @param string $input Type of input field for the filter (e.g., color).
1600 + * @param array $additional_data Data for additional filtering.
1601 + *
1602 + * @return string The generated HTML for the attribute filter list.
1603 + */
1604 + public static function get_attribute_filter_list_html( $data, $input = 'color', $additional_data = [] ) {
1605 + if ( ! function_exists( 'rtwpvs' ) ) {
1606 + return '';
1607 + }
1608 +
1609 + $terms = $data['terms'];
1610 + $term_info = $data['term_info'];
1611 + $show_tooltips = $data['show_tooltips'];
1612 + $show_empty_terms = $data['show_empty_terms'];
1613 + $counter = 0;
1614 +
1615 + $html = '<ul class="product-default-filters rtsb-terms-wrapper ' . esc_attr( $term_info['type'] ) . '-variable-wrapper' . esc_attr( $data['show_label'] ) . '">';
1616 +
1617 + foreach ( $terms as $attr_term ) {
1618 + $count = $attr_term->count;
1619 + $term_link = remove_query_arg( $term_info['filter_name'], $term_info['base_link'] );
1620 + $term_link = add_query_arg( $term_info['filter_name'], $attr_term->slug, $term_link );
1621 + $unique_id = substr( uniqid(), -6 );
1622 + $name = 'term-' . wc_variation_attribute_name( $term_info['attribute'] ) . '-' . $unique_id;
1623 + $selected_class = in_array( $attr_term->slug, $term_info['current_filter'], true ) ? ' selected' : '';
1624 + $selected_item = in_array( $attr_term->slug, $term_info['current_filter'], true ) ? ' checked' : '';
1625 + $active_class = in_array( $attr_term->slug, $term_info['current_filter'], true ) ? ' active' : '';
1626 +
1627 + $args = [
1628 + 'id' => $name,
1629 + 'name' => $attr_term->name,
1630 + 'link' => $term_link,
1631 + 'type' => $term_info['type'],
1632 + 'term_id' => $attr_term->term_id,
1633 + 'term_slug' => $attr_term->slug,
1634 + 'taxonomy' => wc_variation_attribute_name( $term_info['attribute'] ),
1635 + 'tooltips' => $show_tooltips,
1636 + 'attribute_name' => $term_info['attribute'],
1637 + 'selected_item' => $selected_item,
1638 + ];
1639 +
1640 + if ( 'archive' === apply_filters( 'rtsb/builder/set/current/page/type', '' ) && ! empty( $data['count_display'] ) && 'block' === $data['count_display'] ) {
1641 + $count = self::count_tax_data( $args, $attr_term->count );
1642 + }
1643 +
1644 + $args['count'] = $count;
1645 +
1646 + if ( ! $show_empty_terms && 0 === $count ) {
1647 + continue;
1648 + }
1649 +
1650 + $html .= '<li class="rtsb-default-filter-term-item term-item-' . esc_attr( $attr_term->term_id ) . ' rtsb-term rtsb-default-' . esc_attr( $input ) . '-term ' . esc_attr( $term_info['type'] ) . '-variable-term-' . esc_attr( $attr_term->slug ) . esc_attr( $selected_class ) . '">';
1651 + $html .= '<div class="rtsb-default-filter-group' . esc_attr( $active_class ) . '">';
1652 + $html .= self::get_input_type_html( $input, $args );
1653 +
1654 + $counter++;
1655 +
1656 + $html .= '</div>';
1657 + $html .= '</li>';
1658 + }
1659 +
1660 + $html .= '</ul>';
1661 +
1662 + return $html;
1663 + }
1664 + /**
1665 + * Get input type HTML.
1666 + *
1667 + * @param string $input Input type.
1668 + * @param array $args Args.
1669 + * @return mixed|string|null
1670 + */
1671 + public static function get_input_type_html( $input, $args ) {
1672 + $html = '';
1673 + $count = $args['count'];
1674 +
1675 + switch ( $input ) {
1676 + case 'color':
1677 + $color = sanitize_hex_color( get_term_meta( $args['term_id'], 'product_attribute_color', true ) );
1678 +
1679 + $html .= sprintf(
1680 + '<input type="checkbox" id="' . esc_attr( $args['id'] ) . '" value="' . esc_attr( $args['term_slug'] ) . '" class="rtsb-attr-hidden-field" name="rtsb-filter-' . esc_attr( $args['attribute_name'] ) . '[]' . '" ' . esc_attr( $args['selected_item'] ) . '/><label for="%s" title="' . esc_attr( $args['name'] ) . '" class="rtsb-default-filter-trigger rtsb-attr-filter rtsb-color-filter rtsb-term-span rtsb-term-span-%s%s"><span class="default-filter-attr-color" style="background-color:%s;"></span><span class="default-filter-attr-name">%s</span></label><div class="rtsb-count">(%s)</div>',
1681 + esc_attr( $args['id'] ),
1682 + esc_attr( $args['type'] ),
1683 + $args['tooltips'] ? esc_attr( ' tipsy' ) : '',
1684 + esc_attr( $color ),
1685 + esc_html( $args['name'] ),
1686 + absint( $count )
1687 + );
1688 + break;
1689 +
1690 + case 'image':
1691 + if ( ! function_exists( 'rtwpvs' ) ) {
1692 + return $html;
1693 + }
1694 +
1695 + $attachment_id = absint( get_term_meta( $args['term_id'], 'product_attribute_image', true ) );
1696 + $image_size = rtwpvs()->get_option( 'attribute_image_size' );
1697 + $image_url = wp_get_attachment_image_url( $attachment_id, apply_filters( 'rtwpvs_product_attribute_image_size', $image_size ) );
1698 +
1699 + $html .= sprintf(
1700 + '<input type="checkbox" id="' . esc_attr( $args['id'] ) . '" value="' . esc_attr( $args['term_slug'] ) . '" class="rtsb-attr-hidden-field" name="rtsb-filter-' . esc_attr( $args['attribute_name'] ) . '[]' . '" ' . esc_attr( $args['selected_item'] ) . '/><label for="%s" title="' . esc_attr( $args['name'] ) . '" class="rtsb-default-filter-trigger rtsb-image-filter rtsb-term-span rtsb-term-span-%s%s"><img class="rtsb-default-attr-filter" alt="%s" src="%s" /></label>',
1701 + esc_attr( $args['id'] ),
1702 + esc_attr( $args['type'] ),
1703 + $args['tooltips'] ? esc_attr( ' tipsy' ) : '',
1704 + esc_attr( $args['name'] ),
1705 + esc_url( $image_url )
1706 + );
1707 + break;
1708 +
1709 + case 'button':
1710 + $html .= sprintf(
1711 + '<input id="' . esc_attr( $args['id'] ) . '" type="checkbox" value="' . esc_attr( $args['term_slug'] ) . '" class="rtsb-attr-hidden-field" name="rtsb-filter-' . esc_attr( $args['attribute_name'] ) . '[]' . '" ' . esc_attr( $args['selected_item'] ) . '/><label for="%s" title="' . esc_attr( $args['name'] ) . '" class="rtsb-default-filter-trigger rtsb-attr-filter rtsb-button-filter rtsb-term-span rtsb-term-span-%s%s"><span class="default-filter-attr-name">%s</span><div class="rtsb-count">(%s)</div></label>',
1712 + esc_attr( $args['id'] ),
1713 + esc_attr( $args['type'] ),
1714 + $args['tooltips'] ? esc_attr( ' tipsy' ) : '',
1715 + esc_html( $args['name'] ),
1716 + absint( $count )
1717 + );
1718 + break;
1719 +
1720 + default:
1721 + }
1722 +
1723 + return apply_filters( 'rtsb/elementor/default/filter/get_input_type_html', $html );
1724 + }
1725 + /**
1726 + * Get reset button.
1727 + *
1728 + * @param string $btn_text Button text.
1729 + * @param array $settings Settings array.
1730 + *
1731 + * @return string
1732 + */
1733 + public static function get_default_filter_reset_button( $btn_text, $settings ) {
1734 + $html = '';
1735 +
1736 + ob_start();
1737 +
1738 + $active = ! empty( $_SERVER['QUERY_STRING'] ) ? ' active' : '';
1739 + $reset = ! empty( $settings['reset_btn'] );
1740 + $apply_text = ! empty( $settings['apply_filters_btn_text'] ) ? $settings['apply_filters_btn_text'] : esc_html__( 'Apply Filters', 'shopbuilder' );
1741 + $apply_icon = ! empty( $settings['apply_filters_btn_icon'] ) ? $settings['apply_filters_btn_icon'] : [];
1742 + echo '<div class="default-filter-btn-wrapper">';
1743 + ?>
1744 + <?php if ( $settings['show_filter_btn'] ) { ?>
1745 + <div class="rtsb-product-default-filters rtsb-apply-filters-btn">
1746 + <div class="reset-btn-item">
1747 + <button class="rtsb-apply-filters init">
1748 + <span class="icon"><?php Fns::print_html( Fns::icons_manager( $apply_icon, 'icon-default' ) ); ?></span>
1749 + <span class="text reset-text"><?php echo esc_html( $apply_text ); ?></span>
1750 + <span></span>
1751 + </button>
1752 + </div>
1753 + </div>
1754 + <?php } ?>
1755 + <?php
1756 + if ( $reset ) {
1757 + ?>
1758 + <div class="rtsb-product-default-filters rtsb-reset<?php echo esc_attr( $active ); ?>">
1759 + <div class="reset-btn-item">
1760 + <button class="product-default-filter-reset">
1761 + <span class="text reset-text"><?php echo esc_html( $btn_text ); ?></span>
1762 + <span></span>
1763 + </button>
1764 + </div>
1765 + </div>
1766 + <?php
1767 + }
1768 + echo '</div>';
1769 +
1770 + $html .= ob_get_clean();
1771 +
1772 + return $html;
947 1773 }
948 1774 }