PluginProbe
ShopBuilder – WooCommerce Builder For Elementor / 2.1.2
ShopBuilder – WooCommerce Builder For Elementor v2.1.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.1.2, at app/Elementor/Render/Render.php

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