<?php
/**
 * WordPress OAuth Functions
 *
 * @author Justin Greer <justin@justin-greer.com>
 * @package WordPress OAuth Server
 *
 * @todo Convert entire file into library ( class )
 */

// Hook into core filters
require_once dirname(__FILE__) . '/filters.php' ;

// Hook into core actions
require_once( dirname(__FILE__) . '/actions.php' );

/**
 * Generates a 40 Character key is generated by default but should be adjustable in the admin
 * @return [type] [description]
 *
 * @todo Allow more characters to be added to the character list to provide complex keys
 */
function wo_gen_key( $length = 40 ) {

	// Gather the settings
	$options = get_option("wo_options");
	$user_defined_length = (int) $options["client_id_length"];

	// If user setting is larger than 0, then define it
	if ( $user_defined_length > 0 ) {
		$length = $user_defined_length;
	}

	$characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
	$randomString = '';

	for ($i = 0; $i < $length; $i++) {
		$randomString .= $characters[rand(0, strlen($characters) - 1)];
	}

	return $randomString;
}

/**
 * Blowfish Encryptions
 * @param  [type]  $input  [description]
 * @param  integer $rounds [description]
 * @return [type]          [description]
 *
 * REQUIRES ATLEAST 5.3.x
 */
function wo_crypt($input, $rounds = 7) {
	$salt = "";
	$salt_chars = array_merge(range('A', 'Z'), range('a', 'z'), range(0, 9));
	for ($i = 0; $i < 22; $i++) {
		$salt .= $salt_chars[array_rand($salt_chars)];
	}
	return crypt($input, sprintf('$2a$%02d$', $rounds) . $salt);
}

/**
 * Check if there is more than one client in the system
 *
 * @return boolean [description]
 */
function has_a_client (){
	global $wpdb;
	$count = $wpdb->get_results("SELECT * FROM {$wpdb->prefix}oauth_clients");
	//print_r($count);
	if (count($count) >= 1)
		return true;
}

/**
 * Get the client IP multiple ways since REMOTE_ADDR is not always the best way to do so
 * @return [type] [description]
 */
function client_ip(){
	$ipaddress = '';
    if (getenv('HTTP_CLIENT_IP'))
        $ipaddress = getenv('HTTP_CLIENT_IP');
    else if(getenv('HTTP_X_FORWARDED_FOR'))
        $ipaddress = getenv('HTTP_X_FORWARDED_FOR');
    else if(getenv('HTTP_X_FORWARDED'))
        $ipaddress = getenv('HTTP_X_FORWARDED');
    else if(getenv('HTTP_FORWARDED_FOR'))
        $ipaddress = getenv('HTTP_FORWARDED_FOR');
    else if(getenv('HTTP_FORWARDED'))
        $ipaddress = getenv('HTTP_FORWARDED');
    else if(getenv('REMOTE_ADDR'))
        $ipaddress = getenv('REMOTE_ADDR');
    else
        $ipaddress = 'UNKNOWN';

    return $ipaddress;
}

/**
 * Valid the license
 * @param  [type] $l [description]
 * @return [type]    [description]
 */
function _vl() {
	$options = get_option('wo_options');
	return @$options['license_status'] == 'valid' ? true : false;
}

function license_status (){
	$options = get_option('wo_options');
	$status = isset($options['license_status']) ? $options['license_status'] : '';
	switch($status){
		case 'invalid':
			echo 'Invalid. Activate your license now.';
			break;
		case 'valid':
			echo 'Valid';
			break;
	}

}

/**
 * Cron Tasks That the plugin should run daily
 * @return [type] [description]
 */
