<?php

if ( ! defined('ABSPATH') ) {
    exit;
}

use \SearchFilterSort\Filter\Container;
use \SearchFilterSort\Filter\SFSSet;
use \SearchFilterSort\Filter\SFSFields;
use \SearchFilterSort\Filter\PostMetaNumEntity;
use \SearchFilterSort\Filter\PostDateEntity;

/**
 * Returns user's caps level that allows to use the plugin.
 * Developers can modify this level via hook 'sfswp_plugin_user_caps' ot their own risk.
 * @return string
 */
function sfs_plugin_user_caps(){
    return apply_filters( 'sfswp_plugin_user_caps', 'manage_options' );
}

function sfs_the_set( $set_id = 0 ){
    global $sfs_sets;

    if( function_exists('brizy_load' ) ){
        if( ! did_action('wp_print_scripts') ) {
            return false;
        }
    }

    if( $set_id ){
        foreach ( $sfs_sets as $k => $set ){
            if( $set['ID'] === $set_id ){
                unset( $sfs_sets[$k] );
                return $set;
            }
        }
    }

    return array_shift( $sfs_sets );
}

function sfs_print_filters_for( $hook = '' ) {
    global $wp_filter;
    if( empty( $hook ) || !isset( $wp_filter[$hook] ) )
        return;
    return $wp_filter[$hook];
}

function sfs_is_filter_request()
{
    $wpManager = Container::instance()->getWpManager();
    return $wpManager->getQueryVar('sfswp_is_filter_request');
}

function sfs_include($filename )
{
    $path = sfs_get_path( $filename );

    if( file_exists($path) ) {
        include_once( $path );
    }
}

function sfs_get_path($path = '' )
{
    return SFS_PLUGIN_DIR_PATH . ltrim($path, '/');
}

function sfs_ucfirst( $text )
{
    if( ! is_string( $text ) ){
        return $text;
    }
    return mb_strtoupper( mb_substr( $text, 0, 1 ) ) . mb_substr( $text, 1 );
}

function sfs_sanitize_tooltip($var )
{
    return htmlspecialchars(
        wp_kses(
            html_entity_decode( $var ),
            array(
                'br'     => array(),
                'em'     => array(),
                'strong' => array(),
                'small'  => array(),
                'span'   => array(),
                'ul'     => array(),
                'li'     => array(),
                'ol'     => array(),
                'p'      => array(),
                'a'      => array('href'=>true)
            )
        )
    );
}

function sfs_help_tip($tip, $allow_html = false )
{
    if ( $allow_html ) {
        $tip = sfs_sanitize_tooltip( $tip );
    } else {
        $tip = esc_attr( $tip );
    }

    return '<span class="sfswp-help-tip" data-tip="' . $tip . '"></span>';
}

function sfs_tooltip($attr )
{
    if( ! isset( $attr['tooltip'] ) || ! $attr['tooltip'] ){
        return false;
    }

    return sfs_help_tip($attr['tooltip'], true);
}

function sfs_field_instructions($attr)
{
    if( ! isset( $attr['instructions'] ) || ! $attr['instructions'] ){
        return false;
    }
    $instructions = wp_kses(
        $attr['instructions'],
        array(
            'br' => array(),
            'span' => array('class'=>true),
            'strong' => array(),
            'a' => array('href'=>true, 'title'=>true)
        )
    );
    return '<p class="sfswp-field-description">'.$instructions.'</p>';
}

function sfs_add_query_arg(...$args ) {
    if ( is_array( $args[0] ) ) {
        if ( count( $args ) < 2 || false === $args[1] ) {
            $uri = $_SERVER['REQUEST_URI'];
        } else {
            $uri = $args[1];
        }
    } else {
        if ( count( $args ) < 3 || false === $args[2] ) {
            $uri = $_SERVER['REQUEST_URI'];
        } else {
            $uri = $args[2];
        }
    }

    $frag = strstr( $uri, '#' );
    if ( $frag ) {
        $uri = substr( $uri, 0, -strlen( $frag ) );
    } else {
        $frag = '';
    }

    if ( 0 === stripos( $uri, 'http://' ) ) {
        $protocol = 'http://';
        $uri      = substr( $uri, 7 );
    } elseif ( 0 === stripos( $uri, 'https://' ) ) {
        $protocol = 'https://';
        $uri      = substr( $uri, 8 );
    } else {
        $protocol = '';
    }

    if ( strpos( $uri, '?' ) !== false ) {
        list( $base, $query ) = explode( '?', $uri, 2 );
        $base                .= '?';
    } elseif ( $protocol || strpos( $uri, '=' ) === false ) {
        $base  = $uri . '?';
        $query = '';
    } else {
        $base  = '';
        $query = $uri;
    }

    wp_parse_str( $query, $qs );

    if ( is_array( $args[0] ) ) {
        foreach ( $args[0] as $k => $v ) {
            $qs[ $k ] = $v;
        }
    } else {
        $qs[ $args[0] ] = $args[1];
    }

    foreach ( $qs as $k => $v ) {
        if ( false === $v ) {
            unset( $qs[ $k ] );
        }
    }

    $ret = build_query( $qs );
    $ret = trim( $ret, '?' );
    $ret = preg_replace( '#=(&|$)#', '$1', $ret );
    $ret = $protocol . $base . $ret . $frag;
    $ret = rtrim( $ret, '?' );
    return $ret;
}

/**
 * @param $terms array
 * @param $keys array
 *
 * @return array Array of objects with required keys
 */
function sfs_extract_objects_vars( $terms, $keys = [] )
{
    $required = [];

    foreach ( $terms as $i => $term ) {
        $new_object = new \stdClass();

        foreach( $keys as $key ) {
            if( isset( $term->$key ) ){
                $new_object->$key = $term->$key;
                $required[$term->term_id] = $new_object;
            }
        }
    }

    return $required;
}


function sfs_remove_level_array( $array )
{
    /**
     * @feature maybe rewrite this full of shame code
     */
    if( ! is_array( $array ) ){
        return [];
    }

    $flatten = [];

    array_map( function ($a) use(&$flatten){
        if( is_array( $a ) ){
            $flatten = array_merge($flatten, $a);
        }
    },
        $array );

    return $flatten;
}

/**
 * @return bool whether to ask about rate or not
 */
function sfs_ask_for_help(){
    $to_ask        = false;
    $first_install = get_option( 'sfswp_first_install' );
    /**
     * string
     */
    $the_get       = Container::instance()->getTheGet();

    if ( isset( $the_get['remove_help_tab'] ) && $the_get['remove_help_tab'] == 'true' ) {
        $first_install['rate_disabled'] = true;
        update_option( 'sfswp_first_install', $first_install );
        return false;
    }

    if ( $first_install ) {
        // Rate is finally disabled
        if ( isset( $first_install['rate_disabled'] ) && $first_install['rate_disabled'] === true ) {
            return false;
        }
        // If delay time has already passed
        $now = time();
        if ( isset( $first_install['rate_delayed'] ) && $first_install['rate_delayed'] > $now ) {
            return true;
        }
        $_30_days_ago = $now - 2592000;
        if ( isset( $first_install['install_time'] ) && $first_install['install_time'] < $_30_days_ago ) {
            return true;
        }
    }

    return $to_ask;
}

function sfs_get_forbidden_prefixes()
{
    //@todo it seems all existing tax prefixes should be there
    // All them actual only when permalinks off
    $forbidden_prefixes = [ 'srch' ];
    $permalinksEnabled = defined('SFS_PERMALINKS_ENABLED') ? SFS_PERMALINKS_ENABLED : false;
    if( ! $permalinksEnabled ) {
        $forbidden_prefixes = array_merge( $forbidden_prefixes, array('cat', 'tag', 'page', 'author') );
    }

    if( sfs_wpml_active() ){
        $wpml_url_format = apply_filters( 'wpml_setting', 0, 'language_negotiation_type' );
        if( $wpml_url_format === '3' ){
            $forbidden_prefixes[] = 'lang';
        }
    }

    return apply_filters( 'sfswp_forbidden_prefixes', $forbidden_prefixes );
}

function sfs_get_forbidden_meta_keys()
{
    $forbidden_meta_keys = array('sfswp_filter_set_post_type', 'sfswp_seo_rule_post_type');
    return apply_filters( 'sfswp_forbidden_meta_keys', $forbidden_meta_keys );
}

function sfs_array_contains_duplicate($array )
{
    return count($array) != count( array_unique($array) );
}

function sfs_maybe_hide_row( $atts )
{
    if( $atts['type'] === 'Hidden' ){
        echo ' style="display:none;"';
    }
}
function sfs_filter_row_class( $field_atts )
{
    $classes = [ 'sfswp-filter-tr' ];

    if( isset( $field_atts['class'] ) ){
        $classes[] = $field_atts['class'] . '-tr';
    }

    if( isset( $field_atts['additional_class'] ) ){
        $classes[] = $field_atts['additional_class'];
    }

    return implode(" ", $classes);
}


