File: /home/icsla/public_html/wp-content/plugins/chatbot/qcld-wpwbot-search.php
<?php
if (!defined('ABSPATH')) exit; // Exit if accessed directly
/**
* Product indexing, caching & searching features concept is taken from open source 'Advanced wp Search' Wp plugin by ILLID.
*/
//include_once( 'includes/class-wpwbot-cache.php' );
include_once( 'includes/class-wpwbot-table.php' );
include_once( 'includes/class-wpwbot-search.php' );
// Helper function to generate variations for each word in a keyword
if ( ! function_exists( '_wpbot_generate_word_variations' ) ) {
function _wpbot_generate_word_variations($keyword) {
$keyword = strtolower(trim($keyword));
$words = preg_split('/\s+/', $keyword, -1, PREG_SPLIT_NO_EMPTY);
$all_word_variations = [];
foreach ($words as $word) {
$variations = [$word];
// Simple pluralization/singularization and common suffix handling
if (strlen($word) > 1) { // Avoid stemming single letters
// Remove 's' (e.g., 'inspections' -> 'inspection')
if (substr($word, -1) === 's') {
$variations[] = substr($word, 0, -1);
} else { // Add 's' (e.g., 'inspection' -> 'inspections')
$variations[] = $word . 's';
}
// Handle 'er' suffix (e.g., 'inspector' -> 'inspect')
if (substr($word, -2) === 'er') {
$variations[] = substr($word, 0, -2);
}
// Handle 'ing' suffix (e.g., 'inspecting' -> 'inspect')
if (substr($word, -3) === 'ing') {
$variations[] = substr($word, 0, -3);
}
// Add 'er' if the base word is 'inspect' and 'inspector' is not present
if (strpos($word, 'inspect') !== false && strpos($word, 'inspector') === false) {
$variations[] = str_replace('inspect', 'inspector', $word);
}
}
$all_word_variations[] = array_filter(array_unique($variations));
}
return $all_word_variations;
}
}
// Filter function to modify WP_Query search for flexible matching
if ( ! function_exists( 'wpbot_flexible_search_filter' ) ) {
function wpbot_flexible_search_filter($search, $wp_query) {
global $wpdb, $wpbot_search_word_variations;
// Only apply if it's the main search query and our variations are set
if (empty($wpbot_search_word_variations) || !$wp_query->is_search || !$wp_query->is_main_query()) {
return $search;
}
$search_parts_for_and = [];
foreach ($wpbot_search_word_variations as $word_variations) {
$search_parts_for_or = [];
foreach ($word_variations as $term) {
$term = $wpdb->esc_like($term);
// Search in both post_title and post_content
$search_parts_for_or[] = "(({$wpdb->posts}.post_title LIKE '%{$term}%') OR ({$wpdb->posts}.post_content LIKE '%{$term}%'))";
}
if (!empty($search_parts_for_or)) {
$search_parts_for_and[] = '(' . implode(' OR ', $search_parts_for_or) . ')';
}
}
if (!empty($search_parts_for_and)) {
// Completely replace the default search clause generated by WP_Query's 's' parameter
// This ensures our flexible matching takes precedence.
$search = ' AND ' . implode(' AND ', $search_parts_for_and);
}
return $search;
}
}
function wpbo_search_site() {
// Verify nonce for security
$nonce = isset($_POST['security']) ? sanitize_text_field(wp_unslash($_POST['security'])) : (isset($_POST['nonce']) ? sanitize_text_field(wp_unslash($_POST['nonce'])) : '');
if ( ! wp_verify_nonce( $nonce, 'wp_chatbot' ) && ! wp_verify_nonce( $nonce, 'qcsecretbotnonceval123qc' ) ) {
wp_send_json_error( array( 'status' => 'fail', 'message' => 'Security check failed.' ) );
wp_die();
}
global $wpdb;
// Limit results to 5 items.
$limit = 5;
$response = array('status' => 'fail', 'html' => ''); // Initialize response array
// Get default language for load more button text and other language-specific checks.
$default_language = get_locale();
if(get_option('enable_wp_chatbot_post_content') == 1){
$keyword = isset( $_POST['keyword'] ) ? sanitize_text_field(wp_unslash($_POST['keyword'])) : '';
$all_word_variations = _wpbot_generate_word_variations($keyword);
// Temporarily store the variations for the filter
global $wpbot_search_word_variations;
$wpbot_search_word_variations = $all_word_variations;
// Add the custom search filter
add_filter('posts_search', 'wpbot_flexible_search_filter', 10, 2);
// $enable_post_types = array( 'post', 'page'); // This line is commented out, so post_type is not restricted here.
$total_items = $limit;
$query_arg = array(
// 'post_type' => $enable_post_types,
'post_status' => 'publish',
'posts_per_page'=> $total_items,
's' => stripslashes( $keyword ), // Keep original for WP_Query to initiate search, filter will override
'paged' => 1,
'suppress_filters' => false // Crucial for filters to run
);
$resultss = new WP_Query( $query_arg );
$results = $resultss->posts;
// Remove the filter after the query to avoid affecting other queries
remove_filter('posts_search', 'wpbot_flexible_search_filter', 10);
unset($wpbot_search_word_variations); // Clean up global
}else{
$keyword = isset( $_POST['keyword'] ) ? sanitize_text_field(wp_unslash($_POST['keyword'])) : '';
$all_word_variations = _wpbot_generate_word_variations($keyword);
$sql_parts_for_and = [];
$sql_params = [];
foreach ($all_word_variations as $word_variations) {
$sql_parts_for_or = [];
foreach ($word_variations as $term) {
$sql_parts_for_or[] = "post_title LIKE %s";
$sql_params[] = '%' . $wpdb->esc_like($term) . '%';
}
if (!empty($sql_parts_for_or)) {
$sql_parts_for_and[] = '(' . implode(' OR ', $sql_parts_for_or) . ')';
}
}
$where_clause = '';
if (!empty($sql_parts_for_and)) {
$where_clause = ' AND ' . implode(' AND ', $sql_parts_for_and);
} else {
// Fallback to original behavior if no variations generated (e.g., empty keyword)
$where_clause = " AND (post_title LIKE %s)";
$sql_params[] = '%' . $wpdb->esc_like($keyword) . '%';
}
// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared, PluginCheck.Security.DirectDB.UnescapedDBParameter
$results = $wpdb->get_results( $wpdb->prepare(
"SELECT * FROM " . $wpdb->prefix . "posts WHERE post_status = %s " . $where_clause . " ORDER BY ID DESC LIMIT %d",
array_merge(['publish'], $sql_params, [$limit])
) );
}
if(!empty( $results )){
$response['status'] = 'success';
$response['html'] = '<div class="wpb-search-result">';
$total_post = 0;
$responses = '';
foreach ( $results as $result ) {
$featured_img_url = get_the_post_thumbnail_url( $result->ID, 'full' );
$excerpt = '';
if ( isset( $result->ID ) ) {
$post_obj = get_post( $result->ID );
if ( $post_obj ) {
if ( has_excerpt( $result->ID ) ) {
$excerpt = get_the_excerpt( $result->ID );
} else {
$content = $post_obj->post_content;
// Remove ALL WPBakery shortcodes (paired + self-closing)
$content = preg_replace( '/\[vc_[^\]]*\](.*?)\[\/vc_[^\]]*\]/s', '$1', $content ); // paired
$content = preg_replace( '/\[vc_[^\]]*\]/s', '', $content ); // self-closing
$content = preg_replace('/\[\/?[\w\-]+[^\]]*\]/', '', $content);
// Extra: remove any leftover [] shortcodes (just in case)
$content = strip_shortcodes( $content );
// Run through normal WP content filters
$content_filtered = apply_filters( 'the_content', $content );
// Strip HTML tags, then trim
$excerpt = wp_trim_words( wp_strip_all_tags( $content_filtered ), 20, '...' );
}
}
}
$total_post = $total_post + 1;
$responses .='<div class="wpbot_card_wraper">';
$responses .= '<div class="wpbot_card_image '.($result->post_type=='product'?'wp-chatbot-product':'').' '.( empty($featured_img_url) ?'wpbot_card_image_saas':'').'"><a href="'.esc_url(get_permalink($result->ID)).'" target="_blank" '.($result->post_type=='product'?'wp-chatbot-pid="'.$result->ID.'"':'').'>';
if( !empty($featured_img_url) ){
$responses .= '<img src="'.esc_url_raw($featured_img_url).'" />';
}
$responses .= '<div class="wpbot_card_caption '.( empty($featured_img_url) ?'wpbot_card_caption_saas':'').'">';
$responses .= '<p><span style="padding: 0 5px;color: #1d73b4;display: inline-block;margin: 0 5px 0 0;width: 18px;height: 18px;border-radius: 50%;font-size: 20px;line-height: 22px;"> ✓ </span> '.esc_html($result->post_title).'</p>';
$responses .= '<p>'.esc_html($excerpt).'</p>';
if($result->post_type=='product'){
if ( class_exists( 'WooCommerce' ) ) {
if ( $result->ID ) {
$product = wc_get_product( $result->ID );
$responses .= '<p class="wpbot_product_price">'.get_woocommerce_currency_symbol().$product->get_price_html().'</p>';
}
}
}
$responses .= '</div>';
$responses .= '</a></div>';
$responses .='</div>';
}
$response['html'] .= $responses;
$response['html'] .='</div>';
if($total_post >= $limit ){ // Use $limit for consistency
$load_more = maybe_unserialize(get_option('qlcd_wp_chatbot_load_more_search'));
$response['html'] .='<button type="button" class="wp-chatbot-loadmore" data-search-type="default-wp-search" data-keyword="'.esc_attr($keyword).'" data-page="2">'. ( !empty($load_more) && isset($load_more[$default_language]) ? $load_more[$default_language] : 'Load More').' <span id="wp-chatbot-loadmore-loader" class="wp-chatbot-loadmore-loader"></span></button>';
}
}else{
// Fuzzy search if initial search yields no results
$response['status'] = 'success';
// Use the same word variation logic for fuzzy search
$all_word_variations_for_fuzzy = _wpbot_generate_word_variations($keyword);
$unique_posts = array(); // Store unique post objects
$seen_ids = array(); // Keep track of seen post IDs
// Iterate through each word's variations to find matching posts
foreach ( $all_word_variations_for_fuzzy as $word_variations ) {
foreach ($word_variations as $term) {
$term = $wpdb->esc_like( $term );
$term_results = $wpdb->get_results( // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
$wpdb->prepare("SELECT * FROM ". $wpdb->prefix."posts WHERE post_type IN (%s, %s) AND post_status = %s AND (post_title LIKE %s) ORDER BY ID DESC", 'page', 'post', 'publish', '%'. $term .'%')
);
foreach ($term_results as $res) {
if (!in_array($res->ID, $seen_ids)) {
$unique_posts[] = $res;
$seen_ids[] = $res->ID;
}
}
}
}
$results = $unique_posts; // Now $results contains unique WP_Post objects
if( !empty( $results) ){
$response['html'] = '<div class="wpb-search-result">';
$total_post = 0;
$responses = '';
$selected_lan = get_option('qlcd_wp_chatbot_default_language');
foreach ($results as $value) { // $value is a single post object here
if(!empty($value->guid)){
$post_id = $value->ID;
$current_featured_img_url = get_the_post_thumbnail_url( $post_id, 'full' );
// Corrected URL segment parsing for language check
$url_path = wp_parse_url(get_permalink($post_id), PHP_URL_PATH);
$url_segments = array_filter(explode('/',$url_path));
// Assuming the language slug is the first non-empty segment of the URL path.
$first_segment = !empty($url_segments) ? reset($url_segments) : '';
// If $selected_lan is empty, the language check is effectively skipped.
$language_match = empty($selected_lan) || ($first_segment == $selected_lan);
if($language_match){
$total_post = $total_post + 1;
$responses .='<div class="wpbot_card_wraper">';
$responses .= '<div class="wpbot_card_image '.(empty($current_featured_img_url)?'wpbot_card_image_saas':'').'"><a href="'.esc_url(get_permalink($post_id)).'" target="_blank">';
if(!empty($current_featured_img_url)){
$responses .= '<img src="'.esc_url_raw($current_featured_img_url).'" />';
}
$responses .= '<div class="wpbot_card_caption '.(empty($current_featured_img_url)?'wpbot_card_caption_saas':'').'">';
$responses .= '<p><span style="padding: 0 5px;color: #1d73b4;display: inline-block;margin: 0 5px 0 0;width: 18px;height: 18px;border-radius: 50%;font-size: 20px;line-height: 22px;"> ✓ </span>'.esc_html($value->post_title).'</p>';
$responses .= '</div>';
$responses .= '</a></div>';
$responses .='</div>';
}
}
}
if($total_post > 2 ){ // This condition is different from the first block ($total_post >= $limit)
$load_more = maybe_unserialize(get_option('qlcd_wp_chatbot_load_more_search'));
$response['html'] .='<button type="button" class="wp-chatbot-loadmore2" data-search-type="default-wp-search" data-keyword="'.esc_attr($keyword).'" data-page="2">'. ( !empty($load_more) && isset($load_more[$default_language]) ? $load_more[$default_language] : 'Load More').' <span id="wp-chatbot-loadmore-loader" class="wp-chatbot-loadmore-loader"></span></button>';
$response['status'] = 'success';
}else{
$response['status'] = 'fail';
}
$response['html'] .= $responses;
$response['html'] .='</div>';
} else {
$response['status'] = 'fail'; // No results from fuzzy search either
}
}
echo wp_json_encode($response);
wp_die();
}
add_action( 'wp_ajax_wpbo_search_site', 'wpbo_search_site' );
add_action( 'wp_ajax_nopriv_wpbo_search_site', 'wpbo_search_site' );
if ( ! function_exists( 'qcld_wpbot_modified_keyword' ) ) {
function qcld_wpbot_modified_keyword( $keyword ) {
$keyword = rtrim( $keyword, '!' );
$pattern = '/[?\/]/';
$strings = preg_split( $pattern, $keyword );
$strings = array_filter( array_map( 'trim', $strings ) );
$keyword = rtrim( $strings[0], '!' );
return htmlspecialchars_decode( $keyword );
}
}
add_action( 'wp_ajax_wpbo_search_responseby_intent', 'qcld_wpbo_search_responseby_intent' );
add_action( 'wp_ajax_nopriv_wpbo_search_responseby_intent', 'qcld_wpbo_search_responseby_intent' );
function wpbo_search_site_pagination() {
global $wpdb;
// Verify nonce for security
$p_nonce = isset($_POST['nonce']) ? sanitize_text_field(wp_unslash($_POST['nonce'])) : '';
if ( ! wp_verify_nonce( $p_nonce, 'wp_chatbot' ) && ! wp_verify_nonce( $p_nonce, 'qcsecretbotnonceval123qc' ) ) {
wp_send_json_error( array( 'message' => 'Security check failed' ) );
wp_die();
}
// Sanitize and validate inputs
$keyword = isset( $_POST['keyword'] ) ? sanitize_text_field(wp_unslash($_POST['keyword'])) : '';
$post_type = isset( $_POST['type'] ) ? sanitize_text_field(wp_unslash($_POST['type'])) : 'post';
$page = isset($_POST['page']) ? absint( wp_unslash($_POST['page']) ) : 0;
// Validate post type against allowed types
$allowed_post_types = array( 'post', 'page', 'product' );
if ( ! in_array( $post_type, $allowed_post_types, true ) ) {
$post_type = 'post';
}
$enable_post_types = get_option( 'wppt_post_types' );
$load_more = maybe_unserialize( get_option( 'qlcd_wp_chatbot_load_more' ) );
if ( is_array( $load_more ) && isset( $load_more[ get_locale() ] ) ) {
$load_more = $load_more[ get_locale() ];
}
if ( is_array( $load_more ) ) {
$load_more = $load_more[ array_rand( $load_more ) ];
}
$searchlimit = ( get_option( 'wppt_number_of_result' ) == '' ? 5 : absint( get_option( 'wppt_number_of_result' ) ) );
$orderby = ( get_option( 'wppt_result_orderby' ) == '' ? 'none' : get_option( 'wppt_result_orderby' ) );
$order = ( get_option( 'wppt_result_order' ) == '' ? 'ASC' : get_option( 'wppt_result_order' ) );
$thumb = ( get_option( 'wpbot_search_image_size' ) ? get_option( 'wpbot_search_image_size' ) : 'thumbnail' );
// order by setup
$new_window = get_option( 'wpbot_search_result_new_window' );
$total_items = absint( get_option( 'wppt_number_of_result' ) );
if ( $total_items < 1 ) {
$total_items = 5;
}
$searchkeyword = qcld_wpbot_modified_keyword( $keyword );
$response = array();
$response['status'] = 'fail';
$response['html'] = '';
// Use prepared statements to prevent SQL injection
if ( get_option( 'active_advance_query' ) != '1' ) {
// Simple query - search in post_title only
$total_results = $wpdb->get_results( // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
$wpdb->prepare(
"SELECT * FROM {$wpdb->prefix}posts
WHERE post_type = %s
AND post_status = 'publish'
AND post_title LIKE %s
ORDER BY ID DESC",
$post_type,
'%' . $wpdb->esc_like( $searchkeyword ) . '%'
));
} else {
// Advanced query - search in both post_title and post_content
$total_results = $wpdb->get_results( // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
$wpdb->prepare(
"SELECT * FROM " . $wpdb->prefix . "posts
WHERE post_type = %s
AND post_status = %s
AND (post_title REGEXP %s OR post_content REGEXP %s)
ORDER BY ID DESC",
$post_type,
'publish',
'[[:<:]]' . $searchkeyword . '[[:>:]]',
'[[:<:]]' . $searchkeyword . '[[:>:]]'
));
}
if ( ! empty( $total_results ) ) {
// Validate and sanitize orderby parameter
$valid_orderby = array( 'title', 'date', 'modified', 'none', 'rand' );
if ( ! in_array( $orderby, $valid_orderby, true ) ) {
$orderby = 'none';
}
if ( $orderby == 'title' ) {
$orderby = 'post_title';
}
if ( $orderby == 'date' ) {
$orderby = 'post_date';
}
if ( $orderby == 'modified' ) {
$orderby = 'post_modified';
}
// Validate order parameter
$order = strtoupper( $order );
if ( ! in_array( $order, array( 'ASC', 'DESC' ), true ) ) {
$order = 'ASC';
}
// Build query with pagination
$offset = absint( $total_items * $page );
if ( get_option( 'active_advance_query' ) != '1' ) {
if ( $orderby != 'none' && $orderby != 'rand' ) {
// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared, PluginCheck.Security.DirectDB.UnescapedDBParameter
$results = $wpdb->get_results( $wpdb->prepare(
"SELECT * FROM {$wpdb->prefix}posts
WHERE post_type = %s
AND post_status = 'publish'
AND post_title LIKE %s
ORDER BY {$orderby} {$order}
LIMIT %d, %d",
$post_type,
'%' . $wpdb->esc_like( $searchkeyword ) . '%',
$offset,
$total_items
) );
} else {
$results = $wpdb->get_results( // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
$wpdb->prepare(
"SELECT * FROM {$wpdb->prefix}posts
WHERE post_type = %s
AND post_status = 'publish'
AND post_title LIKE %s
ORDER BY ID DESC
LIMIT %d, %d",
$post_type,
'%' . $wpdb->esc_like( $searchkeyword ) . '%',
$offset,
$total_items
));
}
} else {
if ( $orderby != 'none' && $orderby != 'rand' ) {
// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared, PluginCheck.Security.DirectDB.UnescapedDBParameter
$results = $wpdb->get_results( $wpdb->prepare(
"SELECT * FROM " . $wpdb->prefix . "posts
WHERE post_type = %s
AND post_status = %s
AND (post_title REGEXP %s OR post_content REGEXP %s)
ORDER BY " . $orderby . " " . $order . "
LIMIT %d, %d",
$post_type,
'publish',
'[[:<:]]' . $searchkeyword . '[[:>:]]',
'[[:<:]]' . $searchkeyword . '[[:>:]]',
$offset,
$total_items
) );
} else {
$results = $wpdb->get_results( // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
$wpdb->prepare(
"SELECT * FROM " . $wpdb->prefix . "posts
WHERE post_type = %s
AND post_status = %s
AND (post_title REGEXP %s OR post_content REGEXP %s)
ORDER BY ID DESC
LIMIT %d, %d",
$post_type,
'publish',
'[[:<:]]' . $searchkeyword . '[[:>:]]',
'[[:<:]]' . $searchkeyword . '[[:>:]]',
$offset,
$total_items
));
}
}
} else {
if ( class_exists( 'SitePress' ) ) {
global $sitepress;
$selected_lan = isset( $_POST['language'] ) ? sanitize_text_field(wp_unslash($_POST['language'])) : '';
$selected_lan = explode( '_', $selected_lan );
if ( ! empty( $selected_lan[0] ) ) {
$sitepress->switch_lang( $selected_lan[0], true );
}
}
$query_arg = array(
'post_type' => $post_type,
'post_status' => 'publish',
'posts_per_page' => $total_items,
's' => stripslashes( $keyword ),
'paged' => ( $page + 1 ),
'orderby' => $orderby,
);
if ( class_exists( 'SitePress' ) ) {
global $sitepress;
$selected_lan = isset( $_POST['language'] ) ? sanitize_text_field(wp_unslash($_POST['language'])) : '';
$selected_lan = explode( '_', $selected_lan );
if ( ! empty( $selected_lan[0] ) ) {
$sitepress->switch_lang( $selected_lan[0], true );
}
}
$query_arg['suppress_filters'] = true;
if ( $orderby != 'none' && $orderby != 'rand' ) {
$query_arg['order'] = $order;
}
$totalresults = new WP_Query(
array(
'post_type' => $post_type,
'post_status' => 'publish',
's' => stripslashes( $keyword ),
)
);
$resultss = new WP_Query( $query_arg );
$total_results = $totalresults->posts;
$resultss = new WP_Query( $query_arg );
$results = $resultss->posts;
}
if ( ! empty( $total_results ) ) {
$selected_lan = isset( $_POST['language'] ) ? sanitize_text_field(wp_unslash($_POST['language'])) : '';
$urlss = get_option( 'wpbotml_url_urls' ) ? get_option( 'wpbotml_url_urls' ) : '';
$imagesize = ( get_option( 'wpbot_search_image_size' ) != '' ? get_option( 'wpbot_search_image_size' ) : 'thumbnail' );
$response['html'] .= '<div class="wpb-search-result">';
foreach ( $total_results as $result ) {
if ( $result->post_type == 'product' ) {
if ( ! class_exists( 'WooCommerce' ) ) {
continue;
}
}
$featured_img_url = get_the_post_thumbnail_url( $result->ID, $thumb );
$excerpt = '';
if ( isset( $result->ID ) ) {
$post_obj = get_post( $result->ID );
if ( $post_obj ) {
if ( has_excerpt( $result->ID ) ) {
$excerpt = get_the_excerpt( $result->ID );
} else {
$content = $post_obj->post_content;
// Remove ALL WPBakery shortcodes (paired + self-closing)
$content = preg_replace( '/\[vc_[^\]]*\](.*?)\[\/vc_[^\]]*\]/s', '$1', $content ); // paired
$content = preg_replace( '/\[vc_[^\]]*\]/s', '', $content ); // self-closing
$content = preg_replace('/\[\/?[\w\-]+[^\]]*\]/', '', $content);
// Extra: remove any leftover [] shortcodes (just in case)
$content = strip_shortcodes( $content );
// Run through normal WP content filters
$content_filtered = apply_filters( 'the_content', $content );
// Strip HTML tags, then trim
$excerpt = wp_trim_words( wp_strip_all_tags( $content_filtered ), 20, '...' );
}
}
}
$response['html'] .= '<div class="wpbot_card_wraper">';
$response['html'] .= '<div class="wpbot_card_image ' . ( $result->post_type == 'product' ? 'wp-chatbot-product' : '' ) . ' ' . ( $featured_img_url == '' ? 'wpbot_card_image_saas' : '' ) . '"><a href="' . esc_url( get_permalink( $result->ID ) ) . '" ' . ( $new_window == 1 ? 'target="_blank"' : '' ) . ' ' . ( $result->post_type == 'product' ? 'wp-chatbot-pid="' . absint( $result->ID ) . '"' : '' ) . '>';
if ( $featured_img_url != '' ) {
$response['html'] .= '<img src="' . esc_url_raw( $featured_img_url ) . '" />';
}
$response['html'] .= '<div class="wpbot_card_caption ' . ( $featured_img_url == '' ? 'wpbot_card_caption_saas' : '' ) . '">';
$response['html'] .= '<p class="wpbot_card_caption_title"><span style="padding: 0 5px;color: #1d73b4;display: inline-block;margin: 0 5px 0 0;width: 18px;height: 18px;border-radius: 50%;font-size: 20px;line-height: 22px;"> ✓ </span> ' . esc_html( $result->post_title ) . '</p>';
$response['html'] .= '<p class="wpbot_card_description">' . esc_html( $excerpt ) . '</p>';
if ( $result->post_type == 'product' ) {
if ( class_exists( 'WooCommerce' ) ) {
$product = wc_get_product( $result->ID );
$response['html'] .= '<p class="wpbot_product_price">' . get_woocommerce_currency_symbol() . $product->get_price_html() . '</p>';
}
}
$response['html'] .= '</div>';
$response['html'] .= '</a></div>';
$response['html'] .= '</div>';
}
$response['html'] .= '</div>';
$response['status'] = 'success';
}
wp_reset_query();
if ( $response['status'] != 'success' ) {
$texts = maybe_unserialize( get_option( 'qlcd_wp_chatbot_no_result' ) );
$selected_lan = isset( $_POST['language'] ) ? sanitize_text_field(wp_unslash($_POST['language'])) : '';
if ( ! empty( $texts ) && is_array( $texts ) && isset( $texts[ $selected_lan ][0] ) ) {
$texts = str_replace( "\'", "'", $texts[ $selected_lan ][0] );
$response['html'] = array( $texts );
} else {
$response['html'] = array( 'No results found' );
}
}
wp_send_json( $response );
die();
}
add_action( 'wp_ajax_wpbo_search_site_pagination', 'wpbo_search_site_pagination' );
add_action( 'wp_ajax_nopriv_wpbo_search_site_pagination', 'wpbo_search_site_pagination' );
function qcld_wpbo_search_responseby_intent(){
global $wpdb;
$keyword = isset( $_POST['keyword'] ) ? sanitize_text_field(wp_unslash($_POST['keyword'])) : '';
$table = $wpdb->prefix.'wpbot_response';
$result = $wpdb->get_row( $wpdb->prepare("SELECT `response` FROM %i WHERE 1 and `intent` = %s", $table, $keyword) ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
$response = array('status'=>'fail');
if(!empty($result)){
$response['status'] = 'success';
$response['html'] = $result->response;
}
echo wp_json_encode($response);
die();
}
add_action( 'wp_ajax_wpbo_search_response_catlist', 'wpbo_search_response_catlist' );
add_action( 'wp_ajax_nopriv_wpbo_search_response_catlist', 'wpbo_search_response_catlist' );
function wpbo_search_response_catlist(){
global $wpdb;
$table = $wpdb->prefix.'wpbot_response_category';
$status = array('status'=>'fail');
$results = $wpdb->get_results($wpdb->prepare("SELECT * FROM %i", $table)); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
$response_result = array();
if(!empty($results)){
foreach($results as $result){
$response_result[] = array('name'=>$result->name);
}
}
if(!empty($response_result)){
$status = array('status'=>'success', 'data'=>$response_result);
}
echo wp_json_encode($status);
die();
}
add_action( 'wp_ajax_wpbo_search_response', 'qcld_wpbo_search_response' );
add_action( 'wp_ajax_nopriv_wpbo_search_response', 'qcld_wpbo_search_response' );
function qcld_wpbo_search_response(){
global $wpdb;
$keyword = isset( $_POST['keyword'] ) ? (sanitize_text_field(wp_unslash($_POST['keyword']))) : '';
$strid = isset( $_POST['strid'] ) ? (sanitize_text_field(wp_unslash($_POST['strid']))) : '';
$table = $wpdb->prefix.'wpbot_response';
$response_result = array();
$status = array('status'=>'fail', 'multiple'=>false);
$field = "ID";
if(($strid != '') && empty($response_result)){
$results = $wpdb->get_results($wpdb->prepare("SELECT * FROM %i WHERE %i = %d",$table,$field,$strid)); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
if(!empty($results)){
foreach($results as $result){
$response_result[] = array('id'=>$result->id,'query'=>$result->query, 'response'=>$result->response, 'score'=>1);
}
}
}
$field = "query";
$results = $wpdb->get_results( $wpdb->prepare("SELECT `id`, `query`, `response` FROM %i WHERE 1 and %i = %s", $table, $field,$keyword) ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
if(!empty($results)){
foreach($results as $result){
$response_result[] = array('id'=>$result->id,'query'=>$result->query, 'response'=>$result->response, 'score'=>1);
}
}
$field = "category";
if(empty($response_result)){
$results = $wpdb->get_results( $wpdb->prepare("SELECT `id`, `query`, `response` FROM %i WHERE 1 and %i = %s", $table,$field, $keyword) ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
if(!empty($results)){
foreach($results as $result){
$response_result[] = array('id'=>$result->id,'query'=>$result->query, 'response'=>$result->response, 'score'=>1);
}
if(count($response_result)>1){
$status = array('status'=>'success','category'=> true, 'multiple'=>true, 'data'=>$response_result);
}else{
$status = array('status'=>'success', 'category'=> true, 'multiple'=>false, 'data'=>$response_result);
}
echo wp_json_encode($status);
die();
}
}
if(class_exists('Qcld_str_pro')){
if(get_option('qc_bot_str_remove_stopwords') && get_option('qc_bot_str_remove_stopwords')==1){
$keyword = qcld_strpro_remove_stopwords($keyword);
}
}
if(empty($response_result)){
$fields = get_option('qc_bot_str_fields');
if($fields && !empty($fields)){
$qfields = implode(', ', $fields);
}else{
$qfields = '`query`,`keyword`,`response`';
}
// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared, PluginCheck.Security.DirectDB.UnescapedDBParameter
$results = $wpdb->get_results( $wpdb->prepare("SELECT `id`, `query`, `response`, MATCH($qfields) AGAINST(%s IN NATURAL LANGUAGE MODE) as score FROM %i WHERE MATCH($qfields) AGAINST(%s IN NATURAL LANGUAGE MODE) order by score desc limit 15",$keyword,$table,$keyword) );
$weight = get_option('qc_bot_str_weight')!=''?get_option('qc_bot_str_weight'):'0.4';
if(!empty($results)){
$max_score = max(array_column($results, 'score'));
if ($max_score <= 0) {
$max_score = 1; // Set to 1 to avoid division by zero
}
foreach($results as $result){
if(($result->score/$max_score) >= $weight){
$response_result[] = array('id'=>$result->id,'query'=>$result->query, 'response'=>$result->response, 'score'=>$result->score);
}
}
}
}
$field = "keyword";
if( empty( $response_result ) ){
$results = $wpdb->get_results($wpdb->prepare("SELECT * FROM %i WHERE %i REGEXP %s", $table,$field,$keyword)); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
if(!empty($results)){
foreach($results as $result){
$response_result[] = array('id'=>$result->id,'query'=>$result->query, 'response'=>$result->response, 'score'=>1);
}
}
}
if(!empty($response_result)){
if(count($response_result)>1){
$status = array('status'=>'success', 'multiple'=>true, 'data'=>$response_result);
}else{
$status = array('status'=>'success', 'multiple'=>false, 'data'=>$response_result);
}
}
if(empty($result->query)){
$status = array('status'=>'fail', 'multiple'=>false, 'data'=>$response_result);
}
if(empty($status['data']) || (isset($status['status']) && $status['status']==='fail')){
// Check for space before question mark and try again.
if(preg_match('/ \?$/', $keyword)){
$keyword2 = preg_replace('/ \?$/', '?', $keyword);
// Try again with new keyword.
// Repeat the main search logic with $keyword2.
$response_result = array();
$field = "query";
$results = $wpdb->get_results( $wpdb->prepare("SELECT `id`, `query`, `response` FROM %i WHERE 1 and %i = %s", $table, $field, $keyword2) ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
if(!empty($results)){
foreach($results as $result){
$response_result[] = array('id'=>$result->id,'query'=>$result->query, 'response'=>$result->response, 'score'=>1);
}
if(count($response_result)>1){
$status = array('status'=>'success', 'multiple'=>true, 'data'=>$response_result);
}else{
$status = array('status'=>'success', 'multiple'=>false, 'data'=>$response_result);
}
}else{
$status = array('status'=>'fail', 'multiple'=>false, 'data'=>[]);
}
}
}
if(empty($status['data']) || (isset($status['status']) && $status['status']==='fail')){
// Try a partial match if still nothing found.
if(empty($status['data'])) {
$keyword_like = '%' . preg_replace('/[\\s\\?]+/', '%', $keyword) . '%';
$results = $wpdb->get_results( $wpdb->prepare("SELECT `id`, `query`, `response` FROM %i WHERE `query` LIKE %s", $table, $keyword_like) ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
$response_result = array();
if(!empty($results)){
foreach($results as $result){
$response_result[] = array('id'=>$result->id,'query'=>$result->query, 'response'=>$result->response, 'score'=>1);
}
if(count($response_result)>1){
$status = array('status'=>'success', 'multiple'=>true, 'data'=>$response_result);
}else{
$status = array('status'=>'success', 'multiple'=>false, 'data'=>$response_result);
}
} else {
$status = array('status'=>'fail', 'multiple'=>false, 'data'=>[], 'message'=>'Sorry, I found nothing');
}
}
}
if(empty($status['data'])){
$status = array('status'=>'fail', 'multiple'=>false, 'data'=>[], 'message'=>'no result found');
}
echo wp_json_encode($status);
die();
}
function qcld_strpro_remove_stopwords($keyword){
if(get_option('qlcd_wp_chatbot_stop_words') && get_option('qlcd_wp_chatbot_stop_words')!=''){
$commonWords = explode(',', get_option('qlcd_wp_chatbot_stop_words'));
return preg_replace('/\b('.implode('|',$commonWords).')\b/','',$keyword);
}else{
return $keyword;
}
}