# shopbuilder/1.0.0/app/Elementor/Render/Render.php

ShopBuilder – WooCommerce Builder For Elementor, version 1.0.0. 858 lines.

- Page: https://pluginprobe.com/plugins/shopbuilder/1.0.0/code/app/Elementor/Render/Render.php
- Raw: https://pluginprobe.com/plugins/shopbuilder/1.0.0/raw/app/Elementor/Render/Render.php
- Modified: 2023-03-09T09:36:06+00:00

Line numbers below start at 1. Link to a line or a range by appending a fragment to the
page URL, for example `https://pluginprobe.com/plugins/shopbuilder/1.0.0/code/app/Elementor/Render/Render.php#L10-L20`.

```php
<?php
/**
 * Elementor Render Class.
 *
 * This class contains render logics & output.
 *
 * @package RadiusTheme\SB
 */

namespace RadiusTheme\SB\Elementor\Render;

use RadiusTheme\SB\Helpers\BuilderFns;
use WP_Query;
use Elementor\Icons_Manager;
use RadiusTheme\SB\Helpers\Fns;
use RadiusTheme\SB\Models\QueryArgs;
use RadiusTheme\SB\Traits\SingletonTrait;
use RadiusTheme\SB\Traits\ActionBtnTraits;
use RadiusTheme\SB\Elementor\Helper\RenderHelpers;

// Do not allow directly accessing this file.
if ( ! defined( 'ABSPATH' ) ) {
	exit( 'This script cannot be accessed directly.' );
}

/**
 * Elementor Render Class.
 */
class Render {
	/**
	 * Singleton Trait.
	 */
	use SingletonTrait;

	/**
	 * Action button trait.
	 */
	use ActionBtnTraits;

	/**
	 * HTML.
	 *
	 * @var string
	 */
	private $html = null;

	/**
	 * Settings array
	 *
	 * @var array
	 */
	public $get_settings;

	/**
	 * Get elementor settings.
	 *
	 * @return array
	 */
	public function get_settings_for_display() {
		return $this->get_settings;
	}

	/**
	 * Container Wrapper HTML.
	 *
	 * @param string $content The content.
	 * @param array  $settings Settings.
	 * @param string $class Class.
	 * @param bool   $fullwidth Fullwidth check.
	 *
	 * @return string
	 */
	public function container( $content, $settings, $class = '', $fullwidth = false ) {
		$layout_id       = 'rtsb-container-' . absint( wp_rand() );
		$container_attr  = null;
		$cart_txt_class  = '';
		$container_class = 'rtsb-elementor-container products rtsb-pos-r ' . esc_attr( $class );

		$metas     = RenderHelpers::meta_dataset( $settings );

		$layout    = $metas['layout'];
		$animation = $metas['hover_animation'];

		$is_cat      = preg_match( '/category/', $layout );
		$is_carousel = preg_match( '/slider/', $layout );

		if ( ! $is_cat ) {
			$cart_txt_class = $metas['show_cart_text'] ? ' has-cart-text' : ' no-cart-text';
		}

		if ( $is_carousel ) {
			$fullwidth = true;
		}

		$badge_class = [
			'position'  => $metas['badge_position'],
			'alignment' => $metas['badge_alignment'],
		];

		if ( ! in_array( $layout, array_keys( Fns::free_layouts() ), true ) ) {
			$layout = RenderHelpers::set_default_layout( $layout );
		}

		$d_col = 0 === $metas['d_cols'] ? RenderHelpers::default_columns( $layout ) : $metas['d_cols'];
		$t_col = 0 === $metas['t_cols'] ? 2 : $metas['t_cols'];
		$m_col = 0 === $metas['m_cols'] ? 1 : $metas['m_cols'];

		if ( $fullwidth ) {
			$d_col = 12;
			$t_col = 12;
			$m_col = 12;
		}

		$pagination_attr = ( $is_carousel || $is_cat ? '' : RenderHelpers::pagination_data( $settings ) );

		if ( ! in_array( 'clear-btn', $metas['visibility'], true ) ) {
			$container_class .= ' no-clear-btn';
		}

		$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;
		$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'] );

		if ( $metas['show_overlay'] ) {
			$container_class .= ' has-overlay';
		}

		$this->html = '<div class="' . esc_attr( $container_class ) . '" id="' . esc_attr( $layout_id ) . '" ' . $container_attr . '>';

        if( ! empty( $settings['query_products'] ) && count( $settings['query_products'] ) && 'yes' === $settings['show_section_title'] ){
            $this->html .='<div class="rtsb-section-title-wrapper">';
            $this->html .='<'.esc_attr( $settings['section_title_tag']).' class="rtsb-section-title" >';
            $this->html .=esc_html($settings['section_title_text']);
            $this->html .='</'.esc_attr( $settings['section_title_tag']).'>';
            $this->html .='</div>';
        }

        $this->html .= $content;

		$this->html .= '</div><!-- .rtsb-elementor-container -->';

		// Action button icon reset.
		$this->action_button_icon_set_default();

		$script_generator               = [];
		$script_generator['layout']     = $layout_id;
		$script_generator['rand']       = absint( wp_rand() );
		$script_generator['isCarousel'] = $is_carousel;

		add_action(
			'wp_footer',
			static function () use ( $script_generator ) {
				RenderHelpers::register_scripts( $script_generator );
			}
		);

		return $this->html;
	}

	/**
	 * Row Wrapper HTML.
	 *
	 * @param string $content The content.
	 * @param array  $settings Settings.
	 *
	 * @return string
	 */
	public function row( $content, $settings ) {
		$masonry_class = null;
		$loader_class  = ' rtsb-pre-loader';

		$layout      = $settings['layout'];
		$grid_type   = $settings['grid_type'];
		$is_carousel = preg_match( '/slider/', $layout );

		if ( 'even' === $grid_type ) {
			$masonry_class = ' rtsb-even';
		} elseif ( 'masonry' === $grid_type ) {
			$masonry_class = ' rtsb-masonry';
		}

		if ( ! rtsb()->has_pro() || $is_carousel ) {
			$masonry_class = ' rtsb-even';
		}

		$this->html = '<div data-title="' . esc_html__( 'Loading ...', 'shopbuilder' ) . '" class="rtsb-row rtsb-content-loader element-loading ' . esc_attr( 'rtsb-'.$layout . $masonry_class . $loader_class ) . '">';

		if ( $is_carousel ) {
			$slider_data = RenderHelpers::slider_data( $settings );

			$this->html .= '<div class="rtsb-col-xs-12 ' . esc_attr( $slider_data['class'] ) . '" ' . $slider_data['data'] . '>';
			$this->html .= '<div class="swiper-wrapper">';
		}

		$this->html .= $content;

		if ( $is_carousel ) {
			$this->html .= '</div><!-- .swiper-wrapper -->';

			$left_icon  = $settings['left_arrow_icon'];
			$right_icon = $settings['right_arrow_icon'];

			if ( ! empty( $settings['slider_nav'] ) ) {
				$this->html .=
					'<div class="swiper-nav">
						<div class="swiper-arrow swiper-button-next">
							' . Fns::icons_manager( $right_icon ) . '
						</div>
						<div class="swiper-arrow swiper-button-prev">
							' . Fns::icons_manager( $left_icon ) . '
						</div>
					</div>';
			}

			$this->html .= ! empty( $settings['slider_dot'] ) ? '<div class="swiper-pagination rtsb-pos-s"></div>' : '';

			$this->html .= '</div><!-- .rtsb-carousel-slider -->';
		}

		$this->html .= RenderHelpers::pre_loader( $layout );

		$this->html .= '</div><!-- .rtsb-row -->';

		return $this->html;
	}

	/**
	 * Product loop.
	 *
	 * @param object $query The query.
	 * @param array  $settings Settings.
	 * @param string $template Template.
	 *
	 * @return string|null
	 */
	public function product_loop( $query, $settings, $template ) {
		$html = null;

		if ( empty( $query ) ) {
			return null;
		}

		while ( $query->have_posts() ) {
			$query->the_post();

			// Loop arg.
			$arg = $this->arg_dataset( $settings, get_the_ID(), $settings['lazy_load'] );

			// Get template.
			$html .= Fns::load_template( $template . $settings['layout'], $arg, true );
		}

		return $html;
	}

	/**
	 * Product loop.
	 *
	 * @param object $query The query.
	 * @param array  $settings Settings.
	 * @param string $template Template.
	 * @param bool   $is_single Single category.
	 *
	 * @return string|null
	 */
	public function category_loop( $query, $settings, $template, $is_single = false ) {
		$html      = null;
		$term_link = null;

		if ( $is_single ) {
			// Loop arg.
			$arg = $this->cat_arg_dataset( $settings, $query, true );

			// Get template.
			$html .= Fns::load_template( $template . $settings['layout'], $arg, true );
		} else {
			foreach ( $query as $term ) {
				// Loop arg.
				$arg = $this->cat_arg_dataset( $settings, $term );

				// Get template.
				$html .= Fns::load_template( $template . $settings['layout'], $arg, true );
			}
		}

		return $html;
	}

	/**
	 * Render Product View.
	 *
	 * @param string $template Template name.
	 * @param array  $settings Control settings.
	 *
	 * @return string
	 */
	public function product_view( $template, $settings ) {
		$this->get_settings = $settings;

		$metas       = RenderHelpers::meta_dataset( $settings );
		$is_carousel = preg_match( '/slider/', $metas['layout'] );
		$pagination  = $metas['pagination'];

		// Query Args.
		$args = ( new QueryArgs() )->buildArgs( $metas, 'product', $is_carousel );

		// Query.
		$product_query = new WP_Query( $args );

		if ( $product_query->have_posts() ) {
			// Row.
			$this->row( $this->product_loop( $product_query, $metas, $template ), $metas );

			// Pagination.
			if ( $pagination ) {
				$this->html .= RenderHelpers::render_pagination(
					$product_query,
					$metas,
					$settings['posts_limit'],
					$settings['pagination_per_page']
				);
			}
		} else {
			$this->html .= '<p>' . esc_html__( 'No products found', 'shopbuilder' ) . '</p>';
		}

		wp_reset_postdata();

		// Container.
		$this->container( $this->html, $settings, 'rtsb-products-container', $is_carousel );

		return $this->html;
	}


	/**
	 * Render Product View.
	 *
	 * @param string $template Template name.
	 * @param array  $settings Control settings.
	 *
	 * @return string
	 */
	public function wc_loop_for_product_view( $template, $settings ) {
		global $wp_query, $post;

		$this->get_settings = $settings;

		$metas      = RenderHelpers::meta_dataset( $settings );
		$pagination = $metas['pagination'];

		$page_type      = BuilderFns::builder_type( get_the_ID() );
		$is_preview     = BuilderFns::is_builder_preview() && array_key_exists( $page_type, BuilderFns::builder_page_types() );
		$posts_per_page = wc_get_default_products_per_row() * wc_get_default_product_rows_per_page();

		if ( $is_preview ) {
			$main_query = clone $wp_query;
			$main_post  = clone $post;

			$ordering      = ( new \WC_Query() )->get_catalog_ordering_args();
			$wp_query_args = [
				'post_type'      => 'product',
				'posts_per_page' => $posts_per_page,
			];

			if ( ! empty( $ordering['orderby'] ) ) {
				$wp_query_args['orderby'] = $ordering['orderby'];
			}

			if ( ! empty( $ordering['order'] ) ) {
				$wp_query_args['order'] = $ordering['order'];
			}

			$wp_query = new \WP_Query( $wp_query_args ); // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited
			wc_set_loop_prop( 'total', $wp_query->found_posts );
			wc_set_loop_prop( 'total_pages', $wp_query->max_num_pages );
		}

		// column_per_row.
		if ( woocommerce_product_loop() ) {
			if ( wc_get_loop_prop( 'total' ) ) {
				// Row.
				$this->row( $this->product_loop( $wp_query, $metas, $template ), $metas );
			}

			// Pagination.
			if ( $pagination ) {
				$this->html .= RenderHelpers::render_pagination(
					$wp_query,
					$metas,
					wc_get_loop_prop( 'total' ),
					$posts_per_page
				);
			}
		} else {
			$this->html .= '<p>' . esc_html__( 'No products found', 'shopbuilder' ) . '</p>';
		}

		if ( $is_preview ) {
			$wp_query = $main_query;
			$post     = $main_post;

			wp_reset_query();
			wp_reset_postdata();
		}

		// Container.
		$this->container( $this->html, $settings, 'rtsb-products-container' );

		return $this->html;
	}

	/**
	 * Render Product View.
	 *
	 * @param string $template Template name.
	 * @param array  $settings Control settings.
	 *
	 * @return string
	 */
	public function setup_loop_for_product_view( $template, $settings ) {
		if ( empty( $settings['query_products'] ) ) {
			return $this->html;
		}

		$html = null;

		$metas = RenderHelpers::meta_dataset( $settings );

		foreach ( $settings['query_products'] as $_product ) {
			$post_object = get_post( $_product->get_id() );

			setup_postdata( $GLOBALS['post'] =& $post_object ); // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited, Squiz.PHP.DisallowMultipleAssignments.Found

			// Loop arg.
			$arg = $this->arg_dataset( $metas, get_the_ID() );
			// Get template.
			$html .= Fns::load_template( $template . $settings['layout'], $arg, true );

			$this->row( $html, $metas );
		}

		// Container.
		$this->container( $this->html, $settings, 'rtsb-products-container' );

		wp_reset_postdata();

		return $this->html;

	}
	/**
	 * Render Category View.
	 *
	 * @param string $template Template name.
	 * @param array  $settings Control settings.
	 * @param bool   $is_single Single category.
	 *
	 * @return string
	 */
	public function category_view( $template, $settings, $is_single = false ) {
		$this->get_settings = $settings;

		$metas    = RenderHelpers::meta_dataset( $settings );
		$taxonomy = $metas['category_source'];
		$term     = $metas['category_term'];

		// Query.
		if ( $is_single ) {
			if ( empty( $term ) ) {
				return '<p>' . esc_html__( 'Please select a category.', 'shopbuilder' ) . '</p>';
			}

			$category_query = get_term( $term, $taxonomy );
		} else {
			// Query Args.
			$args = ( new QueryArgs() )->buildArgs( $metas, 'category' );

			$category_query = get_terms( $args );
		}

		if ( ! empty( $category_query ) ) {
			// Row.
			$this->row( $this->category_loop( $category_query, $metas, $template, $is_single ), $metas );
		} else {
			$this->html .= '<p>' . esc_html__( 'No categories found', 'shopbuilder' ) . '</p>';
		}

		// Container.
		$this->container( $this->html, $settings, 'rtsb-categories-container', $is_single );

		return $this->html;
	}

	/**
	 * Render Category View.
	 *
	 * @param string $template Template name.
	 * @param array  $settings Control settings.
	 *
	 * @return string
	 */
	public function social_share_view( $template, $settings ) {
		$share_items = [];

		foreach ( $settings['share_platforms'] as $platform ) {
			$share_items[] = [
				'share_items' => $platform['share_items'],
				'share_text'  => $platform['share_text'],
			];
		}

		if ( ! empty( $share_items ) && is_array( $share_items ) ) {
			$arg['p_id']        = get_the_ID();
			$arg['share_items'] = $share_items;
			$arg['preset']      = $settings['layout'];
			$arg['show_icon']   = $settings['show_share_icon'];
			$this->html = Fns::load_template( $template, $arg, true );
		} else {
			$this->html = '<p>' . esc_html__( 'Please select a social sharing platform.', 'shopbuilder' ) . '</p>';
		}

		return $this->html;
	}

	/**
	 * Builds an array with meta values.
	 *
	 * @param array $meta Meta values.
	 * @param int   $post_id Post ID.
	 * @param bool  $lazy_load Lazy Load.
	 * @return array
	 */
	public function arg_dataset( array $meta, int $post_id, bool $lazy_load = false ) {
		if ( empty( $meta ) && ! $post_id ) {
			return [];
		}

		$arg      = [];
		$_product = wc_get_product( $post_id );
		$p_type   = $_product->get_type();

		$arg['class']          = null;
		$arg['grid']           = null;
		$arg['anchor_class']   = null;
		$arg['hover_img_html'] = null;
		$arg['s_link']         = [];
		$arg['add_to_cart']    = '';
		$arg['p_id']           = $post_id;
		$arg['p_link']         = get_permalink();
		$arg['p_sale']         = '';
		$cart_icon_html        = '';

		$layout = $meta['layout'];

		$arg['target']              = '_self';
		$arg['f_img']               = $meta['f_img'];
		$arg['items']               = $meta['visibility'];
		$arg['title_tag']           = $meta['title_tag'];
		$arg['title_class']         = 'product-title rtsb-text-limit limit-' . $meta['title_limit'] . ( ! $meta['title_link'] ? ' no-link' : '' );
		$arg['title']               = Fns::text_truncation( get_the_title(), $meta['title_limit_custom'] );
		$arg['excerpt_limit']       = $meta['excerpt_limit'];
		$arg['excerpt']             = wpautop( Fns::text_truncation( get_the_excerpt(), $meta['excerpt_limit_custom'] ) );
		$arg['title_link']          = $meta['title_link'];
		$arg['image_link']          = $meta['image_link'];
		$arg['out_of_stock']        = $meta['out_of_stock_badge_text'];
		$arg['action_btn_preset']   = $meta['btn_preset'];
		$arg['action_btn_position'] = $meta['btn_position'];

		$is_list     = preg_match( '/list/', $layout );
		$is_carousel = preg_match( '/slider/', $layout );

		$d_col = 0 === $meta['d_cols'] ? RenderHelpers::default_columns( $layout ) : $meta['d_cols'];
		$t_col = 0 === $meta['t_cols'] ? 2 : $meta['t_cols'];
		$m_col = 0 === $meta['m_cols'] ? 1 : $meta['m_cols'];

		$d_col = 5 === $d_col ? '24' : round( 12 / $d_col );
		$t_col = 5 === $t_col ? '24' : round( 12 / $t_col );
		$m_col = 5 === $m_col ? '24' : round( 12 / $m_col );

		if ( ! $is_carousel ) {
			$arg['grid']  .= 'rtsb-col-md-' . $d_col . ' rtsb-col-sm-' . $t_col . ' rtsb-col-xs-' . $m_col . ' ';
			$arg['class'] .= ' ' . ( rtsb()->has_pro() ? $meta['gridType'] : 'even' ) . '-grid-item ';
		} else {
			$arg['grid'] .= 'rtsb-slide-item swiper-slide ';
		}

		$arg['class'] .= 'rtsb-product';

		if ( $is_list ) {
			$arg['class'] .= ' rtsb-product-list';
		}

        $arg['class'] .= ' animated fadeIn';

		if ( in_array( 'badges', $meta['visibility'], true ) ) {
			$arg['p_sale'] = Fns::get_sale_badge(
				$meta['sale_badge_type'],
				$meta['sale_badge_text'],
				$meta['out_of_stock_badge_text']
			);
		}

		$arg['badge_class'] = RenderHelpers::badge_class( $meta['badge_preset'] );

		if ( ! $meta['show_cart_text'] ) {
			$meta['add_to_cart_text'] = '';
		}

		if ( in_array( 'add_to_cart', $meta['visibility'], true ) ) {
			if ( ! empty( $meta['add_to_cart_icon'] ) ) {
				$cart_icon_html .= Fns::icons_manager( $meta['add_to_cart_icon'], 'cart-icon' );
			}

			if ( ! empty( $meta['add_to_cart_success_icon'] ) ) {
				$cart_icon_html .= Fns::icons_manager( $meta['add_to_cart_success_icon'], 'cart-success-icon' );
			}

			$cart_icon = '<span class="icon">' . $cart_icon_html . '</span>';

			if ( $_product->is_purchasable() ) {
				if ( $_product->is_in_stock() ) {
					// TODO:: Replace add to cart with WC hooks
					$arg['add_to_cart'] = $this->render_add_to_cart_button(
						get_permalink(),
						$post_id,
						$p_type,
						$meta['add_to_cart_text'],
						$cart_icon,
						$meta['add_to_cart_alignment']
					);
				}
			}
		}

		if ( in_array( 'quick_view', $meta['visibility'], true ) ) {
			add_filter( 'rtsb/module/quick_view/button_params', [ $this, 'button_classes' ] );
			add_filter( 'rtsb/module/quick_view/icon_html', [ $this, 'quick_view_icon' ] );
		}

		if ( in_array( 'compare', $meta['visibility'], true ) ) {
			add_filter( 'rtsb/module/compare/button_params', [ $this, 'button_classes' ] );
			add_filter( 'rtsb/module/compare/icon_html', [ $this, 'compare_icon' ] );
		}

		if ( in_array( 'wishlist', $meta['visibility'], true ) ) {
			add_filter( 'rtsb/module/wishlist/button_params', [ $this, 'button_classes' ] );
			add_filter( 'rtsb/module/wishlist/icon_html', [ $this, 'wishlist_icon' ] );
		}

		$arg['img_html'] = $meta['f_img'] ? Fns::get_product_image_html(
			'product',
			$post_id,
			$meta['f_img_size'],
			$meta['default_img_id'],
			$meta['custom_img_size'],
			$lazy_load
		) : null;

		$gallery_ids = $_product->get_gallery_image_ids();

		if ( $meta['hover_img'] && ! empty( $gallery_ids ) ) {
			$arg['class']         .= ' rtsb-double-img';
			$arg['hover_img_html'] = Fns::get_product_image_html(
				'product',
				$gallery_ids[0],
				$meta['f_img_size'],
				null,
				$meta['custom_img_size'],
				$lazy_load,
				true
			);
		}

		$arg['hover_btn_text'] = $meta['hover_btn_text'];

		if ( $meta['show_hover_btn_icon'] && ! empty( $meta['hover_btn_icon'] ) ) {
			$arg['hover_btn_icon'] = '<span class="icon">' . Fns::icons_manager( $meta['hover_btn_icon'], 'hover-btn-icon' ) . '</span>';
		}

		return $arg;
	}

	/**
	 * Builds an array with meta values.
	 *
	 * @param array  $meta Meta values.
	 * @param Object $query Category object.
	 * @param bool   $fullwidth Fullwidth check.
	 * @param bool   $lazy_load Lazy Load.
	 * @return array
	 */
	public function cat_arg_dataset( $meta, $query = null, $fullwidth = false, $lazy_load = false ) {
		if ( empty( $meta ) ) {
			return [];
		}

		$arg = [];

		$arg['class']            = null;
		$arg['grid']             = null;
		$arg['anchor_class']     = null;
		$arg['p_sale']           = null;
		$arg['count']            = max( $query->count, 0 );
		$arg['count_position']   = $meta['count_position'];
		$arg['excerpt_position'] = $meta['cat_excerpt_position'];
		$arg['cat_link']         = get_term_link( $query );
		$arg['target']           = '_self';

		if ( ! empty( $meta['custom_link']['url'] ) ) {
			$arg['cat_link'] = $meta['custom_link']['url'];
			$arg['target']   = $meta['custom_link']['is_external'] ? '_blank' : '_self';
		}

		$title   = $query->name;
		$excerpt = $query->description;

		if ( in_array( 'badges', $meta['visibility'], true ) ) {
			$arg['p_sale'] = $meta['custom_badge_text'];
		}

		$arg['badge_class'] = RenderHelpers::badge_class( $meta['badge_preset'] );

		if ( $arg['count'] >= 0 ) {
			$prefix = ! empty( $meta['before_count'] ) ? $meta['before_count'] : '';
			$suffix = ! empty( $meta['after_count'] ) ? $meta['after_count'] : '';

			$arg['count'] = $prefix . $arg['count'] . $suffix;
		}

		if ( $meta['show_custom_title'] && ! empty( $meta['cat_custom_title'] ) ) {
			$title = $meta['cat_custom_title'];
		}

		if ( $meta['show_custom_excerpt'] && ! empty( $meta['cat_custom_excerpt'] ) ) {
			$excerpt = $meta['cat_custom_excerpt'];
		}

		$layout = $meta['layout'];

		$arg['c_img']         = $meta['c_img'];
		$arg['items']         = $meta['visibility'];
		$arg['title_tag']     = $meta['title_tag'];
		$arg['title_class']   = 'category-title rtsb-text-limit limit-' . $meta['title_limit'] . ( ! $meta['title_link'] ? ' no-link' : '' );
		$arg['title']         = Fns::text_truncation( $title, $meta['title_limit_custom'] );
		$arg['excerpt_limit'] = $meta['excerpt_limit'];
		$arg['excerpt']       = wpautop( Fns::text_truncation( $excerpt, $meta['excerpt_limit_custom'] ) );
		$arg['title_link']    = $meta['title_link'];
		$arg['image_link']    = $meta['image_link'];

		$d_col = 0 === $meta['d_cols'] ? RenderHelpers::default_columns( $layout ) : absint( $meta['d_cols'] );
		$t_col = 0 === $meta['t_cols'] ? 2 : absint( $meta['t_cols'] );
		$m_col = 0 === $meta['m_cols'] ? 1 : absint( $meta['m_cols'] );

		$d_col = 5 === $d_col ? '24' : round( 12 / $d_col );
		$t_col = 5 === $t_col ? '24' : round( 12 / $t_col );
		$m_col = 5 === $m_col ? '24' : round( 12 / $m_col );

		if ( ! $fullwidth ) {
			$arg['grid']  .= 'rtsb-col-md-' . $d_col . ' rtsb-col-sm-' . $t_col . ' rtsb-col-xs-' . $m_col . ' ';
			$arg['class'] .= ' ' . ( rtsb()->has_pro() ? $meta['gridType'] : 'even' ) . '-grid-item ';
		} else {
			$arg['grid'] .= 'rtsb-col-xs-12 ';
		}

		$arg['class'] .= 'rtsb-category-grid';

		$arg['img_html'] = $meta['c_img'] ? Fns::get_product_image_html(
			'category',
			$query->term_id,
			$meta['f_img_size'],
			$meta['default_img_id'],
			$meta['custom_img_size'],
			$lazy_load
		) : null;

		if ( $meta['show_custom_image'] && ! empty( $meta['custom_image'] ) ) {
			$arg['img_html'] = Fns::get_product_image_html(
				'custom',
				null,
				$meta['f_img_size'],
				$meta['custom_image'],
				$meta['custom_img_size'],
				$lazy_load
			);
		}

		$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' : '' );

		return $arg;
	}

	/**
	 * Renders add to cart button.
	 *
	 * @param string $link Product link.
	 * @param int    $id Product ID.
	 * @param string $type Product type.
	 * @param string $text Custom text.
	 * @param string $icon_html Custom icon.
	 * @param string $alignment Icon alignment.
	 * @return string
	 */
	public function render_add_to_cart_button( $link, $id, $type, $text, $icon_html, $alignment ) {
		$content      = null;
		$tooltip_attr = '';

		if ( empty( $text ) ) {
			$tooltip_attr = ' title="' . esc_attr__( 'Add to Cart', 'shopbuilder' ) . '"';

			if ( 'variable' === $type ) {
				$tooltip_attr = ' title="' . esc_attr__( 'Select Options', 'shopbuilder' ) . '"';
			}
		}

		if ( 'variable' === $type ) {
			$content .= sprintf(
				'<div class="rtsb-wc-add-to-cart-wrap">
					<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>
				</div>',
				esc_url( $link ),
				esc_html__( 'Select Options', 'shopbuilder' ),
				absint( $id ),
				esc_attr( $alignment ),
				empty( $text ) ? 'no-text' : 'has-text',
				$tooltip_attr,
				$icon_html,
			);

			return $content;
		}

		$content .= sprintf(
			'<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>',
			esc_url( $link ),
			absint( $id ),
			esc_attr( $type ),
			$icon_html,
			esc_html( $text ),
			esc_attr( $alignment ),
			empty( $text ) ? 'no-text' : 'has-text',
			$tooltip_attr
		);

		return $content;
	}

	/**
	 * Button classes.
	 *
	 * @param array $params Button params.
	 * @return array
	 */
	public function button_classes( $params ) {
		$params['classes'] = array_merge( $params['classes'], [ 'rtsb-action-btn', 'tipsy' ] );

		return $params;
	}
}

```