function sfs_include_admin_view( $path, $args = [] )
{
    $templateManager = Container::instance()->getTemplateManager();
    $templateManager->includeAdminView( $path, $args );
}

function sfs_include_front_view( $path, $args = [] )
{
    $templateManager = Container::instance()->getTemplateManager();
    $templateManager->includeFrontView( $path, $args );
}

function sfs_create_filters_nonce()
{
    return SFSSet::createNonce();
}

function sfs_get_filter_fields_mapping()
{
    return Container::instance()->getSFSFieldsService()->getFieldsMapping();
}

function sfs_get_configured_filters($post_id )
{
    $filterFields   = Container::instance()->getSFSFieldsService();
    return $filterFields->getFiltersInputs( $post_id );
}

function sfs_get_filter_view_name($view_key )
{
    $view_options = SFSFields::getViewOptions();
    if( isset( $view_options[ $view_key ] ) ){
        return esc_html($view_options[ $view_key ]);
    }

    return esc_html($view_key);
}

function sfs_get_filter_entity_name($entity_key )
{
    $em = Container::instance()->getEntityManager();
    $entities = $em->getPossibleEntities();

    foreach( $entities as $key => $entity_array ){
        if( isset( $entity_array['entities'][ $entity_key ] ) ){
            return esc_html($entity_array['entities'][ $entity_key ]);
        }
    }

    if( $entity_key === 'post_meta_exists' && ! defined('SFS_FILTERS_PRO') ){
        return esc_html__('Available in PRO', 'searchfiltersort');
    }

    return esc_html($entity_key);
}

function sfs_get_set_settings_fields($post_id)
{
    $filterSet = Container::instance()->getSFSSetService();
    return $filterSet->getSettingsTypeFields( $post_id );
}

function sfs_get_set_search_fields($post_id)
{
    $filterSet = Container::instance()->getSFSSetService();
    return $filterSet->getSearchTypeFields( $post_id );
}
function sfs_get_set_sort_fields($post_id)
{
    $filterSet = Container::instance()->getSFSSetService();
    return $filterSet->getSortTypeFields( $post_id );
}

function sfs_render_input( $atts )
{
    $className = isset( $atts['type'] ) ? '\SearchFilterSort\Filter\\' . $atts['type'] : '\SearchFilterSort\Filter\Text';

    if( class_exists( $className ) ){
        $input = new $className( $atts );
        return $input->render();
    }

    return false;
}

function sfs_extract_vars(&$array, $keys )
{
    $r = [];
    foreach( $keys as $key ) {
        $var = sfs_extract_var( $array, $key );
        if( $var ){
            $r[ $key ] = $var;
        }
    }
    return $r;
}

function sfs_extract_var(&$array, $key, $default = null )
{
    // check if exists
    // - uses array_key_exists to extract NULL values (isset will fail)
    if( is_array($array) && array_key_exists($key, $array) ) {
        $v = $array[ $key ];
        unset( $array[ $key ] );
        return $v;
    }
    return $default;
}

function sfs_get_empty_filter( $set_id )
{
    $filterFields = Container::instance()->getSFSFieldsService();
    return $filterFields->getEmptyFilterObject( $set_id );
}

function sfs_excluded_taxonomies()
{
    $excluded_taxonomies = array(
        'nav_menu',
        'link_category',
        'post_format',
        'template_category',
        'element_category',
        'fusion_tb_category',
        'slide-page',
        'elementor_font_type',
        'post_translations',
        'term_language',
        'term_translations',
        'wp_theme',
        'wp_template_part_area',
        'wp_pattern_category',
    );

    return apply_filters( 'sfswp_excluded_taxonomies', $excluded_taxonomies );
}

function sfs_force_non_unique_slug($notNull, $originalSlug )
{
    return $originalSlug;
}

function sfs_redirect_to_error($post_id, $errors )
{
    $redirect = get_edit_post_link( $post_id, 'url' );
    $error_code = 20; // Default error code

    if( !empty( $errors ) && is_array( $errors ) ){
        $error_code = reset( $errors );
    }

    $redirect = add_query_arg( 'message', $error_code, $redirect );
    wp_redirect( $redirect );
    exit;
}

function sfs_sanitize_int( $var )
{
    return preg_replace('/[^\d]+/', '', $var );
}

function sfs_range_input_name( $slug, $edge = 'min', $type = 'num' )
{
    if ( $type === 'date' ) {
        return PostDateEntity::inputName( $slug, $edge );
    }

    return PostMetaNumEntity::inputName( $slug, $edge );
}

function sfs_query_string_form_fields( $values = null, $exclude = [], $current_key = '', $return = false ) {

    $sfs_exclude = array_keys( apply_filters( 'sfswp_unnecessary_get_parameters', [] ) );
    $exclude = array_merge( $exclude, $sfs_exclude );

    if ( is_null( $values ) ) {
        // phpcs:ignore WordPress.Security.NonceVerification.Recommended
        $values = Container::instance()->getTheGet();
        // For compatibility with some Nginx configurations
        unset($values['q']);
    } elseif ( is_string( $values ) ) {
        $url_parts = wp_parse_url( $values );
        $values    = [];

        if ( ! empty( $url_parts['query'] ) ) {
            // This is to preserve full-stops, pluses and spaces in the query string when ran through parse_str.
            $replace_chars = array(
                '.' => '{dot}',
                '+' => '{plus}',
            );

            $query_string = str_replace( array_keys( $replace_chars ), array_values( $replace_chars ), $url_parts['query'] );

            // Parse the string.
            parse_str( $query_string, $parsed_query_string );

            // Convert the full-stops, pluses and spaces back and add to values array.
            foreach ( $parsed_query_string as $key => $value ) {
                $new_key            = str_replace( array_values( $replace_chars ), array_keys( $replace_chars ), $key );
                $new_value          = str_replace( array_values( $replace_chars ), array_keys( $replace_chars ), $value );
                $values[ $new_key ] = $new_value;
            }
        }
    }
    $html = '';

    foreach ( $values as $key => $value ) {
        if ( in_array( $key, $exclude, true ) ) {
            continue;
        }
        if ( $current_key ) {
            $key = $current_key . '[' . $key . ']';
        }
        if ( is_array( $value ) ) {
            $html .= sfs_query_string_form_fields( $value, $exclude, $key, true );
        } else {
            $html .= '<input type="hidden" name="' . esc_attr( $key ) . '" value="' . esc_attr( wp_unslash( $value ) ) . '" />';
        }
    }

    if ( $return ) {
        return $html;
    }

    echo $html; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
}

function sfs_get_query_string_parameters()
{
    $container  = Container::instance();
    $get        = $container->getTheGet();
    $post       = $container->getThePost();

    // For compatibility with some Nginx configurations
    unset($get['q']);

    if( isset( $post['sfs_ajax_link'] ) ){
        $parts = parse_url( $post['sfs_ajax_link'] );
        if( isset( $parts['query'] ) ){
            parse_str( $parts['query'], $output );
            return $output;
        }
    }

    return $get;
}



function sfs_count( $term, $show = 'yes' )
{
    _deprecated_function( 'sfs_count', '1.7.6', 'sfs_filter_count()' );
    sfs_filter_count( $term, $show );
}

if ( ! function_exists( 'sfs_filter_count' ) ){
    function sfs_filter_count( $term, $show = 'yes' )
    {
        if( $show === 'yes' ) :
            echo sfs_filter_get_count( $term );
        endif;
    }
}

/**
 * @since 1.0.5
 * @param $term
 * @return string
 */
function sfs_filter_get_count( $term ){
    return '<span class="sfswp-term-count"><span class="sfswp-term-count-brackets-open">(</span><span class="sfswp-term-count-value">'.esc_html( $term->cross_count ).'</span><span class="sfswp-term-count-brackets-close">)</span></span>&nbsp;';
}

if ( ! function_exists( 'sfs_spinner_html' ) ) {
    function sfs_spinner_html()
    {
        return '<div class="sfswp-spinner"></div>';
    }
}

function sfs_filters_widget_content_class( $setId )
{
    if ( isset( $_COOKIE[ SFS_OPEN_CLOSE_BUTTON_COOKIE_NAME ] ) ) {

        if ( $_COOKIE[ SFS_OPEN_CLOSE_BUTTON_COOKIE_NAME ] === $setId ) {
            return ' sfswp-opened';
        }else{
            return ' sfswp-closed';
        }
    }
}

