<?php
/**
 * @author      Elicus Technologies <hello@elicus.com>
 * @link        https://www.elicus.com/
 * @copyright   2024 Elicus Technologies Private Limited
 * @version     1.5.0
 */

if ( ! function_exists( 'aioc_get_post_thumbnail' ) ) {
    function aioc_get_post_thumbnail( $post_id, $size, $class, $print = false, $url = false ) {
        if ( ! $post_id ) {
            return;
        }

        $thumb     = '';
        $thumb_url = '';
        $atts      = array();
        if ( has_post_thumbnail( $post_id ) ) {
            $attach_id = get_post_thumbnail_id( $post_id );
            if ( 0 !== $attach_id && '' !== $attach_id && '0' !== $attach_id ) {
                $atts['alt'] = get_post_meta( $attach_id, '_wp_attachment_image_alt', true );
            } else {
                $atts['alt'] = get_the_title( $post_id );
            }

            if ( $class ) {
                $atts['class'] = $class;
            }
            $thumb     = get_the_post_thumbnail( $post_id, esc_attr( $size ), $atts );
            $thumb_url = get_the_post_thumbnail_url( $post_id, esc_attr( $size ) );
        } else {
            $post_object         = get_post( $post_id );
            $unprocessed_content = $post_object->post_content;

            // truncate Post based shortcodes if Divi Builder enabled to avoid infinite loops.
            if ( function_exists( 'et_strip_shortcodes' ) ) {
                $unprocessed_content = et_strip_shortcodes( $post_object->post_content, true );
            }

            // Check if content should be overridden with a custom value.
            $custom = apply_filters( 'et_first_image_use_custom_content', false, $unprocessed_content, $post_object );
            // apply the_content filter to execute all shortcodes and get the correct image from the processed content.
            $processed_content = false === $custom ? apply_filters( 'the_content', $unprocessed_content ) : $custom;

            $output = preg_match_all( '/<img.+src=[\'"]([^\'"]+)[\'"].*>/i', $processed_content, $matches );
            if ( isset( $matches[1][0] ) ) {
                $image = trim( $matches[1][0] );
            }

            if ( isset( $image ) ) {
                $attach_id = attachment_url_to_postid( $image );
                if ( 0 !== $attach_id && '' !== $attach_id && '0' !== $attach_id ) {
                    $atts['alt'] = get_post_meta( $attach_id, '_wp_attachment_image_alt', true );
                } else {
                    $atts['alt'] = get_the_title( $post_id );
                }
                if ( $class ) {
                    $atts['class'] = esc_attr( $class );
                }
                $thumb_url = wp_get_attachment_image_url( $attach_id, esc_attr( $size ) );
                $thumb     = wp_get_attachment_image( $attach_id, esc_attr( $size ), false, $atts );
            }
        }

        if ( $print ) {
            if ( $url ) {
                echo esc_url( $thumb_url );
            } else {
                echo et_core_intentionally_unescaped( $thumb, 'html' );
            }
        } else {
            if ( $url ) {
                return esc_url( $thumb_url );
            } else {
                return et_core_intentionally_unescaped( $thumb, 'html' );
            }
        }
    }
}

if ( ! function_exists( 'aioc_strip_shortcodes' ) ) {
    function aioc_strip_shortcodes( $content, $truncate_post_based_shortcodes_only = false ) {
        global $shortcode_tags;

        $content = trim( $content );

        $strip_content_shortcodes = array(
            'et_pb_code',
            'et_pb_fullwidth_code',
            'dipl_modal',
            'el_modal_popup',
        );

        // list of post-based shortcodes.
        if ( $truncate_post_based_shortcodes_only ) {
            $strip_content_shortcodes = array(
                'et_pb_post_slider',
                'et_pb_fullwidth_post_slider',
                'et_pb_blog',
                'et_pb_blog_extras',
                'et_pb_comments',
            );
        }

        foreach ( $strip_content_shortcodes as $shortcode_name ) {
            $regex = sprintf(
                '(\[%1$s[^\]]*\][^\[]*\[\/%1$s\]|\[%1$s[^\]]*\])',
                esc_html( $shortcode_name )
            );

            $content = preg_replace( $regex, '', $content );
        }

        // do not proceed if we need to truncate post-based shortcodes only.
        if ( $truncate_post_based_shortcodes_only ) {
            return $content;
        }

        $shortcode_tag_names = array();
        foreach ( $shortcode_tags as $shortcode_tag_name => $shortcode_tag_cb ) {
            if ( 0 !== strpos( $shortcode_tag_name, 'et_pb_' ) ) {
                continue;
            }

            $shortcode_tag_names[] = $shortcode_tag_name;
        }

        $et_shortcodes = implode( '|', $shortcode_tag_names );

        $regex_opening_shortcodes = sprintf( '(\[(%1$s)[^\]]+\])', esc_html( $et_shortcodes ) );
        $regex_closing_shortcodes = sprintf( '(\[\/(%1$s)\])', esc_html( $et_shortcodes ) );

        $content = preg_replace( $regex_opening_shortcodes, '', $content );
        $content = preg_replace( $regex_closing_shortcodes, '', $content );

        return et_core_intentionally_unescaped( $content, 'html' );
    }
}

if ( ! function_exists( 'aioc_truncate_post' ) ) {
    function aioc_truncate_post( $amount, $echo = true, $post_id = '', $strip_shortcodes = false ) {
        global $shortname;

        if ( '' === $post_id ) {
            return '';
        }

        $post_object = get_post( $post_id );

        $post_excerpt = '';
        $post_excerpt = apply_filters( 'the_excerpt', $post_object->post_excerpt );

        if ( 'on' === et_get_option( $shortname . '_use_excerpt' ) && '' !== $post_excerpt ) {
            if ( $echo ) {
                echo et_core_intentionally_unescaped( $post_excerpt, 'html' );
            } else {
                return $post_excerpt;
            }
        } else {
            // get the post content.
            $truncate = $post_object->post_content;

            // remove caption shortcode from the post content.
            $truncate = preg_replace( '@\[caption[^\]]*?\].*?\[\/caption]@si', '', $truncate );

            // remove post nav shortcode from the post content.
            $truncate = preg_replace( '@\[et_pb_post_nav[^\]]*?\].*?\[\/et_pb_post_nav]@si', '', $truncate );

            // Remove audio shortcode from post content to prevent unwanted audio file on the excerpt
            // due to unparsed audio shortcode.
            $truncate = preg_replace( '@\[audio[^\]]*?\].*?\[\/audio]@si', '', $truncate );

            // Remove embed shortcode from post content.
            $truncate = preg_replace( '@\[embed[^\]]*?\].*?\[\/embed]@si', '', $truncate );

            if ( $strip_shortcodes ) {
                $truncate = aioc_strip_shortcodes( $truncate );
                $truncate = et_builder_strip_dynamic_content( $truncate );
            } else {
                // apply content filters.
                $truncate = apply_filters( 'the_content', $truncate );
            }

            // decide if we need to append dots at the end of the string.
            if ( strlen( $truncate ) <= $amount ) {
                $echo_out = '';
            } else {
                $echo_out = '...';
                if ( $amount > 3 ) {
                    $amount = $amount - 3;
                }
            }

            // trim text to a certain number of characters, also remove spaces from the end of a string ( space counts as a character ).
            $truncate = rtrim( et_wp_trim_words( $truncate, $amount, '' ) );

            // remove the last word to make sure we display all words correctly.
            if ( '' !== $echo_out ) {
                $new_words_array = (array) explode( ' ', $truncate );
                array_pop( $new_words_array );

                $truncate = implode( ' ', $new_words_array );

                // append dots to the end of the string.
                if ( '' !== $truncate ) {
                    $truncate .= $echo_out;
                }
            }

            if ( $echo ) {
                echo et_core_intentionally_unescaped( $truncate, 'html' );
            } else {
                return et_core_intentionally_unescaped( $truncate, 'html' );
            }
        }
    }
}

