<?php

/* * *************************************************************************
 *
 *  ----------------------------------------------------------------------
 *                      DO NOT EDIT THIS FILE
 *  ----------------------------------------------------------------------
 *
 *                       Copyright (C) Themify
 *
 *  ----------------------------------------------------------------------
 *
 * ************************************************************************* */

if (!defined('ABSPATH'))
    exit; // Exit if accessed directly

    /*  Utilities
      /************************************************************************** */

function themify_clear_menu_cache() {
    global $wpdb;
    $wpdb->query("DELETE FROM $wpdb->options WHERE `option_name` LIKE ('_transient_tf_menu_%')");
    return Themify_Storage::deleteByPrefix('tf_menu_');
}


/**
 * Image Helper - Echoes themify_get_image
 * @param string $args Format string.
 */
function themify_image($args) {//deprecated use themify_get_image
    echo themify_get_image($args);
}

function themify_find_nearest_image_size(?int $attachment_id,int $width,int $height ) : string {
    $image_meta = wp_get_attachment_metadata( $attachment_id );
    $size = '';
    if ( ! empty( $image_meta['sizes'] ) ) {
        $last_pixel_count = 0;
        foreach ( $image_meta['sizes'] as $key => $value ) {
            /* image size is smaller than what we need, skip */
            if ( $width > $value['width'] || $height > $value['height'] ) {
                continue;
            }

            /* find smallest size */
            $pixels = $value['width'] * $value['height'];
            if ( $last_pixel_count === 0 || $pixels < $last_pixel_count ) {
                $last_pixel_count = $pixels;
                $size = $key;
            }
        }
    }

    return $size;
}

/**
 * Returns the post image, either from Themify Custom Panel fields or from WordPress Featured Image.
 * @param string|array $args Format string.
 * @return string String with <img> tag and optional content prepended and/or appended
 */
function themify_get_image($args):string {
    global $themify;
    /**
     * List of parameters
     * @var array
     */
    $defaults = array(
        'src' => '',
        'class' => '',
        'style' => '',
        'preload' => false,
        'prefetch' => false,
        'lazy_load' => true,
        'is_slider' => false,
        'disable_responsive' => false,
        'w' => '', // width
        'h' => '', // height
        'before' => '',
        'after' => '',
        'alt' => '',
        'title' => '',
        'crop' => true,
        'field_name' => 'post_image,image,wp_thumb,feature_image',
        'urlonly' => false,
        'image_size' => '',
        'image_meta' => false,
        'f_image' => false,
        'attr' => array(),
        'fallback' => ''//when there is no image
    );
    if (is_string($args)) {
        $arr = array();
        parse_str($args, $arr);
        $args = array();
        foreach ($arr as $k => $v) {
            if ($v === 'true') {
                $args[$k] = true;
            } elseif ($v === 'false') {
                $args[$k] = false;
            } else {
                $args[$k] = $v;
            }
        }
    }
    $args+=$defaults;
    unset($defaults);
    /**
     * Post ID for single, query or archive views.
     * Page ID is stored separately in $themify->page_id.
     * @var string
     */
    $post_id = get_the_ID();

    /**
     * URL of the image to use
     * @var string
     */
    $img_url = '';

    /**
     * Image width
     * @var string
     */
    $width = $args['w'];
    if ($width !== '') {
        $width = (int) $width;
    }
    /**
     * Image height
     * @var string
     */
    $height = $args['h'];
    if ($height !== '') {
        $height = (int) $height;
    }

    $attachment_id = 0;

    $is_disabled = themify_is_image_script_disabled();
    if (is_numeric($args['src'])) {
        $attachment_id = $args['src'];
        $img = wp_get_attachment_image_src($attachment_id, 'large');
        $args['src'] = !empty($img[0]) ? $img[0] : '';
        unset($img);
    } elseif ($args['fallback'] !== '' && empty($args['src']) && !has_post_thumbnail()) {
        $args['src'] = $args['fallback'];
    }
    if ($is_disabled === true) { // Use WP standard image sizes
        if (!empty($args['image_size'])) { // If image_size parameter is set
            $feature_size = $args['image_size'];
        } elseif (!empty($themify->image_size)) { // or if Themify::image_size is set
            $feature_size = $themify->image_size;
        } elseif (empty($themify->is_shortcode) && in_the_loop()) { // Main query area
            if (is_single()) {
                $feature_size = get_post_meta($post_id, 'feature_size', true);
                if (empty($feature_size) || 'blank' === $feature_size) {
                    $feature_size = themify_get('setting-image_post_single_feature_size', null, true);
                }
            } elseif (!empty($themify->page_id) && !empty($themify->query_post_type) && themify_is_query_page()) {
                $feature_size = get_post_meta($themify->page_id, $themify->query_post_type . 'feature_size_page', true);
                if (empty($feature_size)) {
                    $feature_size = null;
                }
            } elseif (is_archive() || is_tax() || is_search() || is_home()) {
                $feature_size = themify_get('setting-image_post_feature_size', null, true);
            }
        }
        if (!empty($args['src'])) {
            $attachment_id = themify_get_attachment_id_from_url($args['src']);
        }
        if (!isset($feature_size) || 'blank' === $feature_size) {
            $feature_size = $attachment_id && ! empty( $width ) && ! empty( $height ) ? themify_find_nearest_image_size( $attachment_id, $width, $height ) : '';
            if ( $feature_size === '' ) {
                $feature_size = apply_filters('themify_global_feature_size', themify_get('setting-global_feature_size', 'large', true));
            }
        }
        if (!empty($attachment_id)) {
            $tmp = wp_get_attachment_image_src($attachment_id, $feature_size);
            if (!empty($tmp)) {
                $img_url = $tmp[0];
            }
            unset($tmp);
        }
        if ($img_url === '') {
            // Set URL to use for final output.
            $img_url = empty($args['src']) ? themify_image_url(false, $feature_size) : $args['src'];
            $img_url = trim($img_url);
            // Fix for showing feature_image when Themify Image Script is disabled
            if ('' === $img_url) {
                foreach (explode(',', $args['field_name']) as $field) {
                    if ($img_url = get_post_meta($post_id, trim($field), true))
                        break;
                }
            }
        }
    } else { // Use Image Script
        if (empty($args['src'])) {
            if (has_post_thumbnail()) {
                $img_url = $width !== '' && $height !== '' ? ((int) get_post_thumbnail_id()) : get_the_post_thumbnail_url(); /* Image script works with thumbnail IDs as well as URLs, use ID which is faster */
            } elseif ('attachment' === get_post_type()) {
                $img_url = wp_get_attachment_url($post_id);
            } else {
                foreach (explode(',', $args['field_name']) as $field) {
                    if ($img_url = get_post_meta($post_id, trim($field), true)) {
                        break;
                    }
                }
            }
        } else {
            $img_url = $args['src'];
        }
        if ($height !== '' && 0 === ((int) $height )) {
            $height = 0;
            $args['crop'] = false;
        }
        /** filter $img_url before it goes off to themify_do_img for processing * */
        $img_url = apply_filters('themify_get_image_before_do_img', $img_url, $width, $height, $args);

        // Set URL to use for final output.
        $temp = themify_do_img((empty($attachment_id) ? $img_url : $attachment_id), $width, $height, (bool) $args['crop']);
        $img_url = $temp['url'];
        if ($temp['width'] !== '' && $temp['height'] !== '') {
            $width = (int) $temp['width'];
            $height = (int) $temp['height'];
        }
        // Get title/alt text by attachment id if it was returned.
        if (!$attachment_id && isset($temp['attachment_id'])) {
            $attachment_id = $temp['attachment_id'];
        }
    }

    if ($attachment_id) {
        $attachment_id = themify_maybe_translate_object_id($attachment_id);
    }

    // No image was defined, parse content to find the first image.
    if (empty($img_url) && ($args['f_image'] || themify_check('setting-auto_featured_image', true) )) {

        $content = get_the_content();
        $upload_dir = themify_upload_dir('baseurl');
        foreach ( [ 'img', 'iframe' ] as $tag) {
            $count = substr_count($content, '<' . $tag);
            if ($count >= 1) {
                $start = strpos($content, '<' . $tag, 0);
                $pos = substr($content, $start);
                $end = strpos($pos, '>');
                $temp = themify_prep_image(substr($pos, 0, $end + 1));
                $src = $temp['src'];
                $parse = parse_url($src);
                if (!empty($parse['query'])) {
                    $src = str_replace('?' . $parse['query'], '', $src);
                }
                $auto_image_url = isset($temp['src']) ? $temp['src'] : '';
                if (isset($temp['class'])) {
                    $args['class'] .= ' ' . $temp['class'];
                }
                $args['alt'] = $temp['alt'];
                if ($is_disabled === true) {
                    $img_url = themify_image_url(false, $feature_size, themify_get_attachment_id_from_url($auto_image_url, $upload_dir));
                    if (empty($img_url)) {
                        $img_url = esc_url($auto_image_url);
                    }
                } elseif ($temp = themify_do_img($auto_image_url, $width, $height, (bool) $args['crop'])) {
                    $img_url = $temp['url'];
                }
                break;
            }
        }
        unset($content, $upload_dir);
    }

    if (!empty($img_url)) {
        if (isset($temp['is_large']) && current_user_can('edit_post', $post_id)) {
            $args['class'] .= ' tf_large_img';
        } else {
            if ($args['preload'] !== false || $args['prefetch'] !== false) {
                Themify_Enqueue_Assets::addPreLoadMedia($img_url, $args['preload'] !== false ? 'preload' : 'prefetch');
            }
            themify_generateWebp($img_url);
        }
        unset($temp);
        if ($args['urlonly']) {
            $out = $img_url;
        } else {
            // Build final image
            $out = '<img src="' . $img_url . '"';
            if ($width !== '' && $width !== 0) {
                $out .= ' width="' . $width . '"';
            }
            if ($height !== '' && $height !== 0) {
                $out .= ' height="' . $height . '"';
            }
            if ($attachment_id != 0) {
                $args['class'] .= ' wp-post-image wp-image-' . $attachment_id; /* add attachment_id class to img tag */
            }
            if ($args['class'] !== '') {
                $out .= ' class="' . trim($args['class']) . '"';
            }
            if ($args['style'] !== '') {
                $out .= ' style="' . $args['style'] . '"';
            }
            $title = '';
            if (!empty($args['alt'])) {
                $out_alt = $args['alt'];
            } else {
                $out_alt = $attachment_id ? get_post_meta($attachment_id, '_wp_attachment_image_alt', true) : '';
                if (!$out_alt) {
                    $out_alt = !empty($args['title']) ? $args['title'] : '';
                    if (!$out_alt && $attachment_id) {
                        $p = get_post($attachment_id);
                        $out_alt = !empty($p) ? $p->post_title : '';
                        $p = null;
                    }
                    if (!$out_alt) {
                        $out_alt = the_title_attribute('echo=0');
                    }
                    $title = $out_alt;
                }
            }
            if($args['title'] !== false ){
                if ($title === '') {
                    if (!empty($args['title'])) {
                        $title = $args['title'];
                    } elseif ($attachment_id) {
                        $p = get_post($attachment_id);
                        if (!empty($p)) {
                            $title = $p->post_title;
                        }
                        $p = null;
                    }
                }
                // Add title attribute only if explicitly set in $args
                if (!empty($title)) {
                    $out .= ' title="' . esc_attr($title) . '"';
                }
            }
            if ($args['lazy_load'] === false || $args['lazy_load'] === 'eager') {
                $out .= ' data-tf-not-load="1"';
                if ($args['lazy_load'] === 'eager') {
                    $out .= ' loading="eager" decoding="auto"';
                }
            }
            if (!empty($args['attr'])) {
                foreach ($args['attr'] as $k => $v) {
                    $out .= ' ' . $k . '="' . esc_attr($v) . '"';
                }
            }
            if (!empty($out_alt)) {
                $out .= ' alt="' . esc_attr($out_alt) . '"';
            }
            $out .= '>';
            if ($attachment_id && $args['disable_responsive'] === false) {
                $out = function_exists('wp_filter_content_tags') ? wp_img_tag_add_srcset_and_sizes_attr($out, null, $attachment_id) // WP 5.5
                    : wp_make_content_images_responsive($out);
            }
            if (($args['is_slider'] === true || $themify->post_layout === 'slider') && $args['lazy_load'] === true) {
                $out = themify_make_lazy($out, false);
            }
            if ($args['image_meta'] == true) {
                $out .= "<meta itemprop=\"width\" content=\"{$width}\"><meta itemprop=\"height\" content=\"{$height}\"><meta itemprop=\"url\" content=\"{$img_url}\">" . $out;
            }
            $out = $args['before'] . $out . $args['after'];
        }
    } else {
        $out = '';
    }

    return $out;
}