function sfs_filters_button( $setId = 0, $class = '' )
{
    /**
     * @feature add nice wrapper to this functions to allow users put it into themes.
     */
    $classes         = [];
    $sets            = [];
    $wpManager       = \SearchFilterSort\Filter\Container::instance()->getWpManager();
    $templateManager = \SearchFilterSort\Filter\Container::instance()->getTemplateManager();

    $draft_sets = $wpManager->getQueryVar('sfswp_page_related_set_ids');

    foreach ( $draft_sets as $set ){
        if( isset( $set['show_on_the_page'] ) && $set['show_on_the_page'] ){
            $sets[] = $set;
        }
    }

    if( ! $setId && isset( $sets[0]['ID'] ) ){
        $setId = $sets[0]['ID'];
    }

    foreach ( $sets as $set ){
        if( $set['ID'] === $setId ){
            $theSet = $set;
            break;
        }
    }

    if( sfs_get_option('mobile_filter_settings') === 'show_bottom_widget' ){
        $classes[] = 'sfswp-filters-open-widget';
    }else{
        $classes[] = 'sfswp-open-close-filters-button';
    }

    if( $class ){
        $classes[] = trim($class);
    }

    $attrClass = implode(" ", $classes);
    $setId = preg_replace('/[^\d]+/', '', $setId);

    $sfswp_found_posts = NULL;
    $srch = isset( $_GET['srch'] ) ? filter_input( INPUT_GET, 'srch', FILTER_SANITIZE_SPECIAL_CHARS ) : '';
    $all  = false;
    if ( $srch ) {
        $all = true;
    }

    if( $wpManager->getQueryVar('sfswp_is_filter_request' ) || $srch ){
        $sfswp_found_posts = sfs_posts_found_quantity( $setId, $all );
    }

    $templateManager->includeFrontView( 'filters-button', array( 'sfswp_found_posts' => $sfswp_found_posts, 'class' => $attrClass, 'set_id' => $setId ) );
}

function sfs_posts_found( $setid = 0, $all = false )
{
    $templateManager = \SearchFilterSort\Filter\Container::instance()->getTemplateManager();
    $fss             = \SearchFilterSort\Filter\Container::instance()->getSFSSetService();

    if ( isset( $_GET['srch'] ) && $_GET['srch'] ) {
        $all         = true;
    }
    $count           = sfs_posts_found_quantity( $setid, $all );

    $theSet          = $fss->getSet( $setid );
    $postType        = isset( $theSet['post_type']['value'] ) ? $theSet['post_type']['value'] : '';

    $obj             = get_post_type_object($postType);
    $pluralLabel     = isset( $obj->label ) ? apply_filters( 'sfswp_label_singular_posts_found_msg', $obj->label ) : esc_html__('items', 'searchfiltersort');
    $singularLabel   = isset( $obj->labels->singular_name ) ? apply_filters( 'sfswp_label_plural_posts_found_msg', $obj->labels->singular_name ) : esc_html__('item', 'searchfiltersort');

    $templateManager->includeFrontView( 'posts-found', array( 'posts_found_count' => $count, 'singular_label' => $singularLabel, 'plural_label' => $pluralLabel) );
}

function sfs_get_option( $key, $default = false )
{
    $settings = get_option('sfswp_filter_settings');

    if( isset( $settings[$key] ) ){
        return apply_filters( 'sfswp_get_option', $settings[$key], $key);
    }

    if( $default ){
        return $default;
    }

    return false;

}

function sfs_remove_option($key )
{
    $settings = get_option('sfswp_filter_settings');

    if (isset($settings[$key]) && $settings[$key]) {
        unset($settings[$key]);
        return update_option('sfswp_filter_settings', $settings);
    }

    return false;
}

function sfs_get_experimental_option($key, $default = false )
{
    /**
     * @todo This should be rewritten
     */
    $settings = get_option('sfswp_filter_experimental');

    if( isset( $settings[$key] ) ){
        return apply_filters( 'sfswp_get_option', $settings[$key], $key);
    }

    if( $default !== false ){
        return apply_filters( 'sfswp_get_option', $default, $key);
    }

    return apply_filters( 'sfswp_get_option', false, $key );

}

function sfs_get_status_css_class( $id, $cookieName, $classes = [ 'opened' => 'sfswp-opened', 'closed' => 'sfswp-closed' ] ){

    if ( isset( $_COOKIE[ $cookieName ] ) ) {
        $openediDs = explode(",", $_COOKIE[ $cookieName ] );

        if ( in_array( $id, $openediDs ) ) {
            return $classes['opened'];
        } elseif ( in_array( -$id, $openediDs ) ) {
            return $classes['closed'];
        } else {
            return '';
        }
    }

    return '';
}

if ( ! function_exists('sfs_filter_header') ) {
    function sfs_filter_header( $filter, $terms )
    {
        $openButton     = ($filter['collapse'] === 'yes') ? '<button><span class="sfswp-wrap-icons">' : '';
        $closeButton    = ($filter['collapse'] === 'yes') ? '</span><span class="sfswp-open-icon"></span></button>' : '';
        $tooltip        = '';

        if ( $filter['collapse'] === 'yes' && !empty($filter['values']) && !empty($terms) ) {
            $selected = [];
            $list = '<span class="sfswp-filter-selected-values">&mdash; ';
            // Does not work for numeric filters
            // @todo
            foreach ( $terms as $id => $term_object ) {

                if ( in_array( $term_object->slug, $filter['values'] ) ) {
                    $selected[] = $term_object->name;
                }
            }

            $list .= implode(", ", $selected) . '</span>';

            $closeButton = $list . $closeButton;
        }

        if ( isset( $filter['tooltip'] ) && $filter['tooltip'] ) {
            $tooltip = sfs_help_tip( $filter['tooltip'], true );
        }

        $filter_label = apply_filters( 'sfswp_filter_title', $filter['label'], $filter );

        ?>
        <div class="sfswp-filter-header"><div class="widget-title sfswp-filter-title"><?php
                echo $openButton . esc_html( $filter_label ) . $tooltip . $closeButton;
                ?></div></div><?php
    }
}

function sfs_filter_class( $filter, $default_classes = [], $terms = [], $args = [] )
{
    $digits = [];
    $length = 1;
    if( ! empty( $terms ) ) {
        foreach ( $terms as $term ) {
            $digits[] = $term->cross_count;
        }
    }

    if( ! empty( $digits ) ){
        $length = strlen( (string) max( $digits ) );
    }

    $classes = array(
        'sfswp-filters-section',
        'sfswp-filters-section-'.esc_attr( $filter['ID'] ),
        'sfswp-filter-'.esc_attr( $filter['e_name'] ),
        'sfswp-filter-'.esc_attr( $filter['entity'] ),
        'sfswp-filter-layout-'.esc_attr( $filter['view'] ),
        'sfswp-counter-length-'.esc_attr( $length )
    );

    if ( isset( $filter['values'] ) && ! empty( $filter['values'] ) ) {
        $classes[] = 'sfswp-filter-has-selected';
    }

    // Set correct more/less class for specific views
    if ( in_array( $filter['view'], [ 'checkboxes', 'radio', 'labels' ] ) ) {
        if ( isset( $filter['more_less'] ) && $filter['more_less'] === 'yes' ) {

            $classes[] = 'sfswp-filter-more-less';

            if ( in_array( $filter['ID'], sfs_more_less_opened() ) ) {
                $classes[] = 'sfswp-show-more-reverse';
            }

            $classes[] = sfs_get_status_css_class( $filter['ID'], SFS_MORELESS_COOKIE_NAME, [ 'opened' => 'sfswp-show-more', 'closed' => 'sfswp-show-less'] );

            // We have to count only first-level terms if hierarchy is enabled
            if( isset( $filter['hierarchy'] ) && $filter['hierarchy'] === 'yes' ) {
                if ( ! empty( $terms ) ) {
                    $only_parents = [];
                    foreach ( $terms as $term_id => $term ) {
                       if ( $term->parent == 0 ) {
                           $only_parents[ $term_id ] = $term;
                       }
                    }

                    $terms = $only_parents;
                    unset( $only_parents );
                }
            }

            if ( count( $terms ) <= sfs_more_less_count() || $args['hide'] ) {
                $classes[] = 'sfswp-filter-few-terms';
            }

        } else {
            $classes[] = 'sfswp-filter-full-height';
        }
    }

    if ( isset( $filter['collapse'] ) && $filter['collapse'] === 'yes' ) {
        if ( in_array( $filter['ID'], sfs_folding_opened() ) ) {
            $classes[] = 'sfswp-filter-collapsible-reverse';
        }

        $classes[] = 'sfswp-filter-collapsible';

        $classes[] = sfs_get_status_css_class( $filter['ID'], SFS_FOLDING_COOKIE_NAME );
    }

    if ( in_array( $filter['ID'], sfs_hierarchy_opened() ) ) {
        if( isset( $filter['hierarchy'] ) && $filter['hierarchy'] === 'yes' ){
            $classes[] = 'sfswp-filter-hierarchy-reverse';
        }
    }

    if ( in_array( $filter['entity'], [ 'post_date', 'post_meta_date' ] ) ) {
        $classes[] = 'sfswp-datetype-'.$filter['date_type'];
    }

    if ( ! empty( $default_classes ) ) {
        $classes = array_merge( $classes, $default_classes );
    }

    $classes[] = 'sfswp-filter-terms-count-'.count( $terms );

    $classes = apply_filters( 'sfswp_filter_classes', $classes, $filter, $default_classes, $terms, $args );

    return implode( " ", $classes );
}

