PluginProbe
ShopBuilder – WooCommerce Builder For Elementor / 2.6.2
ShopBuilder – WooCommerce Builder For Elementor v2.6.2
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 +1148 -199 2.0.3 → 2.6.2 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.' );
@@ -20,11 +24,31 @@
20 24 /**
21 25 * BuilderFns class
22 26 */
23 27 class RenderHelpers {
28 + /**
29 + * @var array
30 + */
31 + private static $cache = [];
32 + /**
33 + * Get data.
34 + *
35 + * @param array|string $haystack The array or string to search for the value.
36 + * @param string $needle The key to look for in the array or the string itself.
37 + * @param mixed $default The default value to return if the key is not.
38 + *
39 + * @return mixed
40 + */
41 + public static function get_data( $haystack, $needle, $default = null ) {
42 + if ( is_array( $haystack ) && ! empty( $haystack[ $needle ] ) ) {
43 + return $haystack[ $needle ];
44 + } elseif ( is_string( $haystack ) && ! empty( $haystack ) ) {
45 + return $haystack;
46 + } else {
47 + return $default;
48 + }
49 + }
24 50
25 -
26 -
27 51 /**
28 52 * Builds an array with field values.
29 53 *
30 54 * @param array $meta Field values.
@@ -33,15 +57,15 @@
33 57 *
34 58 * @return array
35 59 */
36 60 public static function meta_dataset( array $meta, $template = '', $raw_settings = [] ) {
37 - $c_image_size = ! empty( $meta['image_custom_dimension'] ) ? $meta['image_custom_dimension'] : [];
38 - $c_image_size['crop'] = ! empty( $meta['image_crop'] ) ? $meta['image_crop'] : '';
61 + $c_image_size = self::get_data( $meta, 'image_custom_dimension', [] );
62 + $c_image_size['crop'] = self::get_data( $meta, 'image_crop', [] );
39 63
40 - if ( ( ! empty( $_GET['displayview'] ) && 'list' === $_GET['displayview'] ) || ( empty( $_GET['displayview'] ) && ( ! empty( $meta['view_mode'] ) && 'list' === $meta['view_mode'] ) ) ) {
41 - $meta['cols'] = ! empty( $meta['list_cols'] ) ? $meta['list_cols'] : 1;
42 - $meta['cols_tablet'] = ! empty( $meta['list_cols_tablet'] ) ? $meta['list_cols_tablet'] : $meta['cols'];
43 - $meta['cols_mobile'] = ! empty( $meta['list_cols_mobile'] ) ? $meta['list_cols_mobile'] : $meta['cols'];
64 + if ( ( ! empty( $_GET['displayview'] ) && 'list' === $_GET['displayview'] ) || ( empty( $_GET['displayview'] ) && ( ! empty( $meta['view_mode'] ) && 'list' === $meta['view_mode'] ) ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
65 + $meta['cols'] = self::get_data( $meta, 'list_cols', 1 );
66 + $meta['cols_tablet'] = self::get_data( $meta, 'list_cols_tablet', $meta['cols'] );
67 + $meta['cols_mobile'] = self::get_data( $meta, 'list_cols_mobile', $meta['cols'] );
44 68 }
45 69
46 70 $data = apply_filters(
47 71 'rtsb/elementor/render/meta_dataset',
@@ -47,53 +71,53 @@
47 71 'rtsb/elementor/render/meta_dataset',
48 72 [
49 73 // Layout.
50 74 'widget' => 'custom',
51 - 'template' => ! empty( $template ) ? $template : '',
52 - 'raw_settings' => ! empty( $raw_settings ) ? $raw_settings : [],
53 - 'layout' => ! empty( $meta['layout'] ) ? $meta['layout'] : 'layout1',
54 - 'grid_layout' => ! empty( $raw_settings['layout'] ) ? $raw_settings['layout'] : 'grid-layout1',
55 - 'list_layout' => ! empty( $raw_settings['list_layout'] ) ? $raw_settings['list_layout'] : 'list-layout1',
56 - 'd_cols' => ! empty( $meta['cols'] ) ? $meta['cols'] : 0,
57 - 't_cols' => ! empty( $meta['cols_tablet'] ) ? $meta['cols_tablet'] : 2,
58 - 'm_cols' => ! empty( $meta['cols_mobile'] ) ? $meta['cols_mobile'] : 1,
59 - 'grid_type' => ! empty( $meta['grid_style'] ) ? $meta['grid_style'] : 'even',
75 + 'template' => self::get_data( $template, '', '' ),
76 + 'raw_settings' => $raw_settings,
77 + 'layout' => self::get_data( $meta, 'layout', 'layout1' ),
78 + 'grid_layout' => self::get_data( $raw_settings, 'layout', 'grid-layout1' ),
79 + 'list_layout' => self::get_data( $raw_settings, 'list_layout', 'list-layout1' ),
80 + 'd_cols' => self::get_data( $meta, 'cols', 0 ),
81 + 't_cols' => self::get_data( $meta, 'cols_tablet', 2 ),
82 + 'm_cols' => self::get_data( $meta, 'cols_mobile', 1 ),
83 + 'grid_type' => self::get_data( $meta, 'grid_style', 'even' ),
60 84
61 85 // Query.
62 - 'post_in' => ! empty( $meta['include_posts'] ) && is_array( $meta['include_posts'] ) ? $meta['include_posts'] : [],
63 - 'post_not_in' => ! empty( $meta['exclude_posts'] ) && is_array( $meta['exclude_posts'] ) ? $meta['exclude_posts'] : [],
86 + 'post_in' => self::get_data( $meta, 'include_posts', [] ),
87 + 'post_not_in' => self::get_data( $meta, 'exclude_posts', [] ),
64 88 'limit' => ( empty( $meta['posts_limit'] ) || '-1' === $meta['posts_limit'] ) ? 10000000 : $meta['posts_limit'],
65 - 'offset' => ! empty( $meta['posts_offset'] ) ? $meta['posts_offset'] : 0,
66 - 'order_by' => ! empty( $meta['posts_order_by'] ) ? $meta['posts_order_by'] : 'date',
67 - 'order' => ! empty( $meta['posts_order'] ) ? $meta['posts_order'] : 'DESC',
68 - 'author_in' => ! empty( $meta['filter_author'] ) && is_array( $meta['filter_author'] ) ? $meta['filter_author'] : [],
69 - 'display_by' => ! empty( $meta['products_filter'] ) ? $meta['products_filter'] : 'date',
70 - 'categories' => ! empty( $meta['filter_categories'] ) && is_array( $meta['filter_categories'] ) ? $meta['filter_categories'] : [],
71 - 'tags' => ! empty( $meta['filter_tags'] ) && is_array( $meta['filter_tags'] ) ? $meta['filter_tags'] : [],
72 - 'attributes' => ! empty( $meta['filter_attributes'] ) && is_array( $meta['filter_attributes'] ) ? $meta['filter_attributes'] : [],
73 - 'relation' => ! empty( $meta['tax_relation'] ) ? $meta['tax_relation'] : 'OR',
74 - 'category_source' => ! empty( $meta['select_source'] ) ? $meta['select_source'] : 'product_cat',
75 - 'category_term' => ! empty( $meta['select_cat'] ) ? $meta['select_cat'] : null,
76 - 'display_cat_by' => ! empty( $meta['display_cat_by'] ) ? $meta['display_cat_by'] : null,
77 - 'include_cats' => ! empty( $meta['include_cats'] ) && is_array( $meta['include_cats'] ) ? $meta['include_cats'] : [],
78 - 'exclude_cats' => ! empty( $meta['exclude_cats'] ) && is_array( $meta['exclude_cats'] ) ? $meta['exclude_cats'] : [],
79 - 'select_parent_cat' => ! empty( $meta['select_parent_cat'] ) ? $meta['select_parent_cat'] : null,
80 - 'select_cats' => ! empty( $meta['select_cats'] ) && is_array( $meta['select_cats'] ) ? $meta['select_cats'] : [],
81 - 'select_cat_ids' => ! empty( $meta['include_cat_ids'] ) ? $meta['include_cat_ids'] : '',
89 + 'offset' => self::get_data( $meta, 'posts_offset', 0 ),
90 + 'order_by' => self::get_data( $meta, 'posts_order_by', 'date' ),
91 + 'order' => self::get_data( $meta, 'posts_order', 'DESC' ),
92 + 'author_in' => self::get_data( $meta, 'filter_author', [] ),
93 + 'display_by' => self::get_data( $meta, 'products_filter', 'date' ),
94 + 'categories' => self::get_data( $meta, 'filter_categories', [] ),
95 + 'tags' => self::get_data( $meta, 'filter_tags', [] ),
96 + 'attributes' => self::get_data( $meta, 'filter_attributes', [] ),
97 + 'relation' => self::get_data( $meta, 'tax_relation', 'OR' ),
98 + 'category_source' => self::get_data( $meta, 'select_source', 'product_cat' ),
99 + 'category_term' => self::get_data( $meta, 'select_cat' ),
100 + 'display_cat_by' => self::get_data( $meta, 'display_cat_by' ),
101 + 'include_cats' => self::get_data( $meta, 'include_cats', [] ),
102 + 'exclude_cats' => self::get_data( $meta, 'exclude_cats', [] ),
103 + 'select_parent_cat' => self::get_data( $meta, 'select_parent_cat' ),
104 + 'select_cats' => self::get_data( $meta, 'select_cats', [] ),
105 + 'select_cat_ids' => self::get_data( $meta, 'include_cat_ids', '' ),
82 106 'cats_limit' => ( empty( $meta['cats_limit'] ) || '-1' === $meta['cats_limit'] ) ? 10000000 : $meta['cats_limit'],
83 107 'show_empty' => ! empty( $meta['show_empty'] ),
84 108 'show_uncategorized' => ! empty( $meta['show_uncategorized'] ),
85 109 'show_subcats' => ! empty( $meta['show_subcats'] ),
86 110 'show_top_level_cats' => ! empty( $meta['show_top_level_cats'] ),
87 - 'cats_order_by' => ! empty( $meta['cats_order_by'] ) ? $meta['cats_order_by'] : 'name',
88 - 'cats_order' => ! empty( $meta['cats_order'] ) ? $meta['cats_order'] : 'DESC',
89 - 'rtsb_order' => ! empty( $meta['rtsb_order'] ) ? $meta['rtsb_order'] : 'ASC',
90 - 'rtsb_orderby' => ! empty( $meta['rtsb_orderby'] ) ? $meta['rtsb_orderby'] : 'menu_order',
111 + 'cats_order_by' => self::get_data( $meta, 'cats_order_by', 'name' ),
112 + 'cats_order' => self::get_data( $meta, 'cats_order', 'DESC' ),
113 + 'rtsb_order' => self::get_data( $meta, 'rtsb_order', 'ASC' ),
114 + 'rtsb_orderby' => self::get_data( $meta, 'rtsb_orderby', 'menu_order' ),
91 115
92 116 // Pagination.
93 117 'pagination' => ! empty( $meta['show_pagination'] ),
94 - 'posts_loading_type' => ! empty( $meta['pagination_type'] ) ? $meta['pagination_type'] : 'pagination',
95 - 'posts_per_page' => ! empty( $meta['pagination_per_page'] ) ? $meta['pagination_per_page'] : '',
118 + 'posts_loading_type' => self::get_data( $meta, 'pagination_type', 'pagination' ),
119 + 'posts_per_page' => self::get_data( $meta, 'pagination_per_page', '' ),
96 120
97 121 // Image.
98 122 'f_img' => ! empty( $meta['show_featured_image'] ),
99 123 'gallery_img' => ! empty( $meta['show_product_gallery'] ),
@@ -98,13 +122,13 @@
98 122 'f_img' => ! empty( $meta['show_featured_image'] ),
99 123 'gallery_img' => ! empty( $meta['show_product_gallery'] ),
100 124 'c_img' => ! empty( $meta['show_cat_image'] ),
101 125 'hover_img' => ! empty( $meta['show_hover_image'] ),
102 - 'f_img_size' => ! empty( $meta['image'] ) ? $meta['image'] : 'medium',
126 + 'f_img_size' => self::get_data( $meta, 'image', 'medium' ),
103 127 'custom_img_size' => ! empty( $c_image_size ) && is_array( $c_image_size ) ? $c_image_size : [],
104 128 'default_img_id' => ! empty( $meta['default_preview_image']['id'] ) ? $meta['default_preview_image']['id'] : null,
105 129 'show_overlay' => ! empty( $meta['show_overlay'] ),
106 - 'hover_animation' => ! empty( $meta['image_hover_animation'] ) ? $meta['image_hover_animation'] : 'none',
130 + 'hover_animation' => self::get_data( $meta, 'image_hover_animation', 'none' ),
107 131 'show_custom_image' => ! empty( $meta['show_custom_image'] ),
108 132 'custom_image' => ! empty( $meta['custom_image']['id'] ) ? $meta['custom_image']['id'] : null,
109 133
110 134 // Visibility.
@@ -110,90 +134,96 @@
110 134 // Visibility.
111 135 'visibility' => ! empty( self::content_visibility( $meta ) ) ? self::content_visibility( $meta ) : [],
112 136
113 137 // Action Buttons.
114 - 'btn_preset' => ! empty( $meta['action_btn_preset'] ) ? $meta['action_btn_preset'] : 'preset1',
115 - 'btn_position' => ! empty( $meta['action_btn_position'] ) ? $meta['action_btn_position'] : 'above',
116 - 'tooltip_position' => ! empty( $meta['action_btn_tooltip_position'] ) ? $meta['action_btn_tooltip_position'] : 'top',
138 + 'btn_preset' => self::get_data( $meta, 'action_btn_preset', 'preset1' ),
139 + 'btn_position' => self::get_data( $meta, 'action_btn_position', 'above' ),
140 + 'tooltip_position' => self::get_data( $meta, 'action_btn_tooltip_position', 'top' ),
117 141
118 142 // Product Title.
119 - 'title_tag' => ! empty( $meta['title_tag'] ) ? $meta['title_tag'] : 'h3',
143 + 'title_tag' => self::get_data( $meta, 'title_tag', 'h3' ),
120 144 'title_hover' => ! empty( $meta['title_hover'] ),
121 - 'title_limit' => ! empty( $meta['title_limit'] ) ? $meta['title_limit'] : 'default',
122 - 'title_limit_custom' => ! empty( $meta['title_limit_custom'] ) ? $meta['title_limit_custom'] : null,
145 + 'title_limit' => self::get_data( $meta, 'title_limit', 'default' ),
146 + 'title_limit_custom' => self::get_data( $meta, 'title_limit_custom' ),
123 147 'show_custom_title' => ! empty( $meta['show_custom_title'] ),
124 - 'cat_custom_title' => ! empty( $meta['custom_title'] ) ? $meta['custom_title'] : '',
148 + 'cat_custom_title' => self::get_data( $meta, 'custom_title', '' ),
125 149
126 150 // Variation Swatches.
127 - 'swatch_position' => ! empty( $meta['swatch_position'] ) ? $meta['swatch_position'] : 'top',
128 - 'swatch_type' => ! empty( $meta['swatch_type'] ) ? $meta['swatch_type'] : 'circle',
151 + 'swatch_position' => self::get_data( $meta, 'swatch_position', 'top' ),
152 + 'swatch_type' => self::get_data( $meta, 'swatch_type', 'circle' ),
129 153
130 154 // Short Description.
131 155 'show_custom_excerpt' => ! empty( $meta['show_custom_description'] ),
132 - 'cat_custom_excerpt' => ! empty( $meta['custom_description'] ) ? $meta['custom_description'] : '',
133 - 'cat_excerpt_position' => ! empty( $meta['excerpt_position'] ) ? $meta['excerpt_position'] : 'below',
134 - 'excerpt_limit' => ! empty( $meta['excerpt_limit'] ) ? $meta['excerpt_limit'] : 'default',
135 - 'excerpt_limit_custom' => ! empty( $meta['excerpt_limit_custom'] ) ? $meta['excerpt_limit_custom'] : 200,
156 + 'cat_custom_excerpt' => self::get_data( $meta, 'custom_description', '' ),
157 + 'cat_excerpt_position' => self::get_data( $meta, 'excerpt_position', 'below' ),
158 + 'excerpt_limit' => self::get_data( $meta, 'excerpt_limit', 'default' ),
159 + 'excerpt_limit_custom' => self::get_data( $meta, 'excerpt_limit_custom', 200 ),
136 160
137 161 // Count.
138 - 'count_position' => ! empty( $meta['count_display_type'] ) ? $meta['count_display_type'] : 'flex',
139 - 'before_count' => ! empty( $meta['before_count'] ) ? $meta['before_count'] : '',
140 - 'after_count' => ! empty( $meta['after_count'] ) ? $meta['after_count'] : '',
162 + 'count_position' => self::get_data( $meta, 'count_display_type', 'flex' ),
163 + 'before_count' => self::get_data( $meta, 'before_count', '' ),
164 + 'after_count' => self::get_data( $meta, 'after_count', '' ),
141 165
142 166 // Add to cart.
143 167 'show_cart_icon' => ! empty( $meta['show_cart_icon'] ),
144 168 'show_cart_text' => ! empty( $meta['show_cart_text'] ),
145 - 'add_to_cart_icon' => ! empty( $meta['add_to_cart_icon'] ) ? $meta['add_to_cart_icon'] : [],
146 - 'add_to_cart_success_icon' => ! empty( $meta['add_to_cart_success_icon'] ) ? $meta['add_to_cart_success_icon'] : [],
147 - 'add_to_cart_text' => ! empty( $meta['add_to_cart_text'] ) ? $meta['add_to_cart_text'] : esc_html__( 'Add to Cart', 'shopbuilder' ),
148 - 'add_to_cart_success_text' => ! empty( $meta['add_to_cart_success_text'] ) ? $meta['add_to_cart_success_text'] : '',
149 - 'add_to_cart_alignment' => ! empty( $meta['cart_icon_alignment'] ) ? $meta['cart_icon_alignment'] : 'left',
169 + 'add_to_cart_icon' => self::get_data( $meta, 'add_to_cart_icon', [] ),
170 + 'add_to_cart_success_icon' => self::get_data( $meta, 'add_to_cart_success_icon', [] ),
171 + 'add_to_cart_text' => self::get_data( $meta, 'add_to_cart_text', esc_html__( 'Add to Cart', 'shopbuilder' ) ),
172 + 'add_to_cart_success_text' => self::get_data( $meta, 'add_to_cart_success_text', '' ),
173 + 'add_to_cart_alignment' => self::get_data( $meta, 'cart_icon_alignment', 'left' ),
150 174
151 175 // Action Button Icons.
152 - 'quick_view_icon' => ! empty( $meta['quick_view_icon'] ) ? $meta['quick_view_icon'] : [],
153 - 'comparison_icon' => ! empty( $meta['comparison_icon'] ) ? $meta['comparison_icon'] : [],
154 - 'comparison_icon_added' => ! empty( $meta['comparison_icon_added'] ) ? $meta['comparison_icon_added'] : [],
155 - 'wishlist_icon' => ! empty( $meta['wishlist_icon'] ) ? $meta['wishlist_icon'] : [],
156 - 'wishlist_icon_added' => ! empty( $meta['wishlist_icon_added'] ) ? $meta['wishlist_icon_added'] : [],
176 + 'quick_view_icon' => self::get_data( $meta, 'quick_view_icon', [] ),
177 + 'comparison_icon' => self::get_data( $meta, 'comparison_icon', [] ),
178 + 'comparison_icon_added' => self::get_data( $meta, 'comparison_icon_added', [] ),
179 + 'wishlist_icon' => self::get_data( $meta, 'wishlist_icon', [] ),
180 + 'wishlist_icon_added' => self::get_data( $meta, 'wishlist_icon_added', [] ),
157 181
158 182 // Badges.
159 - 'sale_badge_type' => ! empty( $meta['sale_badges_type'] ) ? $meta['sale_badges_type'] : 'percentage',
160 - 'sale_badge_text' => ! empty( $meta['sale_badges_text'] ) ? $meta['sale_badges_text'] : esc_html__( 'Sale', 'shopbuilder' ),
161 - 'custom_badge_text' => ! empty( $meta['custom_badge_text'] ) ? $meta['custom_badge_text'] : esc_html__( 'Sale', 'shopbuilder' ),
162 - 'out_of_stock_badge_text' => ! empty( $meta['stock_badges_text'] ) ? $meta['stock_badges_text'] : esc_html__( 'Out of Stock', 'shopbuilder' ),
163 - 'badge_position' => ! empty( $meta['badges_position'] ) ? $meta['badges_position'] : 'top',
164 - 'badge_alignment' => ! empty( $meta['badges_alignment'] ) ? $meta['badges_alignment'] : 'left',
165 - 'badge_preset' => ! empty( $meta['custom_badge_preset'] ) ? $meta['custom_badge_preset'] : 'preset-1',
183 + 'sale_badge_type' => self::get_data( $meta, 'sale_badges_type', 'percentage' ),
184 + 'sale_badge_text' => self::get_data( $meta, 'sale_badges_text', esc_html__( 'Sale', 'shopbuilder' ) ),
185 + 'custom_badge_text' => self::get_data( $meta, 'custom_badge_text', esc_html__( 'Sale', 'shopbuilder' ) ),
186 + 'out_of_stock_badge_text' => self::get_data( $meta, 'stock_badges_text', esc_html__( 'Out of Stock', 'shopbuilder' ) ),
187 + 'badge_position' => self::get_data( $meta, 'badges_position', 'top' ),
188 + 'badge_alignment' => self::get_data( $meta, 'badges_alignment', 'left' ),
189 + 'badge_preset' => self::get_data( $meta, 'custom_badge_preset', 'preset-1' ),
190 + 'enable_badges_module' => self::get_data( $meta, 'enable_badges_module', '' ),
166 191
167 192 // Link.
168 193 'image_link' => ! empty( $meta['image_link'] ),
169 194 'title_link' => ! empty( $meta['title_link'] ),
170 - 'hover_btn_text' => ! empty( $meta['hover_btn_text'] ) ? $meta['hover_btn_text'] : esc_html__( 'See Details', 'shopbuilder' ),
195 + 'hover_btn_text' => self::get_data( $meta, 'hover_btn_text', esc_html__( 'See Details', 'shopbuilder' ) ),
171 196 'show_hover_btn_icon' => ! empty( $meta['show_hover_btn_icon'] ),
172 - 'hover_btn_icon' => ! empty( $meta['hover_btn_icon'] ) ? $meta['hover_btn_icon'] : [],
173 - 'custom_link' => ! empty( $meta['custom_link'] ) ? $meta['custom_link'] : null,
197 + 'hover_btn_icon' => self::get_data( $meta, 'hover_btn_icon', [] ),
198 + 'custom_link' => self::get_data( $meta, 'custom_link' ),
174 199
175 200 // Slider.
176 - 'd_group' => ! empty( $meta['cols_group'] ) ? $meta['cols_group'] : 1,
177 - 't_group' => ! empty( $meta['cols_group_tablet'] ) ? $meta['cols_group_tablet'] : 1,
178 - 'm_group' => ! empty( $meta['cols_group_mobile'] ) ? $meta['cols_group_mobile'] : 1,
201 + 'd_group' => self::get_data( $meta, 'cols_group', 1 ),
202 + 't_group' => self::get_data( $meta, 'cols_group_tablet', 1 ),
203 + 'm_group' => self::get_data( $meta, 'cols_group_mobile', 1 ),
179 204 'auto_play' => ! empty( $meta['slide_autoplay'] ),
180 205 'stop_on_hover' => ! empty( $meta['pause_hover'] ),
181 206 'slider_nav' => ! empty( $meta['slider_nav'] ),
182 207 'slider_dot' => ! empty( $meta['slider_pagi'] ),
208 + 'slider_dynamic_dot' => ! empty( $meta['slider_dynamic_pagi'] ),
183 209 'loop' => ! empty( $meta['slider_loop'] ),
184 210 'lazy_load' => ! empty( $meta['slider_lazy_load'] ),
185 211 'auto_height' => ! empty( $meta['slider_auto_height'] ),
186 - 'speed' => ! empty( $meta['slide_speed'] ) ? $meta['slide_speed'] : 2000,
212 + 'speed' => self::get_data( $meta, 'slide_speed', 2000 ),
187 213 'space_between' => isset( $meta['grid_gap']['size'] ) && strlen( $meta['grid_gap']['size'] ) ? $meta['grid_gap']['size'] : 30,
188 - 'auto_play_timeout' => ! empty( $meta['autoplay_timeout'] ) ? $meta['autoplay_timeout'] : 5000,
189 - 'nav_position' => ! empty( $meta['slider_nav_position'] ) ? $meta['slider_nav_position'] : 'top',
190 - 'left_arrow_icon' => ! empty( $meta['slider_left_arrow_icon'] ) ? $meta['slider_left_arrow_icon'] : [],
191 - 'right_arrow_icon' => ! empty( $meta['slider_right_arrow_icon'] ) ? $meta['slider_right_arrow_icon'] : [],
214 + 'auto_play_timeout' => self::get_data( $meta, 'autoplay_timeout', 5000 ),
215 + 'nav_position' => self::get_data( $meta, 'slider_nav_position', 'top' ),
216 + 'left_arrow_icon' => self::get_data( $meta, 'slider_left_arrow_icon', [] ),
217 + 'right_arrow_icon' => self::get_data( $meta, 'slider_right_arrow_icon', [] ),
192 218 ],
193 219 $meta
194 220 );
195 221
222 + if ( ! empty( $meta['active_cat_slider'] ) ) {
223 + $data['active_cat_slider'] = true;
224 + }
225 +
196 226 if ( ! empty( $meta['cols_widescreen'] ) ) {
197 227 $data['w_cols'] = $meta['cols_widescreen'];
198 228 }
199 229
@@ -211,11 +241,11 @@
211 241
212 242 $queried_obj = get_queried_object();
213 243
214 244 if ( is_shop() || is_product_taxonomy() ) {
215 - $data['posts_per_page'] = wc_get_default_products_per_row() * wc_get_default_product_rows_per_page();
216 - $data['order_by'] = ! empty( $data['rtsb_orderby'] ) ? esc_html( $data['rtsb_orderby'] ) : $data['orderby'];
217 - $data['order'] = ! empty( $data['rtsb_order'] ) ? esc_html( $data['rtsb_order'] ) : $data['order'];
245 + $data['posts_per_page'] = self::get_products_per_page();
246 + $data['order_by'] = self::get_data( $data, 'rtsb_orderby', $data['order_by'] );
247 + $data['order'] = self::get_data( $data, 'rtsb_order', $data['order'] );
218 248 }
219 249
220 250 if ( ! is_shop() && is_product_taxonomy() ) {
221 251 if ( ! empty( $queried_obj->taxonomy ) ) {
@@ -238,19 +268,15 @@
238 268 *
239 269 * @return array
240 270 */
241 271 public static function archive_meta_dataset( array $meta, $template = '' ) {
242 - $products_row = absint( get_option( 'woocommerce_catalog_rows', 4 ) );
243 - $products_col = absint( get_option( 'woocommerce_catalog_columns', 4 ) );
244 - $products_per_page = apply_filters( 'rtsb/elementor/archive/products_per_page', $products_row * $products_col );
245 -
246 272 $data = apply_filters(
247 273 'rtsb/elementor/render/archive_meta_dataset',
248 274 [
249 275 // Layout.
250 276 'widget' => 'default',
251 - 'template' => ! empty( $template ) ? $template : '',
252 - 'view_mode' => ! empty( $meta['view_mode'] ) ? $meta['view_mode'] : 'grid',
277 + 'template' => self::get_data( $template, '', '' ),
278 + 'view_mode' => self::get_data( $meta, 'view_mode', 'grid' ),
253 279 'show_flash_sale' => ! empty( $meta['show_flash_sale'] ),
254 280 'wishlist_button' => ! empty( $meta['wishlist_button'] ),
255 281 'comparison_button' => ! empty( $meta['comparison_button'] ),
256 282 'quick_view_button' => ! empty( $meta['quick_view_button'] ),
@@ -255,20 +281,20 @@
255 281 'comparison_button' => ! empty( $meta['comparison_button'] ),
256 282 'quick_view_button' => ! empty( $meta['quick_view_button'] ),
257 283 'show_rating' => ! empty( $meta['show_rating'] ),
258 284 'show_pagination' => ! empty( $meta['show_pagination'] ),
259 - 'cart_icon' => ! empty( $meta['cart_icon'] ) ? $meta['cart_icon'] : [],
260 - 'wishlist_icon' => ! empty( $meta['wishlist_icon'] ) ? $meta['wishlist_icon'] : [],
261 - 'wishlist_icon_added' => ! empty( $meta['wishlist_icon_added'] ) ? $meta['wishlist_icon_added'] : [],
262 - 'comparison_icon' => ! empty( $meta['comparison_icon'] ) ? $meta['comparison_icon'] : [],
263 - 'comparison_icon_added' => ! empty( $meta['comparison_icon_added'] ) ? $meta['comparison_icon_added'] : [],
264 - 'quick_view_icon' => ! empty( $meta['quick_view_icon'] ) ? $meta['quick_view_icon'] : [],
265 - 'prev_icon' => ! empty( $meta['prev_icon'] ) ? $meta['prev_icon'] : [],
266 - 'next_icon' => ! empty( $meta['next_icon'] ) ? $meta['next_icon'] : [],
267 - 'posts_per_page' => ! empty( $products_per_page ) ? $products_per_page : 12,
268 - 'rtsb_order' => ! empty( $meta['rtsb_order'] ) ? $meta['rtsb_order'] : 'ASC',
269 - 'rtsb_orderby' => ! empty( $meta['rtsb_orderby'] ) ? $meta['rtsb_orderby'] : 'menu_order',
270 - 'tooltip_position' => ! empty( $meta['action_btn_tooltip_position'] ) ? $meta['action_btn_tooltip_position'] : 'top',
285 + 'cart_icon' => self::get_data( $meta, 'cart_icon', [] ),
286 + 'wishlist_icon' => self::get_data( $meta, 'wishlist_icon', [] ),
287 + 'wishlist_icon_added' => self::get_data( $meta, 'wishlist_icon_added', [] ),
288 + 'comparison_icon' => self::get_data( $meta, 'comparison_icon', [] ),
289 + 'comparison_icon_added' => self::get_data( $meta, 'comparison_icon_added', [] ),
290 + 'quick_view_icon' => self::get_data( $meta, 'quick_view_icon', [] ),
291 + 'prev_icon' => self::get_data( $meta, 'prev_icon', [] ),
292 + 'next_icon' => self::get_data( $meta, 'next_icon', [] ),
293 + 'posts_per_page' => self::get_products_per_page(),
294 + 'rtsb_order' => self::get_data( $meta, 'rtsb_order', 'ASC' ),
295 + 'rtsb_orderby' => self::get_data( $meta, 'rtsb_orderby', 'menu_order' ),
296 + 'tooltip_position' => self::get_data( $meta, 'action_btn_tooltip_position', 'top' ),
271 297 ],
272 298 $meta
273 299 );
274 300
@@ -391,24 +417,47 @@
391 417 * @return int
392 418 */
393 419 public static function default_columns( $layout ) {
394 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':
395 427 case 'grid-layout2':
396 428 case 'slider-layout2':
429 + case 'rtsb-coupon-layout1':
430 + case 'rtsb-coupon-layout2':
431 + case 'rtsb-coupon-layout3':
397 432 $columns = 3;
398 433 break;
399 -
434 + case 'rtsb-post-list-layout1':
435 + case 'rtsb-post-list-layout2':
400 436 case 'list-layout1':
401 437 case 'list-layout2':
402 438 case 'list-layout3':
439 + case 'list-layout7':
403 440 case 'list-layout5':
404 441 $columns = 1;
405 442 break;
406 -
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':
407 448 case 'list-layout4':
449 + case 'list-layout6':
408 450 case 'slider-layout5':
451 + case 'slider-layout8':
409 452 $columns = 2;
410 453 break;
454 + case 'rtsb-logo-layout1':
455 + case 'rtsb-logo-layout2':
456 + case 'grid-layout6':
457 + case 'grid-layout9':
458 + $columns = 5;
459 + break;
411 460
412 461 case 'category-layout1':
413 462 $columns = 6;
414 463 break;
@@ -431,12 +480,207 @@
431 480 */
432 481 public static function pagination_data( $metas, $template ) {
433 482 $el_data = self::meta_dataset( $metas, $template );
434 483
435 - return ' data-rtsb-ajax=\'' . esc_js( wp_json_encode( $el_data ) ) . '\'';
484 + return esc_js( wp_json_encode( $el_data, JSON_UNESCAPED_UNICODE ) );
436 485 }
437 486
438 487 /**
488 + * Container classes
489 + *
490 + * @param array $metas Meta data.
491 + * @param array $settings Settings array.
492 + * @param string $custom_class Custom class.
493 + *
494 + * @return mixed|null
495 + */
496 + public static function prepare_container_classes( $metas = [], $settings = [], $custom_class = '' ) {
497 + $classes = 'rtsb-elementor-container products rtsb-pos-r ';
498 + $classes .= $custom_class;
499 +
500 + $raw_layout = esc_html( $metas['layout'] );
501 + $layout = self::filter_layout( $raw_layout );
502 + $is_cat = preg_match( '/category/', $layout );
503 + $cart_txt_class = '';
504 +
505 + $animation = $metas['hover_animation'];
506 +
507 + if ( ! $is_cat ) {
508 + $cart_txt_class = $metas['show_cart_text'] ? ' has-cart-text' : ' no-cart-text';
509 + $animation .= ' gallery-hover-' . ( ! empty( $settings['gallery_hover_animation'] ) ? $settings['gallery_hover_animation'] : 'fade' );
510 + }
511 +
512 + $badge_class = [
513 + 'position' => $metas['badge_position'],
514 + 'alignment' => $metas['badge_alignment'],
515 + ];
516 +
517 + if ( ! in_array( 'clear-btn', $metas['visibility'], true ) ) {
518 + $classes .= ' no-clear-btn';
519 + }
520 +
521 + $classes .= ! empty( $metas['pagination'] ) ? ' rtsb-has-pagination' : ' rtsb-no-pagination';
522 + $classes .= ' badge-' . esc_attr( $badge_class['position'] ) . ' badge-' . esc_attr( $badge_class['alignment'] ) . esc_attr( $cart_txt_class ) . ' img-hover-' . esc_attr( $animation ) . ' excerpt-' . esc_attr( $metas['cat_excerpt_position'] );
523 +
524 + if ( $metas['show_overlay'] ) {
525 + $classes .= ' has-overlay';
526 + }
527 +
528 + if ( in_array( 'single-cat', $metas['visibility'], true ) ) {
529 + $classes .= ' show-single-cat';
530 + }
531 +
532 + if ( ! $is_cat ) {
533 + $action_btn_classes = [
534 + 'show_compare_text' => 'has-compare-text',
535 + 'show_quick_view_text' => 'has-quick-view-text',
536 + 'show_wishlist_text' => 'has-wishlist-text',
537 + 'show_compare_icon' => 'no-compare-icon',
538 + 'show_quick_view_icon' => 'no-quick-view-icon',
539 + 'show_wishlist_icon' => 'no-wishlist-icon',
540 + 'show_quick_checkout_icon' => 'no-quick_checkout-icon',
541 + ];
542 +
543 + foreach ( $action_btn_classes as $setting_key => $class ) {
544 + if ( strpos( $setting_key, 'icon' ) !== false ) {
545 + $classes .= empty( $settings[ $setting_key ] ) ? ' ' . $class : '';
546 + } else {
547 + $classes .= ! empty( $settings[ $setting_key ] ) ? ' ' . $class : '';
548 + }
549 + }
550 +
551 + if ( rtsb()->has_pro() && ! empty( $settings['custom_ordering'] ) ) {
552 + $classes .= ' has-custom-ordering';
553 + }
554 + }
555 + if ( rtsb()->has_pro() && ! empty( $settings['slider_slide_animation'] ) ) {
556 + $classes .= ' has-slide-animation';
557 + }
558 +
559 + return apply_filters( 'rtsb/product/container/class', $classes, $settings );
560 + }
561 +
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 + /**
606 + * Row classes
607 + *
608 + * @param array $settings Settings array.
609 + *
610 + * @return mixed|null
611 + */
612 + public static function prepare_row_classes( $settings = [] ) {
613 + $masonry_class = null;
614 + $classes = 'rtsb-row rtsb-content-loader element-loading';
615 + $loader_class = ' rtsb-pre-loader';
616 +
617 + $raw_layout = esc_html( $settings['layout'] );
618 + $layout = self::filter_layout( $raw_layout );
619 + $grid_type = $settings['grid_type'];
620 + $is_carousel = preg_match( '/slider/', $layout );
621 +
622 + if ( preg_match( '/category/', $layout ) && ! empty( $settings['active_cat_slider'] ) ) {
623 + $classes .= ' rtsb-slider-layout';
624 + }
625 +
626 + if ( 'equal' === $grid_type ) {
627 + $masonry_class = ' rtsb-equal';
628 + } elseif ( 'masonry' === $grid_type ) {
629 + $masonry_class = ' rtsb-masonry';
630 + } else {
631 + $masonry_class = ' rtsb-even';
632 + }
633 +
634 + if ( ! rtsb()->has_pro() || $is_carousel ) {
635 + $masonry_class = ' rtsb-even';
636 + }
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 +
649 + $classes .= ' rtsb-' . $layout . $masonry_class . $loader_class;
650 +
651 + return apply_filters( 'rtsb/elementor/row/classes', $classes, $settings );
652 + }
653 +
654 + /**
655 + * Prepare pagination attributes.
656 + *
657 + * @param string $layout The layout type.
658 + * @param bool $has_filters Whether the widget has filters.
659 + * @param string $template The template name.
660 + * @param array $settings The widget settings.
661 + * @param bool $ajax Whether to enable AJAX pagination.
662 + *
663 + * @return string
664 + */
665 + public static function prepare_pagination_attr( $layout, $has_filters, $template, $settings, $ajax ) {
666 + $is_cat = preg_match( '/category/', $layout );
667 + $is_carousel = preg_match( '/slider/', $layout );
668 +
669 + if ( $is_carousel ) {
670 + return $has_filters ? self::pagination_data( $settings, $template ) : '';
671 + } elseif ( $is_cat ) {
672 + return '';
673 + } else {
674 + $ajax_pagination = ! empty( $settings['show_pagination'] ) && 'pagination' !== $settings['pagination_type'];
675 + $page = Fns::product_filters_has_ajax( apply_filters( 'rtsb/builder/set/current/page/type', '' ) );
676 + $condition = rtsb()->has_pro() && $ajax && ( $ajax_pagination || $has_filters || $page );
677 +
678 + return $condition ? self::pagination_data( $settings, $template ) : '';
679 + }
680 + }
681 +
682 + /**
439 683 * Archive JSON data.
440 684 *
441 685 * @param array $metas Data set.
442 686 * @param string $template Template name.
@@ -457,34 +701,35 @@
457 701 *
458 702 * @return array
459 703 */
460 704 public static function slider_data( array $meta, $settings = [] ) {
461 - $has_dots = $meta['slider_dot'] ? ' has-dot' : ' no-dot';
462 - $has_dots .= $meta['slider_nav'] ? ' has-nav' : ' no-nav';
463 - $d_col = 0 === $meta['d_cols'] ? self::default_columns( $meta['layout'] ) : $meta['d_cols'];
464 - $t_col = 0 === $meta['t_cols'] ? 2 : $meta['t_cols'];
465 - $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'];
466 711
467 - if ( \Elementor\Plugin::$instance->breakpoints->has_custom_breakpoints() ) {
712 + if ( Plugin::$instance->breakpoints->has_custom_breakpoints() ) {
468 713 // Widescreen.
469 - $w_col = ! empty( $settings['cols_widescreen'] ) ? $settings['cols_widescreen'] : null;
714 + $w_col = self::get_data( $settings, 'cols_widescreen' );
470 715 $w_col = 0 === $w_col ? self::default_columns( $meta['layout'] ) : $w_col;
471 - $w_group = ! empty( $settings['cols_group_widescreen'] ) ? $settings['cols_group_widescreen'] : 1;
716 + $w_group = self::get_data( $settings, 'cols_group_widescreen', 1 );
472 717
473 718 // Laptop.
474 - $l_col = ! empty( $settings['cols_laptop'] ) ? $settings['cols_laptop'] : null;
719 + $l_col = self::get_data( $settings, 'cols_laptop' );
475 720 $l_col = 0 === $l_col ? self::default_columns( $meta['layout'] ) : $l_col;
476 - $l_group = ! empty( $settings['cols_group_laptop'] ) ? $settings['cols_group_laptop'] : 1;
721 + $l_group = self::get_data( $settings, 'cols_group_laptop', 1 );
477 722
478 723 // Tablet Landscape.
479 - $te_col = ! empty( $settings['cols_tablet_extra'] ) ? $settings['cols_tablet_extra'] : null;
724 + $te_col = self::get_data( $settings, 'cols_tablet_extra' );
480 725 $te_col = 0 === $te_col ? 3 : $te_col;
481 - $te_group = ! empty( $settings['cols_group_tablet_extra'] ) ? $settings['cols_group_tablet_extra'] : 1;
726 + $te_group = self::get_data( $settings, 'cols_group_tablet_extra', 1 );
482 727
483 728 // Mobile Landscape.
484 - $me_col = ! empty( $settings['cols_mobile_extra'] ) ? $settings['cols_mobile_extra'] : null;
729 + $me_col = self::get_data( $settings, 'cols_mobile_extra' );
485 730 $me_col = 0 === $me_col ? 2 : $me_col;
486 - $me_group = ! empty( $settings['cols_group_mobile_extra'] ) ? $settings['cols_group_mobile_extra'] : 1;
731 + $me_group = self::get_data( $settings, 'cols_group_mobile_extra', 1 );
487 732
488 733 $el_breakpoints = Fns::get_elementor_breakpoints();
489 734
490 735 foreach ( $el_breakpoints as $key => $value ) {
@@ -497,9 +742,9 @@
497 742 0 => [
498 743 'slidesPerView' => absint( $m_col ),
499 744 'slidesPerGroup' => absint( $meta['m_group'] ),
500 745 'pagination' => [
501 - 'dynamicBullets' => true,
746 + 'dynamicBullets' => $has_dynamic_dots,
502 747 ],
503 748 ],
504 749 ];
505 750
@@ -524,16 +769,16 @@
524 769 }
525 770
526 771 foreach ( $el_breakpoints as $el_breakpoint => $value ) {
527 772 $breakpoint_value = ! empty( $value['value'] ) ? $value['value'] : $value['default_value'];
528 - $dynamic_bullets = false;
773 + $dynamic_bullets = $has_dynamic_dots;
529 774 $slides_per_view = $d_col;
530 775 $slides_per_group = $meta['d_group'];
531 776
532 777 switch ( $el_breakpoint ) {
533 778 case 'widescreen':
534 - $slides_per_view = $w_col;
535 - $slides_per_group = $w_group;
779 + $slides_per_view = $w_col;
780 + $slides_per_group = $w_group;
536 781
537 782 break;
538 783
539 784 case 'laptop':
@@ -542,10 +787,10 @@
542 787
543 788 break;
544 789
545 790 case 'tablet_extra':
546 - $slides_per_view = $l_col;
547 - $slides_per_group = $l_group;
791 + $slides_per_view = $l_col;
792 + $slides_per_group = $l_group;
548 793
549 794 if ( empty( $el_breakpoints['laptop'] ) ) {
550 795 $slides_per_view = $d_col;
551 796 $slides_per_group = $meta['d_group'];
@@ -570,11 +815,11 @@
570 815
571 816 break;
572 817
573 818 case 'mobile_extra':
574 - $slides_per_view = $t_col;
575 - $slides_per_group = $meta['t_group'];
576 - $dynamic_bullets = true;
819 + $slides_per_view = $t_col;
820 + $slides_per_group = $meta['t_group'];
821 + $dynamic_bullets = $has_dynamic_dots;
577 822
578 823 break;
579 824
580 825 case 'mobile':
@@ -579,9 +824,9 @@
579 824
580 825 case 'mobile':
581 826 $slides_per_view = $t_col;
582 827 $slides_per_group = $meta['t_group'];
583 - $dynamic_bullets = true;
828 + $dynamic_bullets = $has_dynamic_dots;
584 829
585 830 if ( ! empty( $el_breakpoints['mobile_extra'] ) ) {
586 831 $slides_per_view = $me_col;
587 832 $slides_per_group = $me_group;
@@ -607,9 +852,9 @@
607 852 0 => [
608 853 'slidesPerView' => absint( $m_col ),
609 854 'slidesPerGroup' => absint( $meta['m_group'] ),
610 855 'pagination' => [
611 - 'dynamicBullets' => true,
856 + 'dynamicBullets' => $has_dynamic_dots,
612 857 ],
613 858 ],
614 859 768 => [
615 860 'slidesPerView' => absint( $t_col ),
@@ -614,9 +859,9 @@
614 859 768 => [
615 860 'slidesPerView' => absint( $t_col ),
616 861 'slidesPerGroup' => absint( $meta['t_group'] ),
617 862 'pagination' => [
618 - 'dynamicBullets' => false,
863 + 'dynamicBullets' => $has_dynamic_dots,
619 864 ],
620 865 ],
621 866 1025 => [
622 867 'slidesPerView' => absint( $d_col ),
@@ -621,9 +866,9 @@
621 866 1025 => [
622 867 'slidesPerView' => absint( $d_col ),
623 868 'slidesPerGroup' => absint( $meta['d_group'] ),
624 869 'pagination' => [
625 - 'dynamicBullets' => false,
870 + 'dynamicBullets' => $has_dynamic_dots,
626 871 ],
627 872 ],
628 873 ];
629 874 }
@@ -638,8 +883,11 @@
638 883 'lazy' => $meta['lazy_load'],
639 884 'breakpoints' => $breakpoints,
640 885 ];
641 886
887 + if ( ! empty( $meta['raw_settings']['slider_slide_animation'] ) ) {
888 + $slider_options['watchSlidesProgress'] = true;
889 + }
642 890 if ( $meta['auto_play'] ) {
643 891 $slider_options['autoplay'] = [
644 892 'delay' => absint( $meta['auto_play_timeout'] ),
645 893 'pauseOnMouseEnter' => $meta['stop_on_hover'],
@@ -650,69 +898,14 @@
650 898 $slider_options = apply_filters( 'rtsb/elementor/render/slider_dataset', $slider_options, $meta );
651 899 $carouselClass = 'rtsb-carousel-slider slider-loading rtsb-pos-s ' . $meta['nav_position'] . '-nav' . $has_dots;
652 900
653 901 return [
654 - 'data' => ' data-options=\'' . esc_js( wp_json_encode( $slider_options ) ) . '\'',
902 + 'data' => esc_js( wp_json_encode( $slider_options ) ),
655 903 'class' => $carouselClass,
656 904 ];
657 905 }
658 906
659 907 /**
660 - * Renders pagination
661 - *
662 - * @param object $wp_query WP_Query object.
663 - * @param array $meta Meta values.
664 - * @param int $limit Post limit.
665 - * @param int $per_page Posts per page.
666 - *
667 - * @return string
668 - */
669 - public static function render_pagination( $wp_query, $meta, $limit, $per_page ) {
670 - $html_utility = null;
671 - $html = null;
672 - $ajax = false;
673 - $is_grid = preg_match( '/grid-layout/', $meta['layout'] ) || preg_match( '/list-layout/', $meta['layout'] );
674 - $posts_per_page = $wp_query->query_vars['posts_per_page'];
675 - $total_page = $wp_query->max_num_pages;
676 -
677 - if ( $limit && ( empty( $wp_query->query['tax_query'] ) ) ) {
678 - $found_post = $wp_query->found_posts;
679 -
680 - if ( $per_page && $found_post > $per_page ) {
681 - $found_post = $limit;
682 - $total_page = ceil( $found_post / $per_page );
683 - }
684 - }
685 -
686 - $total_page = absint( $total_page );
687 -
688 - $args = [
689 - 'total_page' => $total_page,
690 - 'posts_per_page' => $posts_per_page,
691 - 'ajax' => $ajax,
692 - ];
693 -
694 - if ( 'pagination' === $meta['posts_loading_type'] ) {
695 - if ( $is_grid ) {
696 - $html_utility .= Fns::custom_pagination(
697 - $total_page,
698 - $posts_per_page
699 - );
700 - }
701 - } else {
702 - ob_start();
703 - do_action( 'rtsb/elementor/render/pagination', $meta, $wp_query, $args );
704 - $html_utility .= ob_get_clean();
705 - }
706 -
707 - if ( $html_utility ) {
708 - $html .= '<div class="rtsb-pagination-wrap element-loading" data-total-pages="' . absint( $total_page ) . '" data-posts-per-page="' . absint( $posts_per_page ) . '" data-type="' . esc_attr( $meta['posts_loading_type'] ) . '">' . $html_utility . '</div>';
709 - }
710 -
711 - return $html;
712 - }
713 -
714 - /**
715 908 * Preloader.
716 909 *
717 910 * @param string $layout Layout.
718 911 *
@@ -768,10 +961,11 @@
768 961 *
769 962 * @return void
770 963 */
771 964 public static function register_scripts( $scripts ) {
772 - $caro = false;
773 - $script = [];
965 + $caro = false;
966 + $masonry = false;
967 + $script = [];
774 968
775 969 $script[] = 'jquery';
776 970
777 971 foreach ( $scripts as $sc => $value ) {
@@ -778,8 +972,12 @@
778 972 if ( ! empty( $sc ) ) {
779 973 if ( 'isCarousel' === $sc ) {
780 974 $caro = $value;
781 975 }
976 +
977 + if ( 'isMasonry' === $sc ) {
978 + $masonry = $value;
979 + }
782 980 }
783 981 }
784 982
785 983 if ( count( $scripts ) ) {
@@ -789,12 +987,18 @@
789 987 if ( $caro ) {
790 988 $script[] = 'swiper';
791 989 }
792 990
991 + if ( $masonry ) {
992 + $script[] = 'masonry';
993 + }
994 +
793 995 $script[] = 'rtsb-imagesloaded';
794 996 $script[] = 'rtsb-public';
795 997
796 - wp_enqueue_script( $script );
998 + foreach ( $script as $sc ) {
999 + wp_enqueue_script( $sc );
1000 + }
797 1001 }
798 1002 }
799 1003
800 1004 /**
@@ -820,6 +1024,751 @@
820 1024 return true;
821 1025 }
822 1026
823 1027 return false;
1028 + }
1029 +
1030 + /**
1031 + * Get the number of products per page based on WooCommerce settings.
1032 + *
1033 + * @return int
1034 + */
1035 + public static function get_products_per_page() {
1036 + $products_row = absint( get_option( 'woocommerce_catalog_rows', 4 ) );
1037 + $products_col = absint( get_option( 'woocommerce_catalog_columns', 4 ) );
1038 + $products_per_page = apply_filters( 'rtsb/elementor/archive/products_per_page', $products_row * $products_col );
1039 +
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;
824 1773 }
825 1774 }