<?php
/**
 * Widget: WooCommerce Search (Advanced search form)
 *
 * @package ThemeREX Addons
 * @since v1.6.38
 */

// Don't load directly
if ( ! defined( 'TRX_ADDONS_VERSION' ) ) {
	exit;
}

if ( ! defined('TRX_ADDONS_WOOCOMMERCE_SEARCH_FIELDS') ) define('TRX_ADDONS_WOOCOMMERCE_SEARCH_FIELDS', 8);

// Load widget
if ( ! function_exists('trx_addons_widget_woocommerce_search_load') ) {
	add_action( 'widgets_init', 'trx_addons_widget_woocommerce_search_load', 21 );
	function trx_addons_widget_woocommerce_search_load() {
		if ( ! trx_addons_exists_woocommerce() ) return;
		register_widget('trx_addons_widget_woocommerce_search');
	}
}


// Return list of styles for "WooCommerce Search"
if ( !function_exists( 'trx_addons_get_list_woocommerce_search_types' ) ) {
	function trx_addons_get_list_woocommerce_search_types() {
		return apply_filters('trx_addons_filter_get_list_woocommerce_search_types', array(
			'inline' => esc_html__('Inline', 'trx_addons'),
			'form'   => esc_html__('Form', 'trx_addons'),
			'filter' => esc_html__('Filter', 'trx_addons'),
		));
	}
}


// Return list of the WooCommerce filters
if ( !function_exists( 'trx_addons_get_list_woocommerce_search_filters' ) ) {
	function trx_addons_get_list_woocommerce_search_filters($none_key = 'none') {
		$list = array(
			$none_key		=> trx_addons_get_not_selected_text( __( 'Not selected', 'trx_addons' ) ),
			's'				=> __('Search string', 'trx_addons'),
			'product_cat'	=> __('Product Category', 'trx_addons'),
			'product_tag'	=> __('Product Tag', 'trx_addons'),
			'min_price'		=> __('Min. price', 'trx_addons'),
			'max_price'		=> __('Max. price', 'trx_addons'),
			'rating'		=> __('Rating', 'trx_addons')
		);
		$attribute_taxonomies = wc_get_attribute_taxonomies();
		if ( !empty($attribute_taxonomies) ) {
			foreach ( $attribute_taxonomies as $attribute ) {
				$list[wc_attribute_taxonomy_name($attribute->attribute_name)] = $attribute->attribute_label;
			}
		}
		return $list;
	}
}


// Return list of expanded filters
if ( !function_exists( 'trx_addons_get_list_woocommerce_search_expanded' ) ) {
	function trx_addons_get_list_woocommerce_search_expanded() {
		$list = array(
					0 => esc_html__('Collapse all filters', 'trx_addons'),
					999 => esc_html__('Expand all filters', 'trx_addons'),
					1 => esc_html__('Expand first item only', 'trx_addons'),
				);
		for ( $i=2; $i < TRX_ADDONS_WOOCOMMERCE_SEARCH_FIELDS; $i++ ) {
			$list[$i] = sprintf( esc_html__('Expand first %d items', 'trx_addons'), $i );
		}
		return apply_filters( 'trx_addons_filter_get_list_woocommerce_search_expanded', $list );
	}
}


// Mark start of inline classes inside WooCommerce output (used in AJAX)
if ( ! function_exists( 'trx_addons_widget_woocommerce_search_woocommerce_output_start' ) ) {
	add_action('woocommerce_before_main_content', 'trx_addons_widget_woocommerce_search_woocommerce_output_start', 1);
	function trx_addons_widget_woocommerce_search_woocommerce_output_start() {
		trx_addons_add_inline_css( '#woocommerce_output_start{}' );
	}
}

// Mark end of inline classes inside WooCommerce output (used in AJAX)
if ( ! function_exists( 'trx_addons_widget_woocommerce_search_woocommerce_output_end' ) ) {
	add_action('woocommerce_after_main_content', 'trx_addons_widget_woocommerce_search_woocommerce_output_end', 1000);
	function trx_addons_widget_woocommerce_search_woocommerce_output_end() {
		trx_addons_add_inline_css( '#woocommerce_output_end{}' );
	}
}


// Widget Class
class trx_addons_widget_woocommerce_search extends TRX_Addons_Widget {

	protected $search_fields = TRX_ADDONS_WOOCOMMERCE_SEARCH_FIELDS;