function sfs_filter_content_class( $filter, $default_classes = [] )
{
    $classes = array(
        'sfswp-filter-content'
    );

    if( isset( $filter['e_name'] ) ){
        $classes[] = 'sfswp-filter-'.$filter['e_name'];
    }

    if( isset( $filter['hierarchy'] ) && $filter['hierarchy'] === 'yes' ){
        $classes[] = 'sfswp-filter-has-hierarchy';
    }

    if( ! empty( $default_classes ) ){
        $classes = array_merge( $classes, $default_classes );
    }

    $classes = apply_filters( 'sfswp_filter_content_classes', $classes, $default_classes );

    return implode( " ", $classes );

}

if ( ! function_exists( 'sfs_filter_no_terms_message' ) ) {
    /**
     * Outputs "No terms" message
     * @param string  $tag   HTML tag name for the message wrapper
     * @since 1.7.6
     */
    function sfs_filter_no_terms_message( $tag = 'li' ) {
        if ( ! $tag || $tag === '' ) {
            $tag = 'li';
        }

        $srch = isset( $_GET['srch'] ) ? filter_input( INPUT_GET, 'srch', FILTER_SANITIZE_SPECIAL_CHARS ) : '';

        echo '<'.$tag.' class="sfswp-no-filter-terms">';
            if ( ! sfs_is_filter_request() && ! $srch ) {
                esc_html_e('There are no filter terms yet', 'searchfiltersort' );
                if( sfs_is_debug_mode() ){
                    echo '&nbsp;'.sfs_help_tip(
                            esc_html__('Possible reasons: 1) Filter\'s criterion doesn\'t contain any terms yet, and you have to add them 2) Terms may be created, but no one post that should be filtered attached to these terms 3) You excluded all possible terms in Filter\'s options.', 'searchfiltersort')
                        );
                }
            } else {
                esc_html_e('N/A', 'searchfiltersort' );
            }
        echo '</'.$tag.'>';
    }
}

if ( ! function_exists( 'sfs_filter_more_less' ) ) {
    /**
     * Outputs More/Less toggle link
     * @param array $filter Filter array
     * @since 1.7.6
     */
    function sfs_filter_more_less( $filter ) {
        if ( isset( $filter['more_less'] ) && $filter['more_less'] === 'yes' ): ?>
            <a class="sfswp-see-more-control sfswp-toggle-a" href="javascript:void(0);" data-fid="<?php echo esc_attr( $filter['ID'] ); ?>"><?php esc_html_e('See more', 'searchfiltersort' ); ?></a>
            <a class="sfswp-see-less-control sfswp-toggle-a" href="javascript:void(0);" data-fid="<?php echo esc_attr( $filter['ID'] ); ?>"><?php esc_html_e('See less', 'searchfiltersort' ); ?></a>
        <?php endif;
    }
}

if ( ! function_exists( 'sfs_filter_search_field' ) ) {
    /**
     * Outputs filter search field
     * @since 1.7.6
     */
    function sfs_filter_search_field( $filter, $view_args, $terms ) {
        if ( empty( $terms ) ) {
            return false;
        }

        if( $filter['search'] === 'yes' && $view_args['ask_to_select_parent'] === false ):  ?>
            <div class="sfswp-filter-search-wrapper sfswp-filter-search-wrapper-<?php echo esc_attr( $filter['ID'] ); ?>">
                <input class="sfswp-filter-search-field" type="text" value="" placeholder="<?php esc_html_e('Search', 'searchfiltersort' ) ?>" />
                <button class="sfswp-search-clear" type="button" title="<?php esc_html_e('Clear search', 'searchfiltersort' ) ?>"><span class="sfswp-search-clear-icon">&#215;</span></button>
            </div>
        <?php endif;
    }
}

function sfs_get_contrast_ratio($hexColor){
    // hexColor RGB
    $R1 = hexdec(substr($hexColor, 1, 2));
    $G1 = hexdec(substr($hexColor, 3, 2));
    $B1 = hexdec(substr($hexColor, 5, 2));

    // Black RGB
    $blackColor = "#000000";
    $R2BlackColor = hexdec(substr($blackColor, 1, 2));
    $G2BlackColor = hexdec(substr($blackColor, 3, 2));
    $B2BlackColor = hexdec(substr($blackColor, 5, 2));

    // Calc contrast ratio
    $L1 = 0.2126 * pow($R1 / 255, 2.2) +
        0.7152 * pow($G1 / 255, 2.2) +
        0.0722 * pow($B1 / 255, 2.2);

    $L2 = 0.2126 * pow($R2BlackColor / 255, 2.2) +
        0.7152 * pow($G2BlackColor / 255, 2.2) +
        0.0722 * pow($B2BlackColor / 255, 2.2);

    $contrastRatio = 0;
    if ($L1 > $L2) {
        $contrastRatio = (int)(($L1 + 0.05) / ($L2 + 0.05));
    } else {
        $contrastRatio = (int)(($L2 + 0.05) / ($L1 + 0.05));
    }
    return round($contrastRatio);
}
function sfs_get_contrast_color($hexColor)
{

    $contrastRatio = sfs_get_contrast_ratio($hexColor);
    // If contrast is more than 5, return black color
    if ($contrastRatio > 10) {
        return '#333333';
    } else {
        // if not, return white color.
        return '#f5f5f5';
    }
}
function sfs_hex_to_rgb($hexColor, $opacity = 100) {
    $hexColor = ltrim($hexColor, '#');

    $r = hexdec(substr($hexColor, 0, 2));
    $g = hexdec(substr($hexColor, 2, 2));
    $b = hexdec(substr($hexColor, 4, 2));
    $opacity = $opacity/100;
    return "rgb($r $g $b / $opacity)";
}

function sfs_add_color_opacity($hexColor, $opacity = 50){
    $contrastRatio = sfs_get_contrast_ratio($hexColor);

    if ($contrastRatio <= 15) {
        return sfs_hex_to_rgb($hexColor, $opacity);
    } else {
        return $hexColor;
    }
}


function sfs_default_posts_container()
{
    return  apply_filters( 'sfswp_theme_posts_container', '#primary' );
}

function sfs_default_theme_color()
{
    return  apply_filters( 'sfswp_theme_color', '#0570e2' );
}

function sfs_term_id($name, $filter, $id, $echo = true )
{
    $attr = esc_attr( "sfswp-" . $name . "-" . $filter['entity'] . "-" . esc_attr( $filter['e_name'] ) . "-" . $id );
    if( $echo ){
        echo $attr;
    } else {
        return $attr;
    }
}