if (!function_exists('themify_edit_link')) {

    function themify_edit_link(string $title = '') : bool {
        static $is = null;
        if ($is === null) {
            $is = is_user_logged_in() && (!class_exists('Themify_Builder_Model',false) || !Themify_Builder::$frontedit_active === true) && !themify_is_rest();
        }
        if ($is === true) {
            if ($title === '') {
                $title = sprintf( __('Edit %s', 'themify'), '<span class="tf_hide">' . get_post_type_object( get_post_type() )->labels->singular_name . '</span>' );
            }
            edit_post_link($title, '<span class="edit-button tf_edit_post_' . get_the_ID() . '">', '</span>');
        }

        return $is;
    }

}

if (!function_exists('themify_image_url')) {

    /**
     * Returns the featured image url
     * @param bool $echo Specify to echo or return the url
     * @param string $size The image size to return
     * @param null|int $attachment_id ID of image to load.
     * @return void|string
     */
    function themify_image_url(bool $echo = false, string $size = 'full', $attachment_id = null):string {
        $url = '';
        if (has_post_thumbnail()) {
            $image = wp_get_attachment_image_src(get_post_thumbnail_id(), $size);
            $url = $image === false ? '' : $image[0];
        } elseif ($attachment_id !== null) {
            $image = wp_get_attachment_image_src($attachment_id, $size);
            if ($image) {
                $url = $image[0];
            }
        }
        $url = apply_filters('themify_image_url', $url);
        if ($echo) {
            echo esc_url($url);
            return '';
        }
        return $url;
    }

}

/**
 * Image Helper - Prep Image
 * @param $tag
 * @return array
 */
function themify_prep_image(string $tag):array {
    $image = [];
    preg_match_all( '/(alt|title|src|class)=(("|\')[^("|\')]*("|\'))/i', $tag, $image_reg );
    foreach ( $image_reg[1] as $index => $attribute ) {
        $image[ $attribute ] = substr( $image_reg[2][ $index ], 1, -1 );
    }
    $image += [ 'src' => '', 'alt' => '', 'title' => '' ];

    if (strpos($image['src'], 'youtube.com') !== false || strpos($image['src'], 'vimeo.com') !== false) {
        $image['src'] = themify_video_image($image['src']);
    }

    $image['src'] = preg_replace('/(-\d+x\d+)(?=\.\w{3,4})/', '', $image['src']);

    return $image;
}

/**
 * Vimeo / Youtube Thumbnail grab
 *
 * @param $url
 *
 * @return string
 */
function themify_video_image(string $url):string {
    $image_url = parse_url($url);
    $return_url = '';
    if ($image_url['host'] === 'www.youtube.com' || $image_url['host'] === 'youtube.com') {
        parse_str($image_url['query'], $query);
        if (!empty($query['v'])) {
            $id = $query['v'];
        } else {
            $path = explode('/', $image_url['path']);
            $id = $path[count($path) - 1];
        }
        $return_url = 'https://img.youtube.com/vi/' . $id . '/hqdefault.jpg';
    } elseif ($image_url['host'] === 'www.vimeo.com' || $image_url['host'] === 'vimeo.com' || $image_url['host'] === 'player.vimeo.com') {
        parse_str($image_url['query'], $query);
        if (!empty($query['clip_id'])) {
            $id = $query['clip_id'];
        } else {
            $path = explode('/', $image_url['path']);
            $id = $path[(count($path) - 1)];
        }
        $content = Themify_Filesystem::get_contents('https://vimeo.com/api/v2/video/' . $id . '.php');
        if (!empty($content)) {
            $hash = unserialize($content);
            if (!empty($hash[0])) {
                $return_url = $hash[0]["thumbnail_large"];
            }
        }
    }
    return $return_url;
}

/**
 * Checks if a value referenced by $var exists in theme settings or post meta data.
 * @param $var
 * @return bool
 */
function themify_check(string $var, bool $data_only = false):bool {
    $val = themify_get($var, null, $data_only);
    return $val !== null && $val !== '' && $val !== 'off';
}

/**
 * Returns a value referenced by $var checking in theme settings or post meta data.
 * @param $var
 * @return mixed
 */
