PluginProbe
ShopBuilder – WooCommerce Builder For Elementor / 2.6.4
ShopBuilder – WooCommerce Builder For Elementor v2.6.4
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 2.6.4, at app/Elementor/Helper/RenderHelpers.php

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