function sfs_get_icon_svg($color = '#ffffff' )
{
    /*$svg = '<svg enable-background="new 0 0 26 26" id="Layer_1" version="1.1" viewBox="0 0 26 26" xml:space="preserve" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><g><path d="M1.75,7.75h6.6803589c0.3355713,1.2952271,1.5039063,2.2587891,2.9026489,2.2587891   S13.9000854,9.0452271,14.2356567,7.75H24.25C24.6640625,7.75,25,7.4140625,25,7s-0.3359375-0.75-0.75-0.75H14.2356567   c-0.3355713-1.2952271-1.5039063-2.2587891-2.9026489-2.2587891S8.7659302,4.9547729,8.4303589,6.25H1.75   C1.3359375,6.25,1,6.5859375,1,7S1.3359375,7.75,1.75,7.75z M11.3330078,5.4912109   c0.8320313,0,1.5087891,0.6767578,1.5087891,1.5087891s-0.6767578,1.5087891-1.5087891,1.5087891S9.8242188,7.8320313,9.8242188,7   S10.5009766,5.4912109,11.3330078,5.4912109z" fill="'.$color.'"/><path d="M24.25,12.25h-1.6061401c-0.3355713-1.2952271-1.5039063-2.2587891-2.9026489-2.2587891   S17.1741333,10.9547729,16.838562,12.25H1.75C1.3359375,12.25,1,12.5859375,1,13s0.3359375,0.75,0.75,0.75h15.088562   c0.3355713,1.2952271,1.5039063,2.2587891,2.9026489,2.2587891s2.5670776-0.963562,2.9026489-2.2587891H24.25   c0.4140625,0,0.75-0.3359375,0.75-0.75S24.6640625,12.25,24.25,12.25z M19.7412109,14.5087891   c-0.8320313,0-1.5087891-0.6767578-1.5087891-1.5087891s0.6767578-1.5087891,1.5087891-1.5087891S21.25,12.1679688,21.25,13   S20.5732422,14.5087891,19.7412109,14.5087891z" fill="'.$color.'"/><path d="M24.25,18.25H9.7181396c-0.3355103-1.2952271-1.5037842-2.2587891-2.9017334-2.2587891   c-1.3987427,0-2.5670776,0.963562-2.9026489,2.2587891H1.75C1.3359375,18.25,1,18.5859375,1,19s0.3359375,0.75,0.75,0.75h2.1637573   c0.3355713,1.2952271,1.5039063,2.2587891,2.9026489,2.2587891c1.3979492,0,2.5662231-0.963562,2.9017334-2.2587891H24.25   c0.4140625,0,0.75-0.3359375,0.75-0.75S24.6640625,18.25,24.25,18.25z M6.8164063,20.5087891   c-0.8320313,0-1.5087891-0.6767578-1.5087891-1.5087891s0.6767578-1.5087891,1.5087891-1.5087891   c0.8310547,0,1.5078125,0.6767578,1.5078125,1.5087891S7.6474609,20.5087891,6.8164063,20.5087891z" fill="'.$color.'"/></g></svg>';*/

    return SFS_PLUGIN_DIR_URL . 'assets/images/dashicons-wpsyncsheets.svg';

    $svg = '<svg width="54" height="41" viewBox="0 0 54 41" fill="none" xmlns="http://www.w3.org/2000/svg">
        <path d="M26.6405 0L0 27.3595L13.658 40.6572L27.0158 26.9902L40.6737 40.3315L54 26.6465L26.6405 0Z" fill="#A7AAAD"/>
        <path d="M13.3863 13.6112L27.0773 26.921" stroke="'.$color.'" stroke-width="0.148587"/>
        <path d="M26.9632 26.9005L40.252 13.253" stroke="'.$color.'" stroke-width="0.148587"/>
        <path d="M25.8961 17.9746C25.8141 17.9707 25.7368 17.9349 25.6808 17.875C25.6247 17.815 25.5943 17.7355 25.5959 17.6534L25.665 14.6426L22.8343 11.3812C22.7251 11.2533 22.6538 11.0973 22.6287 10.931C22.6058 10.7624 22.6324 10.5909 22.7052 10.4372C22.7755 10.28 22.8909 10.1472 23.0369 10.056C23.182 9.96633 23.3498 9.92047 23.5202 9.92388L30.2186 10.083C30.3885 10.0874 30.5535 10.1409 30.6936 10.237C30.8337 10.3332 30.9429 10.4679 31.0081 10.6248C31.0737 10.7819 31.0921 10.9548 31.0609 11.1223C31.0297 11.2897 30.9503 11.4444 30.8325 11.5673L27.8548 14.6937L27.8127 16.4527C27.8111 16.4997 27.7993 16.5457 27.7782 16.5878C27.7574 16.6297 27.7271 16.6662 27.6897 16.6943L26.0942 17.91C26.0375 17.9535 25.9676 17.9763 25.8961 17.9746ZM23.5052 10.5543C23.4565 10.5527 23.4084 10.5658 23.3671 10.5918C23.3255 10.6173 23.2922 10.6543 23.2711 10.6983C23.2499 10.7421 23.2426 10.7913 23.2501 10.8394C23.2563 10.8878 23.2767 10.9332 23.3086 10.97L26.2143 14.329C26.2641 14.3864 26.2913 14.46 26.2908 14.5361L26.2323 17.017L27.1899 16.2816L27.2304 14.5586C27.232 14.4806 27.2631 14.406 27.3174 14.35L30.3792 11.1321C30.4105 11.0963 30.4318 11.0527 30.4408 11.006C30.4488 10.959 30.4431 10.9107 30.4245 10.8668C30.4059 10.8229 30.3751 10.7853 30.3357 10.7584C30.2969 10.7311 30.251 10.7155 30.2036 10.7133L23.5052 10.5543Z" fill="'.$color.'"/>
        <path d="M16.3791 23.864C16.414 23.8302 16.4552 23.8037 16.5004 23.7859C16.5456 23.7681 16.5939 23.7594 16.6424 23.7604C16.691 23.7614 16.7389 23.772 16.7834 23.7916C16.8278 23.8112 16.8679 23.8394 16.9014 23.8745C17.162 24.1462 17.3586 24.4725 17.477 24.8298C17.5954 25.1871 17.6326 25.5663 17.5858 25.9398C17.575 26.0307 17.5308 26.1145 17.4617 26.1746C17.3927 26.2348 17.3037 26.2672 17.2121 26.2654H17.1746C17.0771 26.2538 16.9882 26.2039 16.9274 26.1269C16.8667 26.0498 16.839 25.9517 16.8504 25.8542C16.8839 25.5898 16.8581 25.3213 16.7748 25.0681C16.6914 24.815 16.5527 24.5836 16.3686 24.3908C16.3343 24.3558 16.3073 24.3142 16.2892 24.2686C16.2712 24.223 16.2624 24.1743 16.2633 24.1252C16.2643 24.0762 16.2751 24.0278 16.2949 23.983C16.3148 23.9381 16.3434 23.8977 16.3791 23.864Z" fill="'.$color.'"/>
        <path d="M14.9562 21.56C15.7939 21.5759 16.608 21.8399 17.2956 22.3185C17.9833 22.7972 18.5135 23.4691 18.8192 24.2491C19.125 25.0291 19.1925 25.8823 19.0133 26.7008C18.834 27.5192 18.4161 28.2661 17.8123 28.8469C17.2086 29.4278 16.4461 29.8166 15.6214 29.9641C14.7966 30.1115 13.9467 30.0111 13.179 29.6754C12.4114 29.3398 11.7605 28.784 11.3088 28.0784C10.857 27.3728 10.6247 26.5491 10.6412 25.7114C10.6644 24.5892 11.1317 23.522 11.9406 22.7438C12.7495 21.9656 13.8339 21.5399 14.9562 21.56ZM14.8061 29.2865C15.4967 29.2997 16.1757 29.1079 16.7572 28.7353C17.3388 28.3626 17.7968 27.8259 18.0734 27.193C18.3499 26.5601 18.4326 25.8594 18.3109 25.1795C18.1893 24.4996 17.8687 23.871 17.3899 23.3732C16.911 22.8755 16.2953 22.5309 15.6206 22.383C14.9459 22.2352 14.2425 22.2907 13.5994 22.5426C12.9563 22.7945 12.4022 23.2314 12.0074 23.7981C11.6125 24.3648 11.3946 25.0359 11.3811 25.7264C11.3642 26.6524 11.7154 27.5473 12.3574 28.2147C12.9995 28.8821 13.8802 29.2676 14.8061 29.2865Z" fill="'.$color.'"/>
        <path d="M9.09528 30.8401L11.8374 28.2015C11.872 28.1657 11.9135 28.1372 11.9594 28.1178C12.0053 28.0983 12.0547 28.0884 12.1045 28.0884C12.1543 28.0885 12.2037 28.0986 12.2495 28.1182C12.2953 28.1378 12.3368 28.1664 12.3713 28.2023C12.4058 28.2383 12.4327 28.2808 12.4505 28.3274C12.4682 28.374 12.4763 28.4237 12.4744 28.4735C12.4725 28.5233 12.4605 28.5722 12.4393 28.6173C12.418 28.6623 12.3879 28.7027 12.3507 28.7358L9.60557 31.3684C9.57057 31.4022 9.52922 31.4288 9.48389 31.4466C9.43857 31.4644 9.39017 31.4731 9.34148 31.4721C9.2928 31.4711 9.24479 31.4606 9.20021 31.4409C9.15564 31.4213 9.11539 31.3931 9.08177 31.3579C9.01562 31.2871 8.97996 31.1931 8.98249 31.0962C8.98501 30.9993 9.02552 30.9073 9.09528 30.8401Z" fill="'.$color.'"/>
        <path fill-rule="evenodd" clip-rule="evenodd" d="M40.4981 28.8964L42.2542 30.6569C42.2949 30.6976 42.3432 30.7299 42.3964 30.7519C42.4495 30.7739 42.5065 30.7853 42.5641 30.7853C42.6217 30.7853 42.6787 30.7739 42.7318 30.7519C42.785 30.7299 42.8333 30.6976 42.874 30.6569L44.63 28.8964C44.7103 28.8125 44.7551 28.701 44.7551 28.5849C44.7551 28.4689 44.7103 28.3573 44.63 28.2735C44.5893 28.2326 44.5409 28.2001 44.4876 28.1779C44.4343 28.1557 44.3771 28.1443 44.3194 28.1443C44.2616 28.1443 44.2045 28.1557 44.1511 28.1779C44.0978 28.2001 44.0494 28.2326 44.0087 28.2735L43.0031 29.2821V23.3026C43.0066 23.2428 42.9978 23.1829 42.9774 23.1266C42.9569 23.0703 42.9251 23.0188 42.884 22.9752C42.8429 22.9316 42.7933 22.8969 42.7383 22.8731C42.6833 22.8494 42.624 22.8372 42.5641 22.8372C42.5042 22.8372 42.4449 22.8494 42.3899 22.8731C42.3349 22.8969 42.2853 22.9316 42.2442 22.9752C42.2031 23.0188 42.1713 23.0703 42.1508 23.1266C42.1304 23.1829 42.1216 23.2428 42.1251 23.3026V29.2821L41.1195 28.2735C41.0788 28.2326 41.0304 28.2001 40.977 28.1779C40.9237 28.1557 40.8666 28.1443 40.8088 28.1443C40.7511 28.1443 40.6939 28.1557 40.6406 28.1779C40.5873 28.2001 40.5389 28.2326 40.4981 28.2735C40.4179 28.3573 40.3731 28.4689 40.3731 28.5849C40.3731 28.701 40.4179 28.8125 40.4981 28.8964Z" fill="'.$color.'"/>
        <path fill-rule="evenodd" clip-rule="evenodd" d="M38.1943 22.9905C38.1118 22.9082 38.0001 22.862 37.8836 22.862C37.7671 22.862 37.6554 22.9082 37.5729 22.9905L35.8169 24.751C35.7366 24.8348 35.6918 24.9464 35.6918 25.0625C35.6918 25.1785 35.7366 25.2901 35.8169 25.3739C35.8576 25.4148 35.906 25.4473 35.9594 25.4695C36.0127 25.4916 36.0699 25.503 36.1276 25.503C36.1853 25.503 36.2425 25.4916 36.2958 25.4695C36.3491 25.4473 36.3975 25.4148 36.4383 25.3739L37.4439 24.3653V30.3448C37.4404 30.4046 37.4491 30.4645 37.4696 30.5208C37.4901 30.5771 37.5218 30.6286 37.563 30.6722C37.6041 30.7158 37.6536 30.7505 37.7087 30.7742C37.7637 30.798 37.823 30.8102 37.8829 30.8102C37.9428 30.8102 38.0021 30.798 38.0571 30.7742C38.1121 30.7505 38.1617 30.7158 38.2028 30.6722C38.2439 30.6286 38.2756 30.5771 38.2961 30.5208C38.3166 30.4645 38.3254 30.4046 38.3219 30.3448V24.3653L39.329 25.3739C39.3695 25.415 39.4177 25.4476 39.4709 25.4698C39.5241 25.4921 39.5812 25.5035 39.6389 25.5035C39.6966 25.5035 39.7537 25.4921 39.8069 25.4698C39.8601 25.4476 39.9083 25.415 39.9488 25.3739C40.0291 25.2901 40.0739 25.1785 40.0739 25.0625C40.0739 24.9464 40.0291 24.8348 39.9488 24.751L38.1943 22.9905Z" fill="'.$color.'"/>
    </svg>';

    return 'data:image/svg+xml;base64,' . base64_encode( $svg );

}