function themify_get(string $var, $default = null, bool $data_only = false) {
    $data = themify_get_data();
    if (isset($data[$var]) && $data[$var] !== '') {
        return $data[$var];
    } elseif ($data_only !== true) {
        global $post;

        if (themify_is_shop() && !in_the_loop()) {
            $id = themify_shop_pageId();
        } elseif (is_object($post)) {
            $id = $post->ID;
        } else {
            $id = false;
        }

        $val = ( $id !== false && $id !== 0 ) ? get_post_meta($id, $var, true) : '';

        if ($val !== '') {
            return $val;
        }
    }

    return $default;
}

/**
 * Returns a value referenced by $meta,$var checking in theme settings or post meta data.
 * @param $meta - post meta
 * @param $var - theme settings
 * @param $default
 * @return mixed
 */
function themify_get_both(string $meta, string $var, $default = null) {
    $val = themify_get($meta);
    if ($val === null || $val === 'default') {
        $val = themify_get($var, $default, true);
    }
    return $val;
}

/**
 * Get a color value, uses themify_get and sanitizes the value
 *
 * @return string
 */
function themify_get_color_both(string $meta, string $var, $default = null) {
    $val = themify_get_color($meta);
    if ($val === null || $val === 'default') {
        $val = themify_get_color($var, $default, true);
    }
    return $val;
}

/**
 * Returns a value referenced by $meta,$var checking in theme settings or post meta data.
 * @param $meta - post meta
 * @param $var - theme settings
 * @return mixed
 */
function themify_check_both(string $meta, string $var):bool {
    $val = themify_get($meta, null);
    if ($val === null || $val === 'default') {
        $val = themify_get($var, null, true);
    }
    return $val !== null && $val !== '' && $val !== 'off';
}

function themify_shop_pageId() {
    static $id = null;
    if ($id === null) {
        if (themify_is_woocommerce_active() && function_exists( 'wc_get_page_id' ) ) {
            $id = wc_get_page_id('shop');
            if ($id <= 0) {//wc bug, page id isn't from wc settings,the default should be page with slug 'shop'
                $page = get_page_by_path('shop');
                $id = !empty($page) ? (int) $page->ID : false;
            }
        } else {
            $id = false;
        }
    }
    return $id;
}

/**
 * Get a color value, uses themify_get and sanitizes the value
 *
 * @return string
 */
function themify_get_color(string $var, $default = null, bool $data_only = false) {
    return themify_sanitize_hex_color(themify_get($var, $default, $data_only));
}

/**
 * Sanitize a string to ensure it's valid hex color code
 *
 * @since 3.1.2
 */
function themify_sanitize_hex_color($value) {
    if ($value===null || false === $value) {
        return $value;
    }
    $value = ltrim($value, '#');
    /* match 3 to 6 hex digits */
    if (preg_match('|^([A-Fa-f0-9]{3}){1,2}$|', $value)) {
        $value = '#' . $value;
    }

    return $value;
}

if (!function_exists('themify_get_image_sizes_list')) {

    /**
     * Return list of image sizes with labels for translation.
     * @param bool $nested
     * @return mixed|void
     * @since 1.6.8
     */
    function themify_get_image_sizes_list(bool $nested = true) {
        $size_names = apply_filters('image_size_names_choose',
            array(
                'thumbnail' => __('Thumbnail', 'themify'),
                'medium' => __('Medium', 'themify'),
                'large' => __('Large', 'themify'),
                'full' => __('Original Image', 'themify')
            )
        );
        $out = array(
            array('value' => 'blank', 'name' => ''),
        );
        foreach ($size_names as $size => $label) {
            $out[] = array('value' => $size, 'name' => $label);
        }
        return apply_filters('themify_get_image_sizes_list', $nested ? $out : $size_names, $nested);
    }

}

/**
 * Check if the site is using an HTTPS scheme and returns the proper url
 * @param String $url requested url
 * @return String
 * @since 1.1.5
 */
function themify_https_esc(string $url = ''):string {
    if (is_ssl()) {
        $url = str_replace('http:', 'https:', $url);
    }
    return $url;
}

/**
 * Returns an array with the post types managed by Themify,
 * where the Themify Custom Panel is initialized.
 * Filterable using themify_post_types
 * @param Array $types additional post types
 * @return Array
 * @since 1.1.5
 */
function themify_post_types(array $types = array()):array {
    $defaults = array_merge(array('post', 'page'), apply_filters('themify_specific_post_types', array('menu', 'slider', 'highlight', 'portfolio', 'testimonial', 'section')), $types);
    if (themify_is_themify_theme() && themify_is_woocommerce_active() && is_file(THEME_DIR . '/admin/post-type-product.php')) {
        $defaults[] = 'product';
    }
    return array_keys(array_flip(apply_filters('themify_post_types', $defaults)));
}

if (!function_exists('themify_options_module')) {

    /**
     * Returns list of <option>
     * @param array $options List of options
     * @param string $key
     * @param bool $associative
     * @param string $default
     * @return string
     * @since 1.3.5
     */
    function themify_options_module($options = array(), $key = '', $associative = true, $default = ''):string {
        $data = themify_get_data();
        $sel = isset($data[$key]) ? $data[$key] : $default;
        $data = null;
        $output = '';
        if (true === $associative) {
            foreach ($options as $option) {
                $output .= '<option ' . selected($option['value'], $sel, false) . ' value="' . esc_attr($option['value']) . '">' . esc_html($option['name']) . '</option>';
            }
        } else {
            foreach ($options as $option) {
                $option = esc_attr($option);
                $selected = $sel === $option ? ' selected="selected"' : '';
                $output .= '<option value="' . $option . '"' . $selected . '>' . esc_html($option) . '</option>';
            }
        }
        return $output;
    }

}

if (!function_exists('themify_lightbox_vars_init')) {

    /**
     * Post Gallery lightbox/fullscreen and single lightbox definition
     * @return array Lightbox/Fullscreen galleries initialization parameters
     */
    function themify_lightbox_vars_init():array {
        $gallery_lightbox = themify_get('setting-gallery_lightbox', 'lightbox', true);
        // Lightbox default settings
        $overlay_args = array();
        if (themify_check('setting-lightbox_content_images', true)) {
            $overlay_args['contentImagesAreas'] = '.post, .type-page, .type-highlight, .type-slider';
        }
        if (themify_check('setting-lightbox_disable_share', true)) {
            $overlay_args['disable_sharing'] = true;
        }
        if ($gallery_lightbox === 'none') {
            $overlay_args['gallerySelector'] = '';
        }

        $overlay_args = apply_filters('themify_gallery_plugins_args', $overlay_args);
        // sanitize contentImagesAreas, ensure it's a valid CSS selector
        if (isset($overlay_args['contentImagesAreas'])) {
            $overlay_args['contentImagesAreas'] = trim($overlay_args['contentImagesAreas'], ',');
        }
        $overlay_args['i18n'] = array(
            'tCounter' => __('%curr% of %total%', 'themify'),
        );

        return $overlay_args;
    }

}

if (!function_exists('themify_get_shortcode_template')) {

    /**
     * Returns markup
     * @param $posts
     * @param string $slug
     * @param string $name
     * @return mixed|void
     */
    function themify_get_shortcode_template($posts, string $slug = 'includes/loop', string $name = 'index', array $args = array()):string {
        global $post, $themify;
        Themify_Enqueue_Assets::loadGridCss($themify->post_layout);

        if (is_object($post)){
            $saved_post = clone $post;
        }
        if(property_exists($themify, 'is_shortcode')){
            $isShortcode = $themify->is_shortcode === true;
            $themify->is_shortcode = true;
        }

        // Add flag that template loop is in builder loop
        if (class_exists('\Themify_Builder',false)) {
            $isLoop = Themify_Builder::$is_loop;
            Themify_Builder::$is_loop = true;
        }

        // get_template_part, defined in wp-includes/general-template.php
        $templates = array();
        if ('' !== $name) {
            $templates[] = "{$slug}-{$name}.php";
        }
        $templates[] = "{$slug}.php";
        $template_file = apply_filters('themify_get_shortcode_template_file', locate_template($templates, false, false), $slug, $name);
        $isSlider = $themify->post_layout === 'slider' || (isset($args['isSlider']) && $args['isSlider'] === true);
        ob_start();
        if (!empty($template_file)) {
            $before = isset($args['before_post']) ? $args['before_post'] : '';
            $after = isset($args['after_post']) ? $args['after_post'] : '';
            foreach ($posts as $p) {
                $post=$p;
                setup_postdata($post);
                if ($isSlider === true) {
                    echo '<div class="tf_lazy tf_swiper-slide">';
                }
                echo $before;
                include $template_file;
                echo $after;
                if ($isSlider === true) {
                    echo '</div>';
                }
            }
            $posts = null;
        }

        if (isset($saved_post)) {
            $post = $saved_post;
            setup_postdata($saved_post);
            unset($saved_post);
        }
        // Add flag that template loop is in builder loop
        if (isset($isLoop)) {
            Themify_Builder::$is_loop = $isLoop;
        }
        if(isset($isShortcode)){
            $themify->is_shortcode = $isShortcode;
        }
        $res=ob_get_clean();
        return $res?$res:'';
    }

}