/* Filter the products query arguments */
if ( ! function_exists( 'aioc_filter_products_query' ) ) {
    function aioc_filter_products_query( $args ) {

        if ( function_exists( 'WC' ) ) {
            $args['meta_query'] = WC()->query->get_meta_query( et_()->array_get( $args, 'meta_query', array() ), true );
            $args['tax_query']  = WC()->query->get_tax_query( et_()->array_get( $args, 'tax_query', array() ), true );

            // Add fake cache-busting argument as the filtering is actually done in dwe_apply_woo_widget_filters().
            $args['nocache'] = microtime( true );
        }

        return $args;
    }
}

if ( ! function_exists( 'aioc_render_divi_button' ) ) {
    function aioc_render_divi_button( $args = array() ) {
        // Prepare arguments.
        $defaults = array(
            'button_id'           => '',
            'button_classname'    => array(),
            'button_custom'       => '',
            'button_rel'          => '',
            'button_text'         => '',
            'button_text_escaped' => false,
            'button_url'          => '',
            'custom_icon'         => '',
            'custom_icon_tablet'  => '',
            'custom_icon_phone'   => '',
            'display_button'      => true,
            'has_wrapper'         => true,
            'url_new_window'      => '',
            'multi_view_data'     => '',
        );

        $args = wp_parse_args( $args, $defaults );

        // Do not proceed if display_button argument is false.
        if ( ! $args['display_button'] ) {
            return '';
        }

        $button_text = $args['button_text_escaped'] ? $args['button_text'] : esc_html( $args['button_text'] );

        // Do not proceed if button_text argument is empty and not having multi view value.
        if ( '' === $button_text && ! $args['multi_view_data'] ) {
            return '';
        }

        // Button classname.
        $button_classname = array( 'et_pb_button' );

        if ( ( '' !== $args['custom_icon'] || '' !== $args['custom_icon_tablet'] || '' !== $args['custom_icon_phone'] ) && 'on' === $args['button_custom'] ) {
            $button_classname[] = 'et_pb_custom_button_icon';
        }

        // Add multi view CSS hidden helper class when button text is empty on desktop mode.
        if ( '' === $button_text && $args['multi_view_data'] ) {
            $button_classname[] = 'et_multi_view_hidden';
        }

        if ( ! empty( $args['button_classname'] ) ) {
            $button_classname = array_merge( $button_classname, $args['button_classname'] );
        }

        // Custom icon data attribute.
        $use_data_icon = '' !== $args['custom_icon'] && 'on' === $args['button_custom'];
        $data_icon     = $use_data_icon ? sprintf(
            ' data-icon="%1$s"',
            wp_doing_ajax() && ! ET_BUILDER_LOAD_ON_AJAX ? esc_attr( $args['custom_icon'] ) : esc_attr( et_pb_process_font_icon( $args['custom_icon'] ) )
        ) : '';

        $use_data_icon_tablet = '' !== $args['custom_icon_tablet'] && 'on' === $args['button_custom'];
        $data_icon_tablet     = $use_data_icon_tablet ? sprintf(
            ' data-icon-tablet="%1$s"',
            wp_doing_ajax() && ! ET_BUILDER_LOAD_ON_AJAX ? esc_attr( $args['custom_icon_tablet'] ) : esc_attr( et_pb_process_font_icon( $args['custom_icon_tablet'] ) )
        ) : '';

        $use_data_icon_phone = '' !== $args['custom_icon_phone'] && 'on' === $args['button_custom'];
        $data_icon_phone     = $use_data_icon_phone ? sprintf(
            ' data-icon-phone="%1$s"',
             wp_doing_ajax() && ! ET_BUILDER_LOAD_ON_AJAX ? esc_attr( $args['custom_icon_phone'] ) : esc_attr( et_pb_process_font_icon( $args['custom_icon_phone'] ) )
        ) : '';

        // Render button.
        return sprintf(
            '%6$s<a%8$s class="%5$s" href="%1$s"%3$s%4$s%9$s%10$s%11$s>%2$s</a>%7$s',
            esc_url( $args['button_url'] ),
            et_core_esc_previously( $button_text ),
            ( 'on' === $args['url_new_window'] ? ' target="_blank"' : '' ),
            et_core_esc_previously( $data_icon ),
            esc_attr( implode( ' ', array_unique( $button_classname ) ) ), // #5
            $args['has_wrapper'] ? '<div class="et_pb_button_wrapper">' : '',
            $args['has_wrapper'] ? '</div>' : '',
            '' !== $args['button_id'] ? sprintf( ' id="%1$s"', esc_attr( $args['button_id'] ) ) : '',
            et_core_esc_previously( $data_icon_tablet ),
            et_core_esc_previously( $data_icon_phone ), // #10
            et_core_esc_previously( $args['multi_view_data'] )
        );
    }
}