function sfs_get_icon_html()
{
    ?>
    <svg width="18" height="14" viewBox="0 0 36 27" fill="none" xmlns="http://www.w3.org/2000/svg">
        <path d="M17.6827 0L0 18.1599L9.06548 26.9862L17.9317 17.9148L26.9972 26.7701L35.8425 17.6867L17.6827 0Z" fill="#64748B"></path>
        <path d="M8.88525 9.03445L17.9727 17.8688" stroke="white"></path>
        <path d="M17.8967 17.8552L26.7171 8.79671" stroke="white"></path>
    </svg>
    <?php
}

function sfs_get_plugin_name()
{
    if( defined('SFS_FILTERS_PRO')){
        return esc_html__( 'SearchFilterSort Pro', 'searchfiltersort' );
    }else{
        return esc_html__( 'SearchFilterSort', 'searchfiltersort' );
    }
}

function sfs_get_plugin_url($type = 'about', $full = false )
{
    if( $full ){
        return esc_url($full);
    }

    return esc_url(SFS_PLUGIN_URL . '/' . $type );
}

function sfs_get_term_by_slug($prefix ){
    global $wpdb;

    $sql    = "SELECT {$wpdb->terms}.slug FROM {$wpdb->terms} WHERE {$wpdb->terms}.slug = '%s'";
    $sql    = $wpdb->prepare( $sql, $prefix );
    $result = $wpdb->get_row( $sql );

    if( isset($result->slug) && $result->slug ){
        return $result->slug;
    }

    return false;
}

function sfs_walk_terms_tree( $terms, $args  ) {
    _deprecated_function( 'sfs_walk_terms_tree', '1.7.6', 'sfs_filter_walk_terms_tree()' );
    sfs_filter_walk_terms_tree( $terms, $args );
}

function sfs_filter_walk_terms_tree( $terms, $args ) {
    $walker = new \SearchFilterSort\Filter\WalkerCheckbox();

    $depth = -1;
    if ( isset( $args['filter']['hierarchy'] ) && $args['filter']['hierarchy'] === 'yes' ) {
        $depth = 10;
    }

    return $walker->walk( $terms, $depth, $args );
}

function sfs_get_all_parents($elements, $parent_id, &$ids ){
    if( isset( $elements[$parent_id]->parent ) && $elements[$parent_id]->parent > 0 ){
        $id = $elements[$parent_id]->parent;
        $ids_flipped = array_flip($ids);

        if( ! isset( $ids_flipped[$id] ) ){
            $ids[] = $id;
        }

        sfs_get_all_parents( $elements, $id, $ids );
    }else{
        return $ids;
    }
}

function sfs_get_parents_with_not_empty_children($elements, $key = 'cross_count' ){
    $has_posts_in_children = [];

    if( empty( $elements ) || ! is_array( $elements ) ){
        return $has_posts_in_children;
    }

    $new_elements = [];

    foreach ( $elements as $k => $e ) {
        $new_elements[$e->term_id] = $e;
    }

    $has_posts_in_children_flipped = array_flip( $has_posts_in_children );

    foreach ( $new_elements as $e ) {
        if ( isset( $e->parent ) && ! empty( $e->parent ) && $e->$key > 0 ) {
            // Find all parents for term that contains posts
            if( ! isset( $has_posts_in_children_flipped[ $e->parent ] ) ){
                $has_posts_in_children[] = $e->parent;
            }

            sfs_get_all_parents( $new_elements, $e->parent, $has_posts_in_children );
        }
    }

    return $has_posts_in_children;
}

/**
 * Combines all filter sets for the same WP_Query
 *
 * @param array $all_sets - list of all page related sets
 * @param $current_set
 * @return array $queryRelatedSets IDs of all query related sets
 */
function sfs_get_sets_with_the_same_query( $all_sets, $current_set ){
    $queryRelatedSets = [];
    // First detect desired query index;
    $query      = '';
    $post_type  = '';
    $location   = '';
    $set_id     = $current_set['ID'];

    foreach( $all_sets as $set ){
        if( $set['ID'] === $set_id ){
            // Current Set values
            $query      = $set['query'];
            $post_type  = $set['filtered_post_type'];
            $location   = $set['query_location'];
            break;
        }
    }

    // Then find all sets with such query
    foreach( $all_sets as $set ){
        if( $set['query'] === $query && $post_type === $set['filtered_post_type'] && $location === $set['query_location'] ){
            $queryRelatedSets[] = $set['ID'];
        }
    }

    if( empty( $queryRelatedSets ) ){
        $queryRelatedSets[] = $set_id;
    }

    return $queryRelatedSets;
}

function sfs_find_all_descendants($arr) {
    $all_results = [];

    if( empty( $arr ) || ! is_array( $arr ) ){
        return $all_results;
    }

    foreach ($arr as $k => $v) {
        $curr_result = [];

        for ($stack = [$k]; count($stack);) {
            $el = array_pop($stack);

            if (array_key_exists($el, $arr) && is_array($arr[$el])) {
                foreach ($arr[$el] as $child) {
                    $curr_result []= $child;
                    $stack []= $child;
                }
            }
        }

        if (count($curr_result)) {
            $all_results[$k] = $curr_result;
        }
    }

    return $all_results;
}

function sfs_debug_title(){

    echo '<div class="sfswp-debug-title">'.esc_html__('SearchFilterSort debug', 'searchfiltersort');
    echo  '&nbsp;'.sfs_help_tip(
            sprintf(
                __('Debug messages are visible for logged in administrators only. You can disable them in Filters -> <a href="%s">Settings</a> -> Debug mode.', 'searchfiltersort'),
                admin_url( 'edit.php?post_type=sfs-set&page=sfs-settings' )
            ), true ).'</div>';
}

function sfs_is_debug_mode(){
    $debug_mode = false;
    if( sfs_get_option( 'widget_debug_messages' ) === 'on' ) {
        if( current_user_can( sfs_plugin_user_caps() ) ){
            $debug_mode = true;
        }
    }

    return $debug_mode;
}

function sfs_clean( $var ) {
    if ( is_array( $var ) ) {
        return array_map( 'sfs_clean', $var );
    } else {
        return is_scalar( $var ) ? sanitize_text_field( $var ) : $var;
    }
}

