PluginProbe
ShopBuilder – WooCommerce Builder For Elementor / 3.1.3
ShopBuilder – WooCommerce Builder For Elementor v3.1.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.1.3, at app/Elementor/Helper/RenderHelpers.php

1,795 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 if ( ! rtsb()->has_pro() && ! in_array( $layout, array_keys( Fns::free_layouts( $layout ) ), true ) ) {
592 $layout = self::set_default_layout( $layout );
593 }
594
595 return $layout;
596 } else {
597 return ! empty( $template ) ? self::set_default_layout( $layout ) : $default;
598 }
599 }
600
601 /**
602 * Row classes
603 *
604 * @param array $settings Settings array.
605 *
606 * @return mixed|null
607 */
608 public static function prepare_row_classes( $settings = [] ) {
609 $masonry_class = null;
610 $classes = 'rtsb-row rtsb-content-loader element-loading';
611
612 $loader_class = '';
613 if ( Fns::enable_loader() ) {
614 $loader_class = ' rtsb-pre-loader';
615 }
616 $raw_layout = esc_html( $settings['layout'] );
617 $layout = self::filter_layout( $raw_layout );
618 $grid_type = $settings['grid_type'];
619 $is_carousel = preg_match( '/slider/', $layout );
620
621 if ( preg_match( '/category/', $layout ) && ! empty( $settings['active_cat_slider'] ) ) {
622 $classes .= ' rtsb-slider-layout';
623 }
624
625 if ( 'equal' === $grid_type ) {
626 $masonry_class = ' rtsb-equal';
627 } elseif ( 'masonry' === $grid_type ) {
628 $masonry_class = ' rtsb-masonry';
629 } else {
630 $masonry_class = ' rtsb-even';
631 }
632
633 if ( ! rtsb()->has_pro() || $is_carousel ) {
634 $masonry_class = ' rtsb-even';
635 }
636
637 if ( $is_carousel && ! empty( $settings['raw_settings']['always_show_nav'] ) ) {
638 $classes .= ' always-show-nav';
639 }
640
641 if ( ! empty( $settings['raw_settings']['inner_slider_always_show_nav'] ) ) {
642 $classes .= ' inner-slider-always-show-nav';
643 }
644 if ( empty( $settings['raw_settings']['cols_mobile'] ) ) {
645 $classes .= ' rtsb-mobile-flex-row';
646 }
647
648 $classes .= ' rtsb-' . $layout . $masonry_class . $loader_class;
649
650 return apply_filters( 'rtsb/elementor/row/classes', $classes, $settings );
651 }
652
653 /**
654 * Prepare pagination attributes.
655 *
656 * @param string $layout The layout type.
657 * @param bool $has_filters Whether the widget has filters.
658 * @param string $template The template name.
659 * @param array $settings The widget settings.
660 * @param bool $ajax Whether to enable AJAX pagination.
661 *
662 * @return string
663 */
664 public static function prepare_pagination_attr( $layout, $has_filters, $template, $settings, $ajax ) {
665 $is_cat = preg_match( '/category/', $layout );
666 $is_carousel = preg_match( '/slider/', $layout );
667
668 if ( $is_carousel ) {
669 return $has_filters ? self::pagination_data( $settings, $template ) : '';
670 } elseif ( $is_cat ) {
671 return '';
672 } else {
673 $ajax_pagination = ! empty( $settings['show_pagination'] ) && 'pagination' !== $settings['pagination_type'];
674 $page = Fns::product_filters_has_ajax( apply_filters( 'rtsb/builder/set/current/page/type', '' ) );
675 $condition = rtsb()->has_pro() && $ajax && ( $ajax_pagination || $has_filters || $page );
676
677 return $condition ? self::pagination_data( $settings, $template ) : '';
678 }
679 }
680
681 /**
682 * Archive JSON data.
683 *
684 * @param array $metas Data set.
685 * @param string $template Template name.
686 *
687 * @return string
688 */
689 public static function archive_data( $metas, $template ) {
690 $el_data = self::archive_meta_dataset( $metas, $template );
691
692 return ' data-rtsb-ajax=\'' . esc_js( wp_json_encode( $el_data ) ) . '\'';
693 }
694
695 /**
696 * Slider options.
697 *
698 * @param array $meta Meta values.
699 * @param array $settings Raw Settings.
700 *
701 * @return array
702 */
703 public static function slider_data( array $meta, $settings = [] ) {
704 $has_dots = $meta['slider_dot'] ? ' has-dot' : ' no-dot';
705 $has_dots .= $meta['slider_nav'] ? ' has-nav' : ' no-nav';
706 $has_dynamic_dots = $meta['slider_dynamic_dot'] ? true : false;
707 $d_col = 0 === $meta['d_cols'] ? self::default_columns( $meta['layout'] ) : $meta['d_cols'];
708 $t_col = 0 === $meta['t_cols'] ? 2 : $meta['t_cols'];
709 $m_col = 0 === $meta['m_cols'] ? 1 : $meta['m_cols'];
710
711 if ( Plugin::$instance->breakpoints->has_custom_breakpoints() ) {
712 // Widescreen.
713 $w_col = self::get_data( $settings, 'cols_widescreen' );
714 $w_col = 0 === $w_col ? self::default_columns( $meta['layout'] ) : $w_col;
715 $w_group = self::get_data( $settings, 'cols_group_widescreen', 1 );
716
717 // Laptop.
718 $l_col = self::get_data( $settings, 'cols_laptop' );
719 $l_col = 0 === $l_col ? self::default_columns( $meta['layout'] ) : $l_col;
720 $l_group = self::get_data( $settings, 'cols_group_laptop', 1 );
721
722 // Tablet Landscape.
723 $te_col = self::get_data( $settings, 'cols_tablet_extra' );
724 $te_col = 0 === $te_col ? 3 : $te_col;
725 $te_group = self::get_data( $settings, 'cols_group_tablet_extra', 1 );
726
727 // Mobile Landscape.
728 $me_col = self::get_data( $settings, 'cols_mobile_extra' );
729 $me_col = 0 === $me_col ? 2 : $me_col;
730 $me_group = self::get_data( $settings, 'cols_group_mobile_extra', 1 );
731
732 $el_breakpoints = Fns::get_elementor_breakpoints();
733
734 foreach ( $el_breakpoints as $key => $value ) {
735 if ( isset( $value['is_enabled'] ) && ! $value['is_enabled'] ) {
736 unset( $el_breakpoints[ $key ] );
737 }
738 }
739
740 $breakpoints = [
741 0 => [
742 'slidesPerView' => absint( $m_col ),
743 'slidesPerGroup' => absint( $meta['m_group'] ),
744 'grid' => [
745 'rows' => 1,
746 ],
747 'pagination' => [
748 'dynamicBullets' => $has_dynamic_dots,
749 ],
750 ],
751 ];
752
753 $desktop = [
754 'desktop' => [
755 'label' => 'Desktop',
756 'value' => 1920,
757 'is_enabled' => 1,
758 ],
759 ];
760
761 if ( ! empty( $el_breakpoints['laptop'] ) && $el_breakpoints['laptop']['is_enabled'] ) {
762 $widescreen_position = array_search( 'widescreen', array_keys( $el_breakpoints ), true );
763 $el_breakpoints = array_merge(
764 array_slice( $el_breakpoints, 0, $widescreen_position ),
765 $desktop,
766 array_slice( $el_breakpoints, $widescreen_position )
767 );
768 } else {
769 $desktop['desktop']['value'] = 1366;
770 $el_breakpoints['desktop'] = $desktop['desktop'];
771 }
772
773 foreach ( $el_breakpoints as $el_breakpoint => $value ) {
774 $breakpoint_value = ! empty( $value['value'] ) ? $value['value'] : $value['default_value'];
775 $dynamic_bullets = $has_dynamic_dots;
776 $slides_per_view = $d_col;
777 $slides_per_group = $meta['d_group'];
778
779 switch ( $el_breakpoint ) {
780 case 'widescreen':
781 $slides_per_view = $w_col;
782 $slides_per_group = $w_group;
783
784 break;
785
786 case 'laptop':
787 $slides_per_view = $l_col;
788 $slides_per_group = $l_group;
789
790 break;
791
792 case 'tablet_extra':
793 $slides_per_view = $l_col;
794 $slides_per_group = $l_group;
795
796 if ( empty( $el_breakpoints['laptop'] ) ) {
797 $slides_per_view = $d_col;
798 $slides_per_group = $meta['d_group'];
799 }
800
801 break;
802
803 case 'tablet':
804 $slides_per_view = $te_col;
805 $slides_per_group = $te_group;
806
807 if ( empty( $el_breakpoints['laptop'] ) && empty( $el_breakpoints['tablet_extra'] ) ) {
808 $slides_per_view = $d_col;
809 $slides_per_group = $meta['d_group'];
810 } elseif ( empty( $el_breakpoints['laptop'] ) && ! empty( $el_breakpoints['tablet_extra'] ) ) {
811 $slides_per_view = $te_col;
812 $slides_per_group = $te_group;
813 } elseif ( ! empty( $el_breakpoints['laptop'] ) && empty( $el_breakpoints['tablet_extra'] ) ) {
814 $slides_per_view = $l_col;
815 $slides_per_group = $l_group;
816 }
817
818 break;
819
820 case 'mobile_extra':
821 $slides_per_view = $t_col;
822 $slides_per_group = $meta['t_group'];
823 $dynamic_bullets = $has_dynamic_dots;
824
825 break;
826
827 case 'mobile':
828 $slides_per_view = $t_col;
829 $slides_per_group = $meta['t_group'];
830 $dynamic_bullets = $has_dynamic_dots;
831
832 if ( ! empty( $el_breakpoints['mobile_extra'] ) ) {
833 $slides_per_view = $me_col;
834 $slides_per_group = $me_group;
835 }
836
837 break;
838 }
839
840 if ( $value['is_enabled'] ) {
841 $br = 'widescreen' !== $el_breakpoint ? $breakpoint_value + 1 : $breakpoint_value;
842
843 $breakpoints[ absint( $br ) ] = [
844 'slidesPerView' => absint( $slides_per_view ),
845 'slidesPerGroup' => absint( $slides_per_group ),
846 'pagination' => [
847 'dynamicBullets' => $dynamic_bullets,
848 ],
849 ];
850 }
851 }
852 } else {
853 $breakpoints = [
854 0 => [
855 'slidesPerView' => absint( $m_col ),
856 'slidesPerGroup' => absint( $meta['m_group'] ),
857 'pagination' => [
858 'dynamicBullets' => $has_dynamic_dots,
859 ],
860 ],
861 768 => [
862 'slidesPerView' => absint( $t_col ),
863 'slidesPerGroup' => absint( $meta['t_group'] ),
864 'pagination' => [
865 'dynamicBullets' => $has_dynamic_dots,
866 ],
867 ],
868 1025 => [
869 'slidesPerView' => absint( $d_col ),
870 'slidesPerGroup' => absint( $meta['d_group'] ),
871 'pagination' => [
872 'dynamicBullets' => $has_dynamic_dots,
873 ],
874 ],
875 ];
876 }
877
878 $slider_options = [
879 'slidesPerView' => absint( $d_col ),
880 'slidesPerGroup' => absint( $meta['d_group'] ),
881 'speed' => absint( $meta['speed'] ),
882 'loop' => $meta['loop'],
883 'autoHeight' => $meta['auto_height'],
884 'preloadImages' => ! $meta['lazy_load'],
885 'lazy' => $meta['lazy_load'],
886 'breakpoints' => $breakpoints,
887 ];
888
889 if ( ! empty( $meta['raw_settings']['slider_slide_animation'] ) ) {
890 $slider_options['watchSlidesProgress'] = true;
891 }
892 if ( $meta['auto_play'] ) {
893 $slider_options['autoplay'] = [
894 'delay' => absint( $meta['auto_play_timeout'] ),
895 'pauseOnMouseEnter' => $meta['stop_on_hover'],
896 'disableOnInteraction' => false,
897 ];
898 }
899
900 $slider_options = apply_filters( 'rtsb/elementor/render/slider_dataset', $slider_options, $meta );
901 $carouselClass = 'rtsb-carousel-slider slider-loading rtsb-pos-s ' . $meta['nav_position'] . '-nav' . $has_dots;
902
903 return [
904 'data' => esc_js( wp_json_encode( $slider_options ) ),
905 'class' => $carouselClass,
906 ];
907 }
908
909 /**
910 * Preloader.
911 *
912 * @param string $layout Layout.
913 *
914 * @return string
915 */
916 public static function pre_loader( $layout ) {
917 $loader_class = '';
918
919 $is_carousel = preg_match( '/slider/', $layout );
920
921 if ( $is_carousel ) {
922 $loader_class = ' full-op';
923 }
924 if ( ! Fns::enable_loader() ) {
925 return '';
926 }
927 return '<div class="rtsb-elements-loading rtsb-ball-clip-rotate"><div></div></div>';
928 }
929
930 /**
931 * Badge class.
932 *
933 * @param string $preset Badge preset.
934 *
935 * @return string|null
936 */
937 public static function badge_class( $preset ) {
938 switch ( $preset ) {
939 case 'preset-default':
940 $class = 'default-badge';
941 break;
942 case 'preset2':
943 $class = 'fill angle-right';
944 break;
945 case 'preset3':
946 $class = 'outline';
947 break;
948
949 case 'preset4':
950 $class = 'outline angle-right';
951 break;
952
953 default:
954 $class = 'fill';
955 break;
956 }
957
958 return $class;
959 }
960
961 /**
962 * Registers required scripts.
963 *
964 * @param array $scripts Scripts to register.
965 *
966 * @return void
967 */
968 public static function register_scripts( $scripts ) {
969 $caro = false;
970 $masonry = false;
971 $script = [];
972
973 $script[] = 'jquery';
974
975 foreach ( $scripts as $sc => $value ) {
976 if ( ! empty( $sc ) ) {
977 if ( 'isCarousel' === $sc ) {
978 $caro = $value;
979 }
980
981 if ( 'isMasonry' === $sc ) {
982 $masonry = $value;
983 }
984 }
985 }
986
987 if ( count( $scripts ) ) {
988 /**
989 * Scripts.
990 */
991 if ( $caro ) {
992 $script[] = 'swiper';
993 }
994
995 if ( $masonry ) {
996 $script[] = 'masonry';
997 }
998
999 $script[] = 'imagesloaded';
1000 $script[] = Fns::optimized_handle( 'rtsb-public' );
1001
1002 foreach ( $script as $sc ) {
1003 wp_enqueue_script( $sc );
1004 }
1005 }
1006 }
1007
1008 /**
1009 * Check if a wrapper is needed based on the current theme.
1010 *
1011 * @return bool
1012 */
1013 public static function is_wrapper_needed() {
1014 $theme_list = apply_filters(
1015 'rtsb/products/inner/wrapper/basedon/themes',
1016 [
1017 'twentytwentyone',
1018 'twentytwentytwo',
1019 'twentytwentythree',
1020 'storefront',
1021 'hello-elementor',
1022 'astra',
1023 ],
1024 rtsb()->current_theme
1025 );
1026
1027 if ( in_array( rtsb()->current_theme, $theme_list, true ) ) {
1028 return true;
1029 }
1030
1031 return false;
1032 }
1033
1034 /**
1035 * Get the number of products per page based on WooCommerce settings.
1036 *
1037 * @return int
1038 */
1039 public static function get_products_per_page() {
1040 $products_row = absint( get_option( 'woocommerce_catalog_rows', 4 ) );
1041 $products_col = absint( get_option( 'woocommerce_catalog_columns', 4 ) );
1042 $products_per_page = apply_filters( 'rtsb/elementor/archive/products_per_page', $products_row * $products_col );
1043
1044 return ! empty( $products_per_page ) ? $products_per_page : 12;
1045 }
1046 /**
1047 * Render Filters View.
1048 *
1049 * @param array $templates Template name.
1050 * @param array $settings Control settings.
1051 *
1052 * @return string
1053 */
1054 public static function filters_view( $templates, $settings ) {
1055 global $wp;
1056 $filters = [];
1057 $html = null;
1058 $reset = ! empty( $settings['reset_btn'] );
1059 $reset_mode = 'show' === $settings['reset_btn_behavior'] ? ' show-reset' : ' ondemand-reset';
1060 $reset_text = ! empty( $settings['reset_btn_text'] ) ? $settings['reset_btn_text'] : esc_html__( 'Reset Filter', 'shopbuilder' );
1061 $scroll_mode = ! empty( $settings['enable_scroll'] ) ? ' has-scroll' : ' no-scroll';
1062 $scroll_height = ! empty( $settings['enable_scroll'] ) ? $settings['scroll_height']['size'] : 300;
1063 $has_mobile_toggle = ! empty( $settings['filter_mobile_toggle'] );
1064 $toggle_class = $has_mobile_toggle ? ' default-filter-has-toggle' : ' default-filter-no-toggle';
1065 $mobile_toggle_text = ! empty( $settings['filter_mobile_toggle_text'] ) ? $settings['filter_mobile_toggle_text'] : esc_html__( 'Click to Filter', 'shopbuilder' );
1066 $scroll_attr = '';
1067
1068 if ( ! empty( $settings['enable_scroll'] ) ) {
1069 $scroll_attr = ' style="--rtsb-filter-scroll-height: ' . absint( $scroll_height ) . 'px;"';
1070 }
1071
1072 foreach ( $settings['filter_types'] as $key => $item ) {
1073 if ( ! defined( 'RTWPVS_PLUGIN_FILE' ) && in_array( $item['input_type_all'], [ 'color', 'button', 'image' ], true ) ) {
1074 $item['input_type_all'] = 'checkbox';
1075 }
1076 $filters[] = [
1077 'filter_title' => $item['filter_title'],
1078 'filter_items' => $item['filter_items'],
1079 'filter_attr' => $item['filter_attr'],
1080 'input_type' => 'product_attr' === $item['filter_items'] ? $item['input_type_all'] : $item['input_type'],
1081 ];
1082
1083 if ( 'rating_filter' === $item['filter_items'] ) {
1084 $filters[ $key ]['template'] = $templates['rating'];
1085 } elseif ( 'price_filter' === $item['filter_items'] ) {
1086
1087 $filters[ $key ]['input_type'] = 'slider';
1088 $filters[ $key ]['template'] = $templates['price'];
1089 } else {
1090 $filters[ $key ]['template'] = 'product_attr' === $item['filter_items'] ? $templates[ $item['input_type_all'] ] : $templates[ $item['input_type'] ];
1091 }
1092 }
1093
1094 if ( '' === get_option( 'permalink_structure' ) ) {
1095 $form_action = remove_query_arg( [ 'page', 'paged', 'product-page' ], add_query_arg( $wp->query_string, '', home_url( $wp->request ) ) );
1096 } else {
1097 $form_action = preg_replace( '%\/page/[0-9]+%', '', home_url( trailingslashit( $wp->request ) ) );
1098 }
1099 $args = [
1100 'filters' => $filters,
1101 'scroll_mode' => $scroll_mode,
1102 'reset_mode' => $reset_mode,
1103 'reset' => $reset,
1104 'scroll_attr' => $scroll_attr,
1105 'toggle_class' => $toggle_class,
1106 'reset_text' => $reset_text,
1107 'settings' => $settings,
1108 'form_action' => $form_action,
1109 ];
1110
1111 $html .= '<div class="rtsb-default-archive-filters' . esc_attr( $toggle_class ) . '">';
1112
1113 if ( $has_mobile_toggle ) {
1114 $html .= '<div class="rtsb-filter-mobile-toggle">
1115 <button class="product-filter-toggle">
1116 <span class="icon"><i aria-hidden="true" class="toggle-icon rtsb-icon rtsb-icon-filter"></i></span>
1117 <span class="text reset-text">' . esc_html( $mobile_toggle_text ) . '</span>
1118 <span></span>
1119 </button>
1120 </div>';
1121 }
1122
1123 $html .= Fns::load_template( $templates['layout'], $args, true );
1124 $html .= '</div>';
1125 return $html;
1126 }
1127 /**
1128 * Get taxonomy type.
1129 *
1130 * @param string $tax_type Taxonomy type.
1131 * @param string $attr_type Attribute type.
1132 *
1133 * @return string
1134 */
1135 public static function get_product_filters_tax_type( $tax_type, $attr_type = '' ) {
1136 if ( 'product_attr' !== $tax_type ) {
1137 return $tax_type;
1138 }
1139
1140 if ( empty( $attr_type ) ) {
1141 return $tax_type;
1142 }
1143
1144 return $attr_type;
1145 }
1146 /**
1147 * Get attribute terms.
1148 *
1149 * @param string $tax Taxonomy type.
1150 * @return int[]|string|string[]|\WP_Error|\WP_Term[]
1151 */
1152 public static function get_product_filters_attribute_terms( $tax ) {
1153 $cache_key = 'get_default_filter_attribute_terms_' . $tax;
1154 if ( isset( self::$cache[ $cache_key ] ) ) {
1155 return self::$cache[ $cache_key ];
1156 }
1157
1158 $attributes = wc_get_attribute_taxonomies();
1159 $att_name = str_replace( 'pa_', '', $tax );
1160 $exist = array_search( $att_name, array_column( $attributes, 'attribute_name' ), true );
1161 if ( false === $exist ) {
1162 self::$cache[ $cache_key ] = [];
1163 return self::$cache[ $cache_key ];
1164 }
1165 $attribute = $tax;
1166
1167 if ( ! is_shop() && is_product_taxonomy() ) {
1168 $term = get_queried_object();
1169
1170 if ( ! $term instanceof WP_Term ) {
1171 return [];
1172 }
1173
1174 $args = [
1175 'status' => 'publish',
1176 'limit' => -1,
1177 'return' => 'ids',
1178 ];
1179
1180 if ( 'product_cat' === $term->taxonomy ) {
1181 $args['category'] = [ $term->slug ];
1182 }
1183
1184 if ( 'product_tag' === $term->taxonomy ) {
1185 $args['tag'] = [ $term->slug ];
1186 }
1187
1188 if ( strpos( $term->taxonomy, 'pa_' ) !== false ) {
1189 $args['tax_query'] = [ // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_tax_query
1190 [
1191 'taxonomy' => $term->taxonomy,
1192 'field' => 'term_id',
1193 'terms' => $term->term_id,
1194 'operator' => 'IN',
1195 ],
1196 ];
1197 }
1198
1199 $query = new WC_Product_Query( $args );
1200 $products = $query->get_products();
1201 $attr_terms = [];
1202
1203 foreach ( $products as $product_id ) {
1204 $product_attr = wp_get_post_terms( $product_id, $attribute );
1205
1206 foreach ( $product_attr as $attr ) {
1207 $attr_terms[] = $attr;
1208 }
1209 }
1210 self::$cache[ $cache_key ] = self::filter_products_array_unique( $attr_terms );
1211 return self::$cache[ $cache_key ];
1212 } else {
1213 self::$cache[ $cache_key ] = get_terms(
1214 [
1215 'taxonomy' => $attribute,
1216 'hide_empty' => false,
1217 ]
1218 );
1219 return self::$cache[ $cache_key ];
1220 }
1221 }
1222 /**
1223 * Remove duplicate values from an array.
1224 *
1225 * @param array $array The input array.
1226 * @param bool $keep_key_assoc Whether to keep the key associations after removing duplicates.
1227 * @return array The array with duplicates removed.
1228 */
1229 public static function filter_products_array_unique( $array, $keep_key_assoc = false ) {
1230 $duplicate_keys = [];
1231 $tmp = [];
1232
1233 foreach ( $array as $key => $val ) {
1234 // convert objects to arrays, in_array() does not support objects.
1235 if ( is_object( $val ) ) {
1236 $val = (array) $val;
1237 }
1238
1239 if ( ! in_array( $val, $tmp, true ) ) {
1240 $tmp[] = $val;
1241 } else {
1242 $duplicate_keys[] = $key;
1243 }
1244 }
1245
1246 foreach ( $duplicate_keys as $key ) {
1247 unset( $array[ $key ] );
1248 }
1249
1250 return $keep_key_assoc ? $array : array_values( $array );
1251 }
1252 /**
1253 * Retrieve product categories (including hierarchical support)
1254 *
1255 * @param string $taxonomy Taxonomy name.
1256 * @return int[]|string|string[]|\WP_Error|\WP_Term[]
1257 */
1258 public static function get_all_terms( $taxonomy ) {
1259 $args = [
1260 'taxonomy' => $taxonomy,
1261 'suppress_filter' => true,
1262 'hide_empty' => false,
1263 'pad_counts' => true,
1264 'hierarchical' => true,
1265 ];
1266
1267 $cache_key = 'rtsb_get_terms_filter_products' . $taxonomy;
1268 $taxonomy_terms = wp_cache_get( $cache_key, 'shopbuilder' );
1269
1270 if ( false === $taxonomy_terms ) {
1271 $queried_object = get_queried_object();
1272
1273 if ( 'archive' === apply_filters( 'rtsb/builder/set/current/page/type', '' ) && $queried_object instanceof WP_Term && $queried_object->taxonomy === $taxonomy ) {
1274 $term_id = $queried_object->term_id;
1275 $taxonomy = $queried_object->taxonomy;
1276 $archive_cache_key = 'rtsb_get_terms_filter_products_' . $taxonomy . $term_id;
1277 $taxonomy_terms = wp_cache_get( $archive_cache_key, 'shopbuilder' );
1278 if ( false === $taxonomy_terms ) {
1279 $taxonomy_terms = [ $queried_object ];
1280 $child_args = [
1281 'taxonomy' => $taxonomy,
1282 'child_of' => $term_id,
1283 'hide_empty' => false,
1284 ];
1285
1286 $child_terms = get_terms( $child_args );
1287
1288 if ( ! empty( $child_terms ) ) {
1289 $taxonomy_terms = array_merge( $taxonomy_terms, $child_terms );
1290 }
1291
1292 wp_cache_set( $archive_cache_key, $taxonomy_terms, 'shopbuilder' );
1293 Cache::set_data_cache_key( $archive_cache_key );
1294 }
1295 } else {
1296 $taxonomy_terms = get_terms( $args );
1297 }
1298
1299 wp_cache_set( $cache_key, $taxonomy_terms, 'shopbuilder' );
1300 Cache::set_data_cache_key( $cache_key );
1301 }
1302
1303 return $taxonomy_terms;
1304 }
1305 /**
1306 * Generates an error message block.
1307 *
1308 * @param array $title The title array of the error message block.
1309 * @param string $wrapper Additional CSS class for the wrapper div.
1310 *
1311 * @return string The HTML representation of the error message block.
1312 */
1313 public static function filter_error_message( $title, $wrapper ) {
1314 $html = '<div class="rtsb-product-default-filters ' . esc_attr( $wrapper ) . '">';
1315 $html .= self::get_default_filter_title( $title );
1316 $html .= '<div class="default-filter-content">';
1317 $html .= '<p class="no-filter">' . esc_html__( 'Nothing found.', 'shopbuilder' ) . '</p>';
1318 $html .= '</div>';
1319 $html .= '</div>';
1320
1321 return $html;
1322 }
1323 /**
1324 * Get filter title.
1325 *
1326 * @param array $title Filter title.
1327 * @return string
1328 */
1329 public static function get_default_filter_title( $title ) {
1330 $html = '';
1331
1332 if ( empty( $title['title'] ) ) {
1333 return $html;
1334 }
1335
1336 $html .= '<div class="default-filter-title-wrapper">';
1337
1338 $html .= '<h3 class="widget-title rtsb-d-flex rtsb-align-items-center"><span class="title">' . $title['title'] . '</span></h3>';
1339
1340 $html .= '</div>';
1341
1342 return apply_filters( 'rtsb/elementor/default/filter/title', $html, $title );
1343 }
1344 /**
1345 * Recursive function to generate the filter list with hierarchy.
1346 *
1347 * @param array $data Array of required data.
1348 * @param string $input Type of input field for the filter (e.g., checkbox).
1349 * @param array $additional_data Data for additional filtering.
1350 * @param int $parent ID of the parent term (default: 0).
1351 *
1352 * @return string The generated HTML for the product filter list.
1353 */
1354 public static function get_product_default_filter_list_html( $data, $input = 'checkbox', $additional_data = [], $parent = 0 ) {
1355
1356 $html = '';
1357 $default_tax = [];
1358 $is_attribute = ! empty( $data['is_attribute'] );
1359 $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
1360 $counter = 0;
1361
1362 if ( $is_attribute ) {
1363 list(
1364 'filter_name' => $filter_name,
1365 'base_link' => $base_link
1366 ) = self::get_product_filters_attribute_term_info( $additional_data['taxonomy'] );
1367 }
1368
1369 $html .= '<ul class="product-default-filters input-type-' . esc_attr( $input ) . '">';
1370
1371 foreach ( $data['taxonomy'] as $tax ) {
1372 if ( $tax->parent !== $parent ) {
1373 continue;
1374 }
1375
1376 if ( $is_attribute ) {
1377 $tax_link = remove_query_arg( $filter_name, $base_link );
1378 $tax_link = add_query_arg( $filter_name, $tax->slug, $tax_link );
1379 $active_option = isset( $_GET[ $filter_name ] ) ? explode( ',', sanitize_text_field( wp_unslash( $_GET[ $filter_name ] ) ) ) : []; // phpcs:ignore WordPress.Security.NonceVerification.Recommended
1380 } else {
1381 $tax_link = get_term_link( $tax );
1382 }
1383
1384 $unique_id = substr( uniqid(), -4 );
1385
1386 $active_tax = in_array( $tax->slug, $active_option, true ) ? ' checked' : '';
1387 $active_tax_parent = in_array( $tax->slug, $active_option, true ) ? ' active' : '';
1388 $term_children = in_array( $tax->taxonomy, [ 'product_cat', 'product_brand' ], true ) ? get_term_children( $tax->term_id, $tax->taxonomy ) : [];
1389 $taxonomy = $tax->taxonomy;
1390 $product_count = $tax->count;
1391
1392 // Show count.
1393 if ( 'archive' === apply_filters( 'rtsb/builder/set/current/page/type', '' ) && ! empty( $data['count_display'] ) && 'block' === $data['count_display'] ) {
1394 $product_count = self::count_tax_data( $tax, $tax->count );
1395 }
1396
1397 // Show Empty Categories.
1398 if ( empty( $data['show_empty_terms'] ) && 0 === $product_count ) {
1399 continue;
1400 }
1401
1402 $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' : '' ) . '">
1403 <div class="rtsb-default-filter-group' . esc_attr( $active_tax_parent ) . '">
1404 <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 ) . '>
1405 <label class="rtsb-default-' . esc_attr( $input ) . '-filter-label" for="rtsb-default-term-filter-' . $unique_id . absint( $tax->term_id ) . '">
1406 <span class="name">' . esc_html( $tax->name ) . '</span>
1407 </label>
1408 <div class="rtsb-product-count">(' . esc_html( $product_count ) . ')</div>
1409 ' . ( ! empty( $term_children ) && $data['show_child'] ? '<i class="rtsb-plus-icon"></i>' : '' ) . '
1410 </div>';
1411
1412 // Show Sub-categories.
1413 if ( $data['show_child'] ) {
1414 $children = self::get_product_default_filter_list_html( $data, $input, $additional_data, $tax->term_id );
1415
1416 if ( ! empty( $children ) ) {
1417 $html .= '<div class="filter-child">' . $children . '</div>';
1418 }
1419 }
1420
1421 $counter++;
1422
1423 $html .= '</li>';
1424 }
1425
1426 $html .= '</ul>';
1427
1428 // Check if the output contains any child elements.
1429 $has_children = strpos( $html, '<li class="rtsb-default-filter-term-item' ) !== false;
1430
1431 if ( ! $has_children ) {
1432 // Remove the outer <ul> if there are no child elements.
1433 $html = '';
1434 }
1435 return $html;
1436 }
1437 /**
1438 * Get attribute term info.
1439 *
1440 * @param string $tax Taxonomy type.
1441 * @return array
1442 */
1443 public static function get_product_filters_attribute_term_info( $tax ) {
1444 $result = [];
1445 $attributes = wc_get_attribute_taxonomies();
1446
1447 foreach ( $attributes as $attr ) {
1448 if ( str_replace( 'pa_', '', $tax ) === $attr->attribute_name ) {
1449 $term_type = $attr->attribute_type;
1450 $attribute_slug = $attr->attribute_name;
1451 $attribute = wc_attribute_taxonomy_name( $attr->attribute_name );
1452 break;
1453 }
1454 }
1455
1456 $filter_name = 'filter_' . wc_attribute_taxonomy_slug( $attribute_slug );
1457
1458 $result['attribute'] = $attribute ?? '';
1459 $result['term_type'] = $term_type ?? '';
1460 $result['attribute_slug'] = $attribute_slug ?? '';
1461 $result['filter_name'] = $filter_name;
1462 $result['base_link'] = self::get_base_url();
1463
1464 return $result;
1465 }
1466 /**
1467 * Get base URL.
1468 *
1469 * @return string|null
1470 */
1471 public static function get_base_url() {
1472 global $wp;
1473 return home_url( add_query_arg( [], $wp->request ) );
1474 }
1475 /**
1476 * Count the number of occurrences for a specific term in a taxonomy for the current queried object.
1477 *
1478 * @param object|array $tax The term object for the taxonomy.
1479 * @param int $count The initial count value.
1480 *
1481 * @return int The updated count value.
1482 */
1483 public static function count_tax_data( $tax, $count ) {
1484 $page = get_queried_object();
1485
1486 if ( is_array( $tax ) && strpos( $tax['taxonomy'], 'attribute_' ) !== false ) {
1487 $taxonomy = str_replace( 'attribute_', '', $tax['taxonomy'] );
1488 $term_id = $tax['term_id'];
1489 } else {
1490 $taxonomy = $tax->taxonomy;
1491 $term_id = $tax->term_id;
1492 }
1493
1494 if ( strpos( $page->taxonomy, 'pa_' ) !== false ) {
1495 $args['status'] = 'publish';
1496 $args['limit'] = -1;
1497 $args['return'] = 'ids';
1498 $args['tax_query'] = [ // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_tax_query
1499 'relation' => 'AND',
1500 [
1501 'taxonomy' => $page->taxonomy,
1502 'field' => 'term_id',
1503 'terms' => $page->term_id,
1504 'operator' => 'IN',
1505 ],
1506 [
1507 'taxonomy' => $tax->taxonomy,
1508 'field' => 'term_id',
1509 'terms' => $tax->term_id,
1510 'operator' => 'IN',
1511 ],
1512 ];
1513
1514 $query = new WC_Product_Query( $args );
1515 $products = $query->get_products();
1516
1517 return count( $products );
1518 }
1519
1520 if ( $taxonomy !== $page->taxonomy ) {
1521 $args = [
1522 'limit' => -1,
1523 'return' => 'ids',
1524 'status' => 'publish',
1525 'tax_query' => [ // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_tax_query
1526 [
1527 'taxonomy' => $taxonomy,
1528 'field' => 'term_id',
1529 'terms' => $term_id,
1530 ],
1531 ],
1532 ];
1533
1534 if ( 'product_cat' === $page->taxonomy ) {
1535 $args['category'] = [ $page->slug ];
1536 }
1537
1538 if ( 'product_tag' === $page->taxonomy ) {
1539 $args['tag'] = [ $page->slug ];
1540 }
1541
1542 $query = new WC_Product_Query( $args );
1543 $products = $query->get_products();
1544
1545 $count = count( $products );
1546 }
1547
1548 return $count;
1549 }
1550 /**
1551 * Get filter HTML.
1552 *
1553 * @param string $filter_type Filter type.
1554 * @param array $options Options.
1555 * @param array $additional_data Data for additional filtering.
1556 * @param string $input Input type.
1557 *
1558 * @return string The generated HTML for the attribute filter list.
1559 */
1560 public static function get_default_filter_html( $filter_type, $options, $additional_data = [], $input = 'checkbox' ) {
1561 $html = '<ul class="product-filters input-type-' . esc_attr( $input ) . '" ';
1562 $active_option = isset( $_GET[ $filter_type ] ) ? explode( ',', wc_clean( wp_unslash( $_GET[ $filter_type ] ) ) ) : []; // phpcs:ignore WordPress.Security.NonceVerification.Recommended, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
1563 $option_link = self::get_base_url() . '/' . $filter_type . '/';
1564
1565 foreach ( $options as $option => $option_name ) {
1566 $unique_id = substr( uniqid(), -6 );
1567 $active_tax = in_array( $option, $active_option, true ) ? ' checked' : '';
1568 $active_group = in_array( $option, $active_option, true ) ? ' active' : '';
1569
1570 $html .= '
1571 <li class="rtsb-term-item">
1572 <div class="rtsb-default-filter-group' . esc_attr( $active_group ) . '">
1573 <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 . '>
1574 <label class="rtsb-default-' . esc_attr( $input ) . '-filter-label" for="rtsb-term-default-filter-' . $unique_id . '">
1575 <span class="name">' . esc_html( $option_name ) . '</span>
1576 </label>
1577 </div>
1578 </li>';
1579 }
1580
1581 $html .= '</ul>';
1582
1583 return $html;
1584 }
1585 /**
1586 * Get the count of products with a specific star rating.
1587 *
1588 * @param int $star_rating The star rating value.
1589 *
1590 * @return int
1591 */
1592 public static function get_product_rating_count( $star_rating ) {
1593 $args = [
1594 'status' => 'publish',
1595 'limit' => -1,
1596 'product_rating' => sprintf( '%.1f', $star_rating ),
1597 ];
1598
1599 if ( is_product_taxonomy() ) {
1600 $term = get_queried_object();
1601 $term_type = 'product_cat' === $term->taxonomy ? 'product_category_id' : 'product_tag_id';
1602
1603 if ( $term instanceof WP_Term ) {
1604 $args[ $term_type ] = [ $term->term_id ];
1605 }
1606 }
1607
1608 $query = new WC_Product_Query( $args );
1609 $products = $query->get_products();
1610
1611 return count( $products );
1612 }
1613 /**
1614 * Get attribute filter HTML.
1615 *
1616 * @param array $data Array of required data.
1617 * @param string $input Type of input field for the filter (e.g., color).
1618 *
1619 * @return string The generated HTML for the attribute filter list.
1620 */
1621 public static function get_attribute_filter_list_html( $data, $input = 'color' ) {
1622 if ( ! function_exists( 'rtwpvs' ) ) {
1623 return '';
1624 }
1625
1626 $terms = $data['terms'];
1627 $term_info = $data['term_info'];
1628 $show_tooltips = $data['show_tooltips'];
1629 $show_empty_terms = $data['show_empty_terms'];
1630 $counter = 0;
1631
1632 $html = '<ul class="product-default-filters rtsb-terms-wrapper ' . esc_attr( $term_info['type'] ) . '-variable-wrapper' . esc_attr( $data['show_label'] ) . '">';
1633
1634 foreach ( $terms as $attr_term ) {
1635 $count = $attr_term->count;
1636 $term_link = remove_query_arg( $term_info['filter_name'], $term_info['base_link'] );
1637 $term_link = add_query_arg( $term_info['filter_name'], $attr_term->slug, $term_link );
1638 $unique_id = substr( uniqid(), -6 );
1639 $name = 'term-' . wc_variation_attribute_name( $term_info['attribute'] ) . '-' . $unique_id;
1640 $selected_class = in_array( $attr_term->slug, $term_info['current_filter'], true ) ? ' selected' : '';
1641 $selected_item = in_array( $attr_term->slug, $term_info['current_filter'], true ) ? ' checked' : '';
1642 $active_class = in_array( $attr_term->slug, $term_info['current_filter'], true ) ? ' active' : '';
1643
1644 $args = [
1645 'id' => $name,
1646 'name' => $attr_term->name,
1647 'link' => $term_link,
1648 'type' => $term_info['type'],
1649 'term_id' => $attr_term->term_id,
1650 'term_slug' => $attr_term->slug,
1651 'taxonomy' => wc_variation_attribute_name( $term_info['attribute'] ),
1652 'tooltips' => $show_tooltips,
1653 'attribute_name' => $term_info['attribute'],
1654 'selected_item' => $selected_item,
1655 ];
1656
1657 if ( 'archive' === apply_filters( 'rtsb/builder/set/current/page/type', '' ) && ! empty( $data['count_display'] ) && 'block' === $data['count_display'] ) {
1658 $count = self::count_tax_data( $args, $attr_term->count );
1659 }
1660
1661 $args['count'] = $count;
1662
1663 if ( ! $show_empty_terms && 0 === $count ) {
1664 continue;
1665 }
1666
1667 $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 ) . '">';
1668 $html .= '<div class="rtsb-default-filter-group' . esc_attr( $active_class ) . '">';
1669 $html .= self::get_input_type_html( $input, $args );
1670
1671 $counter++;
1672
1673 $html .= '</div>';
1674 $html .= '</li>';
1675 }
1676
1677 $html .= '</ul>';
1678
1679 return $html;
1680 }
1681 /**
1682 * Get input type HTML.
1683 *
1684 * @param string $input Input type.
1685 * @param array $args Args.
1686 * @return mixed|string|null
1687 */
1688 public static function get_input_type_html( $input, $args ) {
1689 $html = '';
1690 $count = $args['count'];
1691
1692 switch ( $input ) {
1693 case 'color':
1694 $color = sanitize_hex_color( get_term_meta( $args['term_id'], 'product_attribute_color', true ) );
1695
1696 $html .= sprintf(
1697 // phpcs:ignore Generic.Strings.UnnecessaryStringConcat.Found
1698 '<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>',
1699 esc_attr( $args['id'] ),
1700 esc_attr( $args['type'] ),
1701 $args['tooltips'] ? esc_attr( ' tipsy' ) : '',
1702 esc_attr( $color ),
1703 esc_html( $args['name'] ),
1704 absint( $count )
1705 );
1706 break;
1707
1708 case 'image':
1709 if ( ! function_exists( 'rtwpvs' ) ) {
1710 return $html;
1711 }
1712
1713 $attachment_id = absint( get_term_meta( $args['term_id'], 'product_attribute_image', true ) );
1714 $image_size = rtwpvs()->get_option( 'attribute_image_size' );
1715 $image_url = wp_get_attachment_image_url( $attachment_id, apply_filters( 'rtwpvs_product_attribute_image_size', $image_size ) );
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-image-filter rtsb-term-span rtsb-term-span-%s%s"><img class="rtsb-default-attr-filter" alt="%s" src="%s" /></label>',
1720 esc_attr( $args['id'] ),
1721 esc_attr( $args['type'] ),
1722 $args['tooltips'] ? esc_attr( ' tipsy' ) : '',
1723 esc_attr( $args['name'] ),
1724 esc_url( $image_url )
1725 );
1726 break;
1727
1728 case 'button':
1729 $html .= sprintf(
1730 // phpcs:ignore Generic.Strings.UnnecessaryStringConcat.Found
1731 '<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>',
1732 esc_attr( $args['id'] ),
1733 esc_attr( $args['type'] ),
1734 $args['tooltips'] ? esc_attr( ' tipsy' ) : '',
1735 esc_html( $args['name'] ),
1736 absint( $count )
1737 );
1738 break;
1739
1740 default:
1741 }
1742
1743 return apply_filters( 'rtsb/elementor/default/filter/get_input_type_html', $html );
1744 }
1745 /**
1746 * Get reset button.
1747 *
1748 * @param string $btn_text Button text.
1749 * @param array $settings Settings array.
1750 *
1751 * @return string
1752 */
1753 public static function get_default_filter_reset_button( $btn_text, $settings ) {
1754 $html = '';
1755
1756 ob_start();
1757
1758 $active = ! empty( $_SERVER['QUERY_STRING'] ) ? ' active' : '';
1759 $reset = ! empty( $settings['reset_btn'] );
1760 $apply_text = ! empty( $settings['apply_filters_btn_text'] ) ? $settings['apply_filters_btn_text'] : esc_html__( 'Apply Filters', 'shopbuilder' );
1761 $apply_icon = ! empty( $settings['apply_filters_btn_icon'] ) ? $settings['apply_filters_btn_icon'] : [];
1762 echo '<div class="default-filter-btn-wrapper">';
1763 ?>
1764 <?php if ( $settings['show_filter_btn'] ) { ?>
1765 <div class="rtsb-product-default-filters rtsb-apply-filters-btn">
1766 <div class="reset-btn-item">
1767 <button class="rtsb-apply-filters init">
1768 <span class="icon"><?php Fns::print_html( Fns::icons_manager( $apply_icon, 'icon-default' ) ); ?></span>
1769 <span class="text reset-text"><?php echo esc_html( $apply_text ); ?></span>
1770 <span></span>
1771 </button>
1772 </div>
1773 </div>
1774 <?php } ?>
1775 <?php
1776 if ( $reset ) {
1777 ?>
1778 <div class="rtsb-product-default-filters rtsb-reset<?php echo esc_attr( $active ); ?>">
1779 <div class="reset-btn-item">
1780 <button class="product-default-filter-reset">
1781 <span class="text reset-text"><?php echo esc_html( $btn_text ); ?></span>
1782 <span></span>
1783 </button>
1784 </div>
1785 </div>
1786 <?php
1787 }
1788 echo '</div>';
1789
1790 $html .= ob_get_clean();
1791
1792 return $html;
1793 }
1794 }
1795