//add_action( 'wo_daily_tasks_hook', 'wo_daily_tasks' );
function wo_daily_tasks () {
	$options = get_option( 'wo_options' );
	if( @$options['license_status'] == 'valid' ){
		$api_params = array(
			'edd_action'=> 'activate_license',
			'license' 	=> $options['license'],
			'item_name' => urlencode('WP OAuth License'),
			'url'       => home_url()
		);
		$response = wp_remote_get( add_query_arg( $api_params, 'https://wp-oauth.com' ) );
		if ( !is_wp_error( $response ) ){
			$license_data = json_decode( wp_remote_retrieve_body( $response ) );
			if(@$options['license_status'] == 'valid' && $license_data->license != 'valid') {
				wp_mail( get_option('admin_email'), 'Issues found with WP OAuth Server', 'Recent checks show that your license key status for WordPress OAuth Server has been changed.');
				$options['license'] = '';
				$options['license_status'] = '';
			}
			update_option('wo_options', $options);
		}
	}
}

/**
 * WordPress OAuth Server Firewall
 * Called if and license is valid and the firewall is enabled
 */
add_action('wo_before_api', 'wordpress_oauth_firewall_init', 10);
function wordpress_oauth_firewall_init() {
	$options = get_option('wo_options');
	if(!_vl())
		return;

	if(isset($options['firewall_block_all_incomming']) && $options['firewall_block_all_incomming']){
		$remote_addr = client_ip();
		$whitelist = str_replace(' ', '',$options['firewall_ip_whitelist']); // remove all whitespace
		$whitelist_array = explode(',', $whitelist);
		if(in_array($remote_addr, $whitelist_array))
			return;

		header('Content-Type: application/json');
		$response = array(
			'error' => 'Unauthorized'
			);
		print json_encode($response);
		exit;
	}
}

/**
 * Return the private key for signing
 * @since 3.0.5
 * @return [type] [description]
 */
function get_private_server_key () {
	$keys = apply_filters('wo_server_keys', null);
	return file_get_contents( $keys['private'] );
}

/**
 * Returns the public key
 * @return [type] [description]
 * @since 3.1.0
 */
function get_public_server_key () {
	$keys = apply_filters('wo_server_keys', null);
	return file_get_contents( $keys['public'] );
}

/**
 * Returns the set ALGO that is to be used for the server to encode
 *
 * @todo Possibly set this to be adjusted somewhere. The it_token calls for it to be set by each
 * client as a pref but we need to keep this simple.
 *
 * @since 3.1.93
 * @return String Type of algorithm used for encoding and decoding.
 */
function wo_get_algorithm (){
	return 'RS256';
}

/**
 * Check to see if there is certificates that have been generated
 * @return boolean [description]
 */
function wo_has_certificates (){
	return file_exists( dirname(WPOAUTH_FILE) . '/library/keys/public_key.pem' )
	&& file_exists( dirname(WPOAUTH_FILE) . '/library/keys/private_key.pem' );
}

/**
 * [wo_create_client description]
 * @param  [type] $user [description]
 * @return [type]       [description]
 *
 * @todo Add role and permissions check
 */
function wo_create_client( $user=null ){

	do_action('wo_before_create_client', array( $user ) );
	if(! current_user_can( 'manage_options' ) )
		return false;

	$new_client_id = wo_gen_key();
	$new_client_secret = wo_gen_key();

	// Insert the user into the system
	global $wpdb;
	return $wpdb->insert("{$wpdb->prefix}oauth_clients",
		array(
			'client_id' => $new_client_id,
			'client_secret' => $new_client_secret,
			'redirect_uri' => empty($user['client-redirect-uri']) ? '' : $user['client-redirect-uri'],
			'name' => empty($user['client-name']) ? 'No Name' : $user['client-name'],
			'description' => empty($user['client-description']) ? '' : $user['client-description']
			));
}

/**
 * Search SQL filter for matching against post title only.
 *
 * @link    http://wordpress.stackexchange.com/a/11826/1685
 *
 * @param   string      $search
 * @param   WP_Query    $wp_query
 */