function sfs_sorting_option_value(  $order_by_value, $meta_keys, $orders, $i ){
    $meta_key     = isset( $meta_keys[$i] ) ? $meta_keys[$i] : '';
    $order        = isset( $orders[$i] ) ? $orders[$i] : '';

    $option_value = $order_by_value;

    if( in_array( $order_by_value, ['m', 'n'], true ) ){
        $option_value .= $meta_key;
    }

    $option_value .= ( $order === 'desc' ) ? '-'.$order : '';

    return $option_value;
}

function sfs_get_active_plugins(){

    if( is_multisite() ){
        $active_plugins = get_site_option('active_sitewide_plugins');
        if( is_array( $active_plugins ) ){
            $active_plugins = array_keys( $active_plugins );
        }

        $site_active_plugins = apply_filters( 'active_plugins', get_option('active_plugins') );
        $active_plugins      = array_merge( $active_plugins, $site_active_plugins );
    }else{
        $active_plugins = apply_filters( 'active_plugins', get_option('active_plugins') );
    }

    return $active_plugins;
}

function sfs_get_terms_transient_key( $salt, $include_lang = true ){
    $key = 'sfswp_terms_' . $salt;
    if ( sfs_wpml_active() && defined( 'ICL_LANGUAGE_CODE' ) && $include_lang ) {
        $key .= '_'.ICL_LANGUAGE_CODE;
    }

    if( function_exists('pll_current_language') && $include_lang ){
        $pll_lang = pll_current_language();
        if( $pll_lang ){
            $key .= '_'.$pll_lang;
        }
    }

    return $key;
}

function sfs_get_post_ids_transient_key( $salt ){
    $key = 'sfswp_posts_' . $salt;
    if (sfs_wpml_active() && defined('ICL_LANGUAGE_CODE')) {
        $key .= '_'.ICL_LANGUAGE_CODE;
    }

    if( function_exists('pll_current_language') ){
        $pll_lang = pll_current_language();
        if( $pll_lang ){
            $key .= '_'.$pll_lang;
        }
    }

    return $key;
}

function sfs_get_variations_transient_key( $salt ){
    $key = 'sfswp_variations_' . $salt;
    if (sfs_wpml_active() && defined('ICL_LANGUAGE_CODE')) {
        $key .= '_'.ICL_LANGUAGE_CODE;
    }

    if( function_exists('pll_current_language') ){
        $pll_lang = pll_current_language();
        if( $pll_lang ){
            $key .= '_'.$pll_lang;
        }
    }

    return $key;
}

function sfs_is_query_on_page( $setPosts, $searchKey ){
    $sets = [];
    if( ! is_array( $setPosts ) ){
        return $sets;
    }

    foreach ( $setPosts as $set ){

        $parameters = maybe_unserialize( $set->post_content );
        $query      = isset( $parameters['wp_filter_query'] ) ? $parameters['wp_filter_query']: '-1';

        if( isset( $parameters['use_apply_button'] ) && $parameters['use_apply_button'] === 'yes' ){

            $query_on_the_page = false;
            $show_on_the_page  = false;

            if( defined('SFS_FILTERS_PRO') && SFS_FILTERS_PRO ) {
                if ( isset( $parameters['apply_button_post_name'] ) ){

                    if( $parameters['apply_button_post_name'] === $set->post_name ||
                        $parameters['apply_button_post_name'] === 'no_page___no_page' ){
                        $query_on_the_page = true;
                    }

                    if( in_array( $parameters['apply_button_post_name'], $searchKey ) || ( $parameters['apply_button_post_name'] === 'no_page___no_page' ) ){
                        $show_on_the_page = true;
                    }
                }

            }else{
                $query_on_the_page = true;
                $show_on_the_page  = true;
            }

            $sets[] = array(
                'ID'                 => (string) $set->ID,
                'filtered_post_type' => $set->post_excerpt,
                'query'              => $query, // query hash
                'query_location'     => $set->post_name,
                'query_on_the_page'  => $query_on_the_page,
                'page_search_keys'   => $searchKey,
                'show_on_the_page'   => $show_on_the_page
            );

        }else{
            if( in_array( $set->post_name, $searchKey ) ){
                $sets[] = array(
                    'ID'                 => (string) $set->ID,
                    'filtered_post_type' => $set->post_excerpt,
                    'query'              => $query, // query hash
                    'query_location'     => $set->post_name,
                    'query_on_the_page'  => true,
                    'page_search_keys'   => $searchKey,
                    'show_on_the_page'   => true
                );
            }else{
                // This set is for another page and was selected by Apply button location but the button disabled
                continue;
            }
        }

    }

    return $sets;
}

function sfs_remove_empty_terms( $checkTerms, $filter, $has_not_empty_children_flipped = [] ){

    foreach ($checkTerms as $index => $term) {
        if( $filter['hierarchy'] === 'yes' ){

            if(  $term->cross_count === 0
                && ! isset( $has_not_empty_children_flipped[$term->term_id] ) ){
                unset($checkTerms[$index]);
            }

        }else{
            if( $term->cross_count === 0 ){
                unset($checkTerms[$index]);
            }
        }
    }

    return $checkTerms;
}

function sfs_get_wp_queried_term($terms ){
    $wp_queried_terms = false;

    foreach ( $terms as $term ) {
        if ( $term->wp_queried === true ){
            $wp_queried_terms = $term;
            break;
        }
    }

    return $wp_queried_terms;
}

function sfs_get_filter_terms( $filter, $posType, $em = false ) {
    if( ! $em ){
        $em = Container::instance()->getEntityManager();
    }

    $entityObj  = $em->getEntityByFilter( $filter, $posType );
    // Exclude or include terms
    $isInclude = ( isset( $filter['include'] ) && $filter['include'] === 'yes' );
    $entityObj->setExcludedTerms( $filter['exclude'], $isInclude );

    $terms = $entityObj->getTerms();

    return apply_filters( 'sfswp_items_after_calc_term_count', $terms );
}

function sfs_get_term_brand_image( $term_id, $filter ) {
    $src = false;

    if ( $filter['e_name'] === 'pwb-brand' ) {
        $attachment_id = get_term_meta($term_id, 'pwb_brand_image', true);
        $attachment_props = wp_get_attachment_image_src($attachment_id, 'small');
        $src = isset($attachment_props[0]) ? $attachment_props[0] : false;
    } elseif ( in_array( $filter['e_name'], ['yith_product_brand', 'product_brand'] ) ) {
        $attachment_id = get_term_meta($term_id, 'thumbnail_id', true);
        $attachment_props = wp_get_attachment_image_src($attachment_id, 'small');
        $src = isset($attachment_props[0]) ? $attachment_props[0] : false;
    } else {
        // pa_brand
        $src = get_term_meta( $term_id, 'image', true );

        if( intval( $src ) > 0 ){
            $src = wp_get_attachment_image_url( $src,'full' );
        }

        if ( isset( $src['id'] ) && $src['id'] ) {
            $src = wp_get_attachment_image_url( $src['id'],'full' );
        }
    }

    return $src;
}

function sfs_get_term_swatch_image( $term_id, $filter ) {
    $src = false;
    $image_key = 'image';

    if ( strpos( $filter['e_name'], 'pa_' ) === 0 ) {
        $image_key = 'product_attribute_' . $image_key;
    }

    if ( $filter['e_name'] === 'product_cat' ) {
        $image_key = 'thumbnail_id';
    }

    $image_key = apply_filters( 'sfswp_image_term_meta_key', $image_key, $filter );

    $image_id = get_term_meta( $term_id, $image_key, true );
    $swatch_image_size = apply_filters( 'sfswp_swatch_image_size', 'thumbnail' );

    if ( $image_id ) {
        $src = wp_get_attachment_image_url( $image_id, $swatch_image_size );
    }

    return $src;
}

function sfs_get_term_swatch_color( $term_id, $filter ) {
    $color     = false;
    $color_key = 'color';

    if ( strpos( $filter['e_name'], 'pa_' ) === 0 ) {
        $color_key = 'product_attribute_' . $color_key;
    }

    $color_key = apply_filters( 'sfswp_color_term_meta_key', $color_key, $filter );
    $color = get_term_meta( $term_id, $color_key, true );

    return $color;
}

/**
 * Checks and returns date format.
 * Does not check if date is valid
 * @param $date
 * @return string|false date, time format or false
 */
function sfs_detect_date_type( $date_or_time )
{
    if ( ! $date_or_time ) {
        return false;
    }
    $format = false;
    $date   = false;
    $time   = false;

    $date_or_time = str_replace( SFS_DATE_TIME_SEPARATOR, ' ', $date_or_time );

    $pcs = date_parse( $date_or_time );
    if ( $pcs['year'] !== false && $pcs['month'] !== false && $pcs['day'] !== false ) {
        $date = true;
    }

    if ( $pcs['hour'] !== false && $pcs['minute'] !== false && $pcs['second'] !== false ) {
        $time = true;
    }

    if ( $date && $time ) {
        $format = 'datetime';
    } else {
        if ( $date ) {
            $format = 'date';
        }
        if ( $time ) {
            $format = 'time';
        }
    }

    return $format;
}

