PluginProbe
ShopBuilder – WooCommerce Builder For Elementor / 2.0.3
ShopBuilder – WooCommerce Builder For Elementor v2.0.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 / Render / Render.php

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

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