if ( ! function_exists( 'aioc_product_sale_badge' ) ) {
    function aioc_product_sale_badge( $product, $percent = false, $sale_label_text = '' ) {
        if ( ! $product->is_on_sale() ) {
            return '';
        }

        if ( ! $percent ) {

            if ( '' === $sale_label_text ) {
                if ( $product->is_on_sale() ) {
                    $product_post = get_post( $product );
                    $sale_flash = apply_filters( 'woocommerce_sale_flash', '<span class="onsale">' . esc_html__( 'Sale!', 'woocommerce' ) . '</span>', $product_post, $product );
                } else {
                    $sale_flash = '';
                }
            } else {
                $sale_flash = $sale_label_text;
            }

            return  sprintf(
                '<div class="dwe_single_woo_product_sale_badge">
                    %1$s
                </div>',
                esc_html( wp_strip_all_tags( $sale_flash ) )
            );
        }

        $max_percentage = 0;
       
        if ( $product->is_type( 'variable' ) ) {
            $variation_prices = $product->get_variation_prices();
            foreach ( $variation_prices['regular_price'] as $product_id => $regular_price ) {
                if ( 0 === $regular_price ) { 
                    continue;
                }
                if ( $regular_price == $variation_prices['sale_price'][$product_id] ) {
                    continue;
                }
                $percentage = ( ( $regular_price - $variation_prices['sale_price'][$product_id] ) / $regular_price ) * 100;
                if ( $percentage > $max_percentage ) {
                    $max_percentage = $percentage;
                }
            }
        } else if ( $product->is_type( 'grouped' ) ) {
            foreach ( $product->get_children() as $child_product_id ) {
                $child_product  = wc_get_product( $child_product_id );
                $regular_price  = $child_product->get_regular_price();
                $sale_price     = $child_product->get_sale_price();
                if ( 0 !== $regular_price && ! empty( $sale_price ) ) {
                    $percentage = ( ( $regular_price - $sale_price ) / $regular_price ) * 100;
                    if ( $percentage > $max_percentage ) {
                        $max_percentage = $percentage;
                    }
                }
            }
        } else {
            $max_percentage = ( ( $product->get_regular_price() - $product->get_sale_price() ) / $product->get_regular_price() ) * 100;
        }

        if ( isset( $max_percentage ) && round( $max_percentage ) > 0 ) {
            return  sprintf(
                '<div class="dwe_single_woo_product_sale_badge">
                    -%1$s%%
                </div>',
                absint( round( $max_percentage ) )
            );
        }

        return '';
    }
}

if ( ! function_exists( 'aioc_woocommerce_category_thumbnail' ) ) {
    function aioc_woocommerce_category_thumbnail( $category, $size = 'woocommerce_thumbnail' ) {
        $dimensions           = wc_get_image_size( $size );
        $thumbnail_id         = get_term_meta( $category->term_id, 'thumbnail_id', true );

        if ( $thumbnail_id ) {
            $image        = wp_get_attachment_image_src( $thumbnail_id, $size );
            $image        = is_array( $image ) ? $image[0] : wc_placeholder_img_src();
            $image_srcset = function_exists( 'wp_get_attachment_image_srcset' ) ? wp_get_attachment_image_srcset( $thumbnail_id, $size ) : false;
            $image_sizes  = function_exists( 'wp_get_attachment_image_sizes' ) ? wp_get_attachment_image_sizes( $thumbnail_id, $size ) : false;
        } else {
            $image        = wc_placeholder_img_src();
            $image_srcset = false;
            $image_sizes  = false;
        }

        if ( $image ) {
            // Prevent esc_url from breaking spaces in urls for image embeds.
            // Ref: https://core.trac.wordpress.org/ticket/23605.
            $image = str_replace( ' ', '%20', $image );

            // Add responsive image markup if available.
            if ( $image_srcset && $image_sizes ) {
                return '<img src="' . esc_url( $image ) . '" alt="' . esc_attr( $category->name ) . '" width="' . esc_attr( $dimensions['width'] ) . '" height="' . esc_attr( $dimensions['height'] ) . '" srcset="' . esc_attr( $image_srcset ) . '" sizes="' . esc_attr( $image_sizes ) . '" />';
            } else {
                return '<img src="' . esc_url( $image ) . '" alt="' . esc_attr( $category->name ) . '" width="' . esc_attr( $dimensions['width'] ) . '" height="' . esc_attr( $dimensions['height'] ) . '" />';
            }
        }
    }
}

if ( ! function_exists( 'aioc_add_to_cart_button' ) ) {
    function aioc_add_to_cart_button( $product_id, $icon = '', $single = false, $button_text = array() , $args = array() ) {
        $product    = wc_get_product( $product_id );
        $defaults   = array(
            'quantity'   => 1,
            'class'      => implode(
                ' ',
                array_filter(
                    array(
                        'button',
                        'product_type_' . $product->get_type(),
                        $product->is_purchasable() && $product->is_in_stock() ? 'add_to_cart_button' : '',
                        $product->supports( 'ajax_add_to_cart' ) && $product->is_purchasable() && $product->is_in_stock() && ! $single ? 'ajax_add_to_cart' : '',
                        $single ? 'single_add_to_cart_button' : ''
                    )
                )
            ),
            'attributes' => array(
                'data-product_id'  => $product->get_id(),
                'data-product_sku' => $product->get_sku(),
                'aria-label'       => $product->add_to_cart_description(),
                'rel'              => 'nofollow',
            ),
        );

        if ( ! $single ) {
            $args = apply_filters( 'woocommerce_loop_add_to_cart_args', wp_parse_args( $args, $defaults ), $product );
        } else {
            $args = wp_parse_args( $args, $defaults );
        }

        if ( isset( $args['attributes']['aria-label'] ) ) {
            $args['attributes']['aria-label'] = wp_strip_all_tags( $args['attributes']['aria-label'] );
        }

        if ( ! empty( $icon ) ) {
            $icon_output = array();

            foreach ( $icon as $attr => $value ) {
                if ( function_exists( 'et_pb_get_icon_font_family' ) ) {
                    $font_family = et_pb_get_icon_font_family($value);
                } else {
                    $font_family = 'ETmodules';
                }
                $processed_icon = wp_doing_ajax() && ! ET_BUILDER_LOAD_ON_AJAX ? esc_attr( $value ) : esc_attr( et_pb_process_font_icon( $value ) );
                $icon_output[] = 'data-icon_' . esc_attr( $attr ) . '="' . $processed_icon . '" data-icon_family_' . esc_attr( $attr ) . '="' . $font_family . '"';
            }

            $icon_output = implode( ' ', $icon_output );
        }

        if ( ! $single ) {
            return sprintf(
                '<p class="product woocommerce add_to_cart_inline">
                    <a href="%1$s" data-quantity="%2$s" class="%3$s" %4$s %6$s>%5$s</a>
                </p>',
                esc_url( $product->add_to_cart_url() ),
                esc_attr( isset( $args['quantity'] ) ? $args['quantity'] : 1 ),
                esc_attr( isset( $args['class'] ) ? $args['class'] : 'button' ),
                isset( $args['attributes'] ) ? wc_implode_html_attributes( $args['attributes'] ) : '',
                empty( $button_text ) ? esc_html( $product->add_to_cart_text() ) : dwe_add_to_cart_button_text( $product, $button_text ),
                ! empty( $icon ) ? $icon_output : ''
            );
        } else {
            return sprintf(
                '<button type="submit" data-cart_url="%6$s" data-product_type="%5$s" class="%1$s" %2$s %4$s %7$s %8$s>%3$s</button>',
                esc_attr( isset( $args['class'] ) ? $args['class'] : 'button' ),
                isset( $args['attributes'] ) ? wc_implode_html_attributes( $args['attributes'] ) : '',
                esc_html( $product->single_add_to_cart_text() ),
                ! empty( $icon ) ? $icon_output : '',
                esc_attr( $product->get_type() ),
                'external' === $product->get_type() ? esc_url( $product->add_to_cart_url() ) : $product->get_permalink(),
                'simple' === $product->get_type() ? 'name="add-to-cart"' : '',
                'simple' === $product->get_type() ? sprintf( 'value="%1$s"', intval( $product_id ) ) : ''
            );
        }
    }
}

