PluginProbe
ShopBuilder – WooCommerce Builder For Elementor / 3.2.3
ShopBuilder – WooCommerce Builder For Elementor v3.2.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
shopbuilder / app / Elementor / Helper / RenderHelpers.php

RenderHelpers.php in ShopBuilder – WooCommerce Builder For Elementor 3.2.3, at app/Elementor/Helper/RenderHelpers.php

1,816 lines 62.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Elementor Render Helper Class.
4 *
5 * This class contains render helper logics.
6 *
7 * @package RadiusTheme\SB
8 */
9
10 namespace RadiusTheme\SB\Elementor\Helper;
11
12 use Elementor\Plugin;
13 use RadiusTheme\SB\Helpers\Cache;
14 use RadiusTheme\SB\Helpers\Fns;
15 use RadiusTheme\SB\Helpers\BuilderFns;
16 use WC_Product_Query;
17 use WP_Term;
18
19 // Do not allow directly accessing this file.
20 if ( ! defined( 'ABSPATH' ) ) {
21 exit( 'This script cannot be accessed directly.' );
22 }
23
24 /**
25 * BuilderFns class
26 */
27 class RenderHelpers {
28 /**
29 * @var array
30 */
31 private static $cache = [];
32 /**
33 * @param string $order_by value.
34 * @return string
35 */
36 public static function escaping_product_orderby( $order_by ) {
37 $catalog_orderby_options = apply_filters(
38 'woocommerce_catalog_orderby',
39 [
40 'menu_order' => __( 'Default sorting', 'shopbuilder' ),
41 'popularity' => __( 'Sort by popularity', 'shopbuilder' ),
42 'rating' => __( 'Sort by average rating', 'shopbuilder' ),
43 'date' => __( 'Sort by latest', 'shopbuilder' ),
44 'price' => __( 'Sort by price: low to high', 'shopbuilder' ),
45 'price-desc' => __( 'Sort by price: high to low', 'shopbuilder' ),
46 ]
47 );
48 if ( in_array( $order_by, array_keys( $catalog_orderby_options ), true ) ) {
49 return $order_by;
50 }
51 return 'menu_order';
52 }
53 /**
54 * Get data.
55 *
56 * @param array|string $haystack The array or string to search for the value.
57 * @param string $needle The key to look for in the array or the string itself.
58 * @param mixed $default The default value to return if the key is not.
59 *
60 * @return mixed
61 */
62 public static function get_data( $haystack, $needle, $default = null ) {
63 if ( is_array( $haystack ) && ! empty( $haystack[ $needle ] ) ) {
64 return $haystack[ $needle ];
65 } elseif ( is_string( $haystack ) && ! empty( $haystack ) ) {
66 return $haystack;
67 } else {
68 return $default;
69 }
70 }
71
72 /**
73 * Builds an array with field values.
74 *
75 * @param array $meta Field values.
76 * @param string $template Template name.
77 * @param array $raw_settings Raw settings.
78 *
79 * @return array
80 */
81 public static function meta_dataset( array $meta, $template = '', $raw_settings = [] ) {
82 $c_image_size = self::get_data( $meta, 'image_custom_dimension', [] );
83 $c_image_size['crop'] = self::get_data( $meta, 'image_crop', [] );
84
85 if ( ( ! empty( $_GET['displayview'] ) && 'list' === $_GET['displayview'] ) || ( empty( $_GET['displayview'] ) && ( ! empty( $meta['view_mode'] ) && 'list' === $meta['view_mode'] ) ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
86 $meta['cols'] = self::get_data( $meta, 'list_cols', 1 );
87 $meta['cols_tablet'] = self::get_data( $meta, 'list_cols_tablet', $meta['cols'] );
88 $meta['cols_mobile'] = self::get_data( $meta, 'list_cols_mobile', $meta['cols'] );
89 }
90
91 $data = apply_filters(
92 'rtsb/elementor/render/meta_dataset',
93 [
94 // Layout.
95 'widget' => 'custom',
96 'template' => self::get_data( $template, '', '' ),
97 'raw_settings' => $raw_settings,
98 'layout' => self::get_data( $meta, 'layout', 'layout1' ),
99 'grid_layout' => self::get_data( $raw_settings, 'layout', 'grid-layout1' ),
100 'list_layout' => self::get_data( $raw_settings, 'list_layout', 'list-layout1' ),
101 'd_cols' => self::get_data( $meta, 'cols', 0 ),
102 't_cols' => self::get_data( $meta, 'cols_tablet', 2 ),
103 'm_cols' => self::get_data( $meta, 'cols_mobile', 1 ),
104 'grid_type' => self::get_data( $meta, 'grid_style', 'even' ),
105
106 // Query.
107 'post_in' => self::get_data( $meta, 'include_posts', [] ),
108 'post_not_in' => self::get_data( $meta, 'exclude_posts', [] ),
109 'limit' => ( empty( $meta['posts_limit'] ) || '-1' === $meta['posts_limit'] ) ? 10000000 : $meta['posts_limit'],
110 'offset' => self::get_data( $meta, 'posts_offset', 0 ),
111 'order_by' => self::get_data( $meta, 'posts_order_by', 'date' ),
112 'order' => self::get_data( $meta, 'posts_order', 'DESC' ),
113 'author_in' => self::get_data( $meta, 'filter_author', [] ),
114 'display_by' => self::get_data( $meta, 'products_filter', 'date' ),
115 'categories' => self::get_data( $meta, 'filter_categories', [] ),
116 'brands' => self::get_data( $meta, 'filter_brands', [] ),
117 'tags' => self::get_data( $meta, 'filter_tags', [] ),
118 'attributes' => self::get_data( $meta, 'filter_attributes', [] ),
119 'relation' => self::get_data( $meta, 'tax_relation', 'OR' ),
120 'category_source' => self::get_data( $meta, 'select_source', 'product_cat' ),
121 'category_term' => self::get_data( $meta, 'select_cat' ),
122 'display_cat_by' => self::get_data( $meta, 'display_cat_by' ),
123 'include_cats' => self::get_data( $meta, 'include_cats', [] ),
124 'exclude_cats' => self::get_data( $meta, 'exclude_cats', [] ),
125 'select_parent_cat' => self::get_data( $meta, 'select_parent_cat' ),
126 'select_cats' => self::get_data( $meta, 'select_cats', [] ),
127 'select_cat_ids' => self::get_data( $meta, 'include_cat_ids', '' ),
128 'cats_limit' => ( empty( $meta['cats_limit'] ) || '-1' === $meta['cats_limit'] ) ? 10000000 : $meta['cats_limit'],
129 'show_empty' => ! empty( $meta['show_empty'] ),
130 'show_uncategorized' => ! empty( $meta['show_uncategorized'] ),
131 'show_subcats' => ! empty( $meta['show_subcats'] ),
132 'show_top_level_cats' => ! empty( $meta['show_top_level_cats'] ),
133 'cats_order_by' => self::get_data( $meta, 'cats_order_by', 'name' ),
134 'cats_order' => self::get_data( $meta, 'cats_order', 'DESC' ),
135 'rtsb_order' => self::get_data( $meta, 'rtsb_order', 'ASC' ),
136 'rtsb_orderby' => self::get_data( $meta, 'rtsb_orderby', 'menu_order' ),
137
138 // Pagination.
139 'pagination' => ! empty( $meta['show_pagination'] ),
140 'posts_loading_type' => self::get_data( $meta, 'pagination_type', 'pagination' ),
141 'posts_per_page' => self::get_data( $meta, 'pagination_per_page', '' ),
142
143 // Image.
144 'f_img' => ! empty( $meta['show_featured_image'] ),
145 'gallery_img' => ! empty( $meta['show_product_gallery'] ),
146 'c_img' => ! empty( $meta['show_cat_image'] ),
147 'hover_img' => ! empty( $meta['show_hover_image'] ),
148 'f_img_size' => self::get_data( $meta, 'image', 'medium' ),
149 'custom_img_size' => ! empty( $c_image_size ) && is_array( $c_image_size ) ? $c_image_size : [],
150 'default_img_id' => ! empty( $meta['default_preview_image']['id'] ) ? $meta['default_preview_image']['id'] : null,
151 'show_overlay' => ! empty( $meta['show_overlay'] ),
152 'hover_animation' => self::get_data( $meta, 'image_hover_animation', 'none' ),
153 'show_custom_image' => ! empty( $meta['show_custom_image'] ),
154 'custom_image' => ! empty( $meta['custom_image']['id'] ) ? $meta['custom_image']['id'] : null,
155
156 // Visibility.
157 'visibility' => ! empty( self::content_visibility( $meta ) ) ? self::content_visibility( $meta ) : [],
158
159 // Action Buttons.
160 'btn_preset' => self::get_data( $meta, 'action_btn_preset', 'preset1' ),
161 'btn_position' => self::get_data( $meta, 'action_btn_position', 'above' ),
162 'tooltip_position' => self::get_data( $meta, 'action_btn_tooltip_position', 'top' ),
163
164 // Product Title.
165 'title_tag' => self::get_data( $meta, 'title_tag', 'h3' ),
166 'title_hover' => ! empty( $meta['title_hover'] ),
167 'title_limit' => self::get_data( $meta, 'title_limit', 'default' ),
168 'title_limit_custom' => self::get_data( $meta, 'title_limit_custom' ),
169 'show_custom_title' => ! empty( $meta['show_custom_title'] ),
170 'cat_custom_title' => self::get_data( $meta, 'custom_title', '' ),
171
172 // Variation Swatches.
173 'swatch_position' => self::get_data( $meta, 'swatch_position', 'top' ),
174 'swatch_type' => self::get_data( $meta, 'swatch_type', 'circle' ),
175
176 // Short Description.
177 'show_custom_excerpt' => ! empty( $meta['show_custom_description'] ),
178 'cat_custom_excerpt' => self::get_data( $meta, 'custom_description', '' ),
179 'cat_excerpt_position' => self::get_data( $meta, 'excerpt_position', 'below' ),
180 'excerpt_limit' => self::get_data( $meta, 'excerpt_limit', 'default' ),
181 'excerpt_limit_custom' => self::get_data( $meta, 'excerpt_limit_custom', 200 ),
182
183 // Count.
184 'count_position' => self::get_data( $meta, 'count_display_type', 'flex' ),
185 'before_count' => self::get_data( $meta, 'before_count', '' ),
186 'after_count' => self::get_data( $meta, 'after_count', '' ),
187
188 // Add to cart.
189 'show_cart_icon' => ! empty( $meta['show_cart_icon'] ),
190 'show_cart_text' => ! empty( $meta['show_cart_text'] ),
191 'add_to_cart_icon' => self::get_data( $meta, 'add_to_cart_icon', [] ),
192 'add_to_cart_success_icon' => self::get_data( $meta, 'add_to_cart_success_icon', [] ),
193 'add_to_cart_text' => self::get_data( $meta, 'add_to_cart_text', esc_html__( 'Add to Cart', 'shopbuilder' ) ),
194 'add_to_cart_success_text' => self::get_data( $meta, 'add_to_cart_success_text', '' ),
195 'add_to_cart_alignment' => self::get_data( $meta, 'cart_icon_alignment', 'left' ),
196
197 // Action Button Icons.
198 'quick_view_icon' => self::get_data( $meta, 'quick_view_icon', [] ),
199 'comparison_icon' => self::get_data( $meta, 'comparison_icon', [] ),
200 'comparison_icon_added' => self::get_data( $meta, 'comparison_icon_added', [] ),
201 'wishlist_icon' => self::get_data( $meta, 'wishlist_icon', [] ),
202 'wishlist_icon_added' => self::get_data( $meta, 'wishlist_icon_added', [] ),
203
204 // Badges.
205 'sale_badge_type' => self::get_data( $meta, 'sale_badges_type', 'percentage' ),
206 'sale_badge_text' => self::get_data( $meta, 'sale_badges_text', esc_html__( 'Sale', 'shopbuilder' ) ),
207 'custom_badge_text' => self::get_data( $meta, 'custom_badge_text', esc_html__( 'Sale', 'shopbuilder' ) ),
208 'out_of_stock_badge_text' => self::get_data( $meta, 'stock_badges_text', esc_html__( 'Out of Stock', 'shopbuilder' ) ),
209 'badge_position' => self::get_data( $meta, 'badges_position', 'top' ),
210 'badge_alignment' => self::get_data( $meta, 'badges_alignment', 'left' ),
211 'badge_preset' => self::get_data( $meta, 'custom_badge_preset', 'preset-1' ),
212 'enable_badges_module' => self::get_data( $meta, 'enable_badges_module', '' ),
213
214 // Link.
215 'image_link' => ! empty( $meta['image_link'] ),
216 'title_link' => ! empty( $meta['title_link'] ),
217 'hover_btn_text' => self::get_data( $meta, 'hover_btn_text', esc_html__( 'See Details', 'shopbuilder' ) ),
218 'show_hover_btn_icon' => ! empty( $meta['show_hover_btn_icon'] ),
219 'hover_btn_icon' => self::get_data( $meta, 'hover_btn_icon', [] ),
220 'custom_link' => self::get_data( $meta, 'custom_link' ),
221
222 // Slider.
223 'd_group' => self::get_data( $meta, 'cols_group', 1 ),
224 't_group' => self::get_data( $meta, 'cols_group_tablet', 1 ),
225 'm_group' => self::get_data( $meta, 'cols_group_mobile', 1 ),
226 'auto_play' => ! empty( $meta['slide_autoplay'] ),
227 'stop_on_hover' => ! empty( $meta['pause_hover'] ),
228 'slider_nav' => ! empty( $meta['slider_nav'] ),
229 'slider_dot' => ! empty( $meta['slider_pagi'] ),
230 'slider_dynamic_dot' => ! empty( $meta['slider_dynamic_pagi'] ),
231 'loop' => ! empty( $meta['slider_loop'] ),
232 'lazy_load' => ! empty( $meta['slider_lazy_load'] ),
233 'auto_height' => ! empty( $meta['slider_auto_height'] ),
234 'speed' => self::get_data( $meta, 'slide_speed', 2000 ),
235 'space_between' => isset( $meta['grid_gap']['size'] ) && strlen( $meta['grid_gap']['size'] ) ? $meta['grid_gap']['size'] : 30,
236 'auto_play_timeout' => self::get_data( $meta, 'autoplay_timeout', 5000 ),
237 'nav_position' => self::get_data( $meta, 'slider_nav_position', 'top' ),
238 'left_arrow_icon' => self::get_data( $meta, 'slider_left_arrow_icon', [] ),
239 'right_arrow_icon' => self::get_data( $meta, 'slider_right_arrow_icon', [] ),
240 ],
241 $meta
242 );
243
244 if ( ! empty( $meta['active_cat_slider'] ) ) {
245 $data['active_cat_slider'] = true;
246 }
247
248 if ( ! empty( $meta['cols_widescreen'] ) ) {
249 $data['w_cols'] = $meta['cols_widescreen'];
250 }
251
252 if ( ! empty( $meta['cols_laptop'] ) ) {
253 $data['l_cols'] = $meta['cols_laptop'];
254 }
255
256 if ( ! empty( $meta['cols_tablet_extra'] ) ) {
257 $data['te_cols'] = $meta['cols_tablet_extra'];
258 }
259
260 if ( ! empty( $meta['cols_mobile_extra'] ) ) {
261 $data['me_cols'] = $meta['cols_mobile_extra'];
262 }
263
264 $queried_obj = get_queried_object();
265
266 if ( is_shop() || is_product_taxonomy() ) {
267 $data['posts_per_page'] = self::get_products_per_page();
268 $data['order_by'] = self::get_data( $data, 'rtsb_orderby', $data['order_by'] );
269 $data['order'] = self::get_data( $data, 'rtsb_order', $data['order'] );
270 }
271
272 if ( ! is_shop() && is_product_taxonomy() ) {
273 if ( ! empty( $queried_obj->taxonomy ) ) {
274 $data['queried_tax'] = esc_html( $queried_obj->taxonomy );
275 }
276
277 if ( ! empty( $queried_obj->term_id ) ) {
278 $data['queried_term'] = esc_html( $queried_obj->term_id );
279 }
280 }
281
282 return apply_filters( 'rtsb/elementor/render/meta_dataset_final', $data, $meta, $raw_settings );
283 }
284
285 /**
286 * Builds an array with field values.
287 *
288 * @param array $meta Field values.
289 * @param string $template Template name.
290 *
291 * @return array
292 */
293 public static function archive_meta_dataset( array $meta, $template = '' ) {
294 $data = apply_filters(
295 'rtsb/elementor/render/archive_meta_dataset',
296 [
297 // Layout.
298 'widget' => 'default',
299 'template' => self::get_data( $template, '', '' ),
300 'view_mode' => self::get_data( $meta, 'view_mode', 'grid' ),
301 'show_flash_sale' => ! empty( $meta['show_flash_sale'] ),
302 'wishlist_button' => ! empty( $meta['wishlist_button'] ),
303 'comparison_button' => ! empty( $meta['comparison_button'] ),
304 'quick_view_button' => ! empty( $meta['quick_view_button'] ),
305 'show_rating' => ! empty( $meta['show_rating'] ),
306 'show_pagination' => ! empty( $meta['show_pagination'] ),
307 'cart_icon' => self::get_data( $meta, 'cart_icon', [] ),
308 'wishlist_icon' => self::get_data( $meta, 'wishlist_icon', [] ),
309 'wishlist_icon_added' => self::get_data( $meta, 'wishlist_icon_added', [] ),
310 'comparison_icon' => self::get_data( $meta, 'comparison_icon', [] ),
311 'comparison_icon_added' => self::get_data( $meta, 'comparison_icon_added', [] ),
312 'quick_view_icon' => self::get_data( $meta, 'quick_view_icon', [] ),
313 'prev_icon' => self::get_data( $meta, 'prev_icon', [] ),
314 'next_icon' => self::get_data( $meta, 'next_icon', [] ),
315 'posts_per_page' => self::get_products_per_page(),
316 'rtsb_order' => self::get_data( $meta, 'rtsb_order', 'ASC' ),
317 'rtsb_orderby' => self::get_data( $meta, 'rtsb_orderby', 'menu_order' ),
318 'tooltip_position' => self::get_data( $meta, 'action_btn_tooltip_position', 'top' ),
319 ],
320 $meta
321 );
322
323 $queried_obj = get_queried_object();
324
325 if ( ! is_shop() && BuilderFns::is_archive() ) {
326 if ( ! empty( $queried_obj->taxonomy ) ) {
327 $data['queried_tax'] = esc_html( $queried_obj->taxonomy );
328 }
329
330 if ( ! empty( $queried_obj->term_id ) ) {
331 $data['queried_term'] = esc_html( $queried_obj->term_id );
332 }
333 }
334
335 return apply_filters( 'rtsb/elementor/render/archive_meta_dataset_final', $data, $meta );
336 }
337
338 /**
339 * Setting up content visibility
340 *
341 * @param array $settings Elementor settings.
342 *
343 * @return array
344 */
345 public static function content_visibility( $settings ) {
346 $visibility = [];
347
348 if ( ! empty( $settings['show_title'] ) ) {
349 $visibility[] = 'title';
350 }
351
352 if ( ! empty( $settings['show_short_desc'] ) ) {
353 $visibility[] = 'excerpt';
354 }
355
356 if ( ! empty( $settings['show_price'] ) ) {
357 $visibility[] = 'price';
358 }
359
360 if ( ! empty( $settings['show_rating'] ) ) {
361 $visibility[] = 'rating';
362 }
363
364 if ( ! empty( $settings['show_badges'] ) ) {
365 $visibility[] = 'badges';
366 }
367
368 if ( ! empty( $settings['show_categories'] ) ) {
369 $visibility[] = 'categories';
370 }
371
372 if ( ! empty( $settings['single_category'] ) ) {
373 $visibility[] = 'single-cat';
374 }
375 if ( ! empty( $settings['show_brands'] ) ) {
376 $visibility[] = 'brands';
377 }
378
379 if ( ! empty( $settings['single_brand'] ) ) {
380 $visibility[] = 'single-brand';
381 }
382
383 if ( ! empty( $settings['show_swatches'] ) ) {
384 $visibility[] = 'swatches';
385 }
386
387 if ( ! empty( $settings['show_vs_clear_btn'] ) ) {
388 $visibility[] = 'clear-btn';
389 }
390
391 if ( ! empty( $settings['show_count'] ) ) {
392 $visibility[] = 'count';
393 }
394
395 if ( ! empty( $settings['show_wishlist'] ) ) {
396 $visibility[] = 'wishlist';
397 }
398
399 if ( ! empty( $settings['show_compare'] ) ) {
400 $visibility[] = 'compare';
401 }
402
403 if ( ! empty( $settings['show_quick_view'] ) ) {
404 $visibility[] = 'quick_view';
405 }
406
407 if ( ! empty( $settings['show_add_to_cart'] ) ) {
408 $visibility[] = 'add_to_cart';
409 }
410
411 return $visibility;
412 }
413
414 /**
415 * Set Default Layout.
416 *
417 * @param string $layout Layout.
418 *
419 * @return string
420 */
421 public static function set_default_layout( $layout ) {
422 $is_list = preg_match( '/list/', $layout );
423 $is_cat_single = preg_match( '/category-single/', $layout );
424 $is_cat = preg_match( '/category/', $layout );
425 $is_carousel = preg_match( '/slider/', $layout );
426 $default = 'grid-layout1';
427
428 if ( $is_list ) {
429 $default = 'list-layout1';
430 } elseif ( $is_cat_single ) {
431 $default = 'category-single-layout1';
432 } elseif ( $is_cat ) {
433 $default = 'category-layout1';
434 } elseif ( $is_carousel ) {
435 $default = 'slider-layout1';
436 }
437
438 return $default;
439 }
440
441 /**
442 * Default layout columns.
443 *
444 * @param int $layout Layout.
445 *
446 * @return int
447 */
448 public static function default_columns( $layout ) {
449 switch ( $layout ) {
450 case 'rtsb-post-grid-layout1':
451 case 'rtsb-post-grid-layout2':
452 case 'rtsb-post-grid-layout3':
453 case 'rtsb-team-layout1':
454 case 'rtsb-team-layout2':
455 case 'rtsb-testimonial-layout2':
456 case 'grid-layout2':
457 case 'slider-layout2':
458 case 'rtsb-coupon-layout1':
459 case 'rtsb-coupon-layout2':
460 case 'rtsb-coupon-layout3':
461 $columns = 3;
462 break;
463 case 'rtsb-post-list-layout1':
464 case 'rtsb-post-list-layout2':
465 case 'list-layout1':
466 case 'list-layout2':
467 case 'list-layout3':
468 case 'list-layout7':
469 case 'list-layout5':
470 $columns = 1;
471 break;
472 case 'rtsb-team-layout4':
473 case 'rtsb-testimonial-layout1':
474 case 'rtsb-testimonial-layout3':
475 case 'rtsb-testimonial-layout4':
476 case 'rtsb-testimonial-layout5':
477 case 'list-layout4':
478 case 'list-layout6':
479 case 'slider-layout5':
480 case 'slider-layout8':
481 $columns = 2;
482 break;
483 case 'rtsb-logo-layout1':
484 case 'rtsb-logo-layout2':
485 case 'grid-layout6':
486 case 'grid-layout9':
487 $columns = 5;
488 break;
489
490 case 'category-layout1':
491 $columns = 6;
492 break;
493
494 default:
495 $columns = 4;
496 break;
497 }
498
499 return apply_filters( 'rtsb/element/general/default_columns', $columns, $layout );
500 }
501
502 /**
503 * Pagination JSON data.
504 *
505 * @param array $metas Data set.
506 * @param string $template Template name.
507 *
508 * @return string
509 */
510 public static function pagination_data( $metas, $template ) {
511 $el_data = self::meta_dataset( $metas, $template );
512
513 return esc_js( wp_json_encode( $el_data, JSON_UNESCAPED_UNICODE ) );
514 }
515
516 /**
517 * Container classes
518 *
519 * @param array $metas Meta data.
520 * @param array $settings Settings array.
521 * @param string $custom_class Custom class.
522 *
523 * @return mixed|null
524 */
525 public static function prepare_container_classes( $metas = [], $settings = [], $custom_class = '' ) {
526 $classes = 'rtsb-elementor-container products rtsb-pos-r ';
527 $classes .= $custom_class;
528
529 $raw_layout = esc_html( $metas['layout'] );
530 $layout = self::filter_layout( $raw_layout );
531 $is_cat = preg_match( '/category/', $layout );
532 $cart_txt_class = '';
533
534 $animation = $metas['hover_animation'];
535
536 if ( ! $is_cat ) {
537 $cart_txt_class = $metas['show_cart_text'] ? ' has-cart-text' : ' no-cart-text';
538 $animation .= ' gallery-hover-' . ( ! empty( $settings['gallery_hover_animation'] ) ? $settings['gallery_hover_animation'] : 'fade' );
539 }
540
541 $badge_class = [
542 'position' => $metas['badge_position'],
543 'alignment' => $metas['badge_alignment'],
544 ];
545
546 if ( ! in_array( 'clear-btn', $metas['visibility'], true ) ) {
547 $classes .= ' no-clear-btn';
548 }
549
550 $classes .= ! empty( $metas['pagination'] ) ? ' rtsb-has-pagination' : ' rtsb-no-pagination';
551 $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'] );
552
553 if ( $metas['show_overlay'] ) {
554 $classes .= ' has-overlay';
555 }
556
557 if ( in_array( 'single-cat', $metas['visibility'], true ) ) {
558 $classes .= ' show-single-cat';
559 }
560 if ( in_array( 'single-brand', $metas['visibility'], true ) ) {
561 $classes .= ' show-single-brand';
562 }
563
564 if ( ! $is_cat ) {
565 $action_btn_classes = [
566 'show_compare_text' => 'has-compare-text',
567 'show_quick_view_text' => 'has-quick-view-text',
568 'show_wishlist_text' => 'has-wishlist-text',
569 'show_compare_icon' => 'no-compare-icon',
570 'show_quick_view_icon' => 'no-quick-view-icon',
571 'show_wishlist_icon' => 'no-wishlist-icon',
572 'show_quick_checkout_icon' => 'no-quick_checkout-icon',
573 ];
574
575 foreach ( $action_btn_classes as $setting_key => $class ) {
576 if ( strpos( $setting_key, 'icon' ) !== false ) {
577 $classes .= empty( $settings[ $setting_key ] ) ? ' ' . $class : '';
578 } else {
579 $classes .= ! empty( $settings[ $setting_key ] ) ? ' ' . $class : '';
580 }
581 }
582
583 if ( rtsb()->has_pro() && ! empty( $settings['custom_ordering'] ) ) {
584 $classes .= ' has-custom-ordering';
585 }
586 }
587 if ( rtsb()->has_pro() && ! empty( $settings['slider_slide_animation'] ) ) {
588 $classes .= ' has-slide-animation';
589 }
590
591 return apply_filters( 'rtsb/product/container/class', $classes, $settings );
592 }
593
594 /**
595 * Function to filter and validate the layout against allowed patterns.
596 *
597 * @param string $layout The layout string to be filtered.
598 * @param string $template The template to be checked.
599 *
600 * @return string
601 */
602 public static function filter_layout( $layout, $template = '' ) {
603 $allowed_patterns = apply_filters( 'rtsb/elementor/custom_layout', [ 'grid', 'list', 'slider', 'category', 'toyup', 'zilly', 'rtsb' ] );
604 $layout_part = explode( '-', $layout );
605 $default = 'grid-layout1';
606
607 if ( empty( $layout_part[0] ) ) {
608 return $default;
609 }
610
611 if ( in_array( $layout_part[0], $allowed_patterns, true ) ) {
612 if ( ! rtsb()->has_pro() && ! in_array( $layout, array_keys( Fns::free_layouts( $layout ) ), true ) ) {
613 $layout = self::set_default_layout( $layout );
614 }
615
616 return $layout;
617 } else {
618 return ! empty( $template ) ? self::set_default_layout( $layout ) : $default;
619 }
620 }
621
622 /**
623 * Row classes
624 *
625 * @param array $settings Settings array.
626 *
627 * @return mixed|null
628 */
629 public static function prepare_row_classes( $settings = [] ) {
630 $masonry_class = null;
631 $classes = 'rtsb-row rtsb-content-loader element-loading';
632
633 $loader_class = '';
634 if ( Fns::enable_loader() ) {
635 $loader_class = ' rtsb-pre-loader';
636 }
637 $raw_layout = esc_html( $settings['layout'] );
638 $layout = self::filter_layout( $raw_layout );
639 $grid_type = $settings['grid_type'];
640 $is_carousel = preg_match( '/slider/', $layout );
641
642 if ( preg_match( '/category/', $layout ) && ! empty( $settings['active_cat_slider'] ) ) {
643 $classes .= ' rtsb-slider-layout';
644 }
645
646 if ( 'equal' === $grid_type ) {
647 $masonry_class = ' rtsb-equal';
648 } elseif ( 'masonry' === $grid_type ) {
649 $masonry_class = ' rtsb-masonry';
650 } else {
651 $masonry_class = ' rtsb-even';
652 }
653
654 if ( ! rtsb()->has_pro() || $is_carousel ) {
655 $masonry_class = ' rtsb-even';
656 }
657
658 if ( $is_carousel && ! empty( $settings['raw_settings']['always_show_nav'] ) ) {
659 $classes .= ' always-show-nav';
660 }
661
662 if ( ! empty( $settings['raw_settings']['inner_slider_always_show_nav'] ) ) {
663 $classes .= ' inner-slider-always-show-nav';
664 }
665 if ( empty( $settings['raw_settings']['cols_mobile'] ) ) {
666 $classes .= ' rtsb-mobile-flex-row';
667 }
668
669 $classes .= ' rtsb-' . $layout . $masonry_class . $loader_class;
670
671 return apply_filters( 'rtsb/elementor/row/classes', $classes, $settings );
672 }
673
674 /**
675 * Prepare pagination attributes.
676 *
677 * @param string $layout The layout type.
678 * @param bool $has_filters Whether the widget has filters.
679 * @param string $template The template name.
680 * @param array $settings The widget settings.
681 * @param bool $ajax Whether to enable AJAX pagination.
682 *
683 * @return string
684 */
685 public static function prepare_pagination_attr( $layout, $has_filters, $template, $settings, $ajax ) {
686 $is_cat = preg_match( '/category/', $layout );
687 $is_carousel = preg_match( '/slider/', $layout );
688
689 if ( $is_carousel ) {
690 return $has_filters ? self::pagination_data( $settings, $template ) : '';
691 } elseif ( $is_cat ) {
692 return '';
693 } else {
694 $ajax_pagination = ! empty( $settings['show_pagination'] ) && 'pagination' !== $settings['pagination_type'];
695 $page = Fns::product_filters_has_ajax( apply_filters( 'rtsb/builder/set/current/page/type', '' ) );
696 $condition = rtsb()->has_pro() && $ajax && ( $ajax_pagination || $has_filters || $page );
697
698 return $condition ? self::pagination_data( $settings, $template ) : '';
699 }
700 }
701
702 /**
703 * Archive JSON data.
704 *
705 * @param array $metas Data set.
706 * @param string $template Template name.
707 *
708 * @return string
709 */
710 public static function archive_data( $metas, $template ) {
711 $el_data = self::archive_meta_dataset( $metas, $template );
712
713 return ' data-rtsb-ajax=\'' . esc_js( wp_json_encode( $el_data ) ) . '\'';
714 }
715
716 /**
717 * Slider options.
718 *
719 * @param array $meta Meta values.
720 * @param array $settings Raw Settings.
721 *
722 * @return array
723 */
724 public static function slider_data( array $meta, $settings = [] ) {
725 $has_dots = $meta['slider_dot'] ? ' has-dot' : ' no-dot';
726 $has_dots .= $meta['slider_nav'] ? ' has-nav' : ' no-nav';
727 $has_dynamic_dots = $meta['slider_dynamic_dot'] ? true : false;
728 $d_col = 0 === $meta['d_cols'] ? self::default_columns( $meta['layout'] ) : $meta['d_cols'];
729 $t_col = 0 === $meta['t_cols'] ? 2 : $meta['t_cols'];
730 $m_col = 0 === $meta['m_cols'] ? 1 : $meta['m_cols'];
731
732 if ( Plugin::$instance->breakpoints->has_custom_breakpoints() ) {
733 // Widescreen.
734 $w_col = self::get_data( $settings, 'cols_widescreen' );
735 $w_col = 0 === $w_col ? self::default_columns( $meta['layout'] ) : $w_col;
736 $w_group = self::get_data( $settings, 'cols_group_widescreen', 1 );
737
738 // Laptop.
739 $l_col = self::get_data( $settings, 'cols_laptop' );
740 $l_col = 0 === $l_col ? self::default_columns( $meta['layout'] ) : $l_col;
741 $l_group = self::get_data( $settings, 'cols_group_laptop', 1 );
742
743 // Tablet Landscape.
744 $te_col = self::get_data( $settings, 'cols_tablet_extra' );
745 $te_col = 0 === $te_col ? 3 : $te_col;
746 $te_group = self::get_data( $settings, 'cols_group_tablet_extra', 1 );
747
748 // Mobile Landscape.
749 $me_col = self::get_data( $settings, 'cols_mobile_extra' );
750 $me_col = 0 === $me_col ? 2 : $me_col;
751 $me_group = self::get_data( $settings, 'cols_group_mobile_extra', 1 );
752
753 $el_breakpoints = Fns::get_elementor_breakpoints();
754
755 foreach ( $el_breakpoints as $key => $value ) {
756 if ( isset( $value['is_enabled'] ) && ! $value['is_enabled'] ) {
757 unset( $el_breakpoints[ $key ] );
758 }
759 }
760
761 $breakpoints = [
762 0 => [
763 'slidesPerView' => absint( $m_col ),
764 'slidesPerGroup' => absint( $meta['m_group'] ),
765 'grid' => [
766 'rows' => 1,
767 ],
768 'pagination' => [
769 'dynamicBullets' => $has_dynamic_dots,
770 ],
771 ],
772 ];
773
774 $desktop = [
775 'desktop' => [
776 'label' => 'Desktop',
777 'value' => 1920,
778 'is_enabled' => 1,
779 ],
780 ];
781
782 if ( ! empty( $el_breakpoints['laptop'] ) && $el_breakpoints['laptop']['is_enabled'] ) {
783 $widescreen_position = array_search( 'widescreen', array_keys( $el_breakpoints ), true );
784 $el_breakpoints = array_merge(
785 array_slice( $el_breakpoints, 0, $widescreen_position ),
786 $desktop,
787 array_slice( $el_breakpoints, $widescreen_position )
788 );
789 } else {
790 $desktop['desktop']['value'] = 1366;
791 $el_breakpoints['desktop'] = $desktop['desktop'];
792 }
793
794 foreach ( $el_breakpoints as $el_breakpoint => $value ) {
795 $breakpoint_value = ! empty( $value['value'] ) ? $value['value'] : $value['default_value'];
796 $dynamic_bullets = $has_dynamic_dots;
797 $slides_per_view = $d_col;
798 $slides_per_group = $meta['d_group'];
799
800 switch ( $el_breakpoint ) {
801 case 'widescreen':
802 $slides_per_view = $w_col;
803 $slides_per_group = $w_group;
804
805 break;
806
807 case 'laptop':
808 $slides_per_view = $l_col;
809 $slides_per_group = $l_group;
810
811 break;
812
813 case 'tablet_extra':
814 $slides_per_view = $l_col;
815 $slides_per_group = $l_group;
816
817 if ( empty( $el_breakpoints['laptop'] ) ) {
818 $slides_per_view = $d_col;
819 $slides_per_group = $meta['d_group'];
820 }
821
822 break;
823
824 case 'tablet':
825 $slides_per_view = $te_col;
826 $slides_per_group = $te_group;
827
828 if ( empty( $el_breakpoints['laptop'] ) && empty( $el_breakpoints['tablet_extra'] ) ) {
829 $slides_per_view = $d_col;
830 $slides_per_group = $meta['d_group'];
831 } elseif ( empty( $el_breakpoints['laptop'] ) && ! empty( $el_breakpoints['tablet_extra'] ) ) {
832 $slides_per_view = $te_col;
833 $slides_per_group = $te_group;
834 } elseif ( ! empty( $el_breakpoints['laptop'] ) && empty( $el_breakpoints['tablet_extra'] ) ) {
835 $slides_per_view = $l_col;
836 $slides_per_group = $l_group;
837 }
838
839 break;
840
841 case 'mobile_extra':
842 $slides_per_view = $t_col;
843 $slides_per_group = $meta['t_group'];
844 $dynamic_bullets = $has_dynamic_dots;
845
846 break;
847
848 case 'mobile':
849 $slides_per_view = $t_col;
850 $slides_per_group = $meta['t_group'];
851 $dynamic_bullets = $has_dynamic_dots;
852
853 if ( ! empty( $el_breakpoints['mobile_extra'] ) ) {
854 $slides_per_view = $me_col;
855 $slides_per_group = $me_group;
856 }
857
858 break;
859 }
860
861 if ( $value['is_enabled'] ) {
862 $br = 'widescreen' !== $el_breakpoint ? $breakpoint_value + 1 : $breakpoint_value;
863
864 $breakpoints[ absint( $br ) ] = [
865 'slidesPerView' => absint( $slides_per_view ),
866 'slidesPerGroup' => absint( $slides_per_group ),
867 'pagination' => [
868 'dynamicBullets' => $dynamic_bullets,
869 ],
870 ];
871 }
872 }
873 } else {
874 $breakpoints = [
875 0 => [
876 'slidesPerView' => absint( $m_col ),
877 'slidesPerGroup' => absint( $meta['m_group'] ),
878 'pagination' => [
879 'dynamicBullets' => $has_dynamic_dots,
880 ],
881 ],
882 768 => [
883 'slidesPerView' => absint( $t_col ),
884 'slidesPerGroup' => absint( $meta['t_group'] ),
885 'pagination' => [
886 'dynamicBullets' => $has_dynamic_dots,
887 ],
888 ],
889 1025 => [
890 'slidesPerView' => absint( $d_col ),
891 'slidesPerGroup' => absint( $meta['d_group'] ),
892 'pagination' => [
893 'dynamicBullets' => $has_dynamic_dots,
894 ],
895 ],
896 ];
897 }
898
899 $slider_options = [
900 'slidesPerView' => absint( $d_col ),
901 'slidesPerGroup' => absint( $meta['d_group'] ),
902 'speed' => absint( $meta['speed'] ),
903 'loop' => $meta['loop'],
904 'autoHeight' => $meta['auto_height'],
905 'preloadImages' => ! $meta['lazy_load'],
906 'lazy' => $meta['lazy_load'],
907 'breakpoints' => $breakpoints,
908 ];
909
910 if ( ! empty( $meta['raw_settings']['slider_slide_animation'] ) ) {
911 $slider_options['watchSlidesProgress'] = true;
912 }
913 if ( $meta['auto_play'] ) {
914 $slider_options['autoplay'] = [
915 'delay' => absint( $meta['auto_play_timeout'] ),
916 'pauseOnMouseEnter' => $meta['stop_on_hover'],
917 'disableOnInteraction' => false,
918 ];
919 }
920
921 $slider_options = apply_filters( 'rtsb/elementor/render/slider_dataset', $slider_options, $meta );
922 $carouselClass = 'rtsb-carousel-slider slider-loading rtsb-pos-s ' . $meta['nav_position'] . '-nav' . $has_dots;
923
924 return [
925 'data' => esc_js( wp_json_encode( $slider_options ) ),
926 'class' => $carouselClass,
927 ];
928 }
929
930 /**
931 * Preloader.
932 *
933 * @param string $layout Layout.
934 *
935 * @return string
936 */
937 public static function pre_loader( $layout ) {
938 $loader_class = '';
939
940 $is_carousel = preg_match( '/slider/', $layout );
941
942 if ( $is_carousel ) {
943 $loader_class = ' full-op';
944 }
945 if ( ! Fns::enable_loader() ) {
946 return '';
947 }
948 return '<div class="rtsb-elements-loading rtsb-ball-clip-rotate"><div></div></div>';
949 }
950
951 /**
952 * Badge class.
953 *
954 * @param string $preset Badge preset.
955 *
956 * @return string|null
957 */
958 public static function badge_class( $preset ) {
959 switch ( $preset ) {
960 case 'preset-default':
961 $class = 'default-badge';
962 break;
963 case 'preset2':
964 $class = 'fill angle-right';
965 break;
966 case 'preset3':
967 $class = 'outline';
968 break;
969
970 case 'preset4':
971 $class = 'outline angle-right';
972 break;
973
974 default:
975 $class = 'fill';
976 break;
977 }
978
979 return $class;
980 }
981
982 /**
983 * Registers required scripts.
984 *
985 * @param array $scripts Scripts to register.
986 *
987 * @return void
988 */
989 public static function register_scripts( $scripts ) {
990 $caro = false;
991 $masonry = false;
992 $script = [];
993
994 $script[] = 'jquery';
995
996 foreach ( $scripts as $sc => $value ) {
997 if ( ! empty( $sc ) ) {
998 if ( 'isCarousel' === $sc ) {
999 $caro = $value;
1000 }
1001
1002 if ( 'isMasonry' === $sc ) {
1003 $masonry = $value;
1004 }
1005 }
1006 }
1007
1008 if ( count( $scripts ) ) {
1009 /**
1010 * Scripts.
1011 */
1012 if ( $caro ) {
1013 $script[] = 'swiper';
1014 }
1015
1016 if ( $masonry ) {
1017 $script[] = 'masonry';
1018 }
1019
1020 $script[] = 'imagesloaded';
1021 $script[] = Fns::optimized_handle( 'rtsb-public' );
1022
1023 foreach ( $script as $sc ) {
1024 wp_enqueue_script( $sc );
1025 }
1026 }
1027 }
1028
1029 /**
1030 * Check if a wrapper is needed based on the current theme.
1031 *
1032 * @return bool
1033 */
1034 public static function is_wrapper_needed() {
1035 $theme_list = apply_filters(
1036 'rtsb/products/inner/wrapper/basedon/themes',
1037 [
1038 'twentytwentyone',
1039 'twentytwentytwo',
1040 'twentytwentythree',
1041 'storefront',
1042 'hello-elementor',
1043 'astra',
1044 ],
1045 rtsb()->current_theme
1046 );
1047
1048 if ( in_array( rtsb()->current_theme, $theme_list, true ) ) {
1049 return true;
1050 }
1051
1052 return false;
1053 }
1054
1055 /**
1056 * Get the number of products per page based on WooCommerce settings.
1057 *
1058 * @return int
1059 */
1060 public static function get_products_per_page() {
1061 $products_row = absint( get_option( 'woocommerce_catalog_rows', 4 ) );
1062 $products_col = absint( get_option( 'woocommerce_catalog_columns', 4 ) );
1063 $products_per_page = apply_filters( 'rtsb/elementor/archive/products_per_page', $products_row * $products_col );
1064
1065 return ! empty( $products_per_page ) ? $products_per_page : 12;
1066 }
1067 /**
1068 * Render Filters View.
1069 *
1070 * @param array $templates Template name.
1071 * @param array $settings Control settings.
1072 *
1073 * @return string
1074 */
1075 public static function filters_view( $templates, $settings ) {
1076 global $wp;
1077 $filters = [];
1078 $html = null;
1079 $reset = ! empty( $settings['reset_btn'] );
1080 $reset_mode = 'show' === $settings['reset_btn_behavior'] ? ' show-reset' : ' ondemand-reset';
1081 $reset_text = ! empty( $settings['reset_btn_text'] ) ? $settings['reset_btn_text'] : esc_html__( 'Reset Filter', 'shopbuilder' );
1082 $scroll_mode = ! empty( $settings['enable_scroll'] ) ? ' has-scroll' : ' no-scroll';
1083 $scroll_height = ! empty( $settings['enable_scroll'] ) ? $settings['scroll_height']['size'] : 300;
1084 $has_mobile_toggle = ! empty( $settings['filter_mobile_toggle'] );
1085 $toggle_class = $has_mobile_toggle ? ' default-filter-has-toggle' : ' default-filter-no-toggle';
1086 $mobile_toggle_text = ! empty( $settings['filter_mobile_toggle_text'] ) ? $settings['filter_mobile_toggle_text'] : esc_html__( 'Click to Filter', 'shopbuilder' );
1087 $scroll_attr = '';
1088
1089 if ( ! empty( $settings['enable_scroll'] ) ) {
1090 $scroll_attr = ' style="--rtsb-filter-scroll-height: ' . absint( $scroll_height ) . 'px;"';
1091 }
1092
1093 foreach ( $settings['filter_types'] as $key => $item ) {
1094 if ( ! defined( 'RTWPVS_PLUGIN_FILE' ) && in_array( $item['input_type_all'], [ 'color', 'button', 'image' ], true ) ) {
1095 $item['input_type_all'] = 'checkbox';
1096 }
1097 $filters[] = [
1098 'filter_title' => $item['filter_title'],
1099 'filter_items' => $item['filter_items'],
1100 'filter_attr' => $item['filter_attr'],
1101 'input_type' => 'product_attr' === $item['filter_items'] ? $item['input_type_all'] : $item['input_type'],
1102 ];
1103
1104 if ( 'rating_filter' === $item['filter_items'] ) {
1105 $filters[ $key ]['template'] = $templates['rating'];
1106 } elseif ( 'price_filter' === $item['filter_items'] ) {
1107
1108 $filters[ $key ]['input_type'] = 'slider';
1109 $filters[ $key ]['template'] = $templates['price'];
1110 } else {
1111 $filters[ $key ]['template'] = 'product_attr' === $item['filter_items'] ? $templates[ $item['input_type_all'] ] : $templates[ $item['input_type'] ];
1112 }
1113 }
1114
1115 if ( '' === get_option( 'permalink_structure' ) ) {
1116 $form_action = remove_query_arg( [ 'page', 'paged', 'product-page' ], add_query_arg( $wp->query_string, '', home_url( $wp->request ) ) );
1117 } else {
1118 $form_action = preg_replace( '%\/page/[0-9]+%', '', home_url( trailingslashit( $wp->request ) ) );
1119 }
1120 $args = [
1121 'filters' => $filters,
1122 'scroll_mode' => $scroll_mode,
1123 'reset_mode' => $reset_mode,
1124 'reset' => $reset,
1125 'scroll_attr' => $scroll_attr,
1126 'toggle_class' => $toggle_class,
1127 'reset_text' => $reset_text,
1128 'settings' => $settings,
1129 'form_action' => $form_action,
1130 ];
1131
1132 $html .= '<div class="rtsb-default-archive-filters' . esc_attr( $toggle_class ) . '">';
1133
1134 if ( $has_mobile_toggle ) {
1135 $html .= '<div class="rtsb-filter-mobile-toggle">
1136 <button class="product-filter-toggle">
1137 <span class="icon"><i aria-hidden="true" class="toggle-icon rtsb-icon rtsb-icon-filter"></i></span>
1138 <span class="text reset-text">' . esc_html( $mobile_toggle_text ) . '</span>
1139 <span></span>
1140 </button>
1141 </div>';
1142 }
1143
1144 $html .= Fns::load_template( $templates['layout'], $args, true );
1145 $html .= '</div>';
1146 return $html;
1147 }
1148 /**
1149 * Get taxonomy type.
1150 *
1151 * @param string $tax_type Taxonomy type.
1152 * @param string $attr_type Attribute type.
1153 *
1154 * @return string
1155 */
1156 public static function get_product_filters_tax_type( $tax_type, $attr_type = '' ) {
1157 if ( 'product_attr' !== $tax_type ) {
1158 return $tax_type;
1159 }
1160
1161 if ( empty( $attr_type ) ) {
1162 return $tax_type;
1163 }
1164
1165 return $attr_type;
1166 }
1167 /**
1168 * Get attribute terms.
1169 *
1170 * @param string $tax Taxonomy type.
1171 * @return int[]|string|string[]|\WP_Error|\WP_Term[]
1172 */
1173 public static function get_product_filters_attribute_terms( $tax ) {
1174 $cache_key = 'get_default_filter_attribute_terms_' . $tax;
1175 if ( isset( self::$cache[ $cache_key ] ) ) {
1176 return self::$cache[ $cache_key ];
1177 }
1178
1179 $attributes = wc_get_attribute_taxonomies();
1180 $att_name = str_replace( 'pa_', '', $tax );
1181 $exist = array_search( $att_name, array_column( $attributes, 'attribute_name' ), true );
1182 if ( false === $exist ) {
1183 self::$cache[ $cache_key ] = [];
1184 return self::$cache[ $cache_key ];
1185 }
1186 $attribute = $tax;
1187
1188 if ( ! is_shop() && is_product_taxonomy() ) {
1189 $term = get_queried_object();
1190
1191 if ( ! $term instanceof WP_Term ) {
1192 return [];
1193 }
1194
1195 $args = [
1196 'status' => 'publish',
1197 'limit' => -1,
1198 'return' => 'ids',
1199 ];
1200
1201 if ( 'product_cat' === $term->taxonomy ) {
1202 $args['category'] = [ $term->slug ];
1203 }
1204
1205 if ( 'product_tag' === $term->taxonomy ) {
1206 $args['tag'] = [ $term->slug ];
1207 }
1208
1209 if ( strpos( $term->taxonomy, 'pa_' ) !== false ) {
1210 $args['tax_query'] = [ // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_tax_query
1211 [
1212 'taxonomy' => $term->taxonomy,
1213 'field' => 'term_id',
1214 'terms' => $term->term_id,
1215 'operator' => 'IN',
1216 ],
1217 ];
1218 }
1219
1220 $query = new WC_Product_Query( $args );
1221 $products = $query->get_products();
1222 $attr_terms = [];
1223
1224 foreach ( $products as $product_id ) {
1225 $product_attr = wp_get_post_terms( $product_id, $attribute );
1226
1227 foreach ( $product_attr as $attr ) {
1228 $attr_terms[] = $attr;
1229 }
1230 }
1231 self::$cache[ $cache_key ] = self::filter_products_array_unique( $attr_terms );
1232 return self::$cache[ $cache_key ];
1233 } else {
1234 self::$cache[ $cache_key ] = get_terms(
1235 [
1236 'taxonomy' => $attribute,
1237 'hide_empty' => false,
1238 ]
1239 );
1240 return self::$cache[ $cache_key ];
1241 }
1242 }
1243 /**
1244 * Remove duplicate values from an array.
1245 *
1246 * @param array $array The input array.
1247 * @param bool $keep_key_assoc Whether to keep the key associations after removing duplicates.
1248 * @return array The array with duplicates removed.
1249 */
1250 public static function filter_products_array_unique( $array, $keep_key_assoc = false ) {
1251 $duplicate_keys = [];
1252 $tmp = [];
1253
1254 foreach ( $array as $key => $val ) {
1255 // convert objects to arrays, in_array() does not support objects.
1256 if ( is_object( $val ) ) {
1257 $val = (array) $val;
1258 }
1259
1260 if ( ! in_array( $val, $tmp, true ) ) {
1261 $tmp[] = $val;
1262 } else {
1263 $duplicate_keys[] = $key;
1264 }
1265 }
1266
1267 foreach ( $duplicate_keys as $key ) {
1268 unset( $array[ $key ] );
1269 }
1270
1271 return $keep_key_assoc ? $array : array_values( $array );
1272 }
1273 /**
1274 * Retrieve product categories (including hierarchical support)
1275 *
1276 * @param string $taxonomy Taxonomy name.
1277 * @return int[]|string|string[]|\WP_Error|\WP_Term[]
1278 */
1279 public static function get_all_terms( $taxonomy ) {
1280 $args = [
1281 'taxonomy' => $taxonomy,
1282 'suppress_filter' => true,
1283 'hide_empty' => false,
1284 'pad_counts' => true,
1285 'hierarchical' => true,
1286 ];
1287
1288 $cache_key = 'rtsb_get_terms_filter_products' . $taxonomy;
1289 $taxonomy_terms = wp_cache_get( $cache_key, 'shopbuilder' );
1290
1291 if ( false === $taxonomy_terms ) {
1292 $queried_object = get_queried_object();
1293
1294 if ( 'archive' === apply_filters( 'rtsb/builder/set/current/page/type', '' ) && $queried_object instanceof WP_Term && $queried_object->taxonomy === $taxonomy ) {
1295 $term_id = $queried_object->term_id;
1296 $taxonomy = $queried_object->taxonomy;
1297 $archive_cache_key = 'rtsb_get_terms_filter_products_' . $taxonomy . $term_id;
1298 $taxonomy_terms = wp_cache_get( $archive_cache_key, 'shopbuilder' );
1299 if ( false === $taxonomy_terms ) {
1300 $taxonomy_terms = [ $queried_object ];
1301 $child_args = [
1302 'taxonomy' => $taxonomy,
1303 'child_of' => $term_id,
1304 'hide_empty' => false,
1305 ];
1306
1307 $child_terms = get_terms( $child_args );
1308
1309 if ( ! empty( $child_terms ) ) {
1310 $taxonomy_terms = array_merge( $taxonomy_terms, $child_terms );
1311 }
1312
1313 wp_cache_set( $archive_cache_key, $taxonomy_terms, 'shopbuilder' );
1314 Cache::set_data_cache_key( $archive_cache_key );
1315 }
1316 } else {
1317 $taxonomy_terms = get_terms( $args );
1318 }
1319
1320 wp_cache_set( $cache_key, $taxonomy_terms, 'shopbuilder' );
1321 Cache::set_data_cache_key( $cache_key );
1322 }
1323
1324 return $taxonomy_terms;
1325 }
1326 /**
1327 * Generates an error message block.
1328 *
1329 * @param array $title The title array of the error message block.
1330 * @param string $wrapper Additional CSS class for the wrapper div.
1331 *
1332 * @return string The HTML representation of the error message block.
1333 */
1334 public static function filter_error_message( $title, $wrapper ) {
1335 $html = '<div class="rtsb-product-default-filters ' . esc_attr( $wrapper ) . '">';
1336 $html .= self::get_default_filter_title( $title );
1337 $html .= '<div class="default-filter-content">';
1338 $html .= '<p class="no-filter">' . esc_html__( 'Nothing found.', 'shopbuilder' ) . '</p>';
1339 $html .= '</div>';
1340 $html .= '</div>';
1341
1342 return $html;
1343 }
1344 /**
1345 * Get filter title.
1346 *
1347 * @param array $title Filter title.
1348 * @return string
1349 */
1350 public static function get_default_filter_title( $title ) {
1351 $html = '';
1352
1353 if ( empty( $title['title'] ) ) {
1354 return $html;
1355 }
1356
1357 $html .= '<div class="default-filter-title-wrapper">';
1358
1359 $html .= '<h3 class="widget-title rtsb-d-flex rtsb-align-items-center"><span class="title">' . $title['title'] . '</span></h3>';
1360
1361 $html .= '</div>';
1362
1363 return apply_filters( 'rtsb/elementor/default/filter/title', $html, $title );
1364 }
1365 /**
1366 * Recursive function to generate the filter list with hierarchy.
1367 *
1368 * @param array $data Array of required data.
1369 * @param string $input Type of input field for the filter (e.g., checkbox).
1370 * @param array $additional_data Data for additional filtering.
1371 * @param int $parent ID of the parent term (default: 0).
1372 *
1373 * @return string The generated HTML for the product filter list.
1374 */
1375 public static function get_product_default_filter_list_html( $data, $input = 'checkbox', $additional_data = [], $parent = 0 ) {
1376
1377 $html = '';
1378 $default_tax = [];
1379 $is_attribute = ! empty( $data['is_attribute'] );
1380 $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
1381 $counter = 0;
1382
1383 if ( $is_attribute ) {
1384 list(
1385 'filter_name' => $filter_name,
1386 'base_link' => $base_link
1387 ) = self::get_product_filters_attribute_term_info( $additional_data['taxonomy'] );
1388 }
1389
1390 $html .= '<ul class="product-default-filters input-type-' . esc_attr( $input ) . '">';
1391
1392 foreach ( $data['taxonomy'] as $tax ) {
1393 if ( $tax->parent !== $parent ) {
1394 continue;
1395 }
1396
1397 if ( $is_attribute ) {
1398 $tax_link = remove_query_arg( $filter_name, $base_link );
1399 $tax_link = add_query_arg( $filter_name, $tax->slug, $tax_link );
1400 $active_option = isset( $_GET[ $filter_name ] ) ? explode( ',', sanitize_text_field( wp_unslash( $_GET[ $filter_name ] ) ) ) : []; // phpcs:ignore WordPress.Security.NonceVerification.Recommended
1401 } else {
1402 $tax_link = get_term_link( $tax );
1403 }
1404
1405 $unique_id = substr( uniqid(), -4 );
1406
1407 $active_tax = in_array( $tax->slug, $active_option, true ) ? ' checked' : '';
1408 $active_tax_parent = in_array( $tax->slug, $active_option, true ) ? ' active' : '';
1409 $term_children = in_array( $tax->taxonomy, [ 'product_cat', 'product_brand' ], true ) ? get_term_children( $tax->term_id, $tax->taxonomy ) : [];
1410 $taxonomy = $tax->taxonomy;
1411 $product_count = $tax->count;
1412
1413 // Show count.
1414 if ( 'archive' === apply_filters( 'rtsb/builder/set/current/page/type', '' ) && ! empty( $data['count_display'] ) && 'block' === $data['count_display'] ) {
1415 $product_count = self::count_tax_data( $tax, $tax->count );
1416 }
1417
1418 // Show Empty Categories.
1419 if ( empty( $data['show_empty_terms'] ) && 0 === $product_count ) {
1420 continue;
1421 }
1422
1423 $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' : '' ) . '">
1424 <div class="rtsb-default-filter-group' . esc_attr( $active_tax_parent ) . '">
1425 <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 ) . '>
1426 <label class="rtsb-default-' . esc_attr( $input ) . '-filter-label" for="rtsb-default-term-filter-' . $unique_id . absint( $tax->term_id ) . '">
1427 <span class="name">' . esc_html( $tax->name ) . '</span>
1428 </label>
1429 <div class="rtsb-product-count">(' . esc_html( $product_count ) . ')</div>
1430 ' . ( ! empty( $term_children ) && $data['show_child'] ? '<i class="rtsb-plus-icon"></i>' : '' ) . '
1431 </div>';
1432
1433 // Show Sub-categories.
1434 if ( $data['show_child'] ) {
1435 $children = self::get_product_default_filter_list_html( $data, $input, $additional_data, $tax->term_id );
1436
1437 if ( ! empty( $children ) ) {
1438 $html .= '<div class="filter-child">' . $children . '</div>';
1439 }
1440 }
1441
1442 $counter++;
1443
1444 $html .= '</li>';
1445 }
1446
1447 $html .= '</ul>';
1448
1449 // Check if the output contains any child elements.
1450 $has_children = strpos( $html, '<li class="rtsb-default-filter-term-item' ) !== false;
1451
1452 if ( ! $has_children ) {
1453 // Remove the outer <ul> if there are no child elements.
1454 $html = '';
1455 }
1456 return $html;
1457 }
1458 /**
1459 * Get attribute term info.
1460 *
1461 * @param string $tax Taxonomy type.
1462 * @return array
1463 */
1464 public static function get_product_filters_attribute_term_info( $tax ) {
1465 $result = [];
1466 $attributes = wc_get_attribute_taxonomies();
1467
1468 foreach ( $attributes as $attr ) {
1469 if ( str_replace( 'pa_', '', $tax ) === $attr->attribute_name ) {
1470 $term_type = $attr->attribute_type;
1471 $attribute_slug = $attr->attribute_name;
1472 $attribute = wc_attribute_taxonomy_name( $attr->attribute_name );
1473 break;
1474 }
1475 }
1476
1477 $filter_name = 'filter_' . wc_attribute_taxonomy_slug( $attribute_slug );
1478
1479 $result['attribute'] = $attribute ?? '';
1480 $result['term_type'] = $term_type ?? '';
1481 $result['attribute_slug'] = $attribute_slug ?? '';
1482 $result['filter_name'] = $filter_name;
1483 $result['base_link'] = self::get_base_url();
1484
1485 return $result;
1486 }
1487 /**
1488 * Get base URL.
1489 *
1490 * @return string|null
1491 */
1492 public static function get_base_url() {
1493 global $wp;
1494 return home_url( add_query_arg( [], $wp->request ) );
1495 }
1496 /**
1497 * Count the number of occurrences for a specific term in a taxonomy for the current queried object.
1498 *
1499 * @param object|array $tax The term object for the taxonomy.
1500 * @param int $count The initial count value.
1501 *
1502 * @return int The updated count value.
1503 */
1504 public static function count_tax_data( $tax, $count ) {
1505 $page = get_queried_object();
1506
1507 if ( is_array( $tax ) && strpos( $tax['taxonomy'], 'attribute_' ) !== false ) {
1508 $taxonomy = str_replace( 'attribute_', '', $tax['taxonomy'] );
1509 $term_id = $tax['term_id'];
1510 } else {
1511 $taxonomy = $tax->taxonomy;
1512 $term_id = $tax->term_id;
1513 }
1514
1515 if ( strpos( $page->taxonomy, 'pa_' ) !== false ) {
1516 $args['status'] = 'publish';
1517 $args['limit'] = -1;
1518 $args['return'] = 'ids';
1519 $args['tax_query'] = [ // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_tax_query
1520 'relation' => 'AND',
1521 [
1522 'taxonomy' => $page->taxonomy,
1523 'field' => 'term_id',
1524 'terms' => $page->term_id,
1525 'operator' => 'IN',
1526 ],
1527 [
1528 'taxonomy' => $tax->taxonomy,
1529 'field' => 'term_id',
1530 'terms' => $tax->term_id,
1531 'operator' => 'IN',
1532 ],
1533 ];
1534
1535 $query = new WC_Product_Query( $args );
1536 $products = $query->get_products();
1537
1538 return count( $products );
1539 }
1540
1541 if ( $taxonomy !== $page->taxonomy ) {
1542 $args = [
1543 'limit' => -1,
1544 'return' => 'ids',
1545 'status' => 'publish',
1546 'tax_query' => [ // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_tax_query
1547 [
1548 'taxonomy' => $taxonomy,
1549 'field' => 'term_id',
1550 'terms' => $term_id,
1551 ],
1552 ],
1553 ];
1554
1555 if ( 'product_cat' === $page->taxonomy ) {
1556 $args['category'] = [ $page->slug ];
1557 }
1558
1559 if ( 'product_tag' === $page->taxonomy ) {
1560 $args['tag'] = [ $page->slug ];
1561 }
1562
1563 $query = new WC_Product_Query( $args );
1564 $products = $query->get_products();
1565
1566 $count = count( $products );
1567 }
1568
1569 return $count;
1570 }
1571 /**
1572 * Get filter HTML.
1573 *
1574 * @param string $filter_type Filter type.
1575 * @param array $options Options.
1576 * @param array $additional_data Data for additional filtering.
1577 * @param string $input Input type.
1578 *
1579 * @return string The generated HTML for the attribute filter list.
1580 */
1581 public static function get_default_filter_html( $filter_type, $options, $additional_data = [], $input = 'checkbox' ) {
1582 $html = '<ul class="product-filters input-type-' . esc_attr( $input ) . '" ';
1583 $active_option = isset( $_GET[ $filter_type ] ) ? explode( ',', wc_clean( wp_unslash( $_GET[ $filter_type ] ) ) ) : []; // phpcs:ignore WordPress.Security.NonceVerification.Recommended, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
1584 $option_link = self::get_base_url() . '/' . $filter_type . '/';
1585
1586 foreach ( $options as $option => $option_name ) {
1587 $unique_id = substr( uniqid(), -6 );
1588 $active_tax = in_array( $option, $active_option, true ) ? ' checked' : '';
1589 $active_group = in_array( $option, $active_option, true ) ? ' active' : '';
1590
1591 $html .= '
1592 <li class="rtsb-term-item">
1593 <div class="rtsb-default-filter-group' . esc_attr( $active_group ) . '">
1594 <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 . '>
1595 <label class="rtsb-default-' . esc_attr( $input ) . '-filter-label" for="rtsb-term-default-filter-' . $unique_id . '">
1596 <span class="name">' . esc_html( $option_name ) . '</span>
1597 </label>
1598 </div>
1599 </li>';
1600 }
1601
1602 $html .= '</ul>';
1603
1604 return $html;
1605 }
1606 /**
1607 * Get the count of products with a specific star rating.
1608 *
1609 * @param int $star_rating The star rating value.
1610 *
1611 * @return int
1612 */
1613 public static function get_product_rating_count( $star_rating ) {
1614 $args = [
1615 'status' => 'publish',
1616 'limit' => -1,
1617 'product_rating' => sprintf( '%.1f', $star_rating ),
1618 ];
1619
1620 if ( is_product_taxonomy() ) {
1621 $term = get_queried_object();
1622 $term_type = 'product_cat' === $term->taxonomy ? 'product_category_id' : 'product_tag_id';
1623
1624 if ( $term instanceof WP_Term ) {
1625 $args[ $term_type ] = [ $term->term_id ];
1626 }
1627 }
1628
1629 $query = new WC_Product_Query( $args );
1630 $products = $query->get_products();
1631
1632 return count( $products );
1633 }
1634 /**
1635 * Get attribute filter HTML.
1636 *
1637 * @param array $data Array of required data.
1638 * @param string $input Type of input field for the filter (e.g., color).
1639 *
1640 * @return string The generated HTML for the attribute filter list.
1641 */
1642 public static function get_attribute_filter_list_html( $data, $input = 'color' ) {
1643 if ( ! function_exists( 'rtwpvs' ) ) {
1644 return '';
1645 }
1646
1647 $terms = $data['terms'];
1648 $term_info = $data['term_info'];
1649 $show_tooltips = $data['show_tooltips'];
1650 $show_empty_terms = $data['show_empty_terms'];
1651 $counter = 0;
1652
1653 $html = '<ul class="product-default-filters rtsb-terms-wrapper ' . esc_attr( $term_info['type'] ) . '-variable-wrapper' . esc_attr( $data['show_label'] ) . '">';
1654
1655 foreach ( $terms as $attr_term ) {
1656 $count = $attr_term->count;
1657 $term_link = remove_query_arg( $term_info['filter_name'], $term_info['base_link'] );
1658 $term_link = add_query_arg( $term_info['filter_name'], $attr_term->slug, $term_link );
1659 $unique_id = substr( uniqid(), -6 );
1660 $name = 'term-' . wc_variation_attribute_name( $term_info['attribute'] ) . '-' . $unique_id;
1661 $selected_class = in_array( $attr_term->slug, $term_info['current_filter'], true ) ? ' selected' : '';
1662 $selected_item = in_array( $attr_term->slug, $term_info['current_filter'], true ) ? ' checked' : '';
1663 $active_class = in_array( $attr_term->slug, $term_info['current_filter'], true ) ? ' active' : '';
1664
1665 $args = [
1666 'id' => $name,
1667 'name' => $attr_term->name,
1668 'link' => $term_link,
1669 'type' => $term_info['type'],
1670 'term_id' => $attr_term->term_id,
1671 'term_slug' => $attr_term->slug,
1672 'taxonomy' => wc_variation_attribute_name( $term_info['attribute'] ),
1673 'tooltips' => $show_tooltips,
1674 'attribute_name' => $term_info['attribute'],
1675 'selected_item' => $selected_item,
1676 ];
1677
1678 if ( 'archive' === apply_filters( 'rtsb/builder/set/current/page/type', '' ) && ! empty( $data['count_display'] ) && 'block' === $data['count_display'] ) {
1679 $count = self::count_tax_data( $args, $attr_term->count );
1680 }
1681
1682 $args['count'] = $count;
1683
1684 if ( ! $show_empty_terms && 0 === $count ) {
1685 continue;
1686 }
1687
1688 $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 ) . '">';
1689 $html .= '<div class="rtsb-default-filter-group' . esc_attr( $active_class ) . '">';
1690 $html .= self::get_input_type_html( $input, $args );
1691
1692 $counter++;
1693
1694 $html .= '</div>';
1695 $html .= '</li>';
1696 }
1697
1698 $html .= '</ul>';
1699
1700 return $html;
1701 }
1702 /**
1703 * Get input type HTML.
1704 *
1705 * @param string $input Input type.
1706 * @param array $args Args.
1707 * @return mixed|string|null
1708 */
1709 public static function get_input_type_html( $input, $args ) {
1710 $html = '';
1711 $count = $args['count'];
1712
1713 switch ( $input ) {
1714 case 'color':
1715 $color = sanitize_hex_color( get_term_meta( $args['term_id'], 'product_attribute_color', true ) );
1716
1717 $html .= sprintf(
1718 // phpcs:ignore Generic.Strings.UnnecessaryStringConcat.Found
1719 '<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>',
1720 esc_attr( $args['id'] ),
1721 esc_attr( $args['type'] ),
1722 $args['tooltips'] ? esc_attr( ' tipsy' ) : '',
1723 esc_attr( $color ),
1724 esc_html( $args['name'] ),
1725 absint( $count )
1726 );
1727 break;
1728
1729 case 'image':
1730 if ( ! function_exists( 'rtwpvs' ) ) {
1731 return $html;
1732 }
1733
1734 $attachment_id = absint( get_term_meta( $args['term_id'], 'product_attribute_image', true ) );
1735 $image_size = rtwpvs()->get_option( 'attribute_image_size' );
1736 $image_url = wp_get_attachment_image_url( $attachment_id, apply_filters( 'rtwpvs_product_attribute_image_size', $image_size ) );
1737
1738 $html .= sprintf(
1739 // phpcs:ignore Generic.Strings.UnnecessaryStringConcat.Found
1740 '<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>',
1741 esc_attr( $args['id'] ),
1742 esc_attr( $args['type'] ),
1743 $args['tooltips'] ? esc_attr( ' tipsy' ) : '',
1744 esc_attr( $args['name'] ),
1745 esc_url( $image_url )
1746 );
1747 break;
1748
1749 case 'button':
1750 $html .= sprintf(
1751 // phpcs:ignore Generic.Strings.UnnecessaryStringConcat.Found
1752 '<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>',
1753 esc_attr( $args['id'] ),
1754 esc_attr( $args['type'] ),
1755 $args['tooltips'] ? esc_attr( ' tipsy' ) : '',
1756 esc_html( $args['name'] ),
1757 absint( $count )
1758 );
1759 break;
1760
1761 default:
1762 }
1763
1764 return apply_filters( 'rtsb/elementor/default/filter/get_input_type_html', $html );
1765 }
1766 /**
1767 * Get reset button.
1768 *
1769 * @param string $btn_text Button text.
1770 * @param array $settings Settings array.
1771 *
1772 * @return string
1773 */
1774 public static function get_default_filter_reset_button( $btn_text, $settings ) {
1775 $html = '';
1776
1777 ob_start();
1778
1779 $active = ! empty( $_SERVER['QUERY_STRING'] ) ? ' active' : '';
1780 $reset = ! empty( $settings['reset_btn'] );
1781 $apply_text = ! empty( $settings['apply_filters_btn_text'] ) ? $settings['apply_filters_btn_text'] : esc_html__( 'Apply Filters', 'shopbuilder' );
1782 $apply_icon = ! empty( $settings['apply_filters_btn_icon'] ) ? $settings['apply_filters_btn_icon'] : [];
1783 echo '<div class="default-filter-btn-wrapper">';
1784 ?>
1785 <?php if ( $settings['show_filter_btn'] ) { ?>
1786 <div class="rtsb-product-default-filters rtsb-apply-filters-btn">
1787 <div class="reset-btn-item">
1788 <button class="rtsb-apply-filters init">
1789 <span class="icon"><?php Fns::print_html( Fns::icons_manager( $apply_icon, 'icon-default' ) ); ?></span>
1790 <span class="text reset-text"><?php echo esc_html( $apply_text ); ?></span>
1791 <span></span>
1792 </button>
1793 </div>
1794 </div>
1795 <?php } ?>
1796 <?php
1797 if ( $reset ) {
1798 ?>
1799 <div class="rtsb-product-default-filters rtsb-reset<?php echo esc_attr( $active ); ?>">
1800 <div class="reset-btn-item">
1801 <button class="product-default-filter-reset">
1802 <span class="text reset-text"><?php echo esc_html( $btn_text ); ?></span>
1803 <span></span>
1804 </button>
1805 </div>
1806 </div>
1807 <?php
1808 }
1809 echo '</div>';
1810
1811 $html .= ob_get_clean();
1812
1813 return $html;
1814 }
1815 }
1816