if (!function_exists('themify_get_gallery_shortcode')) {

    /**
     * Get images from gallery shortcode
     * @return object
     */
    function themify_get_gallery_shortcode(?string $shortcode):array {
        if ($shortcode) {
            preg_match('/\[gallery.*ids.*?=.(.*).\]/si', $shortcode, $ids);
            if (isset($ids[1])) {
                $ids = trim($ids[1], '\\');
                $ids = trim($ids, '"');
                $image_ids = explode(',', $ids);

                // Check if post has more than one image in gallery
                return get_posts(array(
                    'post__in' => $image_ids,
                    'post_type' => 'attachment',
                    'post_mime_type' => 'image',
                    'numberposts' => -1,
                    'no_found_rows' => true,
                    'cache_results' => false,
                    'update_post_term_cache' => false,
                    'update_post_meta_cache' => false,
                    'orderby' => themify_get_gallery_shortcode_params($shortcode, 'orderby', 'post__in'),
                    'order' => themify_get_gallery_shortcode_params($shortcode, 'order', 'ASC')
                ));
            }
        }
        return array();
    }

}

if (!function_exists('themify_get_gallery_shortcode_params')) {

    /**
     * Get gallery shortcode options
     * @param $shortcode
     * @param $param
     */
    function themify_get_gallery_shortcode_params(string $shortcode, string $param = 'link', $default = '') {
        $pattern = '/\[gallery .*?(?=' . $param . ')' . $param . '=.([^\']+)./si';
        preg_match($pattern, $shortcode, $out);
        $out = isset($out[1]) ? explode('"', $out[1]) : array('');
        return $out[0] !== '' ? $out[0] : $default;
    }

}

function themify_get_additional_image_sizes(string $size = 'all', $default = false) {
    $allSizes = wp_get_additional_image_sizes();
    if ($size === 'all') {
        return $allSizes;
    }
    return isset($allSizes[$size]) ? $allSizes[$size] : $default;
}

if (!function_exists('themify_get_all_terms_ids')) {

    /**
     * Returns all IDs from the given taxonomy
     * @param string $tax Taxonomy to retrieve terms from.
     * @return array $term_ids Array of all taxonomy terms
     * @since 1.5.6
     */
    function themify_get_all_terms_ids(string $tax = 'category') {
        if (!$term_ids = wp_cache_get('all_' . $tax . '_ids', $tax)) {
            $term_ids = get_terms(array('taxonomy' => $tax, 'fields' => 'ids', 'get' => 'all'));
            wp_cache_add('all_' . $tax . '_ids', $term_ids, $tax);
        }
        return $term_ids;
    }

}

if (!function_exists('themify_is_touch')) {

    /**
     * According to what $check parameter specifies to check, returns true if it's a phone, tablet, or both.
     * @param string $check
     * @return mixed
     * @since 1.6.8
     */
    function themify_is_touch($check = 'all') {
        static $arr = array();

        if (!isset($arr[$check])) {
            if (!class_exists('Themify_Mobile_Detect',false)) {
                require_once 'class-themify-mobile-detect.php';
            }
            $detect = new Themify_Mobile_Detect();
            $is_tablet = isset($arr['tablet']) ? $arr['tablet'] : $detect->isTablet();
            $is_mobile = isset($arr['phone']) ? $arr['phone'] : (wp_is_mobile() || $detect->isMobile());
            $arr = array(
                'phone' => $is_mobile && !$is_tablet,
                'tablet' => $is_tablet,
                'all' => $is_mobile
            );
            $detect = null;
        }

        return $arr[$check];
    }

}

/**
 * Checks that status of the image script.
 * @return bool
 * @since 1.7.4
 */
function themify_is_image_script_disabled():bool {
    static $is = null;
    if ($is === null) {
        $is = wp_image_editor_supports() ? themify_check('setting-img_settings_use', true) : false;
    }

    return $is;
}


if (!function_exists('themify_get_available_menus')) {

    /**
     * Returns available navigation menus.
     *
     * @since 1.9.5
     *
     * @return array
     */
    function themify_get_available_menus():array {
        $out = array(array('name' => '', 'value' => '', 'selected' => true));
        $menus = get_terms(array(
            'taxonomy' => 'nav_menu',
            'hide_empty' => false,
        ));
        if (!empty($menus) && !is_wp_error($menus)) {
            foreach ($menus as $menu) {
                $out[] = array('name' => $menu->name, 'value' => $menu->slug);
            }
        }
        return apply_filters('themify_get_available_menus', $out);
    }

}

/**
 * Returns true if the active theme is using Themify framework
 *
 * @since 2.2.5
 * @return bool
 */
function themify_is_themify_theme():bool {
    static $is = null;
    if ($is === null) {
        $is = is_file(trailingslashit(get_template_directory()) . 'themify/themify-utils.php');
    }

    return $is;
}

if (!function_exists('themify_is_woocommerce_active')) {

    /**
     * Checks if Woocommerce plugin is active and returns the proper value
     * @return bool
     * @since 1.4.6
     */
    function themify_is_woocommerce_active():bool {
        static $is = null;
        if ($is === null) {
            $plugin = 'woocommerce/woocommerce.php';
            include_once( ABSPATH . 'wp-admin/includes/plugin.php' );
            return is_plugin_active($plugin)
                // validate if $plugin actually exists, the plugin might be active however not installed.
                && is_file(trailingslashit(WP_PLUGIN_DIR) . $plugin);
        }
        return $is;
    }

}

/**
 * Calls is_shop() in a safe manner
 *
 * @note: this function should not be called before template_redirect.
 *
 * @since 2.9.0
 */
function themify_is_shop($pageId = false):bool {
    static $is = null;
    if ($is === null) {
        $is = themify_is_woocommerce_active();
        if ($is === true) {
            $is = is_post_type_archive('product') || ($pageId > 0 && $pageId === themify_shop_pageId()); //don't use shop function will give error
            if ($is === false) {
                $shop_url = themify_get_shop_permalink(); //wc bug, page id isn't set from wc settings,the default should be page with slug 'shop'
                if ($shop_url !== '') {
                    $current_url = 'http';
                    if (is_ssl()) {
                        $current_url .= 's';
                    }
                    $current_url .= '://';
                    if (isset($_SERVER['HTTP_HOST'])) {
                        $current_url .= $_SERVER['HTTP_HOST'];
                    } else {
                        $host = parse_url(home_url(), PHP_URL_HOST);
                        if ($host !== false) {
                            $current_url .= $host;
                        }
                        unset($host);
                    }
                    $current_url .= strtok($_SERVER['REQUEST_URI'], '?');
                    $is = $current_url === $shop_url;
                } else {
                    $is = false;
                }
            }
        }
    }
    return $is;
}

/**
 * Modified version of wp_parse_args which adds filters to modify the args
 *
 * @return array
 * @since 2.7.7
 */
function themify_parse_args($args, $defaults = '', $filter_key = '') {
    // Setup a temporary array from $args
    if (is_object($args)) {
        $r = get_object_vars($args);
    } elseif (is_array($args)) {
        $r = & $args;
    } else {
        wp_parse_str($args, $r);
    }
    // Passively filter the args before the parse
    if (!empty($filter_key)) {
        $r = apply_filters('themify_before_' . $filter_key . '_parse_args', $r);
    }
    // Parse
    if (is_array($defaults)) {
        $r = array_merge($defaults, $r);
    }
    // Aggressively filter the args after the parse
    if (!empty($filter_key)) {
        $r = apply_filters('themify_after_' . $filter_key . '_parse_args', $r);
    }
    // Return the parsed results
    return $r;
}

/**
 * Display the Builder's backend editor in Themify Custom Panel
 *
 * @return null
 * @since 2.8.8
 */
function themify_meta_field_page_builder() {
    do_action('themify_builder_metabox');
}

/**
 * Get an array of key => value pairs and outputs them as HTML attributes
 *
 * @since 2.9.1
 * @return string
 */
function themify_get_element_attributes(array $props):string {
    $out = '';
    foreach ($props as $k => $v) {
        $out .= ' ' . $k . '="' . esc_attr($v) . '"';
    }

    return $out;
}