if ( ! function_exists( 'aioc__add_to_cart_button_text' ) ) {
    function aioc__add_to_cart_button_text( $el_product, $text ) {
        $product_type   = $el_product->get_type();
        $button_text    = esc_html( $el_product->add_to_cart_text() );

        switch( $product_type ) {
            case 'external':
                if ( '' !== $text['external'] ) {
                    $button_text = esc_html( $text['external'] );
                }
                break;

            case 'variable':
                if ( aioc__is_variations_in_stock( $el_product ) ) {
                    if ( '' !== $text['variable'] && $el_product->is_purchasable() ) {
                        $button_text = esc_html( $text['variable'] );
                    }
                } else if ( '' !== $text['out_of_stock'] ) {
                    $button_text = esc_html( $text['out_of_stock'] );
                }
                break;

            case 'grouped':
                if ( '' !== $text['grouped'] ) {
                    $button_text = esc_html( $text['grouped'] );
                }
                break;

            case 'simple':
                if ( $el_product->is_in_stock() ) {
                    if ( '' !== $text['simple'] && $el_product->is_purchasable() ) {
                        $button_text = esc_html( $text['simple'] );
                    }
                } else if ( '' !== $text['out_of_stock'] ) {
                    $button_text = esc_html( $text['out_of_stock'] );
                }
                break;

            default:
                break;
        }

        return $button_text;
    }
}

if ( ! function_exists( 'aioc__is_variations_in_stock' ) ) {
    function aioc__is_variations_in_stock( $el_product ) {
        $variations = $el_product->get_available_variations();
        foreach( $variations as $variation ) {
            $variation_id   = $variation['variation_id'];
            $variation_obj  = new WC_Product_variation( $variation_id );
            if ( $variation_obj && $variation_obj->is_in_stock() ) {
                return true;
            }
        }
        return false;
    }
}

if ( ! function_exists( 'aioc__is_grouped_products_in_stock' ) ) {
    function aioc__is_grouped_products_in_stock( $el_product ) {
        $children = $el_product->get_children();
        if ( is_array( $children ) && ! empty( $children ) ) {
            foreach ( $children as $child ) {
                $child_obj = wc_get_product( $child );
                if ( $child_obj && $child_obj->is_in_stock() ) {
                    return true;
                }
            }
        }
        return false;
    }
}

if ( ! function_exists( 'aioc__is_product_in_stock' ) ) {
    function aioc__is_product_in_stock( $el_product ) {
        $product_type = $el_product->get_type();

        switch( $product_type ) {
            case 'variable':
                return aioc__is_variations_in_stock( $el_product );
                break;

            case 'grouped':
                return aioc__is_grouped_products_in_stock( $el_product );
                break;

            case 'simple':
                return $el_product->is_in_stock();
                break;

            default:
                return true;
                break;
        }

        return true;
    }
}
    
if ( ! function_exists( 'aioc__product_gallery_image' ) ) {
    function aioc__product_gallery_image( $attachment_id, $image_size, $main_image = false ) {
        $gallery_thumbnail = wc_get_image_size( 'gallery_thumbnail' );
        $thumbnail_size    = apply_filters( 'woocommerce_gallery_thumbnail_size', array( $gallery_thumbnail['width'], $gallery_thumbnail['height'] ) );
        $thumbnail_src     = wp_get_attachment_image_src( $attachment_id, $thumbnail_size );
        $full_src          = wp_get_attachment_image_src( $attachment_id, 'full' );
        $alt_text          = trim( wp_strip_all_tags( get_post_meta( $attachment_id, '_wp_attachment_image_alt', true ) ) );
        $image             = wp_get_attachment_image(
            $attachment_id,
            $image_size,
            false,
            array(
                'title'                   => _wp_specialchars( get_post_field( 'post_title', $attachment_id ), ENT_QUOTES, 'UTF-8', true ),
                'data-caption'            => _wp_specialchars( get_post_field( 'post_excerpt', $attachment_id ), ENT_QUOTES, 'UTF-8', true ),
                'data-src'                => esc_url( $full_src[0] ),
                'data-large_image'        => esc_url( $full_src[0] ),
                'data-large_image_width'  => esc_attr( $full_src[1] ),
                'data-large_image_height' => esc_attr( $full_src[2] ),
                'class'                   => esc_attr( $main_image ? 'wp-post-image' : '' ),
            )
        );

        return sprintf(
            '<div data-mfp-src="%1$s" data-thumb="%2$s" data-thumb-alt="%3$s" class="aioc__product_gallery_image">%4$s</div>',
            esc_url( $full_src[0] ),
            esc_url( $thumbnail_src[0] ),
            esc_attr( $alt_text ),
            et_core_intentionally_unescaped( $image, 'html' )
        );
    }
}

/**
 * Get query args.
 *
 * @since 1.0.0
 * @param array $args The arguments of carousel.
 * @return array $qu_args The query args.
 */