/**
 * Modifies datetime to the human format
 * @param $datetime
 * @param $date_type
 * @param string $sep
 * @return mixed|string
 */
function sfs_clean_date_time( $datetime, $date_type, $sep = " " )
{
    if ( $date_type === 'date' ) {
        $pieces = explode( $sep, $datetime );
        return $pieces[0]; //date e.g. 2021-05-14
    } else if ( $date_type === 'time' ) {
        $pieces = explode( $sep, $datetime );
        if ( isset( $pieces[1] ) ) {
            return $pieces[1]; //time e.g. 14:15:47
        }
    } else {
        return $datetime; // str_replace( $sep, ' ', $datetime ); //datetime e.g. 2021-05-14 14:15:47
    }
}

function sfs_apply_date_format( $income_date, $format = "Y-m-d H:i:s" )
{
    $timestamp = strtotime( $income_date );
    return sfs_date( $format, $timestamp );
}

function sfs_date( $format, $timestamp = null ) {
    global $wp_locale;

    if ( null === $timestamp ) {
        $timestamp = time();
    } elseif ( ! is_numeric( $timestamp ) ) {
        return false;
    }

    $datetime = date_create( '@' . $timestamp );

    if ( empty( $wp_locale->month ) || empty( $wp_locale->weekday ) ) {
        $date = $datetime->format( $format );
    } else {
        // We need to unpack shorthand `r` format because it has parts that might be localized.
        $format = preg_replace( '/(?<!\\\\)r/', DATE_RFC2822, $format );

        $new_format    = '';
        $format_length = strlen( $format );
        $month         = $wp_locale->get_month( $datetime->format( 'm' ) );
        $weekday       = $wp_locale->get_weekday( $datetime->format( 'w' ) );

        for ( $i = 0; $i < $format_length; $i++ ) {
            switch ( $format[ $i ] ) {
                case 'D':
                    $new_format .= addcslashes( $wp_locale->get_weekday_abbrev( $weekday ), '\\A..Za..z' );
                    break;
                case 'F':
                    $new_format .= addcslashes( $month, '\\A..Za..z' );
                    break;
                case 'l':
                    $new_format .= addcslashes( $weekday, '\\A..Za..z' );
                    break;
                case 'M':
                    $new_format .= addcslashes( $wp_locale->get_month_abbrev( $month ), '\\A..Za..z' );
                    break;
                case 'a':
                    $new_format .= addcslashes( $wp_locale->get_meridiem( $datetime->format( 'a' ) ), '\\A..Za..z' );
                    break;
                case 'A':
                    $new_format .= addcslashes( $wp_locale->get_meridiem( $datetime->format( 'A' ) ), '\\A..Za..z' );
                    break;
                case '\\':
                    $new_format .= $format[ $i ];

                    // If character follows a slash, we add it without translating.
                    if ( $i < $format_length ) {
                        $new_format .= $format[ ++$i ];
                    }
                    break;
                default:
                    $new_format .= $format[ $i ];
                    break;
            }
        }

        $date = date_format( $datetime, $new_format );
    }

    return $date;
}

function sfs_default_date_format( $date_type = 'date' )
{
    /**
     * @todo date format depend from localization and geo settings
     * we have to relate them here
     */
    $date_format = __('F j, Y');

    switch ( $date_type ) {
        case 'date':
            $date_format = __('F j, Y'); //'d-m-Y';
            break;
        case 'datetime':
            $date_format = __('F j, Y g:i a'); //'d-m-Y H:i:s';
            break;
        case 'time':
            $date_format = __('g:i a'); // 'H:i:s';
            break;
    }

    return $date_format;
}

function sfs_convert_date_to_js( $date_or_time ){
    $date_php_to_js = Container::instance()->getParam('php_to_js_date_formats');
    return sfs_str_replace( $date_or_time, $date_php_to_js );
}

function sfs_convert_time_to_js( $date_or_time ){
    $time_php_to_js = Container::instance()->getParam('php_to_js_time_formats');
    return sfs_str_replace( $date_or_time, $time_php_to_js );
}

function sfs_str_replace( $string = '', $search_replace = array() ) {
    $ignore = array();
    unset( $search_replace[''] );

    foreach ( $search_replace as $search => $replace ) {
        if ( in_array( $search, $ignore ) ) {
            continue;
        }
        if ( strpos( $string, $search ) === false ) {
            continue;
        }
        $string = str_replace( $search, $replace, $string );
        $ignore[] = $replace;
    }

    return $string;
}

function sfs_split_date_time( $date_time = '' ) {
    $php_date = Container::instance()->getParam('php_to_js_date_formats');
    $php_time = Container::instance()->getParam('php_to_js_time_formats');
    $chars    = str_split( $date_time );
    $type     = 'date';

    $data = array(
        'date' => '',
        'time' => '',
    );

    foreach ( $chars as $i => $c ) {
        if ( isset( $php_date[ $c ] ) ) {
            $type = 'date';
        } elseif ( isset( $php_time[ $c ] ) ) {
            $type = 'time';
        }
        $data[ $type ] .= $c;
    }

    $data['date'] = trim( $data['date'] );
    $data['time'] = trim( $data['time'] );

    return $data;
}

function sfs_string_polyfill( $string ) {

    if( is_array( $string ) ){
        return array_map( 'sfs_string_polyfill_body', $string );
    }

    return sfs_string_polyfill_body( $string );
}

function sfs_string_polyfill_body( $string ){
    $str = preg_replace('/\x00|<[^>]*>?/', '', $string );
    return str_replace( ["'", '"'], ['&#39;', '&#34;'], $str );
}

function sfs_rating_star(){
    return '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 25 25">
                                            <polygon class="cls-1" points="19.89 24.5 12.48 19.8 5.06 24.48 7.03 15.62 0.5 9.64 9.12 8.87 12.51 0.5 15.88 8.88 24.5 9.68 17.96 15.63 19.89 24.5"/></svg>';
}

function sfs_check_update_mobile_settings(){

    $settings = get_option('sfswp_filter_settings', false);
    if ($settings !== false){
        if(!sfs_get_option('mobile_filter_settings')){

            $mobile_filter_settings = 'nothing';

            if ( (sfs_get_option('show_bottom_widget') === 'on' && sfs_get_option('show_open_close_button') === 'on')
                || (sfs_get_option('show_bottom_widget') === 'on' && !sfs_get_option('show_open_close_button'))){
                $mobile_filter_settings = 'show_bottom_widget';
            } elseif (sfs_get_option('show_open_close_button') == 'on' && !sfs_get_option('show_bottom_widget')){
                $mobile_filter_settings = 'show_open_close_button';
            }

            $settings = get_option('sfswp_filter_settings');

            if (isset($settings['show_bottom_widget']) && $settings['show_bottom_widget']) {
                unset($settings['show_bottom_widget']);
            }

            if (isset($settings['show_open_close_button']) && $settings['show_open_close_button']) {
                unset($settings['show_open_close_button']);
            }

            $settings['mobile_filter_settings'] = $mobile_filter_settings;
            update_option('sfswp_filter_settings', $settings);
        }
    }
}

if(!function_exists('sfs_set_transient')){
    function sfs_set_transient($transient, $value, $expiration = 0){
        if(defined('SFS_SET_TRANSIENT_ENABLED') && SFS_SET_TRANSIENT_ENABLED){
            set_transient( $transient, $value, $expiration);
        }
    }
}

if(!function_exists('sfs_get_transient')){
    function sfs_get_transient($transient){
        if(defined('SFS_SET_TRANSIENT_ENABLED') && SFS_SET_TRANSIENT_ENABLED){
            return get_transient( $transient );
        }
        return false;
    }
}

if(!class_exists('FlrtWooDiscountRules')) {
    class FlrtWooDiscountRules{

        protected $rules;

        protected $base;
        protected $rule_helper;
        protected $discount_calculator;
        protected $manage_discount;

        //public $filter;
        public function __construct()
        {
            $this->base = new Wdr\App\Controllers\Base();
            $this->rule_helper = new Wdr\App\Helpers\Rule();
            $this->manage_discount = new Wdr\App\Controllers\ManageDiscount();
            $this->rules = $this->manage_discount->getDiscountRules();
            $this->discount_calculator = new Wdr\App\Controllers\DiscountCalculator($this->rule_helper->getAvailableRules($this->base->getAvailableConditions()));
        }

        public function getProductPriceToDisplay($product){
            return $this->discount_calculator->getProductPriceToDisplay($product, 1);
        }
    }
    function sfs_woo_discount_rules_class(){
        return new FlrtWooDiscountRules();
    }
}