/**
 * Get breakpoints settings
 * if it's framework return customizer breakpoints,else if it's builder plugin builder breakpoints
 * @since 3.0.0
 * @return mixed array/int
 */
function themify_get_breakpoints(string $select = 'all', bool $max_min = false) {
    static $res = array();
    if (($select === 'all' && empty($res)) || (empty($res[$select]))) {
        $breakpoints = array(
            'tablet_landscape' => array(769, 1280),
            'tablet' => array(681, 768),
            'mobile' => 680
        );
        if ($max_min === true) {
            return $breakpoints;
        }
        foreach ($breakpoints as $bp => $value) {
            $v = themify_builder_get('setting-customizer_responsive_design_' . $bp, 'builder_responsive_design_' . $bp);
            if ('' != $v) {
                if (is_array($value)) {
                    $res[$bp] = array();
                    $res[$bp][0] = $value[0];
                    $res[$bp][1] = (int) $v;
                } else {
                    $res[$bp] = (int) $v;
                }
            } else {
                $res[$bp] = $value;
            }
        }
        $res['tablet'][0] = $res['mobile'] + 1;
        $res['tablet_landscape'][0] = $res['tablet'][1] + 1;
    }
    return 'all' === $select ? $res : $res[$select];
}

/**
 * Unserialize data if it is serialized
 *
 * If PHP supports it disables unserializing PHP objects in order to prevent object injection.
 *
 * @param string $original Maybe unserialized original, if is needed.
 * @return mixed Unserialized data can be any type.
 */
function themify_maybe_unserialize(string $original) {
    if (is_serialized($original)) { // don't attempt to unserialize data that wasn't serialized going in
        return @unserialize($original, array('allowed_classes' => false));
    }

    return $original;
}

/**
 * Display the post video
 * Must be used inside the loop
 *
 * @since 2.7.3
 */
function themify_post_video(string $url = '', bool $echo = true) {
    $video_file = $url ? $url : themify_get('video_url');
    $output = '';
    if (!empty($video_file)) {
        if ('mp4' !== pathinfo($video_file, PATHINFO_EXTENSION)) {
            global $wp_embed;
            $output = $wp_embed->run_shortcode('[embed]' . $video_file . '[/embed]');
        } else {
            $output = '<div class="post-video">';
            $output .= do_shortcode('[video src="' . $video_file . '"]');
            $output .= '</div>';
        }
    }
    if ($echo === true) {
        echo $output;
    } else {
        return $output;
    }
}

function themify_get_embed(string $url, array $args):string {
    $reg = '#(vimeo\.com|youtu(be\.com|\.be|be))\/(shorts\/|video\/|embed\/|watch\?v=|v\/)?([A-Za-z0-9._%-]*)(\&\S+)?\/?([A-Za-z0-9._%-]*)(\&\S+)?#i';
    preg_match($reg, $url, $m);
    if (!empty($m) && isset($m[1], $m[4])) {
        $type = ($m[1] === 'youtube.com' || strpos($m[1], 'youtu') !== false) ? 'youtube' : ($m[1] === 'vimeo.com' || strpos($m[1], 'vimeo') ? 'vimeo' : false);
        if ($type !== false) {
            $id = $m[4];
            $query_args = array();
            if ($type !== 'youtube' && isset($m[6])) {//h query argument should be first in vimeo
                $query_args['h'] = $m[6];
            }
            $query_args += array(
                'pip' => 1,
                'playsinline' => 1
            );
            $params = parse_url($url);
            if (!empty($params['query'])) {
                parse_str($params['query'], $output);
                unset($output['v']);
                $query_args += $output;
                unset($output);
            }
            if ($type === 'youtube') {
                $allow = 'accelerometer;encrypted-media;gyroscope;picture-in-picture;fullscreen';
                $src = 'https://www.youtube';
                if (!empty($args['privacy'])) {
                    $src .= '-nocookie';
                }
                $src .= '.com/embed/' . $id; 
                if (!empty($args['start']) ) {
                    $query_args['start'] = (float) $args['start'];
                }
                elseif (!empty($params['fragment'])) {
                    $query_args['start'] = (float) $params['fragment'];
                    if(empty($query_args['start'])){
                        unset($query_args['start']);
                    }
                }
                if (!empty($args['end'])) {
                    $query_args['end'] = (float) $args['end'];
                }
            }
             else {

                $allow = 'fullscreen';
                $src = 'https://player.vimeo.com/video/' . $id;
                if (!empty($args['start'])) {
                    $src .= '#t=' . $args['start'];
                } elseif (!empty($params['fragment'])) {
                    $src .= '#' . $params['fragment'];
                }
                if (!empty($args['privacy'])) {
                    $query_args['dnt'] = 1;
                }
                $query_args['byline'] =$query_args['title'] = $query_args['portrait'] = 0;
            }
            unset(
                $params,
                $query_args['modestbranding'],
                $query_args['controls'],
                $query_args['loop'],
                $query_args['mute'],
                $query_args['muted']
            );
            if (!empty($args['hide_controls'])) {
                $query_args['controls'] = 0;
            }

            if (!empty($args['loop'])) {
                $query_args['loop'] = 1;
                if (!isset($query_args['playlist'])) {
                    $query_args['playlist'] = $id;
                }
            }
            if (!empty($args['autoplay']) || !empty($query_args['autoplay'])) {
                $allow .= ';autoplay';
                $query_args['autoplay'] = 1;
            }
            if (!empty($args['muted'])) {
                if ($type === 'youtube') {
                    $query_args['mute'] = 1;
                } else {
                    $query_args['muted'] = 1;
                }
            }
            $lazy = !empty($args['disable_lazy']) ? ' data-no-script' : '';
            $src .= '?' . http_build_query($query_args);
            $class=isset($args['class'])?$args['class']:'tf_abs tf_w tf_h';
            return '<iframe' . $lazy . ' src="' . esc_url( $src ) . '" allow="' . $allow . '" class="'.$class.'"></iframe>';
        }
    }
    return '';
}

function themify_enque_style(string $handle,string $src = '',?array $deps = array(),?string $ver = THEMIFY_VERSION,?string $media = 'all', bool $in_footer = false) {
    Themify_Enqueue_Assets::add_css($handle, $src, $deps, $ver, $media, $in_footer);
}

function themify_enque_script(string $handle, string $src = '', string $ver = THEMIFY_VERSION,?array $deps = array(), bool $in_footer = true) {
    Themify_Enqueue_Assets::add_js($handle, $src, $deps, $ver, $in_footer);
}

if (!function_exists('themify_get_query_categories')) {

    function themify_get_query_categories():array {
        global $themify;

        $taxes = $themify->query_category == '0' ? themify_get_all_terms_ids($themify->query_taxonomy) : explode(',', str_replace(' ', '', $themify->query_category));
        if (empty($taxes) || is_wp_error($taxes)) {
            $taxes= array();
        }
        return $taxes;
    }

}

/**
 * Returns the URL to the WooCommerce Shop page
 *
 * @return string
 * @since 4.5.7
 */
function themify_get_shop_permalink():string {
    static $link = null;
    if ($link === null) {
        $id = themify_shop_pageId();
        $link = !empty($id) ? get_permalink($id) : '';
    }
    return $link;
}

function themify_is_login_page():bool {
    static $is = null;
    if ($is === null) {
        global $pagenow;
        $is = !empty($pagenow) && in_array($pagenow, array('wp-login.php', 'wp-register.php'), true);
    }
    return $is;
}

function themify_is_ajax():bool {
    static $is = null;
    if ($is === null) {
        $is = defined('DOING_AJAX') || (isset($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) === 'xmlhttprequest');
    }
    return $is;
}

function themify_is_rest():bool {
    static $is = null;
    if ($is === null) {
        $is = (defined('REST_REQUEST') && REST_REQUEST) || strpos($_SERVER['REQUEST_URI'], '/wp-json/') !== false;
    }
    return $is;
}

function themify_is_lazyloading():bool {
    static $is = null;
    if ($is === null) {
        $is = !themify_builder_check('setting-disable-lazy', 'performance-disable-lazy', true);
        if ($is === true) {
            global $wp_customize;
            $is = !is_admin() && themify_is_ajax() === false && !isset($_GET['tf-scroll']) && !isset($_GET['post_in_lightbox']) && themify_is_prefetch_request() === false && (!class_exists('Themify_Builder',false) || !Themify_Builder_Model::is_front_builder_activate()) && !( $wp_customize instanceof WP_Customize_Manager && $wp_customize->is_preview());
            if ($is === true) {
                $is = apply_filters('tf_lazy_enable', true);
            }
        } else {
            add_filter('wp_lazy_loading_enabled', '__return_false', 100);
        }
    }
    return $is;
}