function aioc_products_carousel_prepare_query_args( $args ) {
    
    $qu_args = array(
        'post_type'   => 'product',
        'post_status' => 'publish',
        'offset'      => intval( $args['offset_number'] ),
    );

    // Number of posts to get
    if ( isset( $args['products_number'] ) ) {
        $qu_args['posts_per_page'] = intval( $args['products_number'] );
    }

    $qu_args['tax_query'] = array( array(
        'taxonomy'  => 'product_visibility',
        'terms'     => 'exclude-from-catalog',
        'field'     => 'slug',
        'operator'  => 'NOT IN',
    ) );

    $tax_query  = array();
    $meta_query = array();

    // Check with post view type
    if ( ! empty( $args['view_type'] ) ) {
        switch ( $args['view_type'] ) {
            case 'featured':
                $qu_args['tax_query'][] = array(
                    'taxonomy'  => 'product_visibility',
                    'field'     => 'name',
                    'terms'     => 'featured',
                    'operator'  => 'IN',
                );
                break;
            case 'sale':
                $sale_ids               = wc_get_product_ids_on_sale();
                $qu_args['post__in']    = $sale_ids;
                break;
            case 'best_selling':
                $qu_args['meta_key']    = 'total_sales';
                $qu_args['order']       = 'DESC';
                $qu_args['orderby']     = 'meta_value_num';
                break;
            case 'top_rated':
                $qu_args['meta_key']    = '_wc_average_rating';
                $qu_args['order']       = 'DESC';
                $qu_args['orderby']     = 'meta_value_num';
                break;
        }
    }

    // Includes categories
    if ( ! empty( $args['include_categories'] ) ) {
        $tax_query[] = array(
            'taxonomy' => 'product_cat',
            'field'    => 'term_id',
            'terms'    => array_map( 'intval', explode( ',', $args['include_categories'] ) ),
            'operator' => 'IN',
        );
    }

    if ( ! empty( $args['include_tags'] ) ) {
        $tax_query[] = array(
            'taxonomy' => 'product_tag',
            'field'    => 'term_id',
            'terms'    => array_map( 'intval', explode( ',', $args['include_tags'] ) ),
            'operator' => 'IN',
        );
    }

    if ( isset($args['hide_out_of_stock']) && 'on' === $args['hide_out_of_stock'] ) {
        $meta_query[] = array(
            array(
                'key'       => '_stock_status',
                'value'     => 'instock',
                'compare'   => 'IN',
            ),
            array(
                'key'       => '_stock_status',
                'value'     => 'onbackorder',
                'compare'   => 'IN',
            ),
            'relation'  => 'OR'
        );
    }

    // Order by and order
    if ( '' !== $args['products_order_by'] ) {
        if ( 'price' === $args['products_order_by'] ) {
            $args['orderby']    = 'meta_value_num';
            $args['meta_key']   = '_price';
        } else if( 'stock_status' === $args['products_order_by'] ) {
            $args['orderby']    = 'meta_value';
            $args['meta_key']   = '_stock_status';
        } else {
            $args['orderby'] = sanitize_text_field( $args['products_order_by'] );
        }
    }
    if ( '' !== $args['products_order'] ) {
        $args['order'] = sanitize_text_field( $args['products_order'] );
    }

    if ( ! empty( $tax_query ) ) {
        if ( count( $tax_query ) > 1 ) {
            $tax_query['relation']  = !empty($args['taxonomies_relation']) ? sanitize_text_field( $args['taxonomies_relation'] ) : 'OR';
        }
        $qu_args['tax_query'][] = $tax_query;
    }
    $qu_args['tax_query']['relation'] = 'AND';

    if ( ! empty( $meta_query ) ) {
        $qu_args['meta_query'] = $meta_query;
    }

    $qu_args = apply_filters( 'aioc_product_carousel_query_args', $qu_args, $args );
    return $qu_args;
}

/**
 * Before carousel hooks as per display settings.
 *
 * @since 1.0.0
 * @param array $args The arguments of carousel.
 */
function aioc_products_carousel_before_hooks( $args ) {

    // Reverse Divi default actions.
    add_action( 'woocommerce_after_shop_loop_item', 'woocommerce_template_loop_add_to_cart', 10 );

    if ( isset($args['show_thumbnail']) && 'off' === $args['show_thumbnail'] ) {
        aioc_remove_hooks( 'woocommerce_before_shop_loop_item_title', 'woocommerce_template_loop_product_thumbnail' );
    }
    if ( ! empty( $args['thumbnail_size'] ) ) {
        add_filter( 'single_product_archive_thumbnail_size', 'aioc_product_carousel_image_size', 10 );
    }

    if ( isset($args['show_rating']) && 'off' === $args['show_rating'] ) {
        aioc_remove_hooks( 'woocommerce_after_shop_loop_item_title', 'woocommerce_template_loop_rating' );
    }
    if ( isset($args['show_price']) && 'off' === $args['show_price'] ) {
        aioc_remove_hooks( 'woocommerce_after_shop_loop_item_title', 'woocommerce_template_loop_price' );
    }
    if ( isset($args['show_add_to_cart']) && 'off' === $args['show_add_to_cart'] ) {
        aioc_remove_hooks( 'woocommerce_after_shop_loop_item', 'woocommerce_template_loop_add_to_cart' );
    }

    if ( isset($args['enable_quickview']) && 'on' === $args['enable_quickview'] ) {
        add_action( 'woocommerce_product_get_image', 'aioc_product_carousel_quick_view_button', 15, 2 );
    }

    if ( isset($args['hide_out_of_stock']) && 'off' === $args['hide_out_of_stock'] && 
        isset($args['enable_out_of_stock_label']) && 'on' === $args['enable_out_of_stock_label'] ) {
        if ( 'layout2' === $args['product_layout'] ) {
            add_action( 'woocommerce_shop_loop_item_title', 'aioc_product_carousel_outofstock_badge', 9 );
        } else {
            add_action( 'woocommerce_before_shop_loop_item_title', 'aioc_product_carousel_outofstock_badge', 10 );
        }
    }

    $show_sale_badge = isset( $args['show_sale_badge'] ) ? $args['show_sale_badge'] : 'on';
    if ( 'off' === $show_sale_badge ) {
        aioc_remove_hooks( 'woocommerce_before_shop_loop_item_title', 'woocommerce_show_product_loop_sale_flash' );
    } elseif ( 'on' === $show_sale_badge ) {
        $sale_badge_text = isset( $args['sale_badge_text'] ) ? $args['sale_badge_text'] : 'label';
        $sale_label_text = isset( $args['sale_label_text'] ) ? $args['sale_label_text'] : '';
        
        add_filter( 'woocommerce_sale_flash', 'aioc_product_carousel_sale_badge', 10, 3 );
    }

    if ( 'layout1' === $args['product_layout'] && 'on' === $args['show_price'] && 'on' === $args['show_add_to_cart'] ) {
        aioc_remove_hooks( 'woocommerce_after_shop_loop_item_title', 'woocommerce_template_loop_price' );
        aioc_remove_hooks( 'woocommerce_after_shop_loop_item', 'woocommerce_template_loop_add_to_cart' );
        add_action( 'woocommerce_after_shop_loop_item', 'aioc_product_carousel_layout1_bottom', 10 );
    }

    if ( 'layout2' === $args['product_layout'] && 'on' === $args['show_thumbnail'] && 'on' === $args['show_add_to_cart'] ) {
        add_action( 'woocommerce_before_shop_loop_item', 'aioc_add_div_to_top', 0 );
        aioc_remove_hooks( 'woocommerce_after_shop_loop_item', 'woocommerce_template_loop_add_to_cart' );
        add_action( 'woocommerce_before_shop_loop_item_title', 'aioc_woocommerce_template_loop_product_thumbnail', 10 );
    }

    // Check equal height.
    if ( isset($args['equalize_slides_height']) && 'on' === $args['equalize_slides_height'] ) {
        add_filter( 'woocommerce_loop_add_to_cart_link', 'aioc_add_wrap_for_addtocart', 999, 3 );
    }

    // Check lazy load disabled.
    if ( isset($args['disable_lazyload']) && 'on' === $args['disable_lazyload'] ) {
        add_filter( 'wp_get_attachment_image_attributes', 'aioc_disable_lazy_load_image_classes', 999, 3 );
    }
    
    add_filter( 'woocommerce_product_add_to_cart_text', 'aioc_change_add_to_cart_text', 20, 2 );
    add_filter( 'woocommerce_post_class', 'aioc_manage_loop_product_class' );
}

