PluginProbe
ShopBuilder – WooCommerce Builder For Elementor / 2.0.2
ShopBuilder – WooCommerce Builder For Elementor v2.0.2
3.4.2 3.4.1 3.4.0 2.0.1 2.0.2 2.0.3 2.1.0 2.1.1 2.1.10 2.1.11 2.1.12 2.1.13 2.1.14 2.1.15 2.1.2 2.1.3 2.1.4 2.1.5 2.1.6 2.1.7 2.1.8 2.1.9 2.2.0 2.2.1 2.2.2 All 63 releases
shopbuilder / app / Elementor / Render / Render.php

Render.php in ShopBuilder – WooCommerce Builder For Elementor 2.0.2, at app/Elementor/Render/Render.php

1,014 lines 31.1 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Elementor Render Class.
4 *
5 * This class contains render logics & output.
6 *
7 * @package RadiusTheme\SB
8 */
9
10 namespace RadiusTheme\SB\Elementor\Render;
11
12 use WP_Query;
13 use RadiusTheme\SB\Helpers\Fns;
14 use RadiusTheme\SB\Models\QueryArgs;
15 use RadiusTheme\SB\Helpers\BuilderFns;
16 use RadiusTheme\SB\Traits\SingletonTrait;
17 use RadiusTheme\SB\Traits\ActionBtnTraits;
18 use RadiusTheme\SB\Elementor\Helper\RenderHelpers;
19
20 // Do not allow directly accessing this file.
21 if ( ! defined( 'ABSPATH' ) ) {
22 exit( 'This script cannot be accessed directly.' );
23 }
24
25 /**
26 * Elementor Render Class.
27 */
28 class Render {
29 /**
30 * Singleton Trait.
31 */
32 use SingletonTrait;
33
34 /**
35 * Action button trait.
36 */
37 use ActionBtnTraits;
38
39 /**
40 * HTML.
41 *
42 * @var string
43 */
44 private $html = null;
45
46 /**
47 * Settings array
48 *
49 * @var array
50 */
51 public $get_settings;
52
53 /**
54 * Get elementor settings.
55 *
56 * @return array
57 */
58 public function get_settings_for_display() {
59 return $this->get_settings;
60 }
61
62 /**
63 * Container Wrapper HTML.
64 *
65 * @param string $content The content.
66 * @param array $settings Settings.
67 * @param string $class Class.
68 * @param string $template Template name.
69 * @param bool $fullwidth Fullwidth check.
70 *
71 * @return string
72 */
73 public function container( $content, $settings, $class = '', $template = '', $fullwidth = false ) {
74 $layout_id = 'rtsb-container-' . absint( wp_rand() );
75 $container_attr = null;
76 $cart_txt_class = '';
77 $container_class = 'rtsb-elementor-container products rtsb-pos-r ' . esc_attr( $class );
78 $metas = RenderHelpers::meta_dataset( $settings, $template );
79
80 $layout = $metas['layout'];
81 $animation = $metas['hover_animation'];
82
83 $is_cat = preg_match( '/category/', $layout );
84 $is_carousel = preg_match( '/slider/', $layout );
85
86 if ( ! $is_cat ) {
87 $cart_txt_class = $metas['show_cart_text'] ? ' has-cart-text' : ' no-cart-text';
88 }
89
90 if ( $is_carousel ) {
91 $fullwidth = true;
92 }
93
94 $badge_class = [
95 'position' => $metas['badge_position'],
96 'alignment' => $metas['badge_alignment'],
97 ];
98
99 if ( ! in_array( $layout, array_keys( Fns::free_layouts() ), true ) ) {
100 $layout = RenderHelpers::set_default_layout( $layout );
101 }
102
103 if ( $is_carousel ) {
104 $pagination_attr = ! empty( $metas['show_filter'] ) ? RenderHelpers::pagination_data( $settings, $template ) : '';
105 } elseif ( $is_cat ) {
106 $pagination_attr = '';
107 } else {
108 $pagination_attr = RenderHelpers::pagination_data( $settings, $template );
109 }
110
111 if ( ! in_array( 'clear-btn', $metas['visibility'], true ) ) {
112 $container_class .= ' no-clear-btn';
113 }
114
115 $container_class .= ! empty( $metas['pagination'] ) ? ' rtsb-has-pagination' : ' rtsb-no-pagination';
116 $style_attr = ' style="--rtsb-default-columns: ' . esc_attr( RenderHelpers::default_columns( $layout ) ) . '"';
117 $tooltip_attr = ' data-tooltip-position="' . esc_attr( $metas['tooltip_position'] ) . '"';
118
119 $view_mode = $settings['view_mode'] ?? 'grid';
120
121 if ( isset( $_GET['displayview'] ) ) {
122 $view_mode = sanitize_text_field( wp_unslash( $_GET['displayview'] ) );
123 }
124
125 if ( 'list' == $view_mode && ! empty( $metas['tooltip_position_list'] ) ) {
126 $tooltip_attr = ' data-tooltip-position="' . esc_attr( $metas['tooltip_position_list'] ) . '"';
127 }
128
129 $container_attr .= ' data-layout="' . esc_attr( $layout ) . '"' . $style_attr . $tooltip_attr . $pagination_attr;
130 $container_class .= ' 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'] );
131
132 if ( $metas['show_overlay'] ) {
133 $container_class .= ' has-overlay';
134 }
135
136 if ( in_array( 'single-cat', $metas['visibility'], true ) ) {
137 $container_class .= ' show-single-cat';
138 }
139
140 $container_class = apply_filters( 'rtsb/product/container/class', $container_class, $settings );
141 $this->html = '<div class="' . esc_attr( $container_class ) . '" id="' . esc_attr( $layout_id ) . '" ' . $container_attr . '>';
142
143 if ( ! empty( $settings['query_products'] ) && count( $settings['query_products'] ) && 'yes' === $settings['show_section_title'] ) {
144 $this->html .= '<div class="rtsb-section-title-wrapper">';
145 $this->html .= '<' . esc_attr( $settings['section_title_tag'] ) . ' class="rtsb-section-title" >';
146 $this->html .= esc_html( $settings['section_title_text'] );
147 $this->html .= '</' . esc_attr( $settings['section_title_tag'] ) . '>';
148 $this->html .= '</div>';
149 }
150
151 $this->html .= $content;
152
153 $this->html .= '</div><!-- .rtsb-elementor-container -->';
154
155 // Action button icon reset.
156 $this->action_button_icon_set_default();
157
158 $script_generator = [];
159 $script_generator['layout'] = $layout_id;
160 $script_generator['rand'] = absint( wp_rand() );
161 $script_generator['isCarousel'] = $is_carousel;
162
163 add_action(
164 'wp_footer',
165 static function () use ( $script_generator ) {
166 RenderHelpers::register_scripts( $script_generator );
167 }
168 );
169
170 return $this->html;
171 }
172
173 /**
174 * Row Wrapper HTML.
175 *
176 * @param string $content The content.
177 * @param array $settings Settings.
178 * @param string $hook_html Hook HTML.
179 * @param array $raw_settings Raw Settings.
180 *
181 * @return string
182 */
183 public function row( $content, $settings, $hook_html = '', $raw_settings = [] ) {
184 $masonry_class = null;
185 $loader_class = ' rtsb-pre-loader';
186
187 $layout = $settings['layout'];
188 $grid_type = $settings['grid_type'];
189 $is_carousel = preg_match( '/slider/', $layout );
190
191 if ( 'even' === $grid_type ) {
192 $masonry_class = ' rtsb-even';
193 } elseif ( 'masonry' === $grid_type ) {
194 $masonry_class = ' rtsb-masonry';
195 }
196
197 if ( ! rtsb()->has_pro() || $is_carousel ) {
198 $masonry_class = ' rtsb-even';
199 }
200
201 $row_start_class = apply_filters( 'rtsb/custom/layout/row/classes', esc_attr( 'rtsb-row rtsb-content-loader element-loading rtsb-' . $layout . $masonry_class . $loader_class ), $settings );
202 $row_wrapper = '<div data-title="' . esc_html__( 'Loading ...', 'shopbuilder' ) . '" class="' . $row_start_class . '">';
203 $start_wrapper = apply_filters( 'rtsb/custom/layout/row/start', $row_wrapper, $row_start_class );
204 if ( ! empty( $settings['show_filter'] ) ) {
205 $this->html = $hook_html;
206 $this->html .= $start_wrapper;
207 } else {
208 $this->html = $start_wrapper;
209 }
210
211 if ( $is_carousel ) {
212 $slider_data = RenderHelpers::slider_data( $settings, $raw_settings );
213
214 $this->html .= '<div class="rtsb-col-grid ' . esc_attr( $slider_data['class'] ) . '" ' . $slider_data['data'] . '>';
215 $this->html .= '<div class="swiper-wrapper">';
216 }
217
218 $this->html .= $content;
219
220 if ( $is_carousel ) {
221 $this->html .= '</div><!-- .swiper-wrapper -->';
222
223 $left_icon = $settings['left_arrow_icon'];
224 $right_icon = $settings['right_arrow_icon'];
225
226 if ( ! empty( $settings['slider_nav'] ) ) {
227 $this->html .=
228 '<div class="swiper-nav">
229 <div class="swiper-arrow swiper-button-next">
230 ' . Fns::icons_manager( $right_icon ) . '
231 </div>
232 <div class="swiper-arrow swiper-button-prev">
233 ' . Fns::icons_manager( $left_icon ) . '
234 </div>
235 </div>';
236 }
237
238 $this->html .= ! empty( $settings['slider_dot'] ) ? '<div class="swiper-pagination rtsb-pos-s"></div>' : '';
239
240 $this->html .= '</div><!-- .rtsb-carousel-slider -->';
241 }
242
243 $row_end = '</div><!-- .rtsb-row -->';
244
245 $this->html .= apply_filters( 'rtsb/custom/layout/row/end', $row_end );
246
247 $this->html .= RenderHelpers::pre_loader( $layout );
248
249 return $this->html;
250 }
251
252 /**
253 * Product loop.
254 *
255 * @param object $query The query.
256 * @param array $settings Settings.
257 * @param string $template Template.
258 *
259 * @return string|null
260 */
261 public function product_loop( $query, $settings, $template ) {
262 $html = null;
263
264 if ( empty( $query ) ) {
265 return null;
266 }
267
268 $i = 0;
269
270 while ( $query->have_posts() ) {
271 $query->the_post();
272 $i++;
273
274 // Loop arg.
275 $arg = $this->arg_dataset( $settings, get_the_ID(), $settings['lazy_load'], $i );
276
277 // Get template.
278 $html .= Fns::load_template( $template . $settings['layout'], $arg, true );
279 }
280
281 return $html;
282 }
283
284 /**
285 * Product loop.
286 *
287 * @param object $query The query.
288 * @param array $settings Settings.
289 * @param string $template Template.
290 * @param bool $is_single Single category.
291 *
292 * @return string|null
293 */
294 public function category_loop( $query, $settings, $template, $is_single = false ) {
295 $html = null;
296
297 if ( $is_single ) {
298 // Loop arg.
299 $arg = $this->cat_arg_dataset( $settings, $query, true );
300
301 // Get template.
302 $html .= Fns::load_template( $template . $settings['layout'], $arg, true );
303 } else {
304 foreach ( $query as $term ) {
305 // Loop arg.
306 $arg = $this->cat_arg_dataset( $settings, $term );
307
308 // Get template.
309 $html .= Fns::load_template( $template . $settings['layout'], $arg, true );
310 }
311 }
312
313 return $html;
314 }
315
316 /**
317 * Render Product View.
318 *
319 * @param string $template Template name.
320 * @param array $settings Control settings.
321 *
322 * @return string
323 */
324 public function product_view( $template, $settings ) {
325 $this->get_settings = $settings;
326
327 $metas = RenderHelpers::meta_dataset( $settings, $template, $this->get_settings_for_display() );
328 $is_carousel = preg_match( '/slider/', $metas['layout'] );
329 $pagination = $metas['pagination'];
330 $hook_html = '';
331
332 // Query Args.
333 $args = ( new QueryArgs() )->buildArgs( $metas, 'product', $is_carousel );
334
335 $temp_args = $args;
336 $args = apply_filters( 'rtsb/elementor/args_before_loop', $args, $metas );
337
338 // Query.
339 $product_query = new WP_Query( $args );
340
341 if ( $product_query->have_posts() ) {
342 // Elementor Render hook before row.
343 ob_start();
344 do_action( 'rtsb/elementor/render/before_row', $metas, $settings, $product_query, $temp_args );
345 $hook_html .= ob_get_clean();
346
347 // Row.
348 $this->row( $this->product_loop( $product_query, $metas, $template ), $metas, $hook_html, $settings );
349
350 // Pagination.
351 if ( $pagination ) {
352 $this->html .= RenderHelpers::render_pagination(
353 $product_query,
354 $metas,
355 $settings['posts_limit'],
356 $settings['pagination_per_page']
357 );
358 }
359
360 // Elementor Render hook before row.
361 ob_start();
362 do_action( 'rtsb/elementor/render/after_row', $metas, $settings, $product_query );
363 $this->html .= ob_get_clean();
364
365 } else {
366 $content = '<div class="woocommerce-no-products-found"><div class="woocommerce-info">' . esc_html__( 'No products were found matching your selection.', 'shopbuilder-pro' ) . '</div></div>';
367
368 $this->row( $content, $metas );
369 }
370
371 wp_reset_postdata();
372
373 unset( $args['tax_query'] );
374
375 // Container.
376 $this->container( $this->html, $settings, 'rtsb-products-container', $template, $is_carousel );
377
378 return $this->html;
379 }
380
381
382 /**
383 * Render Product View.
384 *
385 * @param string $template Template name.
386 * @param array $settings Control settings.
387 * @param object $widget Reference widget.
388 *
389 * @return string
390 */
391 public function wc_loop_for_product_view( $template, $settings, $widget ) {
392 global $wp_query, $post;
393
394 $this->get_settings = $settings;
395 $metas = RenderHelpers::meta_dataset( $settings, $template, $widget->get_settings_for_display() );
396
397 $settings['rtsb_order'] = ! empty( $wp_query->query_vars['order'] ) ? $wp_query->query_vars['order'] : 'ASC';
398 $settings['rtsb_orderby'] = ! empty( $wp_query->query_vars['orderby'] ) ? $wp_query->query_vars['orderby'] : 'menu_order';
399
400 $pagination = $metas['pagination'];
401
402 $page_type = BuilderFns::builder_type( get_the_ID() );
403 $is_preview = BuilderFns::is_builder_preview() && array_key_exists( $page_type, BuilderFns::builder_page_types() );
404 $posts_per_page = wc_get_default_products_per_row() * wc_get_default_product_rows_per_page();
405
406 if ( $is_preview ) {
407 $main_query = clone $wp_query;
408 $main_post = clone $post;
409
410 $ordering = ( new \WC_Query() )->get_catalog_ordering_args();
411 $wp_query_args = [
412 'post_type' => 'product',
413 'posts_per_page' => $posts_per_page,
414 ];
415
416 if ( ! empty( $ordering['orderby'] ) ) {
417 $wp_query_args['orderby'] = $ordering['orderby'];
418 }
419
420 if ( ! empty( $ordering['order'] ) ) {
421 $wp_query_args['order'] = $ordering['order'];
422 }
423
424 $wp_query = new \WP_Query( $wp_query_args ); // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited
425 wc_set_loop_prop( 'total', $wp_query->found_posts );
426 wc_set_loop_prop( 'total_pages', $wp_query->max_num_pages );
427 }
428
429 // column_per_row.
430 if ( woocommerce_product_loop() ) {
431 if ( wc_get_loop_prop( 'total' ) ) {
432 if ( Fns::product_has_applied_filters( 'shop' ) || Fns::product_has_applied_filters( 'archive' ) || 'rtsb_builder' === get_post_type( get_the_ID() ) ) {
433 echo '<div class="rtsb-active-filters-wrapper"></div>';
434 }
435
436 // Row.
437 $this->row( $this->product_loop( $wp_query, $metas, $template ), $metas );
438 }
439
440 // Pagination.
441 $this->html .= '<div class="rtsb-archive-pagination-wrap">';
442
443 if ( $pagination ) {
444 if ( Fns::product_filters_has_ajax( 'shop' ) || Fns::product_filters_has_ajax( 'archive' ) ) {
445 if ( $wp_query->max_num_pages > 1 ) {
446 $this->html .= "
447 <div class='rtsb-load-more rtsb-pos-r'>
448 <button data-paged='2' data-max-page='{$wp_query->max_num_pages}'><span>" . esc_html__( 'Load More', 'shopbuilder-pro' ) . "</span></button>
449 <div class='rtsb-loadmore-loading rtsb-ball-clip-rotate'><div></div></div>
450 </div>
451 ";
452 }
453 } else {
454 $this->html .= RenderHelpers::render_pagination(
455 $wp_query,
456 $metas,
457 wc_get_loop_prop( 'total' ),
458 $posts_per_page
459 );
460 }
461 }
462
463 $this->html .= '</div>';
464 } else {
465 $content = '<div class="woocommerce-no-products-found"><div class="woocommerce-info">' . esc_html__( 'No products were found matching your selection.', 'shopbuilder-pro' ) . '</div></div>';
466
467 $this->row( $content, $metas );
468 }
469
470 if ( $is_preview ) {
471 $wp_query = $main_query;
472 $post = $main_post;
473
474 wp_reset_query();
475 wp_reset_postdata();
476 }
477
478 // Container.
479 $this->container( $this->html, $settings, 'rtsb-products-container', $template );
480
481 return $this->html;
482 }
483
484 /**
485 * Render Product View.
486 *
487 * @param string $template Template name.
488 * @param array $settings Control settings.
489 *
490 * @return string
491 */
492 public function setup_loop_for_product_view( $template, $settings, $widget ) {
493 if ( empty( $settings['query_products'] ) ) {
494 return $this->html;
495 }
496
497 $html = null;
498
499 $metas = RenderHelpers::meta_dataset( $settings, '', $widget->get_settings_for_display() );
500
501 foreach ( $settings['query_products'] as $_product ) {
502 $post_object = get_post( $_product->get_id() );
503
504 setup_postdata( $GLOBALS['post'] =& $post_object ); // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited, Squiz.PHP.DisallowMultipleAssignments.Found
505
506 // Loop arg.
507 $arg = $this->arg_dataset( $metas, $_product->get_id() );
508 // Get template.
509 $html .= Fns::load_template( $template . $settings['layout'], $arg, true );
510
511 $this->row( $html, $metas );
512 }
513
514 // Container.
515 $this->container( $this->html, $settings, 'rtsb-products-container' );
516
517 wp_reset_postdata();
518
519 return $this->html;
520 }
521
522 /**
523 * Render Category View.
524 *
525 * @param string $template Template name.
526 * @param array $settings Control settings.
527 * @param bool $is_single Single category.
528 *
529 * @return string
530 */
531 public function category_view( $template, $settings, $is_single = false ) {
532 $this->get_settings = $settings;
533
534 $metas = RenderHelpers::meta_dataset( $settings, $template, $this->get_settings_for_display() );
535 $taxonomy = $metas['category_source'];
536 $term = $metas['category_term'];
537
538 if ( rtsb()->has_pro() && ( ! empty( $metas['tag_term'] ) ) ) {
539 $term = $metas['tag_term'];
540 }
541
542 // Query.
543 if ( $is_single ) {
544 if ( empty( $term ) ) {
545 return '<p>' . esc_html__( 'Please select a category.', 'shopbuilder' ) . '</p>';
546 }
547
548 $taxonomy_query = get_term( $term, $taxonomy );
549 } else {
550 // Query Args.
551 $args = ( new QueryArgs() )->buildArgs( $metas, 'category' );
552
553 $taxonomy_query = get_terms( $args );
554 }
555
556 if ( ! empty( $taxonomy_query ) ) {
557 // Row.
558 $this->row( $this->category_loop( $taxonomy_query, $metas, $template, $is_single ), $metas );
559 } else {
560 $this->html .= '<p>' . esc_html__( 'No categories found', 'shopbuilder' ) . '</p>';
561 }
562
563 // Container.
564 $this->container( $this->html, $settings, 'rtsb-categories-container', $is_single );
565
566 return $this->html;
567 }
568
569 /**
570 * Render Category View.
571 *
572 * @param string $template Template name.
573 * @param array $settings Control settings.
574 *
575 * @return string
576 */
577 public function social_share_view( $template, $settings ) {
578 $this->get_settings = $settings;
579 $share_items = [];
580
581 foreach ( $settings['share_platforms'] as $platform ) {
582 $share_items[] = [
583 'share_items' => $platform['share_items'],
584 'share_text' => $platform['share_text'],
585 ];
586 }
587
588 if ( ! empty( $share_items ) && is_array( $share_items ) ) {
589 $arg['p_id'] = get_the_ID();
590 $arg['share_items'] = $share_items;
591 $arg['preset'] = $settings['layout'];
592 $arg['direction'] = ! empty( $settings['layout_direction'] ) ? $settings['layout_direction'] : 'horizontal';
593 $arg['show_icon'] = ! empty( $settings['show_share_icon'] );
594 $arg['show_text'] = ! empty( $settings['show_share_text'] );
595 $arg['show_pre_text'] = ! empty( $settings['show_share_pre_text'] );
596 $arg['share_pre_text'] = ! empty( $settings['share_pre_text'] ) ? $settings['share_pre_text'] : '';
597 $arg['raw_settings'] = $this->get_settings_for_display();
598 $this->html = Fns::load_template( $template, $arg, true );
599 } else {
600 $this->html = '<p>' . esc_html__( 'Please select a social sharing platform.', 'shopbuilder' ) . '</p>';
601 }
602
603 return $this->html;
604 }
605
606 /**
607 * Builds an array with meta values.
608 *
609 * @param array $meta Meta values.
610 * @param int $post_id Post ID.
611 * @param bool $lazy_load Lazy Load.
612 * @param int $i Integer.
613 *
614 * @return array
615 */
616 public function arg_dataset( array $meta, int $post_id, bool $lazy_load = false, $i = 0 ) {
617 if ( ( empty( $meta ) && ! $post_id ) || ! in_array( get_post_type( $post_id ), [ 'product_variation', 'product' ] ) ) {
618 return [];
619 }
620
621 global $post;
622
623 $arg = [];
624 $_product = wc_get_product( $post_id );
625 $p_type = $_product->get_type();
626
627 $arg['class'] = null;
628 $arg['grid'] = null;
629 $arg['anchor_class'] = null;
630 $arg['hover_img_html'] = null;
631 $arg['s_link'] = [];
632 $arg['add_to_cart'] = '';
633 $arg['p_id'] = $post_id;
634 $arg['p_link'] = get_permalink();
635 $arg['p_sale'] = '';
636 $arg['has_attributes'] = $_product->is_type( 'variable' ) && $_product->get_attributes();
637 $arg['raw_settings'] = ! empty( $meta['raw_settings'] ) ? $meta['raw_settings'] : [];
638 $cart_icon_html = '';
639
640 $layout = $meta['layout'];
641
642 $arg['target'] = '_self';
643 $arg['f_img'] = $meta['f_img'];
644 $arg['items'] = $meta['visibility'];
645 $arg['title_tag'] = $meta['title_tag'];
646 $arg['title_class'] = 'product-title rtsb-text-limit limit-' . $meta['title_limit'] . ( ! $meta['title_link'] ? ' no-link' : '' );
647 $arg['title'] = Fns::text_truncation( get_the_title(), $meta['title_limit_custom'] );
648 $arg['excerpt_limit'] = $meta['excerpt_limit'];
649 $arg['excerpt'] = wpautop( Fns::text_truncation( do_shortcode( $post->post_excerpt ), $meta['excerpt_limit_custom'] ) );
650 $arg['title_link'] = $meta['title_link'];
651 $arg['image_link'] = $meta['image_link'];
652 $arg['out_of_stock'] = $meta['out_of_stock_badge_text'];
653 $arg['action_btn_preset'] = $meta['btn_preset'];
654 $arg['action_btn_position'] = $meta['btn_position'];
655 $arg['swatch_position'] = $meta['swatch_position'];
656 $arg['swatch_type'] = $meta['swatch_type'];
657 $arg['tooltip_position'] = $meta['tooltip_position'];
658
659 $is_list = preg_match( '/list/', $layout );
660 $is_carousel = preg_match( '/slider/', $layout );
661
662 if ( ! $is_carousel ) {
663 $arg['grid'] .= 'rtsb-col-grid ';
664 $arg['class'] .= ' even-grid-item ';
665 } else {
666 $arg['grid'] .= 'rtsb-col-grid rtsb-col-full rtsb-slide-item swiper-slide ';
667 }
668
669 $d_cols = 0 === $meta['d_cols'] ? RenderHelpers::default_columns( $layout ) : $meta['d_cols'];
670 $t_cols = 0 === $meta['t_cols'] ? 2 : $meta['t_cols'];
671 $m_cols = 0 === $meta['m_cols'] ? 1 : $meta['m_cols'];
672
673 $arg['grid'] .= 0 === $i % $d_cols ? ' row-last desktop-row-last' : '';
674 $arg['grid'] .= 0 === $i % $t_cols ? ' row-last tablet-row-last' : '';
675 $arg['grid'] .= 0 === $i % $m_cols ? ' row-last mobile-row-last' : '';
676
677 $arg['class'] .= 'rtsb-product';
678
679 if ( $is_list ) {
680 $arg['class'] .= ' rtsb-product-list';
681 }
682
683 $arg['class'] .= ' animated rtFadeIn';
684
685 if ( in_array( 'badges', $meta['visibility'], true ) ) {
686 $arg['p_sale'] = Fns::get_sale_badge(
687 $meta['sale_badge_type'],
688 $meta['sale_badge_text'],
689 $meta['out_of_stock_badge_text']
690 );
691 }
692
693 $arg['badge_class'] = RenderHelpers::badge_class( $meta['badge_preset'] );
694
695 if ( ! $meta['show_cart_text'] ) {
696 $meta['add_to_cart_text'] = '';
697 $meta['add_to_cart_success_text'] = '';
698 }
699
700 if ( in_array( 'add_to_cart', $meta['visibility'], true ) ) {
701 if ( ! empty( $meta['add_to_cart_icon'] ) ) {
702 $cart_icon_html .= Fns::icons_manager( $meta['add_to_cart_icon'], 'cart-icon' );
703 }
704
705 if ( ! empty( $meta['add_to_cart_success_icon'] ) ) {
706 $cart_icon_html .= Fns::icons_manager( $meta['add_to_cart_success_icon'], 'cart-success-icon' );
707 }
708
709 $cart_icon = '<span class="icon">' . $cart_icon_html . '</span>';
710
711 if ( $_product->is_purchasable() || 'grouped' === $p_type || 'external' === $p_type ) {
712 if ( $_product->is_in_stock() ) {
713 $arg['add_to_cart'] = $this->render_add_to_cart_button(
714 get_permalink(),
715 $post_id,
716 $p_type,
717 $meta['add_to_cart_text'],
718 $meta['add_to_cart_success_text'],
719 $cart_icon,
720 $meta['add_to_cart_alignment']
721 );
722 }
723 }
724 }
725
726 if ( in_array( 'quick_view', $meta['visibility'], true ) ) {
727 add_filter( 'rtsb/module/quick_view/button_params', [ $this, 'button_classes' ] );
728 add_filter( 'rtsb/module/quick_view/icon_html', [ $this, 'quick_view_icon' ] );
729 }
730
731 if ( in_array( 'compare', $meta['visibility'], true ) ) {
732 add_filter( 'rtsb/module/compare/button_params', [ $this, 'button_classes' ] );
733 add_filter( 'rtsb/module/compare/icon_html', [ $this, 'compare_icon' ] );
734 }
735
736 if ( in_array( 'wishlist', $meta['visibility'], true ) ) {
737 add_filter( 'rtsb/module/wishlist/button_params', [ $this, 'button_classes' ] );
738 add_filter( 'rtsb/module/wishlist/icon_html', [ $this, 'wishlist_icon' ] );
739 }
740
741 $arg['img_html'] = $meta['f_img'] ? Fns::get_product_image_html(
742 'product',
743 $post_id,
744 $meta['f_img_size'],
745 $meta['default_img_id'],
746 $meta['custom_img_size'],
747 $lazy_load
748 ) : null;
749
750 if ( ! ( function_exists( 'rtwpvsp' ) && $_product->is_type( 'variable' ) && $_product->get_attributes() ) ) {
751 $gallery_ids = $_product->get_gallery_image_ids();
752
753 if ( $meta['hover_img'] && ! empty( $gallery_ids ) ) {
754 $arg['class'] .= ! $meta['gallery_img'] ? ' rtsb-double-img' : '';
755
756 if ( ! rtsb()->has_pro() ) {
757 $arg['class'] .= ' rtsb-double-img';
758 }
759
760 $arg['hover_img_html'] = Fns::get_product_image_html(
761 'product',
762 $gallery_ids[0],
763 $meta['f_img_size'],
764 null,
765 $meta['custom_img_size'],
766 $lazy_load,
767 true
768 );
769 }
770 }
771
772 $arg['hover_btn_text'] = $meta['hover_btn_text'];
773
774 if ( $meta['show_hover_btn_icon'] && ! empty( $meta['hover_btn_icon'] ) ) {
775 $arg['hover_btn_icon'] = '<span class="icon">' . Fns::icons_manager( $meta['hover_btn_icon'], 'hover-btn-icon' ) . '</span>';
776 }
777
778 $arg['img_args'] = [
779 'p_id' => $arg['p_id'],
780 'title' => get_the_title(),
781 'p_link' => $arg['p_link'],
782 'image_link' => $arg['image_link'],
783 'img_html' => $arg['img_html'],
784 'hover_img_html' => $arg['hover_img_html'],
785 'meta' => $meta,
786 ];
787
788 return apply_filters( 'rtsb/elementor/render/arg_dataset', $arg, $post_id, $meta, $lazy_load );
789 }
790
791 /**
792 * Builds an array with meta values.
793 *
794 * @param array $meta Meta values.
795 * @param Object $query Category object.
796 * @param bool $fullwidth Fullwidth check.
797 * @param bool $lazy_load Lazy Load.
798 *
799 * @return array
800 */
801 public function cat_arg_dataset( $meta, $query = null, $fullwidth = false, $lazy_load = false ) {
802 if ( empty( $meta ) ) {
803 return [];
804 }
805
806 $arg = [];
807
808 $arg['class'] = null;
809 $arg['grid'] = null;
810 $arg['anchor_class'] = null;
811 $arg['p_sale'] = null;
812 $arg['count'] = max( $query->count, 0 );
813 $arg['count_position'] = $meta['count_position'];
814 $arg['excerpt_position'] = $meta['cat_excerpt_position'];
815 $arg['cat_link'] = get_term_link( $query );
816 $arg['target'] = '_self';
817 $arg['raw_settings'] = ! empty( $meta['raw_settings'] ) ? $meta['raw_settings'] : [];
818
819 if ( ! empty( $meta['tag_term'] ) ) {
820 $arg['tag_term'] = $meta['tag_term'];
821 }
822
823 if ( ! empty( $meta['custom_link']['url'] ) ) {
824 $arg['cat_link'] = $meta['custom_link']['url'];
825 $arg['target'] = $meta['custom_link']['is_external'] ? '_blank' : '_self';
826 }
827
828 $title = $query->name;
829 $excerpt = $query->description;
830
831 if ( in_array( 'badges', $meta['visibility'], true ) ) {
832 $arg['p_sale'] = $meta['custom_badge_text'];
833 }
834
835 $arg['badge_class'] = RenderHelpers::badge_class( $meta['badge_preset'] );
836
837 if ( $arg['count'] >= 0 ) {
838 $prefix = ! empty( $meta['before_count'] ) ? $meta['before_count'] : '';
839 $suffix = ! empty( $meta['after_count'] ) ? $meta['after_count'] : '';
840
841 $arg['count'] = $prefix . $arg['count'] . $suffix;
842 }
843
844 if ( $meta['show_custom_title'] && ! empty( $meta['cat_custom_title'] ) ) {
845 $title = $meta['cat_custom_title'];
846 }
847
848 if ( $meta['show_custom_excerpt'] && ! empty( $meta['cat_custom_excerpt'] ) ) {
849 $excerpt = $meta['cat_custom_excerpt'];
850 }
851
852 $layout = $meta['layout'];
853
854 $arg['c_img'] = $meta['c_img'];
855 $arg['items'] = $meta['visibility'];
856 $arg['title_tag'] = $meta['title_tag'];
857 $arg['title_class'] = 'category-title rtsb-text-limit limit-' . $meta['title_limit'] . ( ! $meta['title_link'] ? ' no-link' : '' );
858 $arg['title'] = Fns::text_truncation( $title, $meta['title_limit_custom'] );
859 $arg['excerpt_limit'] = $meta['excerpt_limit'];
860 $arg['excerpt'] = wpautop( Fns::text_truncation( $excerpt, $meta['excerpt_limit_custom'] ) );
861 $arg['title_link'] = $meta['title_link'];
862 $arg['image_link'] = $meta['image_link'];
863
864 if ( ! $fullwidth ) {
865 $arg['grid'] .= 'rtsb-col-grid ';
866 $arg['class'] .= ' even-grid-item ';
867 } else {
868 $arg['grid'] .= 'rtsb-col-grid ';
869 }
870
871 $arg['class'] .= 'rtsb-category-grid';
872
873 $arg['img_html'] = $meta['c_img'] ? Fns::get_product_image_html(
874 'category',
875 $query->term_id,
876 $meta['f_img_size'],
877 $meta['default_img_id'],
878 $meta['custom_img_size'],
879 $lazy_load
880 ) : null;
881
882 if ( $meta['show_custom_image'] && ! empty( $meta['custom_image'] ) ) {
883 $arg['img_html'] = Fns::get_product_image_html(
884 'custom',
885 null,
886 $meta['f_img_size'],
887 $meta['custom_image'],
888 $meta['custom_img_size'],
889 $lazy_load
890 );
891 }
892
893 $arg['excerpt_class'] = 'category-info' . ( 'block' === $meta['count_position'] ? ' block-count' : ' inline-count' ) . ( 'above' === $meta['cat_excerpt_position'] ? ' excerpt-above' : '' ) . ( empty( $arg['excerpt'] ) ? ' no-excerpt' : '' );
894
895 return $arg;
896 }
897
898 /**
899 * Renders add to cart button.
900 *
901 * @param string $link Product link.
902 * @param int $id Product ID.
903 * @param string $type Product type.
904 * @param string $text Custom text.
905 * @param string $success Success text.
906 * @param string $icon_html Custom icon.
907 * @param string $alignment Icon alignment.
908 *
909 * @return string
910 */
911 public function render_add_to_cart_button( $link, $id, $type, $text, $success, $icon_html, $alignment ) {
912 $content = null;
913 $tooltip_attr = '';
914 $ext_link = get_post_meta( $id, '_product_url', true );
915 $btn_txt = get_post_meta( $id, '_button_text', true );
916
917 if ( empty( $text ) ) {
918 $tooltip_attr = ' title="' . esc_attr__( 'Add to Cart', 'shopbuilder' ) . '"';
919
920 if ( 'variable' === $type ) {
921 $tooltip_attr = ' title="' . esc_attr__( 'Select Options', 'shopbuilder' ) . '"';
922 }
923
924 if ( 'grouped' === $type ) {
925 $tooltip_attr = ' title="' . esc_attr__( 'View Products', 'shopbuilder' ) . '"';
926 }
927
928 if ( 'external' === $type ) {
929 $tooltip_txt = ! empty( $btn_txt ) ? esc_html( $btn_txt ) : esc_html__( 'Buy Product', 'shopbuilder' );
930 $tooltip_attr = ' title="' . esc_attr( $tooltip_txt ) . '"';
931 }
932 }
933
934 ob_start();
935 do_action( 'rtsb/before/cart/button' );
936 $content .= ob_get_clean();
937
938 if ( 'variable' === $type ) {
939 $content .= sprintf(
940 '<div class="rtsb-wc-add-to-cart-wrap">
941 <a href="%1$s" data-quantity="1" class="rtsb-action-btn variable-product tipsy icon-%4$s %5$s" data-product_id="%3$s" rel="nofollow"%6$s>%7$s<span class="text">%2$s</span></a>
942 </div>',
943 esc_url( $link ),
944 esc_html__( 'Select Options', 'shopbuilder' ),
945 absint( $id ),
946 esc_attr( $alignment ),
947 empty( $text ) ? 'no-text' : 'has-text',
948 $tooltip_attr,
949 $icon_html,
950 );
951 } elseif ( 'grouped' === $type ) {
952 $content .= sprintf(
953 '<div class="rtsb-wc-add-to-cart-wrap">
954 <a href="%1$s" data-quantity="1" class="rtsb-action-btn variable-product tipsy icon-%4$s %5$s" data-product_id="%3$s" rel="nofollow"%6$s>%7$s<span class="text">%2$s</span></a>
955 </div>',
956 esc_url( $link ),
957 esc_html__( 'View Products', 'shopbuilder' ),
958 absint( $id ),
959 esc_attr( $alignment ),
960 empty( $text ) ? 'no-text' : 'has-text',
961 $tooltip_attr,
962 $icon_html,
963 );
964 } elseif ( 'external' === $type ) {
965 $content .= sprintf(
966 '<div class="rtsb-wc-add-to-cart-wrap">
967 <a href="%1$s" data-quantity="1" class="rtsb-action-btn variable-product tipsy icon-%4$s %5$s" data-product_id="%3$s" rel="nofollow"%6$s %8$s>%7$s<span class="text">%2$s</span></a>
968 </div>',
969 ! empty( $ext_link ) ? esc_url( $ext_link ) : esc_url( $link ),
970 ! empty( $btn_txt ) ? esc_html( $btn_txt ) : esc_html__( 'Buy Product', 'shopbuilder' ),
971 absint( $id ),
972 esc_attr( $alignment ),
973 empty( $text ) ? 'no-text' : 'has-text',
974 $tooltip_attr,
975 $icon_html,
976 ! empty( $ext_link ) ? ' target="_blank"' : ''
977 );
978 } else {
979 $content .= sprintf(
980 '<a href="%1$s?add-to-cart=%2$d" data-quantity="1" class="rtsb-action-btn rtsb-add-to-cart-btn tipsy icon-%6$s %7$s" data-id="%2$d" data-type="%3$s"%8$s>%4$s<span class="text %10$s" data-success="%9$s">%5$s</span><span></span></a>',
981 esc_url( $link ),
982 absint( $id ),
983 esc_attr( $type ),
984 $icon_html,
985 esc_html( $text ),
986 esc_attr( $alignment ),
987 empty( $text ) ? 'no-text' : 'has-text',
988 $tooltip_attr,
989 esc_html( $success ),
990 ! empty( $success ) ? 'has-success-text' : 'no-success-text',
991 );
992 }
993
994 ob_start();
995 do_action( 'rtsb/after/cart/button' );
996 $content .= ob_get_clean();
997
998 return $content;
999 }
1000
1001 /**
1002 * Button classes.
1003 *
1004 * @param array $params Button params.
1005 *
1006 * @return array
1007 */
1008 public function button_classes( $params ) {
1009 $params['classes'] = array_merge( $params['classes'], [ 'rtsb-action-btn', 'tipsy' ] );
1010
1011 return $params;
1012 }
1013 }
1014