PluginProbe
ShopBuilder – WooCommerce Builder For Elementor / 1.1.4
ShopBuilder – WooCommerce Builder For Elementor v1.1.4
3.4.2 3.4.1 3.4.0 2.0.1 2.0.2 2.0.3 2.1.0 2.1.1 2.1.10 2.1.11 2.1.12 2.1.13 2.1.14 2.1.15 2.1.2 2.1.3 2.1.4 2.1.5 2.1.6 2.1.7 2.1.8 2.1.9 2.2.0 2.2.1 2.2.2 All 63 releases
← All changes | app/Elementor/Render/Render.php +866 -1388 2.1.111.1.4 View file →
@@ -1,1388 +1,866 @@
1 -<?php
2 -/**
3 - * Elementor Render Class.
4 - *
5 - * This class contains render logics & output. It utilizes WC_Products_Query().
6 - *
7 - * @package RadiusTheme\SB
8 - */
9 -
10 -namespace RadiusTheme\SB\Elementor\Render;
11 -
12 -use WC_Query;
13 -use WP_Query;
14 -use WC_Product;
15 -use Elementor\Utils;
16 -use WC_Product_Query;
17 -use RadiusTheme\SB\Helpers\Fns;
18 -use RadiusTheme\SB\Models\QueryArgs;
19 -use RadiusTheme\SB\Helpers\BuilderFns;
20 -use RadiusTheme\SB\Traits\SingletonTrait;
21 -use RadiusTheme\SB\Traits\ActionBtnTraits;
22 -use RadiusTheme\SB\Elementor\Helper\RenderHelpers;
23 -
24 -// Do not allow directly accessing this file.
25 -if ( ! defined( 'ABSPATH' ) ) {
26 - exit( 'This script cannot be accessed directly.' );
27 -}
28 -
29 -/**
30 - * Elementor Render Class.
31 - */
32 -class Render {
33 - /**
34 - * Singleton Trait.
35 - */
36 - use SingletonTrait;
37 -
38 - /**
39 - * Action button trait.
40 - */
41 - use ActionBtnTraits;
42 -
43 - /**
44 - * HTML.
45 - *
46 - * @var string
47 - */
48 - private $html = null;
49 -
50 - /**
51 - * Settings array
52 - *
53 - * @var array
54 - */
55 - public $get_settings;
56 -
57 - /**
58 - * Element attributes.
59 - *
60 - * @var array
61 - */
62 - private $attributes = [];
63 -
64 - /**
65 - * Get elementor settings.
66 - *
67 - * @return array
68 - */
69 - public function get_settings_for_display() {
70 - return $this->get_settings;
71 - }
72 -
73 - /**
74 - * Container Wrapper HTML.
75 - *
76 - * @param string $content The content.
77 - * @param array $settings Settings.
78 - * @param string $class Class.
79 - * @param string $template Template name.
80 - * @param bool $fullwidth Fullwidth check.
81 - * @param bool $ajax Ajax attributes.
82 - *
83 - * @return string
84 - */
85 - public function container( $content, $settings, $class = '', $template = '', $fullwidth = false, $ajax = true ) {
86 - $rand = wp_rand();
87 - $layout_id = 'rtsb-container-' . $rand;
88 - $metas = RenderHelpers::meta_dataset( $settings, $template );
89 - $layout = $metas['layout'];
90 - $style_attr = '--rtsb-default-columns: ' . esc_attr( RenderHelpers::default_columns( $layout ) );
91 - $view_mode = $settings['view_mode'] ?? 'grid';
92 - $view_mode = isset( $_GET['displayview'] ) ? sanitize_text_field( wp_unslash( $_GET['displayview'] ) ) : $view_mode; // phpcs:ignore WordPress.Security.NonceVerification.Recommended
93 - $tooltip_attr = 'list' == $view_mode && ! empty( $metas['tooltip_position_list'] ) ? esc_attr( $metas['tooltip_position_list'] ) : $metas['tooltip_position'];
94 - $has_pro = rtsb()->has_pro();
95 - $has_filters = $has_pro && ! empty( $settings['tax_filter'] );
96 -
97 - // Set default layout.
98 - if ( ! $has_pro && ! in_array( $layout, array_keys( Fns::free_layouts() ), true ) ) {
99 - $layout = RenderHelpers::set_default_layout( $layout );
100 - }
101 -
102 - // Container classes.
103 - $container_classes = RenderHelpers::prepare_container_classes( $metas, $settings, $class );
104 -
105 - // Pagination attributes.
106 - $pagination_attributes = RenderHelpers::prepare_pagination_attr( $layout, $has_filters, $template, $settings, $ajax );
107 -
108 - // Attributes for the container.
109 - $container_attributes = [
110 - 'id' => $layout_id,
111 - 'class' => $container_classes,
112 - 'style' => $style_attr,
113 - 'data-layout' => $layout,
114 - 'data-tooltip-position' => $tooltip_attr,
115 - ];
116 -
117 - if ( ! empty( $pagination_attributes ) ) {
118 - $container_attributes['data-rtsb-ajax'] = $pagination_attributes;
119 - }
120 -
121 - // Adding render attributes.
122 - $this->add_attribute( 'rtsb_container_attr_' . $rand, $container_attributes );
123 -
124 - // Start rendering.
125 - $this->html = '<div ' . $this->get_attribute_string( 'rtsb_container_attr_' . $rand ) . '>';
126 -
127 - // Section title.
128 - $this->html .= $this->render_section_title( $settings );
129 -
130 - // Content.
131 - $this->html .= $content;
132 -
133 - // End rendering.
134 - $this->html .= '</div><!-- .rtsb-elementor-container -->';
135 -
136 - // Action button icon reset.
137 - $this->action_button_icon_set_default();
138 -
139 - // Script generator.
140 - $script_generator = [];
141 - $script_generator['layout'] = $layout_id;
142 - $script_generator['rand'] = absint( $rand );
143 - $script_generator['isCarousel'] = preg_match( '/slider/', $layout );
144 -
145 - // Register scripts in the wp_footer action.
146 - add_action(
147 - 'wp_footer',
148 - static function () use ( $script_generator ) {
149 - RenderHelpers::register_scripts( $script_generator );
150 - }
151 - );
152 -
153 - return $this->html;
154 - }
155 -
156 - /**
157 - * Row Wrapper HTML.
158 - *
159 - * @param string $content The content.
160 - * @param array $settings Settings.
161 - * @param string $hook_html Hook HTML.
162 - * @param array $raw_settings Raw Settings.
163 - *
164 - * @return string
165 - */
166 - public function row( $content, $settings, $hook_html = '', $raw_settings = [] ) {
167 - $layout = $settings['layout'];
168 - $rand = wp_rand();
169 - $is_carousel = preg_match( '/slider/', $layout );
170 -
171 - if ( preg_match( '/category/', $layout ) && ( ! empty( $settings['active_cat_slider'] ) ) ) {
172 - $is_carousel = true;
173 - }
174 -
175 - // Row classes.
176 - $row_classes = RenderHelpers::prepare_row_classes( $settings );
177 -
178 - // Adding render attributes.
179 - $this->add_attribute( 'rtsb_row_attr_' . $rand, 'class', $row_classes );
180 -
181 - // Start rendering.
182 - $row_wrapper = '<div ' . $this->get_attribute_string( 'rtsb_row_attr_' . $rand ) . '>';
183 - $start_wrapper = apply_filters( 'rtsb/elementor/row/start', $row_wrapper, $raw_settings );
184 -
185 - $this->html = ! empty( $settings['show_filter'] ) ? $hook_html . $start_wrapper : $start_wrapper;
186 -
187 - if ( $is_carousel ) {
188 - $slider_data = RenderHelpers::slider_data( $settings, $raw_settings );
189 -
190 - // Adding slider render attributes.
191 - $this->add_attribute(
192 - 'rtsb_slider_attr_' . $rand,
193 - [
194 - 'class' => 'rtsb-col-grid ' . $slider_data['class'],
195 - 'data-options' => $slider_data['data'],
196 - ]
197 - );
198 -
199 - $this->html .= '<div ' . $this->get_attribute_string( 'rtsb_slider_attr_' . $rand ) . '>';
200 - $this->html .= '<div class="swiper-wrapper">';
201 - }
202 -
203 - $this->html .= $content;
204 -
205 - if ( $is_carousel ) {
206 - $this->html .= '</div><!-- .swiper-wrapper -->';
207 -
208 - // Slider buttons.
209 - $this->html .= $this->render_slider_buttons( $settings );
210 - $this->html .= '</div><!-- .rtsb-carousel-slider -->';
211 - }
212 -
213 - $row_end = '</div><!-- .rtsb-row -->';
214 -
215 - $this->html .= apply_filters( 'rtsb/elementor/row/end', $row_end );
216 -
217 - // Preloader.
218 - $this->html .= RenderHelpers::pre_loader( $layout );
219 -
220 - return $this->html;
221 - }
222 -
223 - /**
224 - * Product loop.
225 - *
226 - * @param object $products Products.
227 - * @param array $settings Settings.
228 - * @param string $template Template.
229 - *
230 - * @return string|null
231 - */
232 - public function product_loop( $products, $settings, $template ) {
233 - $html = null;
234 -
235 - if ( empty( $products ) ) {
236 - return null;
237 - }
238 -
239 - $i = 0;
240 -
241 - foreach ( $products as $product ) {
242 - $i++;
243 - $GLOBALS['product'] = $product;
244 -
245 - /**
246 - * Before product template render hook.
247 - */
248 - do_action( 'rtsb_before_product_template_render' );
249 -
250 - // Loop arg.
251 - $arg = $this->arg_dataset( $settings, $product, $settings['lazy_load'], $i );
252 -
253 - // Get template.
254 - $html .= Fns::load_template( $template . $settings['layout'], $arg, true );
255 -
256 - /**
257 - * After product template render hook.
258 - */
259 - do_action( 'rtsb_after_product_template_render' );
260 -
261 - unset( $GLOBALS['product'] );
262 - }
263 -
264 - return $html;
265 - }
266 -
267 - /**
268 - * WC Product loop.
269 - *
270 - * @param object $query The query.
271 - * @param array $settings Settings.
272 - * @param string $template Template.
273 - *
274 - * @return string|null
275 - */
276 - public function wc_product_loop( $query, $settings, $template ) {
277 - $html = null;
278 -
279 - if ( empty( $query ) ) {
280 - return null;
281 - }
282 -
283 - $i = 0;
284 -
285 - while ( $query->have_posts() ) {
286 - $query->the_post();
287 - $i++;
288 -
289 - // Loop arg.
290 - $arg = $this->arg_dataset( $settings, wc_get_product( get_the_ID() ), $settings['lazy_load'], $i );
291 -
292 - // Get template.
293 - $html .= Fns::load_template( $template . $settings['layout'], $arg, true );
294 - }
295 -
296 - return $html;
297 - }
298 -
299 - /**
300 - * Category loop.
301 - *
302 - * @param object $query The query.
303 - * @param array $settings Settings.
304 - * @param string $template Template.
305 - * @param bool $is_single Single category.
306 - *
307 - * @return string|null
308 - */
309 - public function category_loop( $query, $settings, $template, $is_single = false ) {
310 - $html = null;
311 - $category_loop = false;
312 -
313 - if ( 'category-layout3' === $settings['raw_settings']['layout'] || 'category-single-layout2' === $settings['raw_settings']['layout'] ) {
314 - $category_loop = true;
315 - }
316 -
317 - if ( $is_single ) {
318 - // Loop arg.
319 - $arg = $this->cat_arg_dataset( $settings, $query, true, false, $category_loop );
320 -
321 - // Get template.
322 - $html .= Fns::load_template( $template . $settings['layout'], $arg, true );
323 - } else {
324 - foreach ( $query as $term ) {
325 - // Loop arg.
326 - $arg = $this->cat_arg_dataset( $settings, $term, false, false, $category_loop );
327 -
328 - // Get template.
329 - $html .= Fns::load_template( $template . $settings['layout'], $arg, true );
330 - }
331 - }
332 -
333 - return $html;
334 - }
335 -
336 - /**
337 - * Render Product View.
338 - *
339 - * @param string $template Template name.
340 - * @param array $settings Control settings.
341 - *
342 - * @return string
343 - */
344 - public function product_view( $template, $settings ) {
345 - $this->get_settings = $settings;
346 -
347 - $metas = RenderHelpers::meta_dataset( $settings, $template, $this->get_settings_for_display() );
348 - $is_carousel = preg_match( '/slider/', $metas['layout'] );
349 - $pagination = $metas['pagination'];
350 - $hook_html = '';
351 -
352 - // Query Args.
353 - $args = ( new QueryArgs() )->buildArgs( $metas, 'product', $is_carousel );
354 -
355 - $temp_args = $args;
356 - $default_args = [
357 - 'visibility' => 'visible',
358 - 'status' => 'publish',
359 - ];
360 - $custom_args = apply_filters( 'rtsb/elementor/args_before_loop', $args, $metas );
361 - $args = wp_parse_args( $custom_args, $default_args );
362 -
363 - /**
364 - * Before Product query hook.
365 - *
366 - * @hooked RadiusTheme\SB\Controllers\Hooks\ActionHooks::modify_wc_query_args 10
367 - */
368 - do_action( 'rtsb/elements/render/before_query', $settings, $args );
369 -
370 - // Query.
371 - $product_query = new WC_Product_Query( $args );
372 - $products = $pagination ? $product_query->get_products()->products : $product_query->get_products();
373 -
374 - if ( ! empty( $products ) ) {
375 - // Start rendering.
376 - $hook_html .= $this->render_start( $metas, $settings, $temp_args );
377 -
378 - // Row.
379 - $this->row( $this->product_loop( $products, $metas, $template ), $metas, $hook_html, $settings );
380 -
381 - // Pagination.
382 - if ( $pagination ) {
383 - $pagination_args = [
384 - 'query' => $product_query,
385 - 'meta' => $metas,
386 - 'limit' => $settings['posts_limit'],
387 - 'per_page' => $settings['pagination_per_page'],
388 - ];
389 -
390 - $this->html .= $this->render_products_pagination( $pagination_args );
391 - }
392 -
393 - // End rendering.
394 - $this->html .= $this->render_end( $metas, $settings, $products );
395 - } else {
396 - $this->no_products_msg( $metas );
397 - }
398 -
399 - wp_reset_postdata();
400 -
401 - unset( $args['tax_query'] );
402 -
403 - /**
404 - * After Product query hook.
405 - *
406 - * @hooked RadiusTheme\SB\Controllers\Hooks\ActionHooks::reset_wc_query_args 10
407 - */
408 - do_action( 'rtsb/elements/render/after_query', $settings, $args );
409 -
410 - // Container.
411 - $this->container( $this->html, $settings, 'rtsb-products-container', $template, $is_carousel );
412 -
413 - return $this->html;
414 - }
415 -
416 - /**
417 - * Render Product View.
418 - *
419 - * @param string $template Template name.
420 - * @param array $settings Control settings.
421 - * @param object $widget Reference widget.
422 - *
423 - * @return string
424 - */
425 - public function wc_loop_for_product_view( $template, $settings, $widget ) {
426 - global $wp_query, $post;
427 -
428 - $this->get_settings = $settings;
429 - $rand = wp_rand();
430 - $metas = RenderHelpers::meta_dataset( $settings, $template, $widget->get_settings_for_display() );
431 -
432 - $settings['rtsb_order'] = ! empty( $wp_query->query_vars['order'] ) ? $wp_query->query_vars['order'] : 'ASC';
433 - $settings['rtsb_orderby'] = ! empty( $wp_query->query_vars['orderby'] ) ? $wp_query->query_vars['orderby'] : 'menu_order';
434 -
435 - $pagination = $metas['pagination'];
436 -
437 - $page_type = BuilderFns::builder_type( get_the_ID() );
438 - $is_preview = BuilderFns::is_builder_preview() && array_key_exists( $page_type, BuilderFns::builder_page_types() );
439 - $posts_per_page = wc_get_default_products_per_row() * wc_get_default_product_rows_per_page();
440 -
441 - if ( $is_preview ) {
442 - $main_query = clone $wp_query;
443 - $main_post = clone $post;
444 -
445 - $ordering = ( new WC_Query() )->get_catalog_ordering_args();
446 - $wp_query_args = [
447 - 'post_type' => 'product',
448 - 'posts_per_page' => $posts_per_page,
449 - ];
450 -
451 - if ( ! empty( $ordering['orderby'] ) ) {
452 - $wp_query_args['orderby'] = $ordering['orderby'];
453 - }
454 -
455 - if ( ! empty( $ordering['order'] ) ) {
456 - $wp_query_args['order'] = $ordering['order'];
457 - }
458 -
459 - $wp_query = new WP_Query( $wp_query_args ); // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited
460 -
461 - wc_set_loop_prop( 'total', $wp_query->found_posts );
462 - wc_set_loop_prop( 'total_pages', $wp_query->max_num_pages );
463 - }
464 -
465 - if ( Fns::product_has_applied_filters( 'shop' ) || Fns::product_has_applied_filters( 'archive' ) || 'rtsb_builder' === get_post_type( get_the_ID() ) ) {
466 - echo '<div class="rtsb-active-filters-wrapper"></div>';
467 - }
468 -
469 - // column_per_row.
470 - if ( woocommerce_product_loop() ) {
471 - if ( wc_get_loop_prop( 'total' ) ) {
472 -
473 - // Row.
474 - $this->row( $this->wc_product_loop( $wp_query, $metas, $template ), $metas, '', $settings );
475 - }
476 -
477 - // Pagination.
478 - $this->html .= '<div class="rtsb-archive-pagination-wrap">';
479 -
480 - if ( $pagination ) {
481 - if ( Fns::product_filters_has_ajax( apply_filters( 'rtsb/builder/set/current/page/type', '' ) ) ) {
482 - if ( $wp_query->max_num_pages > 1 ) {
483 - $this->add_attribute(
484 - 'rtsb_load_more_btn_attr_' . $rand,
485 - [
486 - 'data-paged' => '2',
487 - 'data-max-page' => $wp_query->max_num_pages,
488 - ]
489 - );
490 -
491 - $this->html .=
492 - "<div class='rtsb-load-more rtsb-pos-r'>
493 - <button {$this->get_attribute_string( 'rtsb_load_more_btn_attr_' . $rand )}>
494 - <span>" . esc_html__( 'Load More', 'shopbuilder' ) . "</span>
495 - </button>
496 - <div class='rtsb-loadmore-loading rtsb-ball-clip-rotate'><div></div></div>
497 - </div>";
498 - }
499 - } else {
500 - $pagination_args = [
501 - 'query' => $wp_query,
502 - 'meta' => $metas,
503 - 'limit' => wc_get_loop_prop( 'total' ),
504 - 'per_page' => $posts_per_page,
505 - ];
506 -
507 - $this->html .= $this->render_products_pagination( $pagination_args, 'wp' );
508 - }
509 - }
510 -
511 - $this->html .= '</div>';
512 - } else {
513 - $this->no_products_msg( $metas );
514 - }
515 -
516 - if ( $is_preview ) {
517 - // phpcs:disable
518 - $wp_query = $main_query;
519 - $post = $main_post;
520 -
521 - wp_reset_query();
522 - wp_reset_postdata();
523 - // phpcs:enable
524 - }
525 -
526 - // Container.
527 - $this->container( $this->html, $settings, 'rtsb-products-container', $template );
528 -
529 - return $this->html;
530 - }
531 -
532 - /**
533 - * Loop Setup for Product View.
534 - *
535 - * @param string $template Template name.
536 - * @param array $settings Control settings.
537 - * @param object $widget Widget object.
538 - *
539 - * @return string
540 - */
541 - public function setup_loop_for_product_view( $template, $settings, $widget ) {
542 - if ( empty( $settings['query_products'] ) ) {
543 - return $this->html;
544 - }
545 -
546 - $html = null;
547 -
548 - $metas = RenderHelpers::meta_dataset( $settings, '', $widget->get_settings_for_display() );
549 -
550 - foreach ( $settings['query_products'] as $_product ) {
551 - $post_object = get_post( $_product->get_id() );
552 -
553 - setup_postdata( $GLOBALS['post'] =& $post_object ); // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited, Squiz.PHP.DisallowMultipleAssignments.Found
554 -
555 - // Loop arg.
556 - $arg = $this->arg_dataset( $metas, $_product );
557 - // Get template.
558 - $html .= Fns::load_template( $template . $settings['layout'], $arg, true );
559 -
560 - $this->row( $html, $metas, '', $settings );
561 - }
562 -
563 - // Container.
564 - $this->container( $this->html, $settings, 'rtsb-products-container', '', false, false );
565 -
566 - wp_reset_postdata();
567 -
568 - return $this->html;
569 - }
570 -
571 - /**
572 - * Render Category View.
573 - *
574 - * @param string $template Template name.
575 - * @param array $settings Control settings.
576 - * @param bool $is_single Single category.
577 - *
578 - * @return string
579 - */
580 - public function category_view( $template, $settings, $is_single = false ) {
581 - $this->get_settings = $settings;
582 -
583 - $metas = RenderHelpers::meta_dataset( $settings, $template, $this->get_settings_for_display() );
584 - $taxonomy = $metas['category_source'];
585 - $term = $metas['category_term'];
586 -
587 - if ( rtsb()->has_pro() && ( ! empty( $metas['tag_term'] ) ) ) {
588 - $term = $metas['tag_term'];
589 - }
590 -
591 - // Query.
592 - if ( $is_single ) {
593 - if ( empty( $term ) ) {
594 - return '<p>' . esc_html__( 'Please select a category.', 'shopbuilder' ) . '</p>';
595 - }
596 -
597 - $taxonomy_query = get_term( $term, $taxonomy );
598 - } else {
599 - // Query Args.
600 - $args = ( new QueryArgs() )->buildArgs( $metas, 'category' );
601 -
602 - $taxonomy_query = get_terms( $args );
603 - }
604 -
605 - if ( ! is_wp_error( $taxonomy_query ) && ! empty( $taxonomy_query ) ) {
606 - // Row.
607 - $this->row( $this->category_loop( $taxonomy_query, $metas, $template, $is_single ), $metas );
608 - } else {
609 - $this->html .= '<p>' . esc_html__( 'No categories found', 'shopbuilder' ) . '</p>';
610 - }
611 -
612 - // Container.
613 - $this->container( $this->html, $settings, 'rtsb-categories-container', $is_single );
614 -
615 - return $this->html;
616 - }
617 -
618 - /**
619 - * Render Category View.
620 - *
621 - * @param string $template Template name.
622 - * @param array $settings Control settings.
623 - *
624 - * @return string
625 - */
626 - public function social_share_view( $template, $settings ) {
627 - $this->get_settings = $settings;
628 - $share_items = [];
629 -
630 - foreach ( $settings['share_platforms'] as $platform ) {
631 - $share_items[] = [
632 - 'share_items' => $platform['share_items'],
633 - 'share_text' => $platform['share_text'],
634 - ];
635 - }
636 -
637 - if ( ! empty( $share_items ) && is_array( $share_items ) ) {
638 - $arg['p_id'] = get_the_ID();
639 - $arg['share_items'] = $share_items;
640 - $arg['preset'] = $settings['layout'];
641 - $arg['direction'] = ! empty( $settings['layout_direction'] ) ? $settings['layout_direction'] : 'horizontal';
642 - $arg['show_icon'] = ! empty( $settings['show_share_icon'] );
643 - $arg['show_text'] = ! empty( $settings['show_share_text'] );
644 - $arg['show_pre_text'] = ! empty( $settings['show_share_pre_text'] );
645 - $arg['share_pre_text'] = ! empty( $settings['share_pre_text'] ) ? $settings['share_pre_text'] : '';
646 - $arg['raw_settings'] = $this->get_settings_for_display();
647 - $this->html = Fns::load_template( $template, $arg, true );
648 - } else {
649 - $this->html = '<p>' . esc_html__( 'Please select a social sharing platform.', 'shopbuilder' ) . '</p>';
650 - }
651 -
652 - return $this->html;
653 - }
654 -
655 - /**
656 - * Builds an array with meta values.
657 - *
658 - * @param array $meta Meta values.
659 - * @param object $product Product object.
660 - * @param bool $lazy_load Lazy Load.
661 - * @param int $i Integer.
662 - *
663 - * @return array
664 - */
665 - public function arg_dataset( array $meta, object $product, bool $lazy_load = false, $i = 0 ) {
666 - $post_id = $product->get_id();
667 - $arg = $this->build_product_arg(
668 - [
669 - 'product' => $product,
670 - 'id' => $product->get_id(),
671 - 'type' => $product->get_type(),
672 - 'meta' => $meta,
673 - 'lazy_load' => $lazy_load,
674 - 'i' => $i,
675 - ]
676 - );
677 -
678 - return apply_filters( 'rtsb/elementor/render/arg_dataset', $arg, $post_id, $meta, $lazy_load );
679 - }
680 -
681 - /**
682 - * Builds an array with meta values for WP_Query.
683 - *
684 - * @param array $meta Meta values.
685 - * @param int $post_id Post ID.
686 - * @param bool $lazy_load Lazy Load.
687 - * @param int $i Integer.
688 - *
689 - * @return array
690 - */
691 - public function wp_arg_dataset( array $meta, int $post_id, bool $lazy_load = false, $i = 0 ) {
692 - if ( ( empty( $meta ) && ! $post_id ) || ! in_array( get_post_type( $post_id ), [ 'product_variation', 'product' ] ) ) {
693 - return [];
694 - }
695 -
696 - global $product;
697 -
698 - if ( ! $product instanceof WC_Product && $post_id ) {
699 - $product = wc_get_product( $post_id );
700 - }
701 -
702 - $post_id = $product->get_id();
703 - $arg = $this->build_product_arg(
704 - [
705 - 'product' => $product,
706 - 'id' => $post_id,
707 - 'type' => $product->get_type(),
708 - 'meta' => $meta,
709 - 'lazy_load' => $lazy_load,
710 - 'i' => $i,
711 - ]
712 - );
713 -
714 - return apply_filters( 'rtsb/elementor/render/arg_dataset', $arg, $post_id, $meta, $lazy_load );
715 - }
716 -
717 - /**
718 - * Builds an array with meta values.
719 - *
720 - * @param array $meta Meta values.
721 - * @param Object $query Category object.
722 - * @param bool $fullwidth Fullwidth check.
723 - * @param bool $lazy_load Lazy Load.
724 - * @param bool $category_loop Category loop.
725 - *
726 - * @return array
727 - */
728 - public function cat_arg_dataset( $meta, $query = null, $fullwidth = false, $lazy_load = false, $category_loop = false ) {
729 - if ( empty( $meta ) ) {
730 - return [];
731 - }
732 -
733 - $arg = [];
734 -
735 - $products = null;
736 - $arg['class'] = null;
737 - $arg['grid'] = null;
738 - $arg['anchor_class'] = null;
739 - $arg['p_sale'] = null;
740 - $arg['count'] = max( $query->count, 0 );
741 - $arg['count_position'] = $meta['count_position'];
742 - $arg['excerpt_position'] = $meta['cat_excerpt_position'];
743 - $arg['cat_link'] = get_term_link( $query );
744 - $arg['target'] = '_self';
745 - $arg['raw_settings'] = ! empty( $meta['raw_settings'] ) ? $meta['raw_settings'] : [];
746 -
747 - if ( ! empty( $meta['tag_term'] ) ) {
748 - $arg['tag_term'] = $meta['tag_term'];
749 - }
750 -
751 - if ( ! empty( $meta['custom_link']['url'] ) ) {
752 - $arg['cat_link'] = $meta['custom_link']['url'];
753 - $arg['target'] = $meta['custom_link']['is_external'] ? '_blank' : '_self';
754 - }
755 -
756 - $title = $query->name;
757 - $excerpt = $query->description;
758 -
759 - if ( in_array( 'badges', $meta['visibility'], true ) ) {
760 - $arg['p_sale'] = $meta['custom_badge_text'];
761 - }
762 -
763 - $arg['badge_class'] = RenderHelpers::badge_class( $meta['badge_preset'] );
764 -
765 - if ( $arg['count'] >= 0 ) {
766 - $prefix = ! empty( $meta['before_count'] ) ? $meta['before_count'] : '';
767 - $suffix = ! empty( $meta['after_count'] ) ? $meta['after_count'] : '';
768 -
769 - $arg['count'] = $prefix . $arg['count'] . $suffix;
770 - }
771 -
772 - if ( $meta['show_custom_title'] && ! empty( $meta['cat_custom_title'] ) ) {
773 - $title = $meta['cat_custom_title'];
774 - }
775 -
776 - if ( $meta['show_custom_excerpt'] && ! empty( $meta['cat_custom_excerpt'] ) ) {
777 - $excerpt = $meta['cat_custom_excerpt'];
778 - }
779 -
780 - $arg['c_img'] = $meta['c_img'];
781 - $arg['items'] = $meta['visibility'];
782 - $arg['title_tag'] = $meta['title_tag'];
783 - $arg['title_class'] = 'category-title rtsb-text-limit limit-' . $meta['title_limit'] . ( ! $meta['title_link'] ? ' no-link' : '' );
784 - $arg['title'] = Fns::text_truncation( $title, $meta['title_limit_custom'] );
785 - $arg['excerpt_limit'] = $meta['excerpt_limit'];
786 - $arg['excerpt'] = wpautop( Fns::text_truncation( $excerpt, $meta['excerpt_limit_custom'] ) );
787 - $arg['title_link'] = $meta['title_link'];
788 - $arg['image_link'] = $meta['image_link'];
789 - $arg['grid'] .= 'rtsb-col-grid ';
790 -
791 - if ( ! $fullwidth ) {
792 - $arg['class'] .= ' even-grid-item ';
793 - }
794 -
795 - if ( ! empty( $meta['active_cat_slider'] ) ) {
796 - $arg['class'] .= ' rtsb-slide-item swiper-slide animated rtFadeIn ';
797 - }
798 -
799 - $arg['class'] .= 'rtsb-category-grid';
800 -
801 - ob_start();
802 - do_action( 'rtsb/categories/category_image_override', $meta, $query->term_id );
803 - $override_category_image = ob_get_clean();
804 -
805 - $arg['img_html'] = $meta['c_img'] ? Fns::get_product_image_html(
806 - 'category',
807 - $query->term_id,
808 - $meta['f_img_size'],
809 - $meta['default_img_id'],
810 - $meta['custom_img_size'],
811 - $lazy_load,
812 - false,
813 - false,
814 - $override_category_image
815 - ) : null;
816 -
817 - if ( $meta['show_custom_image'] && ! empty( $meta['custom_image'] ) ) {
818 - $arg['img_html'] = Fns::get_product_image_html(
819 - 'custom',
820 - null,
821 - $meta['f_img_size'],
822 - $meta['custom_image'],
823 - $meta['custom_img_size'],
824 - $lazy_load
825 - );
826 - }
827 -
828 - $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' : '' );
829 -
830 - if ( $category_loop ) {
831 - $query_args = [
832 - 'product_category_id' => $query->term_id,
833 - 'limit' => -1,
834 - 'order' => 'DESC',
835 - 'orderby' => 'date',
836 - ];
837 -
838 - $products_query = new WC_Product_Query( $query_args );
839 - $products = $products_query->get_products();
840 - }
841 -
842 - return apply_filters( 'rtsb/elementor/render/cat_arg_dataset', $arg, $meta, $query, $fullwidth, $lazy_load, $products );
843 - }
844 -
845 - /**
846 - * Building product args.
847 - *
848 - * @param array $args Args.
849 - * @return array
850 - */
851 - public function build_product_arg( $args ) {
852 - list(
853 - 'product' => $product,
854 - 'id' => $post_id,
855 - 'type' => $p_type,
856 - 'meta' => $meta,
857 - 'lazy_load' => $lazy_load,
858 - 'i' => $i,
859 - ) = $args;
860 -
861 - $arg = [];
862 - $arg['class'] = null;
863 - $arg['grid'] = null;
864 - $arg['anchor_class'] = null;
865 - $arg['hover_img_html'] = null;
866 - $arg['s_link'] = [];
867 - $arg['add_to_cart'] = '';
868 - $arg['p_id'] = $post_id;
869 - $arg['product'] = $product;
870 - $arg['p_link'] = $product->get_permalink();
871 - $arg['p_sale'] = '';
872 - $arg['rating_args'] = [];
873 - $arg['has_attributes'] = $product->is_type( 'variable' ) && $product->get_attributes();
874 - $arg['raw_settings'] = ! empty( $meta['raw_settings'] ) ? $meta['raw_settings'] : [];
875 - $cart_icon_html = '';
876 - $layout = $meta['layout'];
877 -
878 - // Building the arg.
879 - $arg['target'] = '_self';
880 - $arg['f_img'] = $meta['f_img'];
881 - $arg['items'] = $meta['visibility'];
882 - $arg['title_tag'] = $meta['title_tag'];
883 - $arg['title_class'] = 'product-title rtsb-text-limit limit-' . $meta['title_limit'] . ( ! $meta['title_link'] ? ' no-link' : '' );
884 - $arg['title'] = Fns::text_truncation( $product->get_title(), $meta['title_limit_custom'] );
885 - $arg['excerpt_limit'] = $meta['excerpt_limit'];
886 - $arg['excerpt'] = wpautop( Fns::text_truncation( do_shortcode( get_post_field( 'post_excerpt', $post_id ) ), $meta['excerpt_limit_custom'] ) );
887 - $arg['title_link'] = $meta['title_link'];
888 - $arg['image_link'] = $meta['image_link'];
889 - $arg['out_of_stock'] = $meta['out_of_stock_badge_text'];
890 - $arg['action_btn_preset'] = $meta['btn_preset'];
891 - $arg['action_btn_position'] = $meta['btn_position'];
892 - $arg['swatch_position'] = $meta['swatch_position'];
893 - $arg['swatch_type'] = $meta['swatch_type'];
894 - $arg['tooltip_position'] = $meta['tooltip_position'];
895 -
896 - $is_list = preg_match( '/list/', $layout );
897 - $is_carousel = preg_match( '/slider/', $layout );
898 -
899 - if ( ! $is_carousel ) {
900 - $arg['grid'] .= 'rtsb-col-grid ';
901 - $arg['class'] .= ' even-grid-item ';
902 - } else {
903 - $arg['grid'] .= 'rtsb-col-grid rtsb-col-full rtsb-slide-item swiper-slide ';
904 - }
905 -
906 - $d_cols = 0 === $meta['d_cols'] ? RenderHelpers::default_columns( $layout ) : $meta['d_cols'];
907 - $t_cols = 0 === $meta['t_cols'] ? 2 : $meta['t_cols'];
908 - $m_cols = 0 === $meta['m_cols'] ? 1 : $meta['m_cols'];
909 -
910 - $arg['grid'] .= 0 === $i % $d_cols ? ' row-last desktop-row-last' : '';
911 - $arg['grid'] .= 0 === $i % $t_cols ? ' row-last tablet-row-last' : '';
912 - $arg['grid'] .= 0 === $i % $m_cols ? ' row-last mobile-row-last' : '';
913 -
914 - $arg['class'] .= 'rtsb-product';
915 -
916 - if ( $is_list ) {
917 - $arg['class'] .= ' rtsb-product-list';
918 - }
919 -
920 - $arg['class'] .= ' animated rtFadeIn';
921 -
922 - if ( in_array( 'badges', $meta['visibility'], true ) ) {
923 - $badge_module = ! empty( $meta['enable_badges_module'] );
924 - $arg['p_sale'] = Fns::is_module_active( 'product_badges' ) && $badge_module ? 'rtsb_yes' : Fns::get_promo_badge(
925 - $product,
926 - $meta['sale_badge_type'],
927 - $meta['sale_badge_text'],
928 - apply_filters( 'rtsb/elementor/render/out_of_stock_badge_text', $meta['out_of_stock_badge_text'] )
929 - );
930 - }
931 -
932 - $arg['badge_class'] = RenderHelpers::badge_class( $meta['badge_preset'] );
933 -
934 - if ( ! $meta['show_cart_text'] ) {
935 - $meta['add_to_cart_text'] = '';
936 - $meta['add_to_cart_success_text'] = '';
937 - }
938 -
939 - if ( in_array( 'add_to_cart', $meta['visibility'], true ) ) {
940 - if ( ! empty( $meta['add_to_cart_icon'] ) ) {
941 - $cart_icon_html .= Fns::icons_manager( $meta['add_to_cart_icon'], 'cart-icon' );
942 - }
943 -
944 - if ( ! empty( $meta['add_to_cart_success_icon'] ) ) {
945 - $cart_icon_html .= Fns::icons_manager( $meta['add_to_cart_success_icon'], 'cart-success-icon' );
946 - }
947 -
948 - $cart_icon = ! empty( $cart_icon_html ) ? '<span class="icon">' . $cart_icon_html . '</span>' : '';
949 -
950 - if ( $product->is_purchasable() || 'grouped' === $p_type || 'external' === $p_type ) {
951 - if ( $product->is_in_stock() ) {
952 - $arg['add_to_cart'] = $this->render_add_to_cart_button(
953 - [
954 - 'link' => $product->get_permalink(),
955 - 'id' => $post_id,
956 - 'type' => $p_type,
957 - 'text' => $meta['add_to_cart_text'],
958 - 'success' => $meta['add_to_cart_success_text'],
959 - 'icon_html' => $cart_icon,
960 - 'alignment' => $meta['add_to_cart_alignment'],
961 - ]
962 - );
963 - }
964 - }
965 - }
966 -
967 - if ( in_array( 'quick_view', $meta['visibility'], true ) ) {
968 - add_filter( 'rtsb/module/quick_view/button_params', [ $this, 'button_classes' ] );
969 - add_filter( 'rtsb/module/quick_view/icon_html', [ $this, 'quick_view_icon' ] );
970 - }
971 -
972 - if ( in_array( 'compare', $meta['visibility'], true ) ) {
973 - add_filter( 'rtsb/module/compare/button_params', [ $this, 'button_classes' ] );
974 - add_filter( 'rtsb/module/compare/icon_html', [ $this, 'compare_icon' ] );
975 - }
976 -
977 - if ( in_array( 'wishlist', $meta['visibility'], true ) ) {
978 - add_filter( 'rtsb/module/wishlist/button_params', [ $this, 'button_classes' ] );
979 - add_filter( 'rtsb/module/wishlist/icon_html', [ $this, 'wishlist_icon' ] );
980 - }
981 -
982 - $arg['img_html'] = $meta['f_img'] ? Fns::get_product_image_html(
983 - 'product',
984 - $post_id,
985 - $meta['f_img_size'],
986 - $meta['default_img_id'],
987 - $meta['custom_img_size'],
988 - $lazy_load
989 - ) : null;
990 -
991 - if ( ! ( function_exists( 'rtwpvsp' ) && $product->is_type( 'variable' ) && $product->get_attributes() ) ) {
992 - $gallery_ids = $product->get_gallery_image_ids();
993 -
994 - if ( $meta['hover_img'] && ! empty( $gallery_ids ) ) {
995 - $arg['class'] .= ! $meta['gallery_img'] ? ' rtsb-double-img' : '';
996 -
997 - if ( ! rtsb()->has_pro() ) {
998 - $arg['class'] .= ' rtsb-double-img';
999 - }
1000 -
1001 - $arg['hover_img_html'] = Fns::get_product_image_html(
1002 - 'product',
1003 - $gallery_ids[0],
1004 - $meta['f_img_size'],
1005 - null,
1006 - $meta['custom_img_size'],
1007 - $lazy_load,
1008 - true
1009 - );
1010 - }
1011 - }
1012 -
1013 - $arg['hover_btn_text'] = $meta['hover_btn_text'];
1014 -
1015 - if ( $meta['show_hover_btn_icon'] && ! empty( $meta['hover_btn_icon'] ) ) {
1016 - $arg['hover_btn_icon'] = '<span class="icon">' . Fns::icons_manager( $meta['hover_btn_icon'], 'hover-btn-icon' ) . '</span>';
1017 - }
1018 -
1019 - $arg['img_args'] = [
1020 - 'p_id' => $arg['p_id'],
1021 - 'title' => get_the_title(),
1022 - 'p_link' => $arg['p_link'],
1023 - 'image_link' => $arg['image_link'],
1024 - 'img_html' => $arg['img_html'],
1025 - 'hover_img_html' => $arg['hover_img_html'],
1026 - 'meta' => $meta,
1027 - ];
1028 -
1029 - return $arg;
1030 - }
1031 -
1032 - /**
1033 - * Renders add to cart button.
1034 - *
1035 - * @param array $args Cart args.
1036 - *
1037 - * @return string
1038 - */
1039 - public function render_add_to_cart_button( $args ) {
1040 - list(
1041 - 'link' => $link,
1042 - 'id' => $id,
1043 - 'type' => $type,
1044 - 'text' => $text,
1045 - 'success' => $success,
1046 - 'icon_html' => $icon_html,
1047 - 'alignment' => $alignment
1048 - ) = $args;
1049 -
1050 - $content = null;
1051 - $rand = wp_rand();
1052 - $ext_link = get_post_meta( $id, '_product_url', true );
1053 - $btn_txt = get_post_meta( $id, '_button_text', true );
1054 -
1055 - ob_start();
1056 - do_action( 'rtsb/before/cart/button' );
1057 - $content .= ob_get_clean();
1058 -
1059 - $cart_attr = [
1060 - 'class' => 'rtsb-action-btn ' . $type . '-product tipsy icon-' . $alignment . ' ' . ( empty( $text ) ? 'no-text' : 'has-text' ),
1061 - 'href' => esc_url( $link ),
1062 - 'rel' => 'nofollow',
1063 - 'data-quantity' => '1',
1064 - 'data-product_id' => absint( $id ),
1065 - 'data-id' => absint( $id ),
1066 - ];
1067 -
1068 - if ( empty( $text ) ) {
1069 - $tooltip_mapping = [
1070 - 'simple' => esc_attr__( 'Add to Cart', 'shopbuilder' ),
1071 - 'variable' => esc_attr__( 'Select Options', 'shopbuilder' ),
1072 - 'grouped' => esc_attr__( 'View Products', 'shopbuilder' ),
1073 - 'external' => ! empty( $btn_txt ) ? esc_html( $btn_txt ) : esc_html__( 'Buy Product', 'shopbuilder' ),
1074 - ];
1075 -
1076 - $cart_attr['title'] = $tooltip_mapping[ $type ];
1077 - }
1078 -
1079 - $content .= '<div class="rtsb-wc-add-to-cart-wrap">';
1080 -
1081 - if ( 'variable' === $type || 'grouped' === $type ) {
1082 - $this->add_attribute( 'rtsb_add_to_cart_button_' . $id . $rand, $cart_attr );
1083 -
1084 - $text_btn = 'grouped' === $type ? __( 'View Products', 'shopbuilder' ) : __( 'Select Options', 'shopbuilder' );
1085 -
1086 - $content .= '<a ' . $this->get_attribute_string( 'rtsb_add_to_cart_button_' . $id . $rand ) . '>';
1087 - $content .= $icon_html;
1088 - $content .= '<span class="text ' . ( ! empty( $success ) ? 'has-success-text' : 'no-success-text' ) . '" data-success="' . esc_html( $success ) . '" data-cart-text="' . ( ! empty( $text ) ? esc_attr( $text ) : $tooltip_mapping['simple'] ) . '" data-variable-text="' . esc_attr( $text_btn ) . '">' . esc_html( $text_btn ) . '</span>';
1089 - $content .= '<span></span>';
1090 - } elseif ( 'external' === $type ) {
1091 - if ( ! empty( $ext_link ) ) {
1092 - $cart_attr['target'] = '_blank';
1093 - }
1094 -
1095 - $cart_attr['href'] = ! empty( $ext_link ) ? esc_url( $ext_link ) : esc_url( $link );
1096 -
1097 - $this->add_attribute( 'rtsb_add_to_cart_button_' . $id . $rand, $cart_attr );
1098 -
1099 - $content .= '<a ' . $this->get_attribute_string( 'rtsb_add_to_cart_button_' . $id . $rand ) . '>';
1100 - $content .= $icon_html;
1101 - $content .= '<span class="text">' . ( ! empty( $btn_txt ) ? esc_html( $btn_txt ) : esc_html__( 'Buy Product', 'shopbuilder' ) ) . '</span>';
1102 - } else {
1103 - $cart_attr['href'] = $cart_attr['href'] . '?add-to-cart=' . absint( $id );
1104 - $cart_attr['class'] .= ' rtsb-add-to-cart-btn';
1105 - $cart_attr['data-type'] = $type;
1106 -
1107 - $this->add_attribute( 'rtsb_add_to_cart_button_' . $id . $rand, $cart_attr );
1108 -
1109 - $content .= '<a ' . $this->get_attribute_string( 'rtsb_add_to_cart_button_' . $id . $rand ) . '>';
1110 - $content .= $icon_html;
1111 - $content .= '<span class="text ' . ( ! empty( $success ) ? 'has-success-text' : 'no-success-text' ) . '" data-success="' . esc_html( $success ) . '">' . esc_html( $text ) . '</span>';
1112 - $content .= '<span></span>';
1113 - }
1114 -
1115 - $content .= '</a>';
1116 - $content .= '</div>';
1117 -
1118 - ob_start();
1119 - do_action( 'rtsb/after/cart/button' );
1120 - $content .= ob_get_clean();
1121 -
1122 - return apply_filters( 'rtsb/render/cart/button', $content, $args );
1123 - }
1124 -
1125 - /**
1126 - * Button classes.
1127 - *
1128 - * @param array $params Button params.
1129 - *
1130 - * @return array
1131 - */
1132 - public function button_classes( $params ) {
1133 - $params['classes'] = array_merge( $params['classes'], [ 'rtsb-action-btn', 'tipsy' ] );
1134 -
1135 - return $params;
1136 - }
1137 -
1138 - /**
1139 - * Render the section title.
1140 - *
1141 - * @param array $settings The Elementor settings.
1142 - *
1143 - * @return string
1144 - */
1145 - public function render_section_title( $settings ) {
1146 - $html = '';
1147 - $rand = wp_rand();
1148 -
1149 - if ( empty( $settings['show_section_title'] ) || ( empty( $settings['query_products'] ) && 0 === count( $settings['query_products'] ) ) ) {
1150 - return $html;
1151 - }
1152 -
1153 - // Set attributes for the section title.
1154 - $this->add_attribute( 'rtsb_section_title_wrapper_' . $rand, 'class', 'rtsb-section-title-wrapper' );
1155 - $this->add_attribute( 'rtsb_section_title_' . $rand, 'class', 'rtsb-section-title' );
1156 -
1157 - // Start rendering.
1158 - $html .= '<div ' . $this->get_attribute_string( 'rtsb_section_title_wrapper_' . $rand ) . '>';
1159 - $html .= '<' . esc_attr( $settings['section_title_tag'] ) . ' ' . $this->get_attribute_string( 'rtsb_section_title_' . $rand ) . '>';
1160 - $html .= esc_html( $settings['section_title_text'] );
1161 - $html .= '</' . esc_attr( $settings['section_title_tag'] ) . '>';
1162 - $html .= '</div>';
1163 -
1164 - return $html;
1165 - }
1166 -
1167 - /**
1168 - * Renders products pagination
1169 - *
1170 - * @param array $args Pagination args.
1171 - * @param string $query_type Query type.
1172 - *
1173 - * @return string
1174 - */
1175 - public function render_products_pagination( $args, $query_type = 'wc' ) {
1176 - list(
1177 - 'query' => $query,
1178 - 'meta' => $meta,
1179 - 'limit' => $limit,
1180 - 'per_page' => $per_page
1181 - ) = $args;
1182 -
1183 - $html_utility = null;
1184 - $html = null;
1185 - $ajax = false;
1186 - $is_grid = preg_match( '/grid-layout/', $meta['layout'] ) || preg_match( '/list-layout/', $meta['layout'] );
1187 - $posts_per_page = 'wp' === $query_type ? $query->query_vars['posts_per_page'] : null;
1188 - $total_page = 'wp' === $query_type ? $query->max_num_pages : $query->get_products()->max_num_pages;
1189 -
1190 - if ( $limit ) {
1191 - if ( 'wc' === $query_type ) {
1192 - $found_post = $query->get_products()->total;
1193 - } elseif ( 'wp' === $query_type && ( empty( $wp_query->query['tax_query'] ) ) ) {
1194 - $found_post = $query->found_posts;
1195 - }
1196 -
1197 - if ( $per_page && $found_post > $per_page ) {
1198 - $found_post = $limit;
1199 - $total_page = ceil( $found_post / $per_page );
1200 - }
1201 - }
1202 -
1203 - $total_page = absint( $total_page );
1204 -
1205 - $args = [
1206 - 'total_page' => $total_page,
1207 - 'posts_per_page' => 'wc' === $query_type ? $per_page : $posts_per_page,
1208 - 'ajax' => $ajax,
1209 - ];
1210 -
1211 - if ( 'pagination' === $meta['posts_loading_type'] ) {
1212 - if ( $is_grid ) {
1213 - $html_utility .= Fns::custom_pagination(
1214 - $total_page,
1215 - 'wc' === $query_type ? $per_page : $posts_per_page
1216 - );
1217 - }
1218 - } else {
1219 - ob_start();
1220 - do_action( 'rtsb/elementor/render/pagination', $meta, $query, $args );
1221 - $html_utility .= ob_get_clean();
1222 - }
1223 -
1224 - if ( $html_utility ) {
1225 - $rand = wp_rand();
1226 -
1227 - // Adding pagination render attributes.
1228 - $this->add_attribute(
1229 - 'rtsb_pagination_attr_' . $rand,
1230 - [
1231 - 'class' => 'rtsb-pagination-wrap element-loading',
1232 - 'data-total-pages' => $total_page,
1233 - 'data-posts-per-page' => 'wc' === $query_type ? $per_page : $posts_per_page,
1234 - 'data-type' => $meta['posts_loading_type'],
1235 - ]
1236 - );
1237 -
1238 - // Start rendering.
1239 - $html = '<div ' . $this->get_attribute_string( 'rtsb_pagination_attr_' . $rand ) . '>';
1240 - $html .= $html_utility;
1241 - $html .= '</div><!-- .rtsb-pagination-wrap -->';
1242 - }
1243 -
1244 - return $html;
1245 - }
1246 -
1247 - /**
1248 - * Renders slider buttons
1249 - *
1250 - * @param array $settings Settings array.
1251 - *
1252 - * @return string
1253 - */
1254 - public function render_slider_buttons( $settings ) {
1255 - $html = '';
1256 - $left_icon = $settings['left_arrow_icon'];
1257 - $right_icon = $settings['right_arrow_icon'];
1258 -
1259 - if ( ! empty( $settings['slider_nav'] ) ) {
1260 - $html .=
1261 - '<div class="swiper-nav">
1262 - <div class="swiper-arrow swiper-button-next">
1263 - ' . Fns::icons_manager( $right_icon ) . '
1264 - </div>
1265 - <div class="swiper-arrow swiper-button-prev">
1266 - ' . Fns::icons_manager( $left_icon ) . '
1267 - </div>
1268 - </div>';
1269 - }
1270 -
1271 - $html .= ! empty( $settings['slider_dot'] ) ? '<div class="swiper-pagination rtsb-pos-s"></div>' : '';
1272 -
1273 - return $html;
1274 - }
1275 -
1276 - /**
1277 - * No products message.
1278 - *
1279 - * @param array $metas Meta data.
1280 - *
1281 - * @return void
1282 - */
1283 - public function no_products_msg( $metas ) {
1284 - $content =
1285 - '<div class="rtsb-notice woocommerce-no-products-found">
1286 - <div class="woocommerce-info">' . esc_html__( 'No products were found matching your selection.', 'shopbuilder' ) . '</div>
1287 - </div>';
1288 -
1289 - $this->row( $content, $metas );
1290 - }
1291 -
1292 - /**
1293 - * Start the rendering.
1294 - *
1295 - * @param array $metas Meta Data.
1296 - * @param array $settings Widget settings.
1297 - * @param array $temp_args Additional temporary arguments for rendering.
1298 - *
1299 - * @return string
1300 - */
1301 - public function render_start( $metas, $settings, $temp_args ) {
1302 - ob_start();
1303 -
1304 - /**
1305 - * Before render row hook.
1306 - */
1307 - do_action( 'rtsb/elementor/render/before_row', $metas, $settings, $temp_args, $this );
1308 -
1309 - return ob_get_clean();
1310 - }
1311 -
1312 - /**
1313 - * End the rendering.
1314 - *
1315 - * @param array $metas Meta Data.
1316 - * @param array $settings Widget settings.
1317 - * @param array $products Array of products being rendered.
1318 - *
1319 - * @return string
1320 - */
1321 - public function render_end( $metas, $settings, $products ) {
1322 - ob_start();
1323 -
1324 - /**
1325 - * After render row hook.
1326 - */
1327 - do_action( 'rtsb/elementor/render/after_row', $metas, $settings, $products );
1328 -
1329 - return ob_get_clean();
1330 - }
1331 -
1332 - /**
1333 - * Add render attribute.
1334 - *
1335 - * @param array|string $element The HTML element.
1336 - * @param array|string $key Optional. Attribute key. Default is null.
1337 - * @param array|string $value Optional. Attribute value. Default is null.
1338 - * @param bool $overwrite Optional. Whether to overwrite existing.
1339 - *
1340 - * @return self
1341 - */
1342 - public function add_attribute( $element, $key = null, $value = null, $overwrite = false ) {
1343 - if ( is_array( $element ) ) {
1344 - foreach ( $element as $element_key => $attributes ) {
1345 - $this->add_attribute( $element_key, $attributes, null, $overwrite );
1346 - }
1347 -
1348 - return $this;
1349 - }
1350 -
1351 - if ( is_array( $key ) ) {
1352 - foreach ( $key as $attribute_key => $attributes ) {
1353 - $this->add_attribute( $element, $attribute_key, $attributes, $overwrite );
1354 - }
1355 -
1356 - return $this;
1357 - }
1358 -
1359 - if ( empty( $this->attributes[ $element ][ $key ] ) ) {
1360 - $this->attributes[ $element ][ $key ] = [];
1361 - }
1362 -
1363 - settype( $value, 'array' );
1364 -
1365 - if ( $overwrite ) {
1366 - $this->attributes[ $element ][ $key ] = $value;
1367 - } else {
1368 - $this->attributes[ $element ][ $key ] = array_merge( $this->attributes[ $element ][ $key ], $value );
1369 - }
1370 -
1371 - return $this;
1372 - }
1373 -
1374 - /**
1375 - * Get render attribute string.
1376 - *
1377 - * @param string $element The element.
1378 - *
1379 - * @return string
1380 - */
1381 - public function get_attribute_string( $element ) {
1382 - if ( empty( $this->attributes[ $element ] ) ) {
1383 - return '';
1384 - }
1385 -
1386 - return Utils::render_html_attributes( $this->attributes[ $element ] );
1387 - }
1388 -}
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 RadiusTheme\SB\Helpers\BuilderFns;
13 +use WP_Query;
14 +use Elementor\Icons_Manager;
15 +use RadiusTheme\SB\Helpers\Fns;
16 +use RadiusTheme\SB\Models\QueryArgs;
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 bool $fullwidth Fullwidth check.
70 + *
71 + * @return string
72 + */
73 + public function container( $content, $settings, $class = '', $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 +
79 + $metas = RenderHelpers::meta_dataset( $settings );
80 +
81 + $layout = $metas['layout'];
82 + $animation = $metas['hover_animation'];
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 ( ! in_array( $layout, array_keys( Fns::free_layouts() ), true ) ) {
101 + $layout = RenderHelpers::set_default_layout( $layout );
102 + }
103 +
104 + $d_col = 0 === $metas['d_cols'] ? RenderHelpers::default_columns( $layout ) : $metas['d_cols'];
105 + $t_col = 0 === $metas['t_cols'] ? 2 : $metas['t_cols'];
106 + $m_col = 0 === $metas['m_cols'] ? 1 : $metas['m_cols'];
107 +
108 + if ( $fullwidth ) {
109 + $d_col = 12;
110 + $t_col = 12;
111 + $m_col = 12;
112 + }
113 +
114 + $pagination_attr = ( $is_carousel || $is_cat ? '' : RenderHelpers::pagination_data( $settings ) );
115 +
116 + if ( ! in_array( 'clear-btn', $metas['visibility'], true ) ) {
117 + $container_class .= ' no-clear-btn';
118 + }
119 +
120 + $container_attr .= ' data-layout="' . esc_attr( $layout ) . '" data-desktop-col="' . absint( $d_col ) . '" data-tab-col="' . absint( $t_col ) . '" data-mobile-col="' . absint( $m_col ) . '" ' . $pagination_attr;
121 + $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'] );
122 +
123 + if ( $metas['show_overlay'] ) {
124 + $container_class .= ' has-overlay';
125 + }
126 +
127 + $this->html = '<div class="' . esc_attr( $container_class ) . '" id="' . esc_attr( $layout_id ) . '" ' . $container_attr . '>';
128 +
129 + if ( ! empty( $settings['query_products'] ) && count( $settings['query_products'] ) && 'yes' === $settings['show_section_title'] ) {
130 + $this->html .= '<div class="rtsb-section-title-wrapper">';
131 + $this->html .= '<' . esc_attr( $settings['section_title_tag'] ) . ' class="rtsb-section-title" >';
132 + $this->html .= esc_html( $settings['section_title_text'] );
133 + $this->html .= '</' . esc_attr( $settings['section_title_tag'] ) . '>';
134 + $this->html .= '</div>';
135 + }
136 +
137 + $this->html .= $content;
138 +
139 + $this->html .= '</div><!-- .rtsb-elementor-container -->';
140 +
141 + // Action button icon reset.
142 + $this->action_button_icon_set_default();
143 +
144 + $script_generator = [];
145 + $script_generator['layout'] = $layout_id;
146 + $script_generator['rand'] = absint( wp_rand() );
147 + $script_generator['isCarousel'] = $is_carousel;
148 +
149 + add_action(
150 + 'wp_footer',
151 + static function () use ( $script_generator ) {
152 + RenderHelpers::register_scripts( $script_generator );
153 + }
154 + );
155 +
156 + return $this->html;
157 + }
158 +
159 + /**
160 + * Row Wrapper HTML.
161 + *
162 + * @param string $content The content.
163 + * @param array $settings Settings.
164 + *
165 + * @return string
166 + */
167 + public function row( $content, $settings ) {
168 + $masonry_class = null;
169 + $loader_class = ' rtsb-pre-loader';
170 +
171 + $layout = $settings['layout'];
172 + $grid_type = $settings['grid_type'];
173 + $is_carousel = preg_match( '/slider/', $layout );
174 +
175 + if ( 'even' === $grid_type ) {
176 + $masonry_class = ' rtsb-even';
177 + } elseif ( 'masonry' === $grid_type ) {
178 + $masonry_class = ' rtsb-masonry';
179 + }
180 +
181 + if ( ! rtsb()->has_pro() || $is_carousel ) {
182 + $masonry_class = ' rtsb-even';
183 + }
184 +
185 + $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 );
186 + $row_start = '<div data-title="' . esc_html__( 'Loading ...', 'shopbuilder' ) . '" class="' . $row_start_class . '">';
187 + $this->html = apply_filters( 'rtsb/custom/layout/row/start', $row_start, $row_start_class );
188 +
189 + if ( $is_carousel ) {
190 + $slider_data = RenderHelpers::slider_data( $settings );
191 +
192 + $this->html .= '<div class="rtsb-col-xs-12 ' . esc_attr( $slider_data['class'] ) . '" ' . $slider_data['data'] . '>';
193 + $this->html .= '<div class="swiper-wrapper">';
194 + }
195 +
196 + $this->html .= $content;
197 +
198 + if ( $is_carousel ) {
199 + $this->html .= '</div><!-- .swiper-wrapper -->';
200 +
201 + $left_icon = $settings['left_arrow_icon'];
202 + $right_icon = $settings['right_arrow_icon'];
203 +
204 + if ( ! empty( $settings['slider_nav'] ) ) {
205 + $this->html .=
206 + '<div class="swiper-nav">
207 + <div class="swiper-arrow swiper-button-next">
208 + ' . Fns::icons_manager( $right_icon ) . '
209 + </div>
210 + <div class="swiper-arrow swiper-button-prev">
211 + ' . Fns::icons_manager( $left_icon ) . '
212 + </div>
213 + </div>';
214 + }
215 +
216 + $this->html .= ! empty( $settings['slider_dot'] ) ? '<div class="swiper-pagination rtsb-pos-s"></div>' : '';
217 +
218 + $this->html .= '</div><!-- .rtsb-carousel-slider -->';
219 + }
220 +
221 + $this->html .= RenderHelpers::pre_loader( $layout );
222 +
223 + $row_end = '</div><!-- .rtsb-row -->';
224 +
225 + $this->html .= apply_filters( 'rtsb/custom/layout/row/end', $row_end );
226 +
227 + return $this->html;
228 + }
229 +
230 + /**
231 + * Product loop.
232 + *
233 + * @param object $query The query.
234 + * @param array $settings Settings.
235 + * @param string $template Template.
236 + *
237 + * @return string|null
238 + */
239 + public function product_loop( $query, $settings, $template ) {
240 + $html = null;
241 +
242 + if ( empty( $query ) ) {
243 + return null;
244 + }
245 +
246 + while ( $query->have_posts() ) {
247 + $query->the_post();
248 +
249 + // Loop arg.
250 + $arg = $this->arg_dataset( $settings, get_the_ID(), $settings['lazy_load'] );
251 +
252 + // Get template.
253 + $html .= Fns::load_template( $template . $settings['layout'], $arg, true );
254 + }
255 +
256 + return $html;
257 + }
258 +
259 + /**
260 + * Product loop.
261 + *
262 + * @param object $query The query.
263 + * @param array $settings Settings.
264 + * @param string $template Template.
265 + * @param bool $is_single Single category.
266 + *
267 + * @return string|null
268 + */
269 + public function category_loop( $query, $settings, $template, $is_single = false ) {
270 + $html = null;
271 + $term_link = null;
272 +
273 + if ( $is_single ) {
274 + // Loop arg.
275 + $arg = $this->cat_arg_dataset( $settings, $query, true );
276 +
277 + // Get template.
278 + $html .= Fns::load_template( $template . $settings['layout'], $arg, true );
279 + } else {
280 + foreach ( $query as $term ) {
281 + // Loop arg.
282 + $arg = $this->cat_arg_dataset( $settings, $term );
283 +
284 + // Get template.
285 + $html .= Fns::load_template( $template . $settings['layout'], $arg, true );
286 + }
287 + }
288 +
289 + return $html;
290 + }
291 +
292 + /**
293 + * Render Product View.
294 + *
295 + * @param string $template Template name.
296 + * @param array $settings Control settings.
297 + *
298 + * @return string
299 + */
300 + public function product_view( $template, $settings ) {
301 + $this->get_settings = $settings;
302 +
303 + $metas = RenderHelpers::meta_dataset( $settings );
304 + $is_carousel = preg_match( '/slider/', $metas['layout'] );
305 + $pagination = $metas['pagination'];
306 +
307 + // Query Args.
308 + $args = ( new QueryArgs() )->buildArgs( $metas, 'product', $is_carousel );
309 +
310 + // Query.
311 + $product_query = new WP_Query( $args );
312 +
313 + if ( $product_query->have_posts() ) {
314 + // Row.
315 + $this->row( $this->product_loop( $product_query, $metas, $template ), $metas );
316 +
317 + // Pagination.
318 + if ( $pagination ) {
319 + $this->html .= RenderHelpers::render_pagination(
320 + $product_query,
321 + $metas,
322 + $settings['posts_limit'],
323 + $settings['pagination_per_page']
324 + );
325 + }
326 + } else {
327 + $this->html .= '<p>' . esc_html__( 'No products found', 'shopbuilder' ) . '</p>';
328 + }
329 +
330 + wp_reset_postdata();
331 +
332 + // Container.
333 + $this->container( $this->html, $settings, 'rtsb-products-container', $is_carousel );
334 +
335 + return $this->html;
336 + }
337 +
338 +
339 + /**
340 + * Render Product View.
341 + *
342 + * @param string $template Template name.
343 + * @param array $settings Control settings.
344 + *
345 + * @return string
346 + */
347 + public function wc_loop_for_product_view( $template, $settings ) {
348 + global $wp_query, $post;
349 +
350 + $this->get_settings = $settings;
351 +
352 + $metas = RenderHelpers::meta_dataset( $settings );
353 + $pagination = $metas['pagination'];
354 +
355 + $page_type = BuilderFns::builder_type( get_the_ID() );
356 + $is_preview = BuilderFns::is_builder_preview() && array_key_exists( $page_type, BuilderFns::builder_page_types() );
357 + $posts_per_page = wc_get_default_products_per_row() * wc_get_default_product_rows_per_page();
358 +
359 + if ( $is_preview ) {
360 + $main_query = clone $wp_query;
361 + $main_post = clone $post;
362 +
363 + $ordering = ( new \WC_Query() )->get_catalog_ordering_args();
364 + $wp_query_args = [
365 + 'post_type' => 'product',
366 + 'posts_per_page' => $posts_per_page,
367 + ];
368 +
369 + if ( ! empty( $ordering['orderby'] ) ) {
370 + $wp_query_args['orderby'] = $ordering['orderby'];
371 + }
372 +
373 + if ( ! empty( $ordering['order'] ) ) {
374 + $wp_query_args['order'] = $ordering['order'];
375 + }
376 +
377 + $wp_query = new \WP_Query( $wp_query_args ); // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited
378 + wc_set_loop_prop( 'total', $wp_query->found_posts );
379 + wc_set_loop_prop( 'total_pages', $wp_query->max_num_pages );
380 + }
381 +
382 + // column_per_row.
383 + if ( woocommerce_product_loop() ) {
384 + if ( wc_get_loop_prop( 'total' ) ) {
385 + // Row.
386 + $this->row( $this->product_loop( $wp_query, $metas, $template ), $metas );
387 + }
388 +
389 + // Pagination.
390 + if ( $pagination ) {
391 + $this->html .= RenderHelpers::render_pagination(
392 + $wp_query,
393 + $metas,
394 + wc_get_loop_prop( 'total' ),
395 + $posts_per_page
396 + );
397 + }
398 + } else {
399 + $this->html .= '<p>' . esc_html__( 'No products found', 'shopbuilder' ) . '</p>';
400 + }
401 +
402 + if ( $is_preview ) {
403 + $wp_query = $main_query;
404 + $post = $main_post;
405 +
406 + wp_reset_query();
407 + wp_reset_postdata();
408 + }
409 +
410 + // Container.
411 + $this->container( $this->html, $settings, 'rtsb-products-container' );
412 +
413 + return $this->html;
414 + }
415 +
416 + /**
417 + * Render Product View.
418 + *
419 + * @param string $template Template name.
420 + * @param array $settings Control settings.
421 + *
422 + * @return string
423 + */
424 + public function setup_loop_for_product_view( $template, $settings ) {
425 + if ( empty( $settings['query_products'] ) ) {
426 + return $this->html;
427 + }
428 +
429 + $html = null;
430 +
431 + $metas = RenderHelpers::meta_dataset( $settings );
432 +
433 + foreach ( $settings['query_products'] as $_product ) {
434 + $post_object = get_post( $_product->get_id() );
435 +
436 + setup_postdata( $GLOBALS['post'] =& $post_object ); // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited, Squiz.PHP.DisallowMultipleAssignments.Found
437 +
438 + // Loop arg.
439 + $arg = $this->arg_dataset( $metas, $_product->get_id() );
440 + // Get template.
441 + $html .= Fns::load_template( $template . $settings['layout'], $arg, true );
442 +
443 + $this->row( $html, $metas );
444 + }
445 +
446 + // Container.
447 + $this->container( $this->html, $settings, 'rtsb-products-container' );
448 +
449 + wp_reset_postdata();
450 +
451 + return $this->html;
452 +
453 + }
454 + /**
455 + * Render Category View.
456 + *
457 + * @param string $template Template name.
458 + * @param array $settings Control settings.
459 + * @param bool $is_single Single category.
460 + *
461 + * @return string
462 + */
463 + public function category_view( $template, $settings, $is_single = false ) {
464 + $this->get_settings = $settings;
465 +
466 + $metas = RenderHelpers::meta_dataset( $settings );
467 + $taxonomy = $metas['category_source'];
468 + $term = $metas['category_term'];
469 +
470 + // Query.
471 + if ( $is_single ) {
472 + if ( empty( $term ) ) {
473 + return '<p>' . esc_html__( 'Please select a category.', 'shopbuilder' ) . '</p>';
474 + }
475 +
476 + $category_query = get_term( $term, $taxonomy );
477 + } else {
478 + // Query Args.
479 + $args = ( new QueryArgs() )->buildArgs( $metas, 'category' );
480 +
481 + $category_query = get_terms( $args );
482 + }
483 +
484 + if ( ! empty( $category_query ) ) {
485 + // Row.
486 + $this->row( $this->category_loop( $category_query, $metas, $template, $is_single ), $metas );
487 + } else {
488 + $this->html .= '<p>' . esc_html__( 'No categories found', 'shopbuilder' ) . '</p>';
489 + }
490 +
491 + // Container.
492 + $this->container( $this->html, $settings, 'rtsb-categories-container', $is_single );
493 +
494 + return $this->html;
495 + }
496 +
497 + /**
498 + * Render Category View.
499 + *
500 + * @param string $template Template name.
501 + * @param array $settings Control settings.
502 + *
503 + * @return string
504 + */
505 + public function social_share_view( $template, $settings ) {
506 + $this->get_settings = $settings;
507 + $share_items = [];
508 +
509 + foreach ( $settings['share_platforms'] as $platform ) {
510 + $share_items[] = [
511 + 'share_items' => $platform['share_items'],
512 + 'share_text' => $platform['share_text'],
513 + ];
514 + }
515 +
516 + if ( ! empty( $share_items ) && is_array( $share_items ) ) {
517 + $arg['p_id'] = get_the_ID();
518 + $arg['share_items'] = $share_items;
519 + $arg['preset'] = $settings['layout'];
520 + $arg['show_icon'] = $settings['show_share_icon'];
521 + $arg['raw_settings'] = $this->get_settings_for_display();
522 + $this->html = Fns::load_template( $template, $arg, true );
523 + } else {
524 + $this->html = '<p>' . esc_html__( 'Please select a social sharing platform.', 'shopbuilder' ) . '</p>';
525 + }
526 +
527 + return $this->html;
528 + }
529 +
530 + /**
531 + * Builds an array with meta values.
532 + *
533 + * @param array $meta Meta values.
534 + * @param int $post_id Post ID.
535 + * @param bool $lazy_load Lazy Load.
536 + * @return array
537 + */
538 + public function arg_dataset( array $meta, int $post_id, bool $lazy_load = false ) {
539 + if ( ( empty( $meta ) && ! $post_id ) || ! in_array( get_post_type( $post_id ),['product_variation','product'] ) ) {
540 + return [];
541 + }
542 + global $post;
543 +
544 + $arg = [];
545 + $_product = wc_get_product( $post_id );
546 + $p_type = $_product->get_type();
547 +
548 + $arg['class'] = null;
549 + $arg['grid'] = null;
550 + $arg['anchor_class'] = null;
551 + $arg['hover_img_html'] = null;
552 + $arg['s_link'] = [];
553 + $arg['add_to_cart'] = '';
554 + $arg['p_id'] = $post_id;
555 + $arg['p_link'] = get_permalink();
556 + $arg['p_sale'] = '';
557 + $arg['raw_settings'] = $this->get_settings_for_display();
558 + $cart_icon_html = '';
559 +
560 + $layout = $meta['layout'];
561 +
562 + $arg['target'] = '_self';
563 + $arg['f_img'] = $meta['f_img'];
564 + $arg['items'] = $meta['visibility'];
565 + $arg['title_tag'] = $meta['title_tag'];
566 + $arg['title_class'] = 'product-title rtsb-text-limit limit-' . $meta['title_limit'] . ( ! $meta['title_link'] ? ' no-link' : '' );
567 + $arg['title'] = Fns::text_truncation( get_the_title(), $meta['title_limit_custom'] );
568 + $arg['excerpt_limit'] = $meta['excerpt_limit'];
569 + $arg['excerpt'] = wpautop( Fns::text_truncation( do_shortcode( $post->post_excerpt ), $meta['excerpt_limit_custom'] ) );
570 + $arg['title_link'] = $meta['title_link'];
571 + $arg['image_link'] = $meta['image_link'];
572 + $arg['out_of_stock'] = $meta['out_of_stock_badge_text'];
573 + $arg['action_btn_preset'] = $meta['btn_preset'];
574 + $arg['action_btn_position'] = $meta['btn_position'];
575 +
576 + $is_list = preg_match( '/list/', $layout );
577 + $is_carousel = preg_match( '/slider/', $layout );
578 +
579 + $d_col = 0 === $meta['d_cols'] ? RenderHelpers::default_columns( $layout ) : $meta['d_cols'];
580 + $t_col = 0 === $meta['t_cols'] ? 2 : $meta['t_cols'];
581 + $m_col = 0 === $meta['m_cols'] ? 1 : $meta['m_cols'];
582 +
583 + $d_col = 5 === $d_col ? '24' : round( 12 / $d_col );
584 + $t_col = 5 === $t_col ? '24' : round( 12 / $t_col );
585 + $m_col = 5 === $m_col ? '24' : round( 12 / $m_col );
586 +
587 + if ( ! $is_carousel ) {
588 + $arg['grid'] .= 'rtsb-col-md-' . $d_col . ' rtsb-col-sm-' . $t_col . ' rtsb-col-xs-' . $m_col . ' ';
589 + $arg['class'] .= ' even-grid-item ';
590 + } else {
591 + $arg['grid'] .= 'rtsb-slide-item swiper-slide ';
592 + }
593 +
594 + $arg['class'] .= 'rtsb-product';
595 +
596 + if ( $is_list ) {
597 + $arg['class'] .= ' rtsb-product-list';
598 + }
599 +
600 + $arg['class'] .= ' animated fadeIn';
601 +
602 + if ( in_array( 'badges', $meta['visibility'], true ) ) {
603 + $arg['p_sale'] = Fns::get_sale_badge(
604 + $meta['sale_badge_type'],
605 + $meta['sale_badge_text'],
606 + $meta['out_of_stock_badge_text']
607 + );
608 + }
609 +
610 + $arg['badge_class'] = RenderHelpers::badge_class( $meta['badge_preset'] );
611 +
612 + if ( ! $meta['show_cart_text'] ) {
613 + $meta['add_to_cart_text'] = '';
614 + }
615 +
616 + if ( in_array( 'add_to_cart', $meta['visibility'], true ) ) {
617 + if ( ! empty( $meta['add_to_cart_icon'] ) ) {
618 + $cart_icon_html .= Fns::icons_manager( $meta['add_to_cart_icon'], 'cart-icon' );
619 + }
620 +
621 + if ( ! empty( $meta['add_to_cart_success_icon'] ) ) {
622 + $cart_icon_html .= Fns::icons_manager( $meta['add_to_cart_success_icon'], 'cart-success-icon' );
623 + }
624 +
625 + $cart_icon = '<span class="icon">' . $cart_icon_html . '</span>';
626 +
627 + if ( $_product->is_purchasable() ) {
628 + if ( $_product->is_in_stock() ) {
629 + // TODO:: Replace add to cart with WC hooks
630 + $arg['add_to_cart'] = $this->render_add_to_cart_button(
631 + get_permalink(),
632 + $post_id,
633 + $p_type,
634 + $meta['add_to_cart_text'],
635 + $cart_icon,
636 + $meta['add_to_cart_alignment']
637 + );
638 + }
639 + }
640 + }
641 +
642 + if ( in_array( 'quick_view', $meta['visibility'], true ) ) {
643 + add_filter( 'rtsb/module/quick_view/button_params', [ $this, 'button_classes' ] );
644 + add_filter( 'rtsb/module/quick_view/icon_html', [ $this, 'quick_view_icon' ] );
645 + }
646 +
647 + if ( in_array( 'compare', $meta['visibility'], true ) ) {
648 + add_filter( 'rtsb/module/compare/button_params', [ $this, 'button_classes' ] );
649 + add_filter( 'rtsb/module/compare/icon_html', [ $this, 'compare_icon' ] );
650 + }
651 +
652 + if ( in_array( 'wishlist', $meta['visibility'], true ) ) {
653 + add_filter( 'rtsb/module/wishlist/button_params', [ $this, 'button_classes' ] );
654 + add_filter( 'rtsb/module/wishlist/icon_html', [ $this, 'wishlist_icon' ] );
655 + }
656 +
657 + $arg['img_html'] = $meta['f_img'] ? Fns::get_product_image_html(
658 + 'product',
659 + $post_id,
660 + $meta['f_img_size'],
661 + $meta['default_img_id'],
662 + $meta['custom_img_size'],
663 + $lazy_load
664 + ) : null;
665 +
666 + $gallery_ids = $_product->get_gallery_image_ids();
667 +
668 + if ( $meta['hover_img'] && ! empty( $gallery_ids ) ) {
669 + $arg['class'] .= ' rtsb-double-img';
670 + $arg['hover_img_html'] = Fns::get_product_image_html(
671 + 'product',
672 + $gallery_ids[0],
673 + $meta['f_img_size'],
674 + null,
675 + $meta['custom_img_size'],
676 + $lazy_load,
677 + true
678 + );
679 + }
680 +
681 + $arg['hover_btn_text'] = $meta['hover_btn_text'];
682 +
683 + if ( $meta['show_hover_btn_icon'] && ! empty( $meta['hover_btn_icon'] ) ) {
684 + $arg['hover_btn_icon'] = '<span class="icon">' . Fns::icons_manager( $meta['hover_btn_icon'], 'hover-btn-icon' ) . '</span>';
685 + }
686 +
687 + return $arg;
688 + }
689 +
690 + /**
691 + * Builds an array with meta values.
692 + *
693 + * @param array $meta Meta values.
694 + * @param Object $query Category object.
695 + * @param bool $fullwidth Fullwidth check.
696 + * @param bool $lazy_load Lazy Load.
697 + * @return array
698 + */
699 + public function cat_arg_dataset( $meta, $query = null, $fullwidth = false, $lazy_load = false ) {
700 + if ( empty( $meta ) ) {
701 + return [];
702 + }
703 +
704 + $arg = [];
705 +
706 + $arg['class'] = null;
707 + $arg['grid'] = null;
708 + $arg['anchor_class'] = null;
709 + $arg['p_sale'] = null;
710 + $arg['count'] = max( $query->count, 0 );
711 + $arg['count_position'] = $meta['count_position'];
712 + $arg['excerpt_position'] = $meta['cat_excerpt_position'];
713 + $arg['cat_link'] = get_term_link( $query );
714 + $arg['target'] = '_self';
715 + $arg['raw_settings'] = $this->get_settings_for_display();
716 +
717 + if ( ! empty( $meta['custom_link']['url'] ) ) {
718 + $arg['cat_link'] = $meta['custom_link']['url'];
719 + $arg['target'] = $meta['custom_link']['is_external'] ? '_blank' : '_self';
720 + }
721 +
722 + $title = $query->name;
723 + $excerpt = $query->description;
724 +
725 + if ( in_array( 'badges', $meta['visibility'], true ) ) {
726 + $arg['p_sale'] = $meta['custom_badge_text'];
727 + }
728 +
729 + $arg['badge_class'] = RenderHelpers::badge_class( $meta['badge_preset'] );
730 +
731 + if ( $arg['count'] >= 0 ) {
732 + $prefix = ! empty( $meta['before_count'] ) ? $meta['before_count'] : '';
733 + $suffix = ! empty( $meta['after_count'] ) ? $meta['after_count'] : '';
734 +
735 + $arg['count'] = $prefix . $arg['count'] . $suffix;
736 + }
737 +
738 + if ( $meta['show_custom_title'] && ! empty( $meta['cat_custom_title'] ) ) {
739 + $title = $meta['cat_custom_title'];
740 + }
741 +
742 + if ( $meta['show_custom_excerpt'] && ! empty( $meta['cat_custom_excerpt'] ) ) {
743 + $excerpt = $meta['cat_custom_excerpt'];
744 + }
745 +
746 + $layout = $meta['layout'];
747 +
748 + $arg['c_img'] = $meta['c_img'];
749 + $arg['items'] = $meta['visibility'];
750 + $arg['title_tag'] = $meta['title_tag'];
751 + $arg['title_class'] = 'category-title rtsb-text-limit limit-' . $meta['title_limit'] . ( ! $meta['title_link'] ? ' no-link' : '' );
752 + $arg['title'] = Fns::text_truncation( $title, $meta['title_limit_custom'] );
753 + $arg['excerpt_limit'] = $meta['excerpt_limit'];
754 + $arg['excerpt'] = wpautop( Fns::text_truncation( $excerpt, $meta['excerpt_limit_custom'] ) );
755 + $arg['title_link'] = $meta['title_link'];
756 + $arg['image_link'] = $meta['image_link'];
757 +
758 + $d_col = 0 === $meta['d_cols'] ? RenderHelpers::default_columns( $layout ) : absint( $meta['d_cols'] );
759 + $t_col = 0 === $meta['t_cols'] ? 2 : absint( $meta['t_cols'] );
760 + $m_col = 0 === $meta['m_cols'] ? 1 : absint( $meta['m_cols'] );
761 +
762 + $d_col = 5 === $d_col ? '24' : round( 12 / $d_col );
763 + $t_col = 5 === $t_col ? '24' : round( 12 / $t_col );
764 + $m_col = 5 === $m_col ? '24' : round( 12 / $m_col );
765 +
766 + if ( ! $fullwidth ) {
767 + $arg['grid'] .= 'rtsb-col-md-' . $d_col . ' rtsb-col-sm-' . $t_col . ' rtsb-col-xs-' . $m_col . ' ';
768 + $arg['class'] .= ' even-grid-item ';
769 + } else {
770 + $arg['grid'] .= 'rtsb-col-xs-12 ';
771 + }
772 +
773 + $arg['class'] .= 'rtsb-category-grid';
774 +
775 + $arg['img_html'] = $meta['c_img'] ? Fns::get_product_image_html(
776 + 'category',
777 + $query->term_id,
778 + $meta['f_img_size'],
779 + $meta['default_img_id'],
780 + $meta['custom_img_size'],
781 + $lazy_load
782 + ) : null;
783 +
784 + if ( $meta['show_custom_image'] && ! empty( $meta['custom_image'] ) ) {
785 + $arg['img_html'] = Fns::get_product_image_html(
786 + 'custom',
787 + null,
788 + $meta['f_img_size'],
789 + $meta['custom_image'],
790 + $meta['custom_img_size'],
791 + $lazy_load
792 + );
793 + }
794 +
795 + $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' : '' );
796 +
797 + return $arg;
798 + }
799 +
800 + /**
801 + * Renders add to cart button.
802 + *
803 + * @param string $link Product link.
804 + * @param int $id Product ID.
805 + * @param string $type Product type.
806 + * @param string $text Custom text.
807 + * @param string $icon_html Custom icon.
808 + * @param string $alignment Icon alignment.
809 + * @return string
810 + */
811 + public function render_add_to_cart_button( $link, $id, $type, $text, $icon_html, $alignment ) {
812 + $content = null;
813 + $tooltip_attr = '';
814 +
815 + if ( empty( $text ) ) {
816 + $tooltip_attr = ' title="' . esc_attr__( 'Add to Cart', 'shopbuilder' ) . '"';
817 +
818 + if ( 'variable' === $type ) {
819 + $tooltip_attr = ' title="' . esc_attr__( 'Select Options', 'shopbuilder' ) . '"';
820 + }
821 + }
822 +
823 + if ( 'variable' === $type ) {
824 + $content .= sprintf(
825 + '<div class="rtsb-wc-add-to-cart-wrap">
826 + <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>
827 + </div>',
828 + esc_url( $link ),
829 + esc_html__( 'Select Options', 'shopbuilder' ),
830 + absint( $id ),
831 + esc_attr( $alignment ),
832 + empty( $text ) ? 'no-text' : 'has-text',
833 + $tooltip_attr,
834 + $icon_html,
835 + );
836 +
837 + return $content;
838 + }
839 +
840 + $content .= sprintf(
841 + '<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">%5$s</span><span></span></a>',
842 + esc_url( $link ),
843 + absint( $id ),
844 + esc_attr( $type ),
845 + $icon_html,
846 + esc_html( $text ),
847 + esc_attr( $alignment ),
848 + empty( $text ) ? 'no-text' : 'has-text',
849 + $tooltip_attr
850 + );
851 +
852 + return $content;
853 + }
854 +
855 + /**
856 + * Button classes.
857 + *
858 + * @param array $params Button params.
859 + * @return array
860 + */
861 + public function button_classes( $params ) {
862 + $params['classes'] = array_merge( $params['classes'], [ 'rtsb-action-btn', 'tipsy' ] );
863 +
864 + return $params;
865 + }
866 +}