/**
 * After carousel hooks as per display settings.
 *
 * @since 1.0.0
 * @param array $args The arguments of carousel.
 */
function aioc_products_carousel_after_hooks( $args ) {

    // Add hooks.
    aioc_add_hooks();

    // Reverse Divi default actions.
    remove_action( 'woocommerce_after_shop_loop_item', 'woocommerce_template_loop_add_to_cart', 10 );
    remove_action( 'woocommerce_before_shop_loop_item_title', 'aioc_product_carousel_quick_view_button', 15, 2 );
    
    remove_filter( 'single_product_archive_thumbnail_size', 'aioc_product_carousel_image_size', 10 );
    remove_filter( 'woocommerce_sale_flash', 'aioc_product_carousel_sale_badge', 10, 3 );

    if ( isset($args['hide_out_of_stock']) && 'off' === $args['hide_out_of_stock'] && 
        isset($args['enable_out_of_stock_label']) && 'yes' === $args['enable_out_of_stock_label'] ) {
        if ( 'layout2' === $args['product_layout'] ) {
            remove_action( 'woocommerce_shop_loop_item_title', 'aioc_product_carousel_outofstock_badge', 9 );
        } else {
            remove_action( 'woocommerce_before_shop_loop_item_title', 'aioc_product_carousel_outofstock_badge', 10 );
        }
    }

    // Layout 1 hooks.
    if ( 'layout1' === $args['product_layout'] && 'on' === $args['show_price'] && 'on' === $args['show_add_to_cart'] ) {
        remove_action( 'woocommerce_after_shop_loop_item', 'aioc_product_carousel_layout1_bottom', 10 );
    }

    // Layout 2 hooks.
    if ( 'layout2' === $args['product_layout'] && 'on' === $args['show_thumbnail'] && 'on' === $args['show_add_to_cart'] ) {
        remove_action( 'woocommerce_before_shop_loop_item', 'aioc_add_div_to_top', 0 );
        remove_action( 'woocommerce_before_shop_loop_item_title', 'aioc_woocommerce_template_loop_product_thumbnail', 10 );
    }

    // Check equal height.
    if ( isset($args['equalize_slides_height']) && 'on' === $args['equalize_slides_height'] ) {
        remove_filter( 'woocommerce_loop_add_to_cart_link', 'aioc_add_wrap_for_addtocart', 999, 3 );
    }

    // Check lazy load disabled.
    if ( isset($args['disable_lazyload']) && 'on' === $args['disable_lazyload'] ) {
        remove_filter( 'wp_get_attachment_image_attributes', 'aioc_disable_lazy_load_image_classes', 999, 3 );
    }

    remove_filter( 'woocommerce_product_add_to_cart_text', 'aioc_change_add_to_cart_text', 20, 2 );
    remove_filter( 'woocommerce_post_class', 'aioc_manage_loop_product_class' );
}

/**
 * Remove hooks.
 *
 * It will remove default and custom hooks for woocommerce.
 *
 * @since 1.0.0
 * @param string  $hook_name The name of hook.
 * @param string  $callback The name of callback function.
 * @param boolean $to_add Add after or not.
 */
function aioc_remove_hooks( $hook_name, $callback, $to_add = true ) {
    global $wp_filter;
    $check_hooks   = array(
        'woocommerce_before_shop_loop_item',
        'woocommerce_before_shop_loop_item_title',
        'woocommerce_shop_loop_item_title',
        'woocommerce_after_shop_loop_item_title',
        'woocommerce_after_shop_loop_item',
    );
    $removed_hooks = wp_cache_get( 'aioc_removed_hooks' );
    if ( empty( $removed_hooks ) ) {
        $removed_hooks = array();
    }
    $hook_data  = array(
        'hook'     => $hook_name,
        'callback' => $callback,
    );
    $has_action = has_action( $hook_name, $callback );

    if ( false !== $has_action ) {
        $hook_data['priority']      = $has_action;
        $hook_data['accepted_args'] = 1;
        $removed                    = remove_action( $hook_name, $callback, $has_action );

        if ( $removed && $to_add ) {
            $removed_hooks[] = $hook_data;
        }
    } else {
        foreach ( $check_hooks as $key => $hook ) {
            $hook_data['hook'] = $hook;
            $get_hook          = isset( $wp_filter[ $hook ] ) ? $wp_filter[ $hook ] : array();
            if ( ! empty( $get_hook ) ) {
                $callbacks = $get_hook->callbacks;
                foreach ( $callbacks as $priority => $_callback ) {
                    if ( isset( $_callback[ $callback ]['function'] ) && $_callback[ $callback ]['function'] === $callback ) {
                        $accepted_args              = isset( $_callback[ $callback ]['accepted_args'] ) ? $_callback[ $callback ]['accepted_args'] : 1;
                        $removed                    = remove_action( $hook, $callback, $priority, $accepted_args );
                        $hook_data['priority']      = $priority;
                        $hook_data['accepted_args'] = $accepted_args;
                        if ( $removed && $to_add ) {
                            $removed_hooks[] = $hook_data;
                        }
                    }
                }
            }
        }
    }

    wp_cache_set( 'aioc_removed_hooks', $removed_hooks );
}

/**
 * Add before removed hooks.
 *
 * It will add default and custom hooks for woocommerce.
 *
 * @since 1.0.0
 */