function __search_by_title( $search, $wp_query ) {
    if ( ! empty( $search ) && ! empty( $wp_query->query_vars['search_terms'] ) ) {
        global $wpdb;

        $q = $wp_query->query_vars;
        $n = ! empty( $q['exact'] ) ? '' : '%';

        $search = array();

        foreach ( ( array ) $q['search_terms'] as $term )
            $search[] = $wpdb->prepare( "$wpdb->posts.post_title LIKE %s", $n . $wpdb->esc_like( $term ) . $n );

        if ( ! is_user_logged_in() )
            $search[] = "$wpdb->posts.post_password = ''";

        $search = ' AND ' . implode( ' AND ', $search );
    }

    return $search;
}
//add_filter( 'posts_search', '__search_by_title', 500, 2);

function search_only_found_in_upsells($search, $post_content){
    $search = strtolower($search);
    $item_name_start = strpos($post_content, 'rental_name="') + strlen('rental_name="');
    $item_name_end = strpos($post_content, '"', $item_name_start);
    $item_name = strtolower(substr($post_content, $item_name_start, $item_name_end-$item_name_start));

    $item_description_start = strpos($post_content, 'description="') + strlen('description="');
    $item_description_end = strpos($post_content, '"', $item_description_start);
    $item_description = strtolower(substr($post_content, $item_description_start, $item_description_end-$item_description_start));

    $upsell_start = strpos($post_content, 'upsells="') + strlen('upsells="');
    $upsell_end = strpos($post_content, '"', $upsell_start);
    $upsells = strtolower(substr($post_content, $upsell_start, $upsell_end-$upsell_start));

    //if(!str_contains($item_name, $search) && !str_contains($item_description, $search) && str_contains($upsells, $search))
    if($upsells){
        if(strpos($item_name, $search) === false && strpos($item_description, $search) === false && strpos($upsells, $search) !== false){
            return true;
        }
    }
    return false;
}

function search_only_found_in_landing_pages($search, $post_content){
    $search = strtolower($search);
    $item_name_start = strpos($post_content, 'rental_name="') + strlen('rental_name="');
    $item_name_end = strpos($post_content, '"', $item_name_start);
    $item_name = strtolower(substr($post_content, $item_name_start, $item_name_end-$item_name_start));

    $item_description_start = strpos($post_content, 'description="') + strlen('description="');
    $item_description_end = strpos($post_content, '"', $item_description_start);
    $item_description = strtolower(substr($post_content, $item_description_start, $item_description_end-$item_description_start));

    $landing_pages_start = strpos($post_content, 'landing_pages="') + strlen('landing_pages="');
    $landing_pages_end = strpos($post_content, '"', $landing_pages_start);
    $landing_pages = strtolower(substr($post_content, $landing_pages_start, $landing_pages_end-$landing_pages_start));

    //if(!str_contains($item_name, $search) && !str_contains($item_description, $search) && str_contains($upsells, $search))
    if($landing_pages){
        if(strpos($item_name, $search) === false && strpos($item_description, $search) === false && strpos($landing_pages, $search) !== false){
            return true;
        }
    }
    return false;
}

function adjust_search_pagination($found_posts, $query) {
    if ($query->is_main_query() && $query->is_search) {
        foreach ($query->posts as $key => $post) {
            $post = get_post($post);
            if((strpos($post->post_content, "io_rental") === false && strpos($post->post_content, "io_category") === false) ||
                strpos($post->post_content, 'cat_name="Items"') !== false || strpos($post->post_content, 'cat_name="Inventory"') !== false) {
                unset($query->posts[$key]);
            } else if(strpos($post->post_content, "io_rental") !== false){
                if (search_only_found_in_upsells($query->query['s'], $post->post_content)) {
                    unset($query->posts[$key]);
                }
                if(search_only_found_in_landing_pages($query->query['s'], $post->post_content)){
                    unset($query->posts[$key]);
                }
            }
        }
        $query->posts = array_values($query->posts);
        $found_posts = max(0, count($query->posts));
    }
    return $found_posts;
}
add_filter('found_posts', 'adjust_search_pagination', 10, 2);