function themify_make_lazy(?string $html, bool $load = true):?string {//@todo move to class
    if (isset($html) && (strpos($html, ' src=') !== false || strpos($html, '<audio') !== false || strpos($html, '<video') !== false)) {
        $tags = array(
            'img' => '<img.+?>',
            'iframe' => '<iframe.+?>.*?<\/iframe>',
            'audio' => '<audio.+?>.*?<\/audio>',
            'video' => '<video.+?>.*?<\/video>'
        );
        $hasLazy = themify_is_lazyloading();
        if($hasLazy===false){
            unset($tags['img'],$tags['iframe']);
        }
        foreach ($tags as $k => $v) {
            if (strpos($html, '<' . $k) === false) {
                unset($tags[$k]);
            }
        }
        if (empty($tags)) {
            return $html;
        }
        if (isset($tags['img']) || isset($tags['iframe'])) {//skip noscript img/iframe
            preg_match_all('/<noscript>.*?<\/noscript>/is', $html, $m);
            if (!empty($m[0])) {
                $search = $replace = array();
                $m = !is_array($m[0]) ? array($m[0]) : $m[0];
                foreach ($m as $item) {
                    $orig = $item;
                    $item = str_replace(array("\r" . 'src=', "\n" . 'src='), ' src=', $item);
                    if (strpos($item, ' src=') !== false && strpos($item, 'data-no-script') === false && (strpos($item, '<img') !== false || strpos($item, '<iframe') !== false)) {
                        $search[] = $orig;
                        $replace[] = str_replace(' src=', ' data-no-script src=', $item);
                    }
                }
                unset($m);
                if (!empty($search)) {
                    $html = str_replace($search, $replace, $html);
                }
            }
        }
        
        $reg = '/' . implode('|', $tags) . '/is';
        preg_match_all($reg, $html, $matches);
        unset($reg);
        if (!empty($matches[0])) {  
            $svgRows=4;
            $svgStep=round(100/$svgRows,2);
            $count = 0;
            $search = $replace = array();
            $matches = !is_array($matches[0]) ? array($matches[0]) : $matches[0];
            $tags = array_keys($tags);
            $extCount = count($tags) - 1;
            $placeHolder="data:image/svg+xml,%3Csvg%20xmlns=%27http://www.w3.org/2000/svg%27%20width='{w}'%20height='{h}'%20viewBox=%270%200%20{w}%20{h}%27%3E%3C/svg%3E";
            if ($load === false) {//$load need for some modules,which should be init and than load images(e.g slider)
                $stopLazy = false;
                $useJs = $isJsLazy=true;
            }
            else{
                $_WITHOUTLAZY_ =2;
                $stopLazy = $useJs =$isJsLazy= false;
            }
            foreach ($matches as $item) {
                if (!empty($item) && strpos($item, 'data-lazy', 4) === false && strpos($item, 'data-tf-src', 4) === false && strpos($item, 'data-no-script', 4) === false && strpos($item, 'data:image/', 4) === false && strpos($item, 'display:none', 4) === false && strpos($item, 'application/x-mpegURL', 4) === false && strpos($item, 'display: none', 4) === false && ($count !== 0 || strpos($item, 'gravatar.com', 4) === false)) {
                    if (strpos($item, 'data-tf-not-load', 4) === false) {
                        for ($i = $extCount; $i > -1; --$i) {
                            if (strpos($item, '<' . $tags[$i]) !== false) {
                                $ext = $tags[$i];
                                break;
                            }
                        }
                        if (!isset($ext)) {
                            continue;
                        }
                        $orig = $item;
                        $item = preg_replace('/\s+/', ' ', $item);
                        if ($ext !== 'audio') {
                            preg_match('/ src=["\']([^"]+?)["\']/', $item, $image_src,0,4);
                        }
                        if ($ext === 'audio' || $ext === 'video' || !empty($image_src[1])) {
                            $url = $ext === 'audio' ? true : (isset($image_src[1]) ? trim($image_src[1]) : '');
                            unset($image_src);
                            if ($url === '' && $ext === 'video') {
                                $url = true;
                            }
                            if ($url !== '') {
                                if ($url !== true && $url[0] === '{') {
                                    continue;
                                }
                                if ($ext === 'img') {//skip large images converting,otherwise can crash the site
                                    if (strpos($item, ' srcset', 4) !== false) {
                                        preg_match('/ srcset=["\']([^"]+?)["\']/', $item, $srcset,0,4);
                                        $srcset=$srcset[1]??'';
                                    }else{
                                        $srcset='';
                                    }
                                    if ($count === 0) {
                                        $srcSetSizes='';
                                        if ($srcset!=='') {
                                            preg_match('/ sizes=["\']([^"]+?)["\']/', $item, $srcSetSizes,0,4);
                                            $srcSetSizes = $srcSetSizes[1] ?? '';
                                        }
                                        Themify_Enqueue_Assets::addPreLoadMedia($url, 'preload', 'image', $srcset, $srcSetSizes, 'high'); //load the first images in the page with preload for fast LCP
                                        unset($srcSetSizes);
                                    }
                                    if(strpos($item, 'tf_large_img') === false){
                                        themify_generateWebp($url);
                                        if ($srcset!=='') {
                                            foreach ( explode(',', trim($srcset)) as $_src) {
                                                $tmpS = trim(explode(' ', trim($_src))[0]);
                                                if ($tmpS !== '' && strpos($tmpS, 'data:image') === false) {
                                                    themify_generateWebp($tmpS);
                                                }
                                            }
                                            unset($tmpS,$srcset,$_src);
                                        }
                                        if (strpos($item, ' data-src', 4) !== false) {
                                            preg_match('/ data-src=["\']([^"]+?)["\']/', $item, $tmpsrc,0,4);
                                            if (!empty($tmpsrc[1])) {
                                                themify_generateWebp($tmpsrc[1]);
                                            }
                                            $tmpsrc = null;
                                        }
                                    }
                                }
                                if (strpos($item, 'data-src', 4) !== false || ($hasLazy === false && $ext !== 'audio' && $ext !== 'video')) {
                                    continue;
                                }
                                $s = '';
                                if ($ext === 'audio' || $ext === 'video') {
                                    $s = ' data-lazy="1"';
                                    if (strpos($item, 'preload="none"', 6) === false) {
                                        $s .= ' preload="none"';
                                        $item = str_replace(array('preload="auto"', 'preload="metadata"'), '', $item);
                                    }
                                } else {
                                    if($isJsLazy===false) {
                                        $stopLazy = $count < $_WITHOUTLAZY_; /* skip the first $_WITHOUTLAZY_ matches, assume they're above the fold */
                                        $useJs = $count > 9;
                                        ++$count;
                                    }
                                    if ($ext === 'iframe') {
                                        if ($stopLazy === false) {
                                            if (strpos($item, ' loading=', 6) === false) {
                                                $s .= ' loading="lazy"';
                                            }
                                            if ($isJsLazy === true) {
                                                $s .= ' data-lazy="1" src="about:blank" data-tf-not-load="1"';
                                                $class = 'tf_iframe_lazy';
                                                if (strpos($item, 'class=', 6) === false) {
                                                    $s .= ' class="' . $class . '"';
                                                } else {
                                                    $item = str_replace(' class="', ' class="' . $class . ' ', $item);
                                                }
                                                $item = strtr($item, array(' src=' => ' data-tf-src='));
                                            }
                                        } 
                                        else {
                                            $s .= ' data-tf-not-load="1"';
                                        }
                                    } 
                                    elseif ($ext === 'img') {
                                        $sizes = themify_get_image_size($url,false,$stopLazy===false && $useJs===true?$svgRows:0);
                                        if ($stopLazy === false) {
                                            $useJs = $isJsLazy === true || $useJs === true;
                                            if (strpos($item, ' loading=', 4) === false) {
                                                $s .= ' loading="lazy"';
                                            }
                                            if ($useJs === true) {
                                                $s .= ' data-lazy="1"';
                                                if($isJsLazy===true){
                                                    $s .= ' data-tf-not-load="1"';
                                                }
                                                $class = 'tf_svg_lazy';
                                                if (strpos($item, ' class=', 4) === false) {
                                                    $s .= ' class="' . $class . '"';
                                                } else {
                                                    $item = str_replace(' class="', ' class="' . $class . ' ', $item);
                                                }
                                                $width=$height=0;
                                                if(!empty($sizes)){
                                                    $width=$sizes['w'];
                                                    $height=$sizes['h'];
                                                    if(!empty($sizes['c'])){
                                                        $color='';
                                                        foreach($sizes['c'] as $i=>$c){
                                                            if($i%$svgRows===0){
                                                                $j=1;
                                                                if($color!==''){
                                                                    $color.='),';
                                                                }
                                                                $color.='linear-gradient(to right';
                                                            }
                                                            $color.=',#'.$c;
                                                            if($j!==1 ){
                                                                $color.=' '.($j-1)*$svgStep.'%';
                                                            }
                                                            if($j!==$svgRows){
                                                                $color.=' '.$j*$svgStep.'%';
                                                            }
                                                            ++$j;
                                                        }
                                                        $color='background:'.$color.')';
                                                        if (strpos($item, ' style=', 4) === false) {
                                                            $s .= ' style="'.$color.'"';
                                                        } else {
                                                            $item = str_replace(' style="', ' style="' . $color . ';', $item);
                                                        }
                                                    }
                                                }else{
													if(strpos($item, ' width=', 4)!==false){
														preg_match('/ width=["\']([^"]+?)["\']/', $item, $w,0,4);
														if(!empty($w[1])){
															$width=$w[1];
															unset($w);
														}
													}
													if (strpos($item, ' height=', 4) === false) {
														preg_match('/ height=["\']([^"]+?)["\']/', $item, $h,0,4);
														$height=!empty($h[1])?$h[1]:$width;
														unset($h);
													}
													elseif(!empty($width)){
														$height=$width;
													}
												}
                                                $item = strtr($item, array(' srcset=' => ' data-tf-srcset=', ' sizes=' => ' data-tf-sizes=', ' src=' => ' data-tf-src=')); //sizes need to be replaced to pass html validation
                                                $s = ' src="' . strtr($placeHolder, array('{w}'=>$width,'{h}'=>$height)) . '"' . $s;
                                            }
                                        } 
                                        else {
                                            $s = ' data-tf-not-load="1"';
                                            if ($count === 1) {
                                                if (strpos($s, 'fetchpriority=') === false) {
                                                    $s .= ' fetchpriority="high"';
                                                }
                                                $s .= ' loading="auto" decoding="auto"';
                                            }
                                        }
                                        if (strpos($item, ' decoding=', 4) === false) {
                                            $s .= ' decoding="async"';
                                        }
                                        if(!empty($sizes)){
                                            if (strpos($item, ' width=', 4) === false) {
                                                $s .= ' width="' . $sizes['w'] . '"';
                                            }
                                            if (strpos($item, ' height=', 4) === false) {
                                                $s .= ' height="' . $sizes['h'] . '"';
                                            }
                                        }
                                        unset($sizes);
                                    }
                                }
                                $item = str_replace('<' . $ext, '<' . $ext . $s, $item);
                                if ($ext === 'audio' || $ext === 'video') {
                                    $c = 'tf_lazy tf_' . ($ext === 'video' ? 'vd' : $ext) . '_lazy tf_w tf_rel tf_box';
                                    $r = array();
                                    if (strpos($item, ' data-lazy') !== false) {
                                        $r['<' . $ext] = '<' . $ext . ' data-lazy="1"';
                                    }
                                    if ($ext === 'video') {
                                        $c .= ' tf_rel tf_overflow';
                                        themify_get_icon('fas volume-mute', 'fa');
                                        themify_get_icon('fas volume-up', 'fa');
                                        //themify_get_icon('fas undo', 'fa');
                                        //themify_get_icon('fas redo', 'fa');
                                        //themify_get_icon('far closed-captioning', 'fa');
                                        themify_get_icon('fas external-link-alt', 'fa');
                                        themify_get_icon('fas airplay', 'fa');
                                        themify_get_icon('fas expand', 'fa');
                                        themify_get_icon('fas download', 'fa');
                                        if (strpos($item, ' poster') !== false) {
                                            $r[' poster'] = ' data-poster';
                                        }
                                        if ($url && $url !== true && strpos($item, ' width') === false || strpos($item, ' height') === false) {
                                            $size = themify_get_video_size($url);
                                            if ($size !== null) {
                                                $sv = '';
                                                if ($size['w'] !== '' && strpos($item, ' width') === false) {
                                                    $sv = ' width="' . $size['w'] . '"';
                                                }
                                                if ($size['h'] !== '' && strpos($item, ' height') === false) {
                                                    $sv .= ' height="' . $size['h'] . '"';
                                                }
                                                if ($sv !== '') {
                                                    $r[' preload'] = $sv . ' preload';
                                                }
                                                $sv = null;
                                            }
                                        }
                                    }
                                    if (strpos($item, ' autoplay') !== false) {
                                        $r[' autoplay'] = ' data-autoplay';
                                    }
                                    if (!empty($r)) {
                                        $item = strtr($item, $r);
                                    }
                                    unset($r);
                                    $item = '<div class="' . $c . '" data-playtitle="' . esc_attr__( 'Play/Pause', 'themify' ) . '" data-next="' . esc_attr__( 'Next', 'themify' ) . '" data-prev="' . esc_attr__( 'Previous', 'themify' ) . '" data-timeslider="' . esc_attr__( 'Time Slider', 'themify' ) . '">' . $item . '</div>';
                                    $c = null;
                                }
                                $part = $item;
                                if ($ext === 'img' && $stopLazy === false && $useJs === true) {
                                    $part .= '<noscript>' . strtr($orig, array(' src=' => ' data-tf-not-load src=')) . '</noscript>';
                                }
                                $search[] = $orig;
                                $replace[] = $part;
                            }
                        }
                    } else {
                        ++$count;
                    }
                }
            }
            unset($matches, $tags, $extCount);
            $html = str_replace($search, $replace, $html);
        }
    }
    return $html;
}