	function __construct() {
		$widget_ops = array('classname' => 'widget_woocommerce_search', 'description' => esc_html__('Advanced search form for products', 'trx_addons'));
		parent::__construct( 'trx_addons_widget_woocommerce_search', esc_html__('ThemeREX Product Filters', 'trx_addons'), $widget_ops );
		$this->search_fields = apply_filters( 'trx_addons_filter_widget_woocommerce_filters_total', $this->search_fields );
	}

	// Show widget
	function widget($args, $instance) {

		$style = isset($instance['style']) ? $instance['style'] : 'default';
		$type  = isset($instance['type']) ? $instance['type'] : 'inline';
		$apply = isset($instance['apply']) ? $instance['apply'] : 0;
		$ajax  = isset($instance['ajax']) ? $instance['ajax'] : 0;
		$force_checkboxes = isset($instance['force_checkboxes']) ? $instance['force_checkboxes'] : 0;
		$show_counters = isset($instance['show_counters']) ? $instance['show_counters'] : 1;
		$show_selected = isset($instance['show_selected']) ? $instance['show_selected'] : 1;
		$expanded = isset($instance['expanded']) ? (int) $instance['expanded'] : 0;
		
		// Hide widget on the single product, cart, checkout and user's account pages
		if ( apply_filters( 'trx_addons_filter_woocommerce_search',
							( $type!='inline' && ! is_shop() && ! is_product_category() && ! is_product_tag() && ! is_product_taxonomy() )
							||
							( $type=='inline' && ( is_product() || is_cart() || is_checkout() || is_account_page() ) )
						) 
		) {
			return;
		}

		$title = apply_filters('widget_title', isset($instance['title']) ? $instance['title'] : '', $instance, $this->id_base);
		if (!isset($instance['fields'])) {
			$fields = array();
			for ($i=1; $i<=$this->search_fields; $i++) {
				$fields[] = array(
					'text' => isset($instance["field{$i}_text"]) ? $instance["field{$i}_text"] : '',
					'filter' => isset($instance["field{$i}_filter"]) ? $instance["field{$i}_filter"] : ''
				);
			}
		} else {
			$fields = $instance['fields'];
		}
		$last_text = isset($instance['last_text']) ? $instance['last_text'] : '';
		$button_text = !empty($instance['button_text']) ? $instance['button_text'] : '';

		if ( $type == 'filter' ) {
			wp_enqueue_script('jquery-ui-slider', false, array( 'jquery', 'jquery-ui-core' ), null, true );
		}

		trx_addons_get_template_part(array(
										TRX_ADDONS_PLUGIN_API . 'woocommerce/tpl.widget.woocommerce_search_type_'.trx_addons_esc($type).'.php',
										TRX_ADDONS_PLUGIN_API . 'woocommerce/tpl.widget.woocommerce_search_type_form.php'
										),
									'trx_addons_args_widget_woocommerce_search',
									apply_filters(
										'trx_addons_filter_widget_args',
										array_merge($args, compact('title', 'type', 'apply', 'ajax', 'force_checkboxes', 'show_selected', 'show_counters', 'expanded', 'style', 'fields', 'last_text', 'button_text')),
										$instance,
										'trx_addons_widget_woocommerce_search'
										)
								);
	}

	// Update the widget settings.
	function update($new_instance, $instance) {
		$instance = array_merge($instance, $new_instance);
		$instance['title'] = strip_tags($new_instance['title']);
		$instance['type'] = strip_tags($new_instance['type']);
		$instance['apply'] = ! empty( $new_instance['apply'] ) ? 1 : 0;
		$instance['ajax'] = ! empty( $new_instance['ajax'] ) ? 1 : 0;
		$instance['force_checkboxes'] = ! empty( $new_instance['force_checkboxes'] ) ? 1 : 0;
		$instance['show_selected'] = ! empty( $new_instance['show_selected'] ) ? 1 : 0;
		$instance['show_counters'] = ! empty( $new_instance['show_counters'] ) ? 1 : 0;
		$instance['expanded'] = (int) $new_instance['expanded'];
		for ($i=1; $i<=$this->search_fields; $i++) {
			$instance["field{$i}_text"] = strip_tags($new_instance["field{$i}_text"]);
			$instance["field{$i}_filter"] = strip_tags($new_instance["field{$i}_filter"]);
		}
		$instance["last_text"] = strip_tags($new_instance["last_text"]);
		$instance["button_text"] = strip_tags($new_instance["button_text"]);
		return apply_filters('trx_addons_filter_widget_args_update', $instance, $new_instance, 'trx_addons_widget_woocommerce_search');
	}

