shortcode_handle}", [ $this, 'attr' ] ); add_filter( "fusion_attr_{$this->shortcode_handle}-carousel", [ $this, 'carousel_attr' ] ); // Ajax mechanism for query related part. add_action( "wp_ajax_get_{$this->shortcode_handle}", [ $this, 'ajax_render' ] ); } /** * Check if component should render * * @access public * @since 3.2 * @return boolean */ public function should_render() { return is_singular(); } /** * Checking the right page. * * @since 3.3 * @return string */ public function is_checking_page() { return $this->is_product(); } /** * Render for live editor. * * @static * @access public * @since 3.2 * @return void */ public function ajax_render() { check_ajax_referer( 'fusion_load_nonce', 'fusion_load_nonce' ); $return_data = []; // From Ajax Request. if ( isset( $_POST['model'] ) && isset( $_POST['model']['params'] ) && ! apply_filters( 'fusion_builder_live_request', false ) ) { // phpcs:ignore WordPress.Security.NonceVerification $args = $_POST['model']['params']; // phpcs:ignore WordPress.Security $post_id = isset( $_POST['post_id'] ) ? $_POST['post_id'] : get_the_ID(); // phpcs:ignore WordPress.Security.ValidatedSanitizedInput $this->defaults = self::get_element_defaults(); $this->args = FusionBuilder::set_shortcode_defaults( $this->defaults, $args, $this->shortcode_handle ); fusion_set_live_data(); add_filter( 'fusion_builder_live_request', '__return_true' ); $this->emulate_product(); if ( ! $this->is_checking_page() ) { echo wp_json_encode( $return_data ); wp_die(); } $this->live_ajax = true; $products = $this->get_query(); $return_data[ $this->shortcode_handle ] = is_array( $products['products'] ) && 0 < count( $products['products'] ) ? $this->render_layout( $products ) : $this->get_placeholder(); $return_data['product_counts'] = is_array( $products['products'] ) ? count( $products['products'] ) : 0; $return_data['query_type'] = $this->query_type(); $this->restore_product(); } echo wp_json_encode( $return_data ); wp_die(); } /** * Gets the default values. * * @static * @access public * @since 3.2 * @return array */ public static function get_element_defaults() { $fusion_settings = awb_get_fusion_settings(); return [ 'number_products' => $fusion_settings->get( 'number_related_posts' ), 'products_columns' => $fusion_settings->get( 'woocommerce_related_columns' ), 'products_layout' => 'boxes', 'products_navigation' => 'yes', 'products_autoplay' => 'no', 'products_swipe' => 'no', 'products_column_spacing' => $fusion_settings->get( 'related_posts_column_spacing' ), 'products_swipe_items' => $fusion_settings->get( 'related_posts_swipe_items' ), 'heading_enable' => 'yes', 'heading_size' => '3', 'margin_bottom' => '', 'margin_left' => '', 'margin_right' => '', 'margin_top' => '', 'hide_on_mobile' => fusion_builder_default_visibility( 'string' ), 'class' => '', 'id' => '', 'animation_type' => '', 'animation_direction' => 'down', 'animation_speed' => '0.1', 'animation_delay' => '', 'animation_offset' => $fusion_settings->get( 'animation_offset' ), ]; } /** * Render the shortcode * * @access public * @since 3.2 * @param array $args Shortcode parameters. * @param string $content Content between shortcode. * @return string HTML output. */ public function render( $args, $content = '' ) { $this->emulate_product(); if ( ! $this->is_checking_page() ) { return; } $this->defaults = self::get_element_defaults(); $this->args = FusionBuilder::set_shortcode_defaults( $this->defaults, $args, $this->shortcode_handle ); $products = $this->get_query(); $main_heading = $this->get_main_heading(); $html = '
shortcode_handle ) . '>'; if ( 'yes' === $this->args['heading_enable'] ) { $html .= fusion_render_title( $this->args['heading_size'], apply_filters( $this->shortcode_handle . '_heading_text', $main_heading, 'product' ) ); } if ( is_array( $products['products'] ) && 0 < count( $products['products'] ) ) { $html .= $this->render_layout( $products ); $html .= '
'; } elseif ( is_array( $products['products'] ) && 0 === count( $products['products'] ) && $this->is_builder() ) { // Add preview for Live Builder. $html .= $this->get_placeholder(); } else { $html = ''; } $this->restore_product(); $this->counter++; $this->on_render(); return apply_filters( 'fusion_component_' . $this->shortcode_handle . '_content', $html, $args ); } /** * Builds HTML for Woo Related Products. * * @access public * @since 3.2 * @param array $args layout arguments. * @return string */ public function render_layout( $args ) { $html = ''; // Set global loop values. $this->set_loop_props( $args ); add_filter( 'woocommerce_product_loop_start', [ $this, 'loop_start_attr' ], 20 ); if ( 'carousel' === $this->args['products_layout'] ) { add_filter( 'woocommerce_post_class', [ $this, 'wc_post_class' ], 20, 2 ); add_action( 'woocommerce_before_shop_loop_item', [ $this, 'before_shop_loop_item' ], 8 ); add_action( 'woocommerce_after_shop_loop_item', [ $this, 'after_shop_loop_item' ], 15 ); add_filter( 'woocommerce_product_loop_start', [ $this, 'loop_start_carousel' ], 20 ); add_filter( 'woocommerce_product_loop_end', [ $this, 'loop_end_carousel' ], 20 ); if ( ! $this->live_ajax ) { $html .= '
shortcode_handle . '-carousel' ) . '>'; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped } } if ( ! $this->live_ajax ) { $html .= woocommerce_product_loop_start( false ); } ob_start(); foreach ( $args['products'] as $product_data ) : $post_object = get_post( $product_data->get_id() ); setup_postdata( $GLOBALS['post'] =& $post_object ); // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited, Squiz.PHP.DisallowMultipleAssignments.Found if ( 'carousel' === $this->args['products_layout'] ) { $this->get_template_carousel(); } else { wc_get_template_part( 'content', 'product' ); } endforeach; $html .= ob_get_clean(); if ( ! $this->live_ajax ) { $html .= woocommerce_product_loop_end( false ); } wp_reset_postdata(); /** * Add navigation if needed. */ if ( 'carousel' === $this->args['products_layout'] && 'yes' === $this->args['products_navigation'] && ! $this->live_ajax ) { $html .= awb_get_carousel_nav(); } if ( 'carousel' === $this->args['products_layout'] && ! $this->live_ajax ) { $html .= '
'; } remove_filter( 'woocommerce_product_loop_start', [ $this, 'loop_start_attr' ], 20 ); if ( 'carousel' === $this->args['products_layout'] ) { remove_filter( 'woocommerce_post_class', [ $this, 'wc_post_class' ], 20, 2 ); remove_action( 'woocommerce_before_shop_loop_item', [ $this, 'before_shop_loop_item' ], 8 ); remove_action( 'woocommerce_after_shop_loop_item', [ $this, 'after_shop_loop_item' ], 15 ); remove_filter( 'woocommerce_product_loop_start', [ $this, 'loop_start_carousel' ], 20 ); remove_filter( 'woocommerce_product_loop_end', [ $this, 'loop_end_carousel' ], 20 ); } return $html; } /** * Get product query. * * @access public * @since 3.2 * @return array */ public function get_query() { return []; } /** * Get query type. * * @access public * @since 3.3 * @return string */ public function query_type() { return ''; } /** * Sets the necessary scripts. * * @access public * @since 3.2 * @return void */ public function on_first_render() { Fusion_Dynamic_JS::enqueue_script( 'awb-carousel' ); if ( class_exists( 'Avada' ) ) { global $avada_woocommerce; $js_folder_suffix = FUSION_BUILDER_DEV_MODE ? '/assets/js' : '/assets/min/js'; $js_folder_url = Avada::$template_dir_url . $js_folder_suffix; $js_folder_path = Avada::$template_dir_path . $js_folder_suffix; $version = Avada::get_theme_version(); if ( Avada()->settings->get( 'woocommerce_enable_quick_view' ) ) { Fusion_Dynamic_JS::enqueue_script( 'awb-woo-quick-view', $js_folder_url . '/general/awb-woo-quick-view.js', $js_folder_path . '/general/awb-woo-quick-view.js', [ 'jquery', 'fusion-flexslider' ], $version, true ); Fusion_Dynamic_JS::localize_script( 'awb-woo-quick-view', 'avadaWooCommerceVars', $avada_woocommerce::get_avada_wc_vars() ); } Fusion_Dynamic_JS::enqueue_script( 'avada-woo-products', $js_folder_url . '/general/avada-woo-products.js', $js_folder_path . '/general/avada-woo-products.js', [ 'jquery', 'fusion-flexslider' ], $version, true ); Fusion_Dynamic_JS::localize_script( 'avada-woo-products', 'avadaWooCommerceVars', $avada_woocommerce::get_avada_wc_vars() ); } } /** * Set wc loop props. * * @access public * @param array $args layout arguments. * @since 3.2 * @return void */ public function set_loop_props( $args ) {} /** * Builds the attributes array. * * @access public * @since 3.2 * @return array */ public function attr() { $attr = [ 'class' => "fusion-woo-products-tb {$this->shortcode_classname} {$this->shortcode_classname}-" . $this->counter, 'style' => '', ]; $attr = fusion_builder_visibility_atts( $this->args['hide_on_mobile'], $attr ); if ( '' !== $this->args['animation_type'] ) { $attr = Fusion_Builder_Animation_Helper::add_animation_attributes( $this->args, $attr ); } $attr['style'] .= Fusion_Builder_Margin_Helper::get_margins_style( $this->args ); if ( $this->args['class'] ) { $attr['class'] .= ' ' . $this->args['class']; } if ( $this->args['id'] ) { $attr['id'] = $this->args['id']; } return $attr; } /** * Builds the carousel wrapper attributes array. * * @access public * @since 2.2 * @return array */ public function carousel_attr() { $attr['class'] = 'awb-carousel awb-swiper awb-swiper-carousel'; /** * Set the autoplay variable. */ $attr['data-autoplay'] = $this->args['products_autoplay']; /** * Set the touch scroll variable. */ $attr['data-touchscroll'] = $this->args['products_swipe']; $attr['data-columns'] = $this->args['products_columns']; $attr['data-itemmargin'] = intval( $this->args['products_column_spacing'] ) . 'px'; $attr['data-itemwidth'] = 180; $products_swipe_items = $this->args['products_swipe_items']; $products_swipe_items = ( 0 == $products_swipe_items ) ? '1' : $products_swipe_items; // phpcs:ignore Universal.Operators.StrictComparisons $attr['data-scrollitems'] = $products_swipe_items; return $attr; } /** * Build loop start attributes. * * @access public * @param string $html HTML. * @since 3.2 * @return array */ public function loop_start_attr( $html ) { $html = str_replace( 'columns-', 'products-', $html ); if ( 'carousel' === $this->args['products_layout'] ) { $html = str_replace( 'products', 'products swiper-wrapper', $html ); } return $html; } /** * Build wc post class attributes. * * @access public * @param array $classes classes. * @param object $product product object. * @since 3.2 * @return array */ public function wc_post_class( $classes, $product ) { $key = array_search( 'product-grid-view', $classes, true ); if ( false !== $key ) { unset( $classes[ $key ] ); } $classes[] = 'swiper-slide'; return $classes; } /** * Build wc post class attributes. * * @access public * @since 3.2 * @return void */ public function before_shop_loop_item() { echo ''; } /** * Build loop start carousel. * * @access public * @param string $html HTML. * @since 3.9 * @return array */ public function loop_start_carousel( $html ) { $html = str_replace( '