function themify_upload_dir(string $mode = 'all', bool $reinit = false) {
    static $dir = null;
    if ($dir === null || $reinit === true) {
        /* foolproof the paths, in case they mistakenly have trailing slash */
        $dir = array_map('untrailingslashit', wp_get_upload_dir());
        $dir['baseurl'] = themify_https_esc($dir['baseurl']);
    }

    return $mode === 'all' ? $dir : $dir[$mode];
}

function themify_generateWebp(string $url):string {
    if (empty($url)) {
        return $url;
    }
    static $is = null;
    if ($is === null) {
        $is = !themify_builder_check('setting-webp', 'performance-webp', true) ? true : (is_admin() && !themify_is_ajax());
    }
    if ($is === true) {
        return $url;
    }
    return themify_create_webp($url);
}

function themify_is_prefetch_request():bool {
    static $is = null;
    if ($is === null) {
        if (isset($_SERVER['HTTP_PURPOSE'])) {
            $prev = 'HTTP_PURPOSE';
        } elseif (isset($_SERVER["HTTP_X_PURPOSE"])) {
            $prev = 'HTTP_X_PURPOSE';
        } elseif (isset($_SERVER['HTTP_X_MOZ'])) {
            $prev = 'HTTP_X_MOZ';
        } else {
            $prev = false;
        }
        if ($prev !== false) {
            $prev = strtolower($_SERVER[$prev]);
            $is = $prev === 'prefetch' || $prev === 'preview';
        } else {
            $is = false;
        }
    }
    return $is;
}

function themify_is_dev_mode():bool {
    static $is = null;
    if ($is === null) {
        $is = themify_check('setting-dev-mode', true) || (defined('THEMIFY_DEV') && THEMIFY_DEV);
        $is = apply_filters('themify_dev_mode', $is);
    }
    return $is;
}

function themify_is_concate_disabled():bool {
    return themify_is_dev_mode() && (themify_check('setting-dev-mode-concate', true) || (defined('THEMIFY_DEV') && THEMIFY_DEV));
}

function themify_disable_other_lazy() {
    add_filter('wp_lazy_loading_enabled', '__return_false', 100);
    add_filter('lazyload_is_enabled', '__return_false', 1, 100); //disable jetpack lazy load
    add_filter('rocket_use_native_lazyload', '__return_false', 1, 100);
}

function themify_get_server():string {
    static $is = null;
    if ($is === null) {
        $is = 'apache';
        if (!empty($_SERVER['SERVER_SOFTWARE'])) {
            $is = explode('/', $_SERVER['SERVER_SOFTWARE']);
            $is = str_replace('microsoft-', '', strtolower($is[0]));
        } elseif (is_file(get_home_path() . 'web.config')) {
            $is = 'iis';
        } elseif (!is_file(Themify_Enqueue_Assets::getHtaccessFile()) || is_file('/etc/nginx/nginx.conf')) {
            $is = 'nginx';
        }
    }
    return $is;
}

/**
 * Help tooltip Module
 */