	// Displays the widget settings controls on the widget panel.
	function form($instance) {

		// Set up some default widget settings
		$default = array(
			'title' => '',
			'type' => 'inline',
			'apply' => 1,
			'ajax' => 1,
			'force_checkboxes' => 0,
			'show_selected' => 1,
			'show_counters' => 1,
			'expanded' => 0,
			'last_text' => '',
			'button_text' => ''
		);
		for ($i=1; $i<=$this->search_fields; $i++) {
			$default["field{$i}_text"] = '';
			$default["field{$i}_filter"] = '';
		}
		$instance = wp_parse_args( (array) $instance, apply_filters('trx_addons_filter_widget_args_default', $default, 'trx_addons_widget_woocommerce_search')
		);
		
		do_action('trx_addons_action_before_widget_fields', $instance, 'trx_addons_widget_woocommerce_search', $this);
		
		$this->show_field(array('name' => 'title',
								'title' => __('Widget title:', 'trx_addons'),
								'value' => $instance['title'],
								'type' => 'text'));
		
		do_action('trx_addons_action_after_widget_title', $instance, 'trx_addons_widget_woocommerce_search', $this);

		$this->show_field(array('name' => "type",
								'title' => __('Type', 'trx_addons'),
								'value' => $instance["type"],
								'options' => trx_addons_get_list_woocommerce_search_types(),
								'type' => 'select'));

		$this->show_field(array('name' => "ajax",
								'title' => __('Use AJAX to reload products', 'trx_addons'),
								'label' => __('Use AJAX', 'trx_addons'),
								'description' => __('Use AJAX to refresh the product list in the background instead of reloading the entire page.', 'trx_addons'),
								'dependency' => array(
									'type' => array('filter')
								),
								'value' => $instance["ajax"],
								'type' => 'checkbox'));

		$this->show_field(array('name' => "apply",
								'title' => __('Use "Apply" Button for Filtering', 'trx_addons'),
								'label' => __('Use "Apply" Button', 'trx_addons'),
								'description' => __('Select multiple filter values without the page reloading.', 'trx_addons'),
								'dependency' => array(
									'type' => array('filter')
								),
								'value' => $instance["apply"],
								'type' => 'checkbox'));

		$this->show_field(array('name' => "force_checkboxes",
								'title' => __('Simple view', 'trx_addons'),
								'label' => __('Simple fileds', 'trx_addons'),
								'description' => __('Display colors, images and buttons as checkboxes.', 'trx_addons'),
								'dependency' => array(
									'type' => array('filter')
								),
								'value' => $instance["force_checkboxes"],
								'type' => 'checkbox'));

		$this->show_field(array('name' => "show_counters",
								'title' => __('Show counters', 'trx_addons'),
								'label' => __('Show', 'trx_addons'),
								'description' => __('Show product counters after each item.', 'trx_addons'),
								'dependency' => array(
									'type' => array('filter')
								),
								'value' => $instance["show_counters"],
								'type' => 'checkbox'));

		$this->show_field(array('name' => "show_selected",
								'title' => __('Show selected items', 'trx_addons'),
								'label' => __('Show', 'trx_addons'),
								'description' => __('Show selected items counter and "Clear all" button.', 'trx_addons'),
								'dependency' => array(
									'type' => array('filter')
								),
								'value' => $instance["show_selected"],
								'type' => 'checkbox'));

		$this->show_field(array('name' => "expanded",
								'title' => __('Initial toggle state', 'trx_addons'),
								'description' => __('For sidebar placement ONLY!', 'trx_addons'),
								'value' => $instance["expanded"],
								'dependency' => array(
									'type' => array('filter')
								),
								'options' => trx_addons_get_list_woocommerce_search_expanded(),
								'type' => 'select'));

		for ($i=1; $i<=$this->search_fields; $i++) {
			$this->show_field(array('name' => "field{$i}_text",
									'title' => sprintf(__('Field %d text', 'trx_addons'), $i),
									'value' => $instance["field{$i}_text"],
									'type' => 'text'));
			$this->show_field(array('name' => "field{$i}_filter",
									'title' => sprintf(__('Field %d filter:', 'trx_addons'), $i),
									'value' => $instance["field{$i}_filter"],
									'options' => trx_addons_get_list_woocommerce_search_filters(),
									'type' => 'select'));
		}

		$this->show_field(array('name' => "last_text",
								'title' => __('Last text', 'trx_addons'),
								'value' => $instance["last_text"],
								'type' => 'text'));

		$this->show_field(array('name' => "button_text",
								'title' => __('Button text', 'trx_addons'),
								'value' => $instance["button_text"],
								'type' => 'text'));

		do_action('trx_addons_action_after_widget_fields', $instance, 'trx_addons_widget_woocommerce_search', $this);
	}
}