function custom_posts_per_page( $query ) {
    if ( $query->is_main_query() && $query->is_search ) {
        $query->set( 'posts_per_page', -1 );
    }
}
// Allow main search to get as many pages as we want.
add_action( 'pre_get_posts', 'custom_posts_per_page' );

//used so we can access our widget via a shortcode
function add_widget_by_shortcode($atts) {

    global $wp_widget_factory;

    extract($atts);

    $widget_name = wp_specialchars($widget_name);

    if (!is_a($wp_widget_factory->widgets[$widget_name], 'WP_Widget')):
        $wp_class = 'WP_Widget_'.ucwords(strtolower($class));

        if (!is_a($wp_widget_factory->widgets[$wp_class], 'WP_Widget')):
            return '<p>'.sprintf(__("%s: Widget class not found. Make sure this widget exists and the class name is correct"),'<strong>'.$class.'</strong>').'</p>';
        else:
            $class = $wp_class;
        endif;
    endif;

    if($widget_name=='IO_Featured'){
        if(isset($item_ids)){
            $item_ids = explode(",", $item_ids);
        }else{
            $item_ids = array();
        }
        if(isset($category_ids)){
            $category_ids = explode(",", $category_ids);
        }else{
            $category_ids = array();
        }
        if(empty($item_ids) && empty($category_ids)) {
            // IO-28819 Making sure elementor exists.
            if ( class_exists(")Elementor\Plugin") && (Elementor\Plugin::$instance->editor->is_edit_mode() || Elementor\Plugin::$instance->preview->is_preview_mode()) ) {
                //calling the wp_query and the_post below screws up the main query and affects the_content
                //but using the reset function don't work  for elementor
            }else{
                $args = array('orderby' => 'name', 'order' => 'ASC', 'post_type' => 'page', 'posts_per_page' => -1);
                $loop = new WP_Query($args);
                while ($loop->have_posts()) {
                    $loop->the_post();
                    $content = get_the_content();
                    if (strpos($content, '[sc :io_all_cat') !== FALSE) {
                        $key = get_the_id();
                        $category_ids = array($key);
                        break;
                    }
                }
            }
        }
    }

    ob_start();
    if(!isset($instance)) $instance = '';
    if(!isset($id)) $id = 0;
    if(!isset($show_price)) $show_price = 0;
    if(!isset($view_product_hover)) $view_product_hover = 0;
    if(!isset($add_to_cart)) $add_to_cart = 0;
    if(!isset($width )) $width  = 0;
    if(!isset($io_id )) $io_id  = 0;
    the_widget($widget_name, $instance, array('widget_id'=>'arbitrary-instance-'.$id,
        'before_widget' => '',
        'after_widget' => '',
        'before_title' => '',
        'after_title' => '',
        'cat_only' => 0,
        'categories' => $category_ids,
        'show_price' => $show_price,
        'view_product_hover' => $view_product_hover,
        'add_to_cart' => $add_to_cart,
        'width' => $width,
        'items' => $item_ids,
        'io_id' => $io_id
    ));
    $output = ob_get_contents();
    ob_end_clean();
    return $output;

}
add_shortcode('widget','add_widget_by_shortcode');

/** format: [variable variable_name=" *option_name* "]
 * Takes in the option_name for a variable stored in the wp_options table and returns the value stored in the matching option_value field
 * @param $atts
 * @return false|mixed|null
 */
function access_variable_by_shortcode($atts){

    extract(shortcode_atts(array(
        'variable_name' => FALSE
    ), $atts));

    $variable_name = wp_specialchars($variable_name);

    if(isset($variable_name)) {
        return get_option($variable_name);
    }
    else{
        return '';
    }
}

add_shortcode('variable','access_variable_by_shortcode');