function aioc_add_hooks() {
    $removed_hooks = wp_cache_get( 'aioc_removed_hooks' );
    if ( ! empty( $removed_hooks ) ) {
        foreach ( $removed_hooks as $key => $hookdata ) {
            add_action( $hookdata['hook'], $hookdata['callback'], $hookdata['priority'], $hookdata['accepted_args'] );
        }
        wp_cache_delete( 'aioc_removed_hooks' );
    }
}

/**
 * Change add to cart text
 */
function aioc_change_add_to_cart_text( $button_text, $product ) {

    global $aioc_product_carousel_args;

    $product_type   = $product->get_type();
    switch( $product_type ) {
        case 'external':
            if ( ! empty( $aioc_product_carousel_args['external_add_to_cart_text'] ) ) {
                $button_text = esc_html( $aioc_product_carousel_args['external_add_to_cart_text'] );
            }
            break;
        case 'variable':
            if ( ! empty( $aioc_product_carousel_args['variable_add_to_cart_text'] ) ) {
                $button_text = esc_html( $aioc_product_carousel_args['variable_add_to_cart_text'] );
            }
            break;
        case 'grouped':
            if ( ! empty( $aioc_product_carousel_args['grouped_add_to_cart_text'] ) ) {
                $button_text = esc_html( $aioc_product_carousel_args['grouped_add_to_cart_text'] );
            }
            break;
        case 'simple':
            if ( ! empty( $aioc_product_carousel_args['simple_add_to_cart_text'] ) && $product->is_purchasable() && $product->is_in_stock() ) {
                $button_text = esc_html( $aioc_product_carousel_args['simple_add_to_cart_text'] );
            } else if ( !empty( $aioc_product_carousel_args['out_of_stock_add_to_cart_text'] ) ) {
                $button_text = esc_html( $aioc_product_carousel_args['out_of_stock_add_to_cart_text'] );
            }
            break;
        default:
            break;
    }

    return $button_text;
}

/**
 * remove product class
 */
function aioc_manage_loop_product_class( $classes ) {

    global $aioc_product_carousel_args;

    if ( ! isset($aioc_product_carousel_args['compute_mode']) || false === $aioc_product_carousel_args['compute_mode'] ) {
        $classes[] = 'swiper-slide';
    }

    $last_key  = array_search( 'last', $classes );
    if ( false !== $last_key ) {
        unset( $classes[ $last_key ] );
    }
    $first_key = array_search( 'first', $classes );
    if ( false !== $first_key ) {
        unset( $classes[ $first_key ] );
    }
    return $classes;
}

/**
 * Filter product image size.
 *
 * @since 1.0.0
 * @param string $size (default: 'woocommerce_thumbnail').
 * @return string The size of product image.
 */
function aioc_product_carousel_image_size( $size ) {
    global $aioc_product_carousel_args;
    return $aioc_product_carousel_args['thumbnail_size'];
}

/**
 * Display quick view link.
 *
 * @since 1.0.0
 * @param string $image Image html.
 * @param object $product The product object.
 * @return string The html markup of image.
 */
function aioc_product_carousel_quick_view_button( $image, $product ) {

    global $aioc_product_carousel_args;

    // If product object has error
    if ( empty( $product ) ) {
        return $image;
    }

    $icon        = '';
    $has_icon    = '';
    $pro_id      = $product->get_id();
    $button_text = isset( $aioc_product_carousel_args['quickview_link_text'] ) ? esc_html( $aioc_product_carousel_args['quickview_link_text'] ) : '';
    
    // Check for icon.
    if ( ! empty( $aioc_product_carousel_args['quickview_link_icon'] ) ) {
        $has_icon = ' has-icon';
        $icon     = ' data-icon="' . esc_attr( et_pb_process_font_icon( esc_html($aioc_product_carousel_args['quickview_link_icon']) ) ) . '"';
    }

    $has_text = ! empty( $button_text ) ? ' has-text' : '';

    ob_start();

    if ( ! empty( $button_text ) || ! empty( $icon ) ) {
        do_action( 'aioc_product_carousel_before_quick_view_button_wraper', $product, $image, $aioc_product_carousel_args );
        if ( isset( $aioc_product_carousel_args['product_layout'] ) && 'layout2' !== $aioc_product_carousel_args['product_layout'] ) { ?>
            <div class="aioc-product__overlay">
        <?php }
            do_action( 'aioc_product_carousel_before_quick_view_button', $product, $image, $aioc_product_carousel_args ); ?>
                <button class="et_pb_button button wp-element-button aioc-quick-view-button <?php echo esc_attr( $has_icon . ' ' . $has_text  ); ?>" 
                    type="button" data-product_id="<?php echo esc_attr( $pro_id ); ?>" <?php echo et_core_intentionally_unescaped( $icon, 'html' ); ?>>
                    <?php 
                    do_action( 'aioc_product_carousel_before_quick_view_text', $product, $aioc_product_carousel_args );
                    echo esc_html( $button_text );
                    do_action( 'aioc_product_carousel_after_quick_view_text', $product, $image, $aioc_product_carousel_args ); ?>       
                </button>
            <?php do_action( 'aioc_product_carousel_after_quick_view_button', $product, $image, $aioc_product_carousel_args );
        if ( isset( $aioc_product_carousel_args['product_layout'] ) && 'layout2' !== $aioc_product_carousel_args['product_layout'] ) { ?>
            </div>
        <?php }
        do_action( 'aioc_product_carousel_after_quick_view_button_wraper', $product, $image, $aioc_product_carousel_args );
    }
    
    $html = ob_get_clean();
    
    $html = apply_filters( 'aioc_product_carousel_quick_view_button', $html, $image, $product, $aioc_product_carousel_args );

    $image .= $html;
    return $image;
}

/**
 * Display custom label or percentage to sale badge.
 *
 * @since 1.0.0
 * @param string $html The markup of sale bage.
 * @param object $post The post object.
 * @param object $product The product object.
 * @return string $html The html markup of sale badge.
 */