// Parse query params from GET/POST and wp_query_parameters
if ( !function_exists( 'trx_addons_widget_woocommerce_search_query_params' ) ) {
	function trx_addons_widget_woocommerce_search_query_params($fields, $return_id = false) {
		$params = array();
		$q_obj = get_queried_object();
		// Add both price - min and max
		$need_min = $need_max = 1;
		foreach ($fields as $fld) {
			if ( $fld['filter'] == 'min_price' ) {
				$need_min = 0;
			} else if ( $fld['filter'] == 'max_price' ) {
				$need_min = 0;
			}
		}
		if ( $need_min + $need_max == 1 ) {	// If present only one of couple fields
			if ( $need_min ) {
				$fields[] = array( 'filter' => 'min_price' );
			} else {
				$fields[] = array( 'filter' => 'max_price' );
			}
		}
		// Fill values
		foreach ($fields as $fld) {
			if (trx_addons_is_off($fld['filter'])) continue;
			$tax_name = $fld['filter'];
			if ( $tax_name == 'product_cat' && is_tax($tax_name) ) {
				$params[$tax_name] = $return_id ? $q_obj->term_id : $q_obj->slug;
			} else if ( ($value = trx_addons_get_value_gp($tax_name)) != '') {
				$params[$tax_name] = sanitize_text_field($value);
			} else if ( ($value = trx_addons_get_value_gp(trx_addons_woocommerce_get_filter_name_from_attribute($tax_name))) != '') {
				$params[$tax_name] = sanitize_text_field($value);
			} else if ( ($value = trx_addons_get_value_gp(trx_addons_woocommerce_get_filter_name_from_attribute($tax_name, true))) != '') {
				$params[$tax_name] = sanitize_text_field($value);
			} else {
				$params[$tax_name] = '';
			}
		}
		return $params;
	}
}


// Parse title with counter
if ( !function_exists( 'trx_addons_widget_woocommerce_search_parse_title_with_counter' ) ) {
	function trx_addons_widget_woocommerce_search_parse_title_with_counter( $title ) {
		$result = array(
			'title' => '',
			'total' => ''
		);
		if ( preg_match_all( '/(.*)\\([\\d]+\\)$/', $title, $matches ) ) {
			$result['title'] = $matches[1];
			$result['total'] = $matches[2];
		}
		return apply_filters( 'trx_addons_filter_parse_title_with_counter', $result, $title );
	}
}


// Find min and max price in current result set.
if ( !function_exists( 'trx_addons_widget_woocommerce_search_get_filtered_price' ) ) {
	function trx_addons_widget_woocommerce_search_get_filtered_price() {
		if ( trx_addons_exists_woocommerce() ) {
			global $wpdb;

			$args       = WC()->query->get_main_query()->query_vars;
			$tax_query  = isset( $args['tax_query'] ) ? $args['tax_query'] : array();
			$meta_query = isset( $args['meta_query'] ) ? $args['meta_query'] : array();

			if ( ! is_post_type_archive( 'product' ) && ! empty( $args['taxonomy'] ) && ! empty( $args['term'] ) ) {
				$tax_query[] = WC()->query->get_main_tax_query();
			}

			foreach ( $meta_query + $tax_query as $key => $query ) {
				if ( ! empty( $query['price_filter'] ) || ! empty( $query['rating_filter'] ) ) {
					unset( $meta_query[ $key ] );
				}
			}

			$meta_query = new WP_Meta_Query( $meta_query );
			$tax_query  = new WP_Tax_Query( $tax_query );
			$search     = WC_Query::get_main_search_query_sql();

			$meta_query_sql   = $meta_query->get_sql( 'post', $wpdb->posts, 'ID' );
			$tax_query_sql    = $tax_query->get_sql( $wpdb->posts, 'ID' );
			$search_query_sql = $search ? ' AND ' . $search : '';

			$sql = "
					SELECT min( min_price ) as min_price, MAX( max_price ) as max_price
					FROM {$wpdb->wc_product_meta_lookup}
					WHERE product_id IN (
						SELECT ID FROM {$wpdb->posts}
						" . $tax_query_sql['join'] . $meta_query_sql['join'] . "
						WHERE {$wpdb->posts}.post_type IN ('" . implode( "','", array_map( 'esc_sql', apply_filters( 'woocommerce_price_filter_post_type', array( 'product' ) ) ) ) . "')
						AND {$wpdb->posts}.post_status = 'publish'
						" . $tax_query_sql['where'] . $meta_query_sql['where'] . $search_query_sql . '
					)';

			$sql = apply_filters( 'woocommerce_price_filter_sql', $sql, $meta_query_sql, $tax_query_sql );
			return $wpdb->get_row( $sql ); // WPCS: unprepared SQL ok.
		} else {
			return array(
				'min_price' => 0,
				'max_price' => 0
			);
		}
	}
}


