isset( $settings['slides_to_show'] ) ? absint( $settings['slides_to_show'] ) : 4, 'slidesToScroll' => isset( $settings['slides_to_scroll'] ) ? absint( $settings['slides_to_scroll'] ) : 1, 'autoplaySpeed' => isset( $settings['autoplay_speed'] ) ? absint( $settings['autoplay_speed'] ) : 5000, 'autoplay' => ( isset( $settings['autoplay'] ) && 'yes' === $settings['autoplay'] ), 'infinite' => ( isset( $settings['infinite'] ) && 'yes' === $settings['infinite'] ), 'pauseOnHover' => ( isset( $settings['pause_on_hover'] ) && 'yes' === $settings['pause_on_hover'] ), 'speed' => isset( $settings['transition_speed'] ) ? absint( $settings['transition_speed'] ) : 500, 'arrows' => $show_arrows, 'dots' => $show_dots, 'rtl' => $is_rtl, 'prevArrow' => '', 'nextArrow' => '', ); if ( $settings['slides_to_show_tablet'] || $settings['slides_to_show_mobile'] ) { $slick_options['responsive'] = array(); if ( ! empty( $settings['slides_to_show_tablet'] ) ) { $tablet_show = absint( $settings['slides_to_show_tablet'] ); $tablet_scroll = ( ! empty( $settings['slides_to_scroll_tablet'] ) ) ? absint( $settings['slides_to_scroll_tablet'] ) : $tablet_show; $slick_options['responsive'][] = array( 'breakpoint' => 1024, 'settings' => array( 'slidesToShow' => $tablet_show, 'slidesToScroll' => $tablet_scroll, ), ); } if ( ! empty( $settings['slides_to_show_mobile'] ) ) { $mobile_show = absint( $settings['slides_to_show_mobile'] ); $mobile_scroll = ( ! empty( $settings['slides_to_scroll_mobile'] ) ) ? absint( $settings['slides_to_scroll_mobile'] ) : $mobile_show; $slick_options['responsive'][] = array( 'breakpoint' => 767, 'settings' => array( 'slidesToShow' => $mobile_show, 'slidesToScroll' => $mobile_scroll, ), ); } } $this->add_render_attribute( 'wrapper', array( 'data-woo_slider' => wp_json_encode( $slick_options ), ) ); } /** * Render Query. * * @since 1.1.0 */ public function render_query() { $this->query_posts(); } /** * Get query products based on settings. * * Written in PHP and used to generate the final HTML. * * @since 0.0.1 * @access public */ public function query_posts() { $settings = self::$settings; if ( 'main' === $settings['query_type'] ) { global $wp_query; $main_query = clone $wp_query; self::$query = $main_query; } elseif ( 'related' === $settings['query_type'] ) { if ( is_product() ) { global $product; $product_id = $product->get_id(); $product_visibility_term_ids = wc_get_product_visibility_term_ids(); $query_args = array( 'post_type' => 'product', 'post_status' => 'publish', 'posts_per_page' => -1, 'paged' => 1, 'post__not_in' => array(), ); if ( 'grid' === $settings['products_layout_type'] ) { if ( $settings['products_per_page'] > 0 ) { $query_args['posts_per_page'] = $settings['products_per_page']; } if ( '' !== $settings['pagination_type'] ) { $paged = ( get_query_var( 'paged' ) ) ? get_query_var( 'paged' ) : '1'; if ( isset( $_POST['nonce'] ) && wp_verify_nonce( sanitize_text_field( $_POST['nonce'] ), 'uael-product-nonce' ) ) { if ( isset( $_POST['page_number'] ) && '' !== $_POST['page_number'] ) { $paged = sanitize_text_field( $_POST['page_number'] ); } } $query_args['paged'] = $paged; } } else { if ( $settings['slider_products_per_page'] > 0 ) { $query_args['posts_per_page'] = $settings['slider_products_per_page']; } } // Get current post categories and pass to filter. $product_cat = array(); $product_categories = wp_get_post_terms( $product_id, 'product_cat' ); if ( ! empty( $product_categories ) ) { foreach ( $product_categories as $key => $category ) { $product_cat[] = $category->slug; } } if ( ! empty( $product_cat ) ) { $query_args['tax_query'][] = array( 'taxonomy' => 'product_cat', 'field' => 'slug', 'terms' => $product_cat, 'operator' => 'IN', ); } // Exclude current product. $query_args['post__not_in'][] = $product_id; if ( 'yes' === get_option( 'woocommerce_hide_out_of_stock_items' ) ) { $query_args['tax_query'][] = array( 'taxonomy' => 'product_visibility', 'field' => 'term_taxonomy_id', 'terms' => $product_visibility_term_ids['outofstock'], 'operator' => 'NOT IN', ); } if ( ! empty( $product_visibility_term_ids['exclude-from-catalog'] ) ) { $query_args['tax_query'][] = array( 'taxonomy' => 'product_visibility', 'field' => 'term_taxonomy_id', 'terms' => $product_visibility_term_ids['exclude-from-catalog'], 'operator' => 'NOT IN', ); } // Default ordering args. $ordering_args = WC()->query->get_catalog_ordering_args( $settings['orderby'], $settings['order'] ); $query_args['orderby'] = $ordering_args['orderby']; $query_args['order'] = $ordering_args['order']; $query_args = apply_filters( 'uael_woo_product_query_args', $query_args, $settings ); self::$query = new \WP_Query( $query_args ); } else { $query_args = array( 'post_type' => 'product', 'post_status' => 'publish', 'posts_per_page' => -1, 'paged' => 1, 'post__in' => array( 0 ), ); $query_args = apply_filters( 'uael_woo_product_query_args', $query_args, $settings ); self::$query = new \WP_Query( $query_args ); } } else { global $post; $product_visibility_term_ids = wc_get_product_visibility_term_ids(); $query_args = array( 'post_type' => 'product', 'post_status' => 'publish', 'posts_per_page' => -1, 'paged' => 1, 'post__not_in' => array(), ); if ( 'grid' === $settings['products_layout_type'] ) { if ( $settings['products_per_page'] > 0 ) { $query_args['posts_per_page'] = $settings['products_per_page']; } if ( '' !== $settings['pagination_type'] ) { $paged = ( get_query_var( 'paged' ) ) ? get_query_var( 'paged' ) : '1'; if ( isset( $_POST['nonce'] ) && wp_verify_nonce( sanitize_text_field( $_POST['nonce'] ), 'uael-product-nonce' ) ) { if ( isset( $_POST['page_number'] ) && '' !== $_POST['page_number'] ) { $paged = sanitize_text_field( $_POST['page_number'] ); } } $query_args['paged'] = $paged; } } else { if ( $settings['slider_products_per_page'] > 0 ) { $query_args['posts_per_page'] = $settings['slider_products_per_page']; } } if ( 'price' === $settings['orderby'] || 'popularity' === $settings['orderby'] || 'rating' === $settings['orderby'] ) { if ( 'price' === $settings['orderby'] ) { $query_args['meta_key'] = '_price'; } elseif ( 'popularity' === $settings['orderby'] ) { $query_args['meta_key'] = 'total_sales'; } elseif ( 'rating' === $settings['orderby'] ) { $query_args['meta_key'] = '_wc_average_rating'; } $query_args['orderby'] = 'meta_value_num'; $query_args['order'] = $settings['order']; } else { $ordering_args = WC()->query->get_catalog_ordering_args( $settings['orderby'], $settings['order'] ); $query_args['orderby'] = $ordering_args['orderby']; $query_args['order'] = $ordering_args['order']; } if ( 'sale' === $settings['filter_by'] ) { $query_args['post__in'] = array_merge( array( 0 ), wc_get_product_ids_on_sale() ); } elseif ( 'featured' === $settings['filter_by'] ) { $query_args['tax_query'][] = array( 'taxonomy' => 'product_visibility', 'field' => 'term_taxonomy_id', 'terms' => $product_visibility_term_ids['featured'], ); } if ( 'custom' === $settings['query_type'] ) { if ( ! empty( $settings['category_filter'] ) ) { $cat_operator = $settings['category_filter_rule']; $query_args['tax_query'][] = array( 'taxonomy' => 'product_cat', 'field' => 'slug', 'terms' => $settings['category_filter'], 'operator' => $cat_operator, ); } if ( ! empty( $settings['tag_filter'] ) ) { $tag_operator = $settings['tag_filter_rule']; $query_args['tax_query'][] = array( 'taxonomy' => 'product_tag', 'field' => 'slug', 'terms' => $settings['tag_filter'], 'operator' => $tag_operator, ); } if ( 0 < $settings['offset'] ) { /** * Offset break the pagination. Using WordPress's work around * * @see https://codex.wordpress.org/Making_Custom_Queries_using_Offset_and_Pagination */ $query_args['offset_to_fix'] = $settings['offset']; } } if ( 'manual' === $settings['query_type'] ) { $manual_ids = $settings['query_manual_ids']; $query_args['post__in'] = $manual_ids; } if ( 'manual' !== $settings['query_type'] && 'main' !== $settings['query_type'] ) { if ( '' !== $settings['query_exclude_ids'] ) { $exclude_ids = $settings['query_exclude_ids']; $query_args['post__not_in'] = $exclude_ids; // Exclude from on sale products. if ( 'sale' === $settings['filter_by'] ) { $query_args['post__in'] = array_diff( $query_args['post__in'], $query_args['post__not_in'] ); } } if ( 'yes' === $settings['query_exclude_current'] ) { $query_args['post__not_in'][] = $post->ID; } } if ( 'yes' === get_option( 'woocommerce_hide_out_of_stock_items' ) ) { $query_args['tax_query'][] = array( 'taxonomy' => 'product_visibility', 'field' => 'term_taxonomy_id', 'terms' => $product_visibility_term_ids['outofstock'], 'operator' => 'NOT IN', ); } if ( ! empty( $product_visibility_term_ids['exclude-from-catalog'] ) ) { $query_args['tax_query'][] = array( 'taxonomy' => 'product_visibility', 'field' => 'term_taxonomy_id', 'terms' => $product_visibility_term_ids['exclude-from-catalog'], 'operator' => 'NOT IN', ); } $query_args = apply_filters( 'uael_woo_product_query_args', $query_args, $settings ); self::$query = new \WP_Query( $query_args ); } } /** * Render loop required arguments. * * @since 1.1.0 */ public function render_loop_args() { $query = $this->get_query(); global $woocommerce_loop; $settings = self::$settings; if ( 'grid' === $settings['products_layout_type'] ) { $woocommerce_loop['columns'] = (int) $settings['products_columns']; if ( 'main' !== $settings['query_type'] ) { if ( 0 < $settings['products_per_page'] && '' !== $settings['pagination_type'] ) { /* Pagination */ $paged = ( get_query_var( 'paged' ) ) ? get_query_var( 'paged' ) : 1; if ( isset( $_POST['nonce'] ) && wp_verify_nonce( sanitize_text_field( $_POST['nonce'] ), 'uael-product-nonce' ) ) { if ( isset( $_POST['page_number'] ) && '' !== $_POST['page_number'] ) { $paged = sanitize_text_field( $_POST['page_number'] ); } } $woocommerce_loop['paged'] = $paged; $woocommerce_loop['total'] = $query->found_posts; $woocommerce_loop['post_count'] = $query->post_count; $woocommerce_loop['per_page'] = $settings['products_per_page']; $woocommerce_loop['total_pages'] = ceil( $query->found_posts / $settings['products_per_page'] ); $woocommerce_loop['current_page'] = $paged; } } $this->add_render_attribute( 'inner', array( 'class' => array( ' columns-' . $woocommerce_loop['columns'], ), ) ); } else { if ( in_array( $settings['navigation'], array( 'dots', 'both' ), true ) ) { $this->add_render_attribute( 'inner', array( 'class' => array( 'uael-slick-dotted', ), ) ); } } } /** * Pagination Structure. * * @since 1.1.0 */ public function render_pagination_structure() { $settings = self::$settings; if ( '' !== $settings['pagination_type'] ) { add_filter( 'wc_get_template', array( $this, 'woo_pagination_template' ), 10, 5 ); add_filter( 'uael_woocommerce_pagination_args', array( $this, 'woo_pagination_options' ) ); woocommerce_pagination(); remove_filter( 'uael_woocommerce_pagination_args', array( $this, 'woo_pagination_options' ) ); remove_filter( 'wc_get_template', array( $this, 'woo_pagination_template' ), 10, 5 ); } } /** * Render wrapper start. * * @since 1.1.0 */ public function render_wrapper_start() { $settings = self::$settings; $skin_slug = str_replace( '_', '-', self::$skin ); $page_id = 0; if ( null !== \Elementor\Plugin::$instance->documents->get_current() ) { $page_id = \Elementor\Plugin::$instance->documents->get_current()->get_main_id(); } $this->set_slider_attr(); $this->add_render_attribute( 'wrapper', array( 'class' => array( 'uael-woocommerce', 'uael-woo-products-' . $settings['products_layout_type'], 'uael-woo-skin-' . $skin_slug, 'uael-woo-query-' . $settings['query_type'], ), 'data-page' => $page_id, 'data-skin' => self::$skin, ) ); echo '
get_render_attribute_string( 'wrapper' ) ) . '>'; } /** * Render wrapper end. * * @since 1.1.0 */ public function render_wrapper_end() { echo '
'; } /** * Render inner container start. * * @since 1.1.0 */ public function render_inner_start() { $settings = self::$settings; $product_column_tablet = isset( $settings['products_columns_tablet'] ) ? $settings['products_columns_tablet'] : ''; $product_column_mobile = isset( $settings['products_columns_mobile'] ) ? $settings['products_columns_mobile'] : ''; $this->add_render_attribute( 'inner', array( 'class' => array( 'uael-woo-products-inner', 'uael-woo-product__column-' . $settings['products_columns'], 'uael-woo-product__column-tablet-' . $product_column_tablet, 'uael-woo-product__column-mobile-' . $product_column_mobile, ), ) ); if ( '' !== $settings['products_hover_style'] ) { $this->add_render_attribute( 'inner', array( 'class' => array( 'uael-woo-product__hover-' . $settings['products_hover_style'], ), ) ); } echo '
get_render_attribute_string( 'inner' ) ) . '>'; } /** * Render inner container end. * * @since 1.1.0 */ public function render_inner_end() { echo '
'; } /** * Render woo loop start. * * @since 1.1.0 */ public function render_woo_loop_start() { do_action( 'uael_before_product_loop_start' ); woocommerce_product_loop_start(); } /** * Render woo loop. * * @since 1.1.0 */ public function render_woo_loop() { $query = $this->get_query(); while ( $query->have_posts() ) : $query->the_post(); $this->render_woo_loop_template(); endwhile; } /** * Render woo default template. * * @since 1.1.0 */ public function render_woo_loop_template() { $settings = self::$settings; include UAEL_MODULES_DIR . 'woocommerce/templates/content-product-default.php'; } /** * Render woo loop end. * * @since 1.1.0 */ public function render_woo_loop_end() { woocommerce_product_loop_end(); } /** * Render reset loop. * * @since 1.1.0 */ public function render_reset_loop() { woocommerce_reset_loop(); wp_reset_postdata(); } /** * Quick View. * * @since 0.0.1 * @access public */ public function quick_view_modal() { $quick_view_type = $this->get_instance_value( 'quick_view_type' ); if ( '' !== $quick_view_type ) { wp_enqueue_script( 'wc-add-to-cart-variation' ); wp_enqueue_script( 'flexslider' ); $widget_id = self::$node_id; include UAEL_MODULES_DIR . 'woocommerce/templates/quick-view-modal.php'; } } /** * Register Get Query. * * @since 0.0.1 * @access protected */ public function get_query() { return self::$query; } /** * Get empty products found message. * * Returns the no products found message HTML. * * @since 1.10.0 * @access public */ public function render_empty() { $settings = self::$settings; ?>

render_query(); $query = self::$query; if ( ! $query->have_posts() ) { $this->render_empty(); return; } $this->render_loop_args(); $this->render_wrapper_start(); $this->render_inner_start(); $this->render_woo_loop_start(); $this->render_woo_loop(); $this->render_woo_loop_end(); $this->render_pagination_structure(); $this->render_reset_loop(); $this->render_inner_end(); $this->render_wrapper_end(); $this->quick_view_modal(); } /** * Render settings array for selected skin * * @since 1.5.0 * @param string $control_base_id Skin ID. * @access public */ public function get_instance_value( $control_base_id ) { if ( isset( self::$settings[ self::$skin . '_' . $control_base_id ] ) ) { return self::$settings[ self::$skin . '_' . $control_base_id ]; } else { return null; } } /** * Add render attribute. * * Used to add attributes to a specific HTML element. * * The HTML tag is represented by the element parameter, then you need to * define the attribute key and the attribute key. The final result will be: * ``. * * Example usage: * * `$this->add_render_attribute( 'wrapper', 'class', 'custom-widget-wrapper-class' );` * `$this->add_render_attribute( 'widget', 'id', 'custom-widget-id' );` * `$this->add_render_attribute( 'button', [ 'class' => 'custom-button-class', 'id' => 'custom-button-id' ] );` * * @since 1.0.0 * @access public * * @param array|string $element The HTML element. * @param array|string $key Optional. Attribute key. Default is null. * @param array|string $value Optional. Attribute value. Default is null. * @param bool $overwrite Optional. Whether to overwrite existing * attribute. Default is false, not to overwrite. * * @return Element_Base Current instance of the element. */ public function add_render_attribute( $element, $key = null, $value = null, $overwrite = false ) { if ( is_array( $element ) ) { foreach ( $element as $element_key => $attributes ) { $this->add_render_attribute( $element_key, $attributes, null, $overwrite ); } return $this; } if ( is_array( $key ) ) { foreach ( $key as $attribute_key => $attributes ) { $this->add_render_attribute( $element, $attribute_key, $attributes, $overwrite ); } return $this; } if ( empty( $this->_render_attributes[ $element ][ $key ] ) ) { $this->_render_attributes[ $element ][ $key ] = array(); } settype( $value, 'array' ); if ( $overwrite ) { $this->_render_attributes[ $element ][ $key ] = $value; } else { $this->_render_attributes[ $element ][ $key ] = array_merge( $this->_render_attributes[ $element ][ $key ], $value ); } return $this; } /** * Get render attribute string. * * Used to retrieve the value of the render attribute. * * @since 1.0.0 * @access public * * @param array|string $element The element. * * @return string Render attribute string, or an empty string if the attribute * is empty or not exist. */ public function get_render_attribute_string( $element ) { if ( empty( $this->_render_attributes[ $element ] ) ) { return ''; } $render_attributes = $this->_render_attributes[ $element ]; $attributes = array(); foreach ( $render_attributes as $attribute_key => $attribute_values ) { $attributes[] = sprintf( '%1$s="%2$s"', $attribute_key, esc_attr( implode( ' ', $attribute_values ) ) ); } return implode( ' ', $attributes ); } /** * Render post HTML via AJAX call. * * @param array|string $style_id The style ID. * @param array|string $widget Widget object. * @since 1.5.0 * @access public */ public function inner_render( $style_id, $widget ) { ob_start(); if ( isset( $_POST['nonce'] ) && wp_verify_nonce( sanitize_text_field( $_POST['nonce'] ), 'uael-product-nonce' ) ) { $category = ( isset( $_POST['category'] ) ) ? sanitize_text_field( $_POST['category'] ) : ''; } self::$settings = $widget->get_settings(); self::$skin = $style_id; $this->render_query(); $query = self::$query; $settings = self::$settings; $this->render_loop_args(); $this->render_woo_loop_start(); $this->render_woo_loop(); $this->render_woo_loop_end(); return ob_get_clean(); } /** * Render post pagination HTML via AJAX call. * * @param array|string $style_id The style ID. * @param array|string $widget Widget object. * @since 1.5.0 * @access public */ public function page_render( $style_id, $widget ) { ob_start(); if ( isset( $_POST['nonce'] ) && wp_verify_nonce( sanitize_text_field( $_POST['nonce'] ), 'uael-product-nonce' ) ) { $category = ( isset( $_POST['category'] ) ) ? sanitize_text_field( $_POST['category'] ) : ''; } self::$settings = $widget->get_settings(); self::$skin = $style_id; $this->render_query(); $query = self::$query; $settings = self::$settings; $is_featured = false; $this->render_pagination_structure(); return ob_get_clean(); } }