function aioc_product_carousel_sale_badge( $html, $post, $product ) {

    global $aioc_product_carousel_args;

    //$sale_text = esc_html__( 'Sale!', 'all-in-one-carousel-for-divi' );
    $sale_text = wp_strip_all_tags( $html );

    if ( 'percentage' === $aioc_product_carousel_args['sale_badge_text'] ) {
        $percentages = array();
        $percentage  = '';
        if ( $product->is_type( 'variable' ) ) {
            $prices = $product->get_variation_prices();
            foreach ( $prices['price'] as $key => $price ) {
                if ( $prices['regular_price'][ $key ] !== $price ) {
                    if ( $prices['sale_price'][ $key ] >= 0 ) {
                        $percentages[] = round( 100 - ( $prices['sale_price'][ $key ] / $prices['regular_price'][ $key ] * 100 ) );
                    } else {
                        $percentages[] = 100;
                    }
                }
            }
        } elseif ( $product->is_type( 'grouped' ) ) {
            $percentages = array();
            $children    = array_filter( array_map( 'wc_get_product', $product->get_children() ), 'wc_products_array_filter_visible_grouped' );

            foreach ( $children as $child ) {
                if ( $child->is_purchasable() && ! $child->is_type( 'grouped' ) && $child->is_on_sale() ) {
                    $regular_price = (float) $child->get_regular_price();
                    $sale_price    = (float) $child->get_sale_price();

                    if ( $sale_price >= 0 ) {
                        $percentages[] = round( 100 - ( $sale_price / $regular_price * 100 ) );
                    } else {
                        $percentages[] = 100;
                    }
                }
            }
        } else {
            $regular_price = (float) $product->get_regular_price();
            $sale_price    = (float) $product->get_sale_price();

            $percentage = '100%';
            if ( $sale_price >= 0 ) {
                $percentage = round( 100 - ( $sale_price / $regular_price * 100 ) ) . '%';
            }
        }

        if ( empty( $percentage ) && ! empty( $percentages ) ) {
            $max_percentage = max( $percentages );
            $min_percentage = min( $percentages );
            $percentage     = sprintf( '%s%%', $max_percentage );
        }

        $sale_text = $percentage;

        // $html = str_replace( $sale_text, $percentage, $html );
    } elseif ( ! empty($aioc_product_carousel_args['sale_label_text']) ) {
        $sale_text = esc_html( $aioc_product_carousel_args['sale_label_text'] );
        // $html     = str_replace( $sale_text, $new_text, $html );
    }

    $new_html = sprintf( '<span class="aioc-onsale">%1$s</span>', esc_html( $sale_text ) );

    return apply_filters( 'aioc_product_carousel_sale_badge', $new_html, $html, $post, $product, $aioc_product_carousel_args );
}

/**
 * Display product carousel layout 1
 *
 * @since 1.0.0
 */
function aioc_product_carousel_layout1_bottom() { ?>
    <?php
    do_action( 'aioc_product_carousel_before_layout1_bottom' ); ?>
    
    <div class="aioc-product-bottom">
        <?php do_action( 'aioc_product_carousel_before_layout1_bottom_price' ); ?>
        <span class="aioc-product-bottom-price">
            <?php woocommerce_template_loop_price(); ?>
        </span>
        <span class="aioc-product-bottom-add-to-cart">
            <?php woocommerce_template_loop_add_to_cart(); ?>
        </span>
        <?php do_action( 'aioc_product_carousel_after_layout1_bottom_addtocart' ); ?>
    </div>

    <?php 
    do_action( 'aioc_product_carousel_after_layout1_bottom' );
}

/**
 * Display wraper for layout 2.
 *
 * @since 1.0.0
 */
function aioc_add_div_to_top() {
    do_action( 'aioc_product_carousel_before_layout2_top' );
    echo '<span class="aioc-layout-wraper">';
    do_action( 'aioc_product_carousel_after_layout2_top' );
}

/**
 * Display product carousel layout 2.
 *
 * @since 1.0.0
 */
function aioc_woocommerce_template_loop_product_thumbnail() {
    do_action( 'aioc_product_carousel_before_layout2_closing_a' );
    echo '</a>';
    do_action( 'aioc_product_carousel_before_layout2_addtocart' );
        woocommerce_template_loop_add_to_cart();
    do_action( 'aioc_product_carousel_after_layout2_addtocart' );
    echo '</span>';
    do_action( 'aioc_product_carousel_after_layout2_closing_span' );
    woocommerce_template_loop_product_link_open();
}

/**
 * Display custom out of stock badge.
 *
 * @since 1.0.0
 */
function aioc_product_carousel_outofstock_badge() {

    global $product, $aioc_product_carousel_args;
    if ( ! $product->is_in_stock() ) {

        $availability = $product->get_availability();
        $class        = esc_attr( $availability['class'] );

        if ( ! empty( $aioc_product_carousel_args['out_of_stock_label'] ) ) {
            $out_text = esc_html( $aioc_product_carousel_args['out_of_stock_label'] );
        } else {
            $all_status_text = wc_get_product_stock_status_options();
            $out_text        = $all_status_text['outofstock'];
        }

        $html      = sprintf( '<div class="aioc-products-soldout-wrap"><span class="soldout-text stock %s">%s</span></div>', $class, $out_text );
        $finalhtml = apply_filters( 'woocommerce_get_stock_html', $html, $product );
        $finalhtml = apply_filters( 'aioc_product_carousel_outofstock_badge', $finalhtml, $product, $aioc_product_carousel_args );
        echo $finalhtml; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
    }
}

/**
 * Add wraper to add to cart button for equal height.
 *
 * @since 1.0.0
 * @param string $button The html markup of add to cart button.
 * @param object $product The product object.
 * @param array  $args The add to cart button arguments.
 */
function aioc_add_wrap_for_addtocart( $button, $product, $args ) {

    ob_start();
    do_action( 'aioc_product_carousel_before_euheight_addtocart_wrap' );
    echo '<div class="aioc-add-to-cart-wrap">';
        do_action( 'aioc_product_carousel_before_euheight_addtocart' );
            echo $button; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
        do_action( 'aioc_product_carousel_after_euheight_addtocart' );
    echo '</div>';
    do_action( 'aioc_product_carousel_after_euheight_addtocart_wrap' );

    $button = ob_get_clean();
    return $button;
}

/**
 * Add product image classes to disable lazy load.
 *
 * @param array $attr image attributes
 * @param object $attachment attachment object
 * @param string $size image size
 * @return void
 */
function aioc_disable_lazy_load_image_classes( $attr, $attachment, $size ) {
    $attr['class'] .= ' no-lazyload skip-lazy';

    return  $attr;
}

/**
 * Before carousel hooks quick view popup as per display settings.
 *
 * @since 1.0.0
 */
function aioc_products_carousel_before_quick_view_popup_hooks() {
    add_filter( 'woocommerce_sale_flash', 'aioc_product_carousel_sale_badge', 10, 3 );
}

/**
 * Before carousel hooks quick view popup as per display settings.
 *
 * @since 1.0.0
 */
function aioc_products_carousel_after_quick_view_popup_hooks() {
    remove_filter( 'woocommerce_sale_flash', 'aioc_product_carousel_sale_badge', 10, 3 );
}