// Count products number with specified rating in current result set
if ( !function_exists( 'trx_addons_widget_woocommerce_search_get_filtered_product_count_by_rating' ) ) {
	function trx_addons_widget_woocommerce_search_get_filtered_product_count_by_rating( $rating ) {
		if ( trx_addons_exists_woocommerce() ) {
			global $wpdb;

			$tax_query  = WC_Query::get_main_tax_query();
			$meta_query = WC_Query::get_main_meta_query();

			// Unset current rating filter.
			foreach ( $tax_query as $key => $query ) {
				if ( ! empty( $query['rating_filter'] ) ) {
					unset( $tax_query[ $key ] );
					break;
				}
			}

			// Set new rating filter.
			$product_visibility_terms = wc_get_product_visibility_term_ids();
			$tax_query[]              = array(
				'taxonomy'      => 'product_visibility',
				'field'         => 'term_taxonomy_id',
				'terms'         => $product_visibility_terms[ 'rated-' . $rating ],
				'operator'      => 'IN',
				'rating_filter' => true,
			);

			$meta_query     = new WP_Meta_Query( $meta_query );
			$tax_query      = new WP_Tax_Query( $tax_query );
			$meta_query_sql = $meta_query->get_sql( 'post', $wpdb->posts, 'ID' );
			$tax_query_sql  = $tax_query->get_sql( $wpdb->posts, 'ID' );

			$sql  = "SELECT COUNT( DISTINCT {$wpdb->posts}.ID ) FROM {$wpdb->posts} ";
			$sql .= $tax_query_sql['join'] . $meta_query_sql['join'];
			$sql .= " WHERE {$wpdb->posts}.post_type = 'product' AND {$wpdb->posts}.post_status = 'publish' ";
			$sql .= $tax_query_sql['where'] . $meta_query_sql['where'];

			$search = WC_Query::get_main_search_query_sql();
			if ( $search ) {
				$sql .= ' AND ' . $search;
			}

			return absint( $wpdb->get_var( $sql ) ); // WPCS: unprepared SQL ok.
		} else {
			return 0;
		}
	}
}


// Add widget's specific vars to the JS storage
if ( !function_exists( 'trx_addons_widget_woocommerce_search_localize_script' ) ) {
	add_filter("trx_addons_filter_localize_script", 'trx_addons_widget_woocommerce_search_localize_script');
	function trx_addons_widget_woocommerce_search_localize_script($vars) {
		$vars['msg_no_products_found'] = addslashes( esc_html__("No products found! Please, change query parameters and try again.", 'trx_addons') );
		return $vars;
	}
}


// Add shortcodes
//----------------------------------------------------------------------------

require_once TRX_ADDONS_PLUGIN_DIR . TRX_ADDONS_PLUGIN_API . 'woocommerce/widget.woocommerce_search-sc.php';

// Add shortcodes to Elementor
if ( trx_addons_exists_woocommerce() && trx_addons_exists_elementor() && function_exists('trx_addons_elm_init') ) {
	require_once TRX_ADDONS_PLUGIN_DIR . TRX_ADDONS_PLUGIN_API . 'woocommerce/widget.woocommerce_search-sc-elementor.php';
}

// Add shortcodes to VC
if ( trx_addons_exists_woocommerce() && trx_addons_exists_vc() && function_exists( 'trx_addons_vc_add_id_param' ) ) {
	require_once TRX_ADDONS_PLUGIN_DIR . TRX_ADDONS_PLUGIN_API . 'woocommerce/widget.woocommerce_search-sc-vc.php';
}