function themify_help(string $content):string {
    return sprintf('<span class="tf_help"><i tabindex="-1" class="icon" onclick="return false;">%s</i><span class="tf_help_content">%s</span></span>',
        themify_get_icon('ti-help', 'ti'),
        $content
    );
}

/**
 * Search $subject for $search and replace the first occurrence of it.
 *
 * @return string
 */
function themify_str_replace_first(string $search, string $replace,string $subject):string {
    return implode($replace, explode($search, $subject, 2));
}

/**
 * Search $subject for $search and replace the last occurrence of it.
 *
 * @return string
 */
function themify_str_replace_last(string $search, string $replace, string $subject):string {
    if (( $pos = strrpos($subject, $search) ) !== false) {
        $subject = substr_replace($subject, $replace, $pos, strlen($search));
    }

    return $subject;
}

/**
 * Gets the ID of an object (post or term) and returns that object ID in current language.
 *
 * @return int|mixed
 */
function themify_maybe_translate_object_id(?int $id, string $type = 'page'):?int {
    if (!empty($id)) {
        if (defined('ICL_SITEPRESS_VERSION')) {
            $id = apply_filters('wpml_object_id', $id, $type, true);
        } elseif (defined('POLYLANG_VERSION') && function_exists('pll_get_post')) {
            $translatedpageid = pll_get_post($id);
            if (!empty($translatedpageid) && 'publish' === get_post_status($translatedpageid)) {
                $id = $translatedpageid;
            }
        }
    }

    return $id;
}

/**
 * Returns and caches URL to the homepage, properly filtered for multilingual setups
 *
 * @return string
 */
function themify_home_url():string {
    static $url = null;
    if ($url === null) {
        $url = function_exists('pll_home_url') ? pll_home_url() : home_url();
    }
    return $url;
}

/**
 * Download file from external URL and returns the file
 *
 * @param $post_id Attachments may be associated with a parent post or page.
 *
 * @return WP_Error|int ID of created attachment, or WP_Error
 */
function tf_fetch_remote_file($url, $post_id = null, $title = '') {

    // extract the file name and extension from the url
    $file_name = basename($url);

    // get placeholder file in the upload dir with a unique, sanitized filename
    $upload = wp_upload_bits($file_name, 0, '');
    if ($upload['error'])
        return new WP_Error('upload_dir_error', $upload['error']);

    // fetch the remote url and write it to the placeholder file
    $remote_response = wp_safe_remote_get($url, array(
        'timeout' => 300,
        'stream' => true,
        'filename' => $upload['file'],
    ));

    $headers = wp_remote_retrieve_headers($remote_response);

    // request failed
    if (!$headers) {
        @unlink($upload['file']);
        return new WP_Error('import_file_error', __('Remote server did not respond', 'themify'));
    }

    $remote_response_code = wp_remote_retrieve_response_code($remote_response);

    // make sure the fetch was successful
    if ($remote_response_code != '200') {
        @unlink($upload['file']);
        return new WP_Error('import_file_error', sprintf(__('Remote server returned error response %1$d %2$s', 'themify'), esc_html($remote_response_code), get_status_header_desc($remote_response_code)));
    }

    $filesize = filesize($upload['file']);

    if (0 == $filesize) {
        @unlink($upload['file']);
        return new WP_Error('import_file_error', __('Zero size file downloaded', 'themify'));
    }

    $post = array(
        'post_title' => $title,
        'post_content' => '',
        'post_status' => 'inherit',
    );
    if ($info = wp_check_filetype($upload['file']))
        $post['post_mime_type'] = $info['type'];
    else
        return new WP_Error('mime_type_error', __('Invalid file type', 'themify'));

    $attach_id = wp_insert_attachment($post, $upload['file'], $post_id);
    wp_update_attachment_metadata($attach_id, wp_generate_attachment_metadata($attach_id, $upload['file']));

    return $attach_id;
}

/**
 * Mimics get_template_part but loads a template from THEMIFY_DIR
 *
 * @since 5.5.3
 */
function themify_get_template(string $slug, string $name = '', array $args = array()) {
    $base_dir = THEMIFY_DIR;
    $templates = array();
    $located = '';
    if ($name !== null && '' !== $name) {
        $templates[] = "{$base_dir}/{$slug}-{$name}.php";
    }

    $templates[] = "{$base_dir}/{$slug}.php";

    foreach ($templates as $template) {
        if (is_file($template)) {
            $located = $template;
            break;
        }
    }

    if ($located !== '') {
        load_template($located, false, $args);
    }
}

/* Add category id class in post loop for Masonry filter */
if ( ! function_exists( 'themify_post_filter_class' ) ) :
function themify_post_filter_class(array $classes, $class, $post_id):array {
    $categories = wp_get_object_terms($post_id, get_query_var('tf_query_tax', 'category'));
    if ( ! is_wp_error( $categories ) ) {
        foreach ($categories as $category) {
            $classes[] = ' cat-' . $category->term_id;
        }
        $is_ajax = get_query_var('tf_ajax_filter', false);
        if (true === $is_ajax) {
            if (isset($_POST['action'], $_POST['tax']) && $_POST['action'] === 'themify_ajax_load_more') {
                $classes[] = 'ajax-cat-' . (int) $_POST['tax'];
            } else {
                $classes[] = 'initial-cat';
            }
        }
    }
    return $classes;
}
endif;

function themify_custom_except($excerpt) {
    if (has_excerpt()) {
        $excerpt = wp_trim_words(get_the_excerpt(), apply_filters('excerpt_length', 55));
    }
    return $excerpt;
}

function themify_set_headers(array $headers) {
    if (!headers_sent()) {
        $list = headers_list();
        foreach ($list as $h) {
            $head = strtoupper(trim(explode(':', $h)[0]));
            if (isset($headers[$head])) {
                $vals = trim(trim(str_ireplace($head, '', $h)), ':');
                if ($head === 'CONTENT-SECURITY-POLICY' || is_array($headers[$head])) {
                    $vals = explode(';', $vals);
                    $policy = $headers[$head];
                    $hasChange = false;
                    foreach ($vals as $i => $c) {
                        $c = trim($c);
                        if ($c !== '') {
                            $c = preg_replace('!\s+!', ' ', $c);
                            $values = explode(' ', $c);
                            if (isset($policy[$values[0]])) {
                                $none = array_search('none', $values, true);
                                if ($none !== false) {
                                    unset($values[$none]);
                                }
                                $values = array_merge($values, explode(' ', $policy[$values[0]]));
                                $vals[$i] = implode(' ', array_keys(array_flip($values)));
                                $hasChange = true;
                            }
                        } else {
                            unset($vals[$i]);
                        }
                    }
                    if ($hasChange === true) {
                        header($head . ':' . implode(';', $vals));
                    }
                } elseif ($vals !== $headers[$head]) {
                    header($head . ':' . $headers[$head]);
                }
                unset($headers[$head]);
                if (empty($headers)) {
                    break;
                }
            }
        }
    }
}

function themify_get_lottie(array $arr, string $sel = '') {

    if (!empty($arr['path']) && !empty($arr['seg'])) {
        $lottie = array(
            'path' => $arr['path'],
            'seg' => $arr['seg']
        );
        if (!empty($arr['st'])) {
            $lottie['st'] = $arr['st'];
        }
        if (isset($arr['sp']) && $arr['sp'] != 1) {
            $lottie['sp'] = $arr['sp'];
        }
        if (!empty($arr['dir'])) {
            $lottie['dir'] = $arr['dir'];
        }
        if (!empty($arr['fid'])) {
            $lottie['fid'] = $arr['fid'];
        }
        if (isset($arr['r']) && $arr['r'] !== 'svg') {
            $lottie['r'] = $arr['r'];
        }
        if (isset($arr['count']) && ($arr['count'] > 1 || $arr['count'] == -1)) {
            $lottie['count'] = $arr['count'];
        }
        if ($sel !== '') {
            $lottie['sel'] = $sel;
        }
        if (!isset($arr['lp'])) {
            $lottie = array('actions' => $lottie, 'loop' => 1);
        }
        return sprintf('<tf-lottie data-lazy="1" class="tf_lazy"><template>%s</template></tf-lottie>', json_encode($lottie));
    }
    return '';
}

/**
 * Load/Check minified file is exist
 */
function themify_enque(string $url, bool $check = false, bool $cdn = true) {//backward
    return $check===true?false:$url;
}

function themify_is_minify_enabled():bool{//backward
    return false;
}

function themify_whitelist_tag( string $input, string $default = 'div' ) : string {
    if ( ! in_array( $input, [ 'div', 'p', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'nav' ], true ) ) {
        return $default;
    } else {
        return $input;
    }
}