PluginProbe
WPBot – AI ChatBot for Live Support, Lead Generation, WordPress Automation, AI Services / 8.7.1
WPBot – AI ChatBot for Live Support, Lead Generation, WordPress Automation, AI Services v8.7.1
8.7.7 8.7.6 8.7.5 8.7.4 8.7.3 8.7.2 8.7.1 8.7.0 8.6.9 8.6.8 8.6.7 8.6.6 8.6.5 8.6.4 8.6.2 8.6.1 8.6.0 8.5.9 8.5.8 8.5.7 8.5.6 8.5.5 8.5.4 8.5.3 8.5.2 All 533 releases
chatbot / qcld-wpwbot-search.php

qcld-wpwbot-search.php in WPBot – AI ChatBot for Live Support, Lead Generation, WordPress Automation, AI Services 8.7.1, at qcld-wpwbot-search.php

1,122 lines 45.7 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 if (!defined('ABSPATH')) exit; // Exit if accessed directly
3 /**
4 * Product indexing, caching & searching features concept is taken from open source 'Advanced wp Search' Wp plugin by ILLID.
5 */
6 //include_once( 'includes/class-wpwbot-cache.php' );
7
8 include_once( 'includes/class-wpwbot-table.php' );
9 include_once( 'includes/class-wpwbot-search.php' );
10
11 // Helper function to generate variations for each word in a keyword
12 if ( ! function_exists( '_wpbot_generate_word_variations' ) ) {
13 function _wpbot_generate_word_variations($keyword) {
14 $keyword = strtolower(trim($keyword));
15 $words = preg_split('/\s+/', $keyword, -1, PREG_SPLIT_NO_EMPTY);
16 $all_word_variations = [];
17
18 foreach ($words as $word) {
19 $variations = [$word];
20
21 // Simple pluralization/singularization and common suffix handling
22 if (strlen($word) > 1) { // Avoid stemming single letters
23 // Remove 's' (e.g., 'inspections' -> 'inspection')
24 if (substr($word, -1) === 's') {
25 $variations[] = substr($word, 0, -1);
26 } else { // Add 's' (e.g., 'inspection' -> 'inspections')
27 $variations[] = $word . 's';
28 }
29 // Handle 'er' suffix (e.g., 'inspector' -> 'inspect')
30 if (substr($word, -2) === 'er') {
31 $variations[] = substr($word, 0, -2);
32 }
33 // Handle 'ing' suffix (e.g., 'inspecting' -> 'inspect')
34 if (substr($word, -3) === 'ing') {
35 $variations[] = substr($word, 0, -3);
36 }
37 // Add 'er' if the base word is 'inspect' and 'inspector' is not present
38 if (strpos($word, 'inspect') !== false && strpos($word, 'inspector') === false) {
39 $variations[] = str_replace('inspect', 'inspector', $word);
40 }
41 }
42 $all_word_variations[] = array_filter(array_unique($variations));
43 }
44 return $all_word_variations;
45 }
46 }
47
48 // Filter function to modify WP_Query search for flexible matching
49 if ( ! function_exists( 'wpbot_flexible_search_filter' ) ) {
50 function wpbot_flexible_search_filter($search, $wp_query) {
51 global $wpdb, $wpbot_search_word_variations;
52
53 // Only apply if it's the main search query and our variations are set
54 if (empty($wpbot_search_word_variations) || !$wp_query->is_search || !$wp_query->is_main_query()) {
55 return $search;
56 }
57
58 $search_parts_for_and = [];
59
60 foreach ($wpbot_search_word_variations as $word_variations) {
61 $search_parts_for_or = [];
62 foreach ($word_variations as $term) {
63 $term = $wpdb->esc_like($term);
64 // Search in both post_title and post_content
65 $search_parts_for_or[] = "(({$wpdb->posts}.post_title LIKE '%{$term}%') OR ({$wpdb->posts}.post_content LIKE '%{$term}%'))";
66 }
67 if (!empty($search_parts_for_or)) {
68 $search_parts_for_and[] = '(' . implode(' OR ', $search_parts_for_or) . ')';
69 }
70 }
71
72 if (!empty($search_parts_for_and)) {
73 // Completely replace the default search clause generated by WP_Query's 's' parameter
74 // This ensures our flexible matching takes precedence.
75 $search = ' AND ' . implode(' AND ', $search_parts_for_and);
76 }
77
78 return $search;
79 }
80 }
81
82 function wpbo_search_site() {
83 // Verify nonce for security
84 $nonce = isset($_POST['security']) ? sanitize_text_field(wp_unslash($_POST['security'])) : (isset($_POST['nonce']) ? sanitize_text_field(wp_unslash($_POST['nonce'])) : '');
85 if ( ! wp_verify_nonce( $nonce, 'wp_chatbot' ) && ! wp_verify_nonce( $nonce, 'qcsecretbotnonceval123qc' ) ) {
86 wp_send_json_error( array( 'status' => 'fail', 'message' => 'Security check failed.' ) );
87 wp_die();
88 }
89
90 global $wpdb;
91 // Limit results to 5 items.
92 $limit = 5;
93 $response = array('status' => 'fail', 'html' => ''); // Initialize response array
94
95 // Get default language for load more button text and other language-specific checks.
96 $default_language = get_locale();
97
98 if(get_option('enable_wp_chatbot_post_content') == 1){
99 $keyword = isset( $_POST['keyword'] ) ? sanitize_text_field(wp_unslash($_POST['keyword'])) : '';
100 $all_word_variations = _wpbot_generate_word_variations($keyword);
101
102 // Temporarily store the variations for the filter
103 global $wpbot_search_word_variations;
104 $wpbot_search_word_variations = $all_word_variations;
105
106 // Add the custom search filter
107 add_filter('posts_search', 'wpbot_flexible_search_filter', 10, 2);
108
109 $enable_post_types = array( 'post', 'page', 'product' );
110 $total_items = $limit;
111 $query_arg = array(
112 'post_type' => $enable_post_types,
113 'post_status' => 'publish',
114 'posts_per_page'=> $total_items,
115 's' => stripslashes( $keyword ), // Keep original for WP_Query to initiate search, filter will override
116 'paged' => 1,
117 'suppress_filters' => false // Crucial for filters to run
118 );
119 $resultss = new WP_Query( $query_arg );
120 $results = $resultss->posts;
121
122 // Remove the filter after the query to avoid affecting other queries
123 remove_filter('posts_search', 'wpbot_flexible_search_filter', 10);
124 unset($wpbot_search_word_variations); // Clean up global
125 }else{
126 $keyword = isset( $_POST['keyword'] ) ? sanitize_text_field(wp_unslash($_POST['keyword'])) : '';
127 $all_word_variations = _wpbot_generate_word_variations($keyword);
128
129 $sql_parts_for_and = [];
130 $sql_params = [];
131
132 foreach ($all_word_variations as $word_variations) {
133 $sql_parts_for_or = [];
134 foreach ($word_variations as $term) {
135 $sql_parts_for_or[] = "post_title LIKE %s";
136 $sql_params[] = '%' . $wpdb->esc_like($term) . '%';
137 }
138 if (!empty($sql_parts_for_or)) {
139 $sql_parts_for_and[] = '(' . implode(' OR ', $sql_parts_for_or) . ')';
140 }
141 }
142
143 $where_clause = '';
144 if (!empty($sql_parts_for_and)) {
145 $where_clause = ' AND ' . implode(' AND ', $sql_parts_for_and);
146 } else {
147 // Fallback to original behavior if no variations generated (e.g., empty keyword)
148 $where_clause = " AND (post_title LIKE %s)";
149 $sql_params[] = '%' . $wpdb->esc_like($keyword) . '%';
150 }
151
152 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared, PluginCheck.Security.DirectDB.UnescapedDBParameter
153 $results = $wpdb->get_results( $wpdb->prepare(
154 "SELECT * FROM " . $wpdb->prefix . "posts WHERE post_status = %s " . $where_clause . " ORDER BY ID DESC LIMIT %d",
155 array_merge(['publish'], $sql_params, [$limit])
156 ) );
157 }
158
159 if(!empty( $results )){
160
161 $response['status'] = 'success';
162 $response['html'] = '<div class="wpb-search-result">';
163 $total_post = 0;
164 $responses = '';
165
166 foreach ( $results as $result ) {
167 $featured_img_url = get_the_post_thumbnail_url( $result->ID, 'full' );
168 $excerpt = '';
169 if ( isset( $result->ID ) ) {
170 $post_obj = get_post( $result->ID );
171 if ( $post_obj ) {
172 if ( has_excerpt( $result->ID ) ) {
173 $excerpt = get_the_excerpt( $result->ID );
174 } else {
175 $content = $post_obj->post_content;
176
177 // Remove ALL WPBakery shortcodes (paired + self-closing)
178 $content = preg_replace( '/\[vc_[^\]]*\](.*?)\[\/vc_[^\]]*\]/s', '$1', $content ); // paired
179 $content = preg_replace( '/\[vc_[^\]]*\]/s', '', $content ); // self-closing
180 $content = preg_replace('/\[\/?[\w\-]+[^\]]*\]/', '', $content);
181 // Extra: remove any leftover [] shortcodes (just in case)
182 $content = strip_shortcodes( $content );
183
184 // Run through normal WP content filters
185 $content_filtered = apply_filters( 'the_content', $content );
186
187 // Strip HTML tags, then trim
188 $excerpt = wp_trim_words( wp_strip_all_tags( $content_filtered ), 20, '...' );
189 }
190
191
192 }
193 }
194
195 $total_post = $total_post + 1;
196 $responses .='<div class="wpbot_card_wraper">';
197 $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.'"':'').'>';
198 if( !empty($featured_img_url) ){
199 $responses .= '<img src="'.esc_url_raw($featured_img_url).'" />';
200 }
201 $responses .= '<div class="wpbot_card_caption '.( empty($featured_img_url) ?'wpbot_card_caption_saas':'').'">';
202 $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>';
203 $responses .= '<p>'.esc_html(wp_strip_all_tags($excerpt)).'</p>';
204 if($result->post_type=='product'){
205 if ( class_exists( 'WooCommerce' ) ) {
206 if ( $result->ID ) {
207 $product = wc_get_product( $result->ID );
208 $responses .= '<p class="wpbot_product_price">'.get_woocommerce_currency_symbol().$product->get_price_html().'</p>';
209 }
210 }
211 }
212 $responses .= '</div>';
213 $responses .= '</a></div>';
214 $responses .='</div>';
215
216 }
217 $response['html'] .= $responses;
218 $response['html'] .='</div>';
219 if($total_post >= $limit ){ // Use $limit for consistency
220 $load_more = maybe_unserialize(get_option('qlcd_wp_chatbot_load_more_search'));
221
222 $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>';
223
224 }
225 }else{
226 // Fuzzy search if initial search yields no results
227 $response['status'] = 'success';
228
229 // Use the same word variation logic for fuzzy search
230 $all_word_variations_for_fuzzy = _wpbot_generate_word_variations($keyword);
231
232 $unique_posts = array(); // Store unique post objects
233 $seen_ids = array(); // Keep track of seen post IDs
234
235 // Iterate through each word's variations to find matching posts
236 foreach ( $all_word_variations_for_fuzzy as $word_variations ) {
237 foreach ($word_variations as $term) {
238 $term = $wpdb->esc_like( $term );
239
240 $term_results = $wpdb->get_results( // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
241 $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 .'%')
242 );
243
244 foreach ($term_results as $res) {
245 if (!in_array($res->ID, $seen_ids)) {
246 $unique_posts[] = $res;
247 $seen_ids[] = $res->ID;
248 }
249 }
250 }
251 }
252 $results = $unique_posts; // Now $results contains unique WP_Post objects
253
254 if( !empty( $results) ){
255 $response['html'] = '<div class="wpb-search-result">';
256 $total_post = 0;
257 $responses = '';
258 $selected_lan = get_option('qlcd_wp_chatbot_default_language');
259
260 foreach ($results as $value) { // $value is a single post object here
261 if(!empty($value->guid)){
262 $post_id = $value->ID;
263 $current_featured_img_url = get_the_post_thumbnail_url( $post_id, 'full' );
264
265 // Corrected URL segment parsing for language check
266 $url_path = wp_parse_url(get_permalink($post_id), PHP_URL_PATH);
267 $url_segments = array_filter(explode('/',$url_path));
268
269 // Assuming the language slug is the first non-empty segment of the URL path.
270 $first_segment = !empty($url_segments) ? reset($url_segments) : '';
271
272 // If $selected_lan is empty, the language check is effectively skipped.
273 $language_match = empty($selected_lan) || ($first_segment == $selected_lan);
274
275 if($language_match){
276 $total_post = $total_post + 1;
277 $responses .='<div class="wpbot_card_wraper">';
278 $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">';
279 if(!empty($current_featured_img_url)){
280 $responses .= '<img src="'.esc_url_raw($current_featured_img_url).'" />';
281 }
282 $responses .= '<div class="wpbot_card_caption '.(empty($current_featured_img_url)?'wpbot_card_caption_saas':'').'">';
283 $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>';
284 $responses .= '</div>';
285 $responses .= '</a></div>';
286 $responses .='</div>';
287 }
288 }
289 }
290 if($total_post > 2 ){ // This condition is different from the first block ($total_post >= $limit)
291 $load_more = maybe_unserialize(get_option('qlcd_wp_chatbot_load_more_search'));
292 $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>';
293 $response['status'] = 'success';
294 }else{
295 $response['status'] = 'fail';
296 }
297
298 $response['html'] .= $responses;
299 $response['html'] .='</div>';
300 } else {
301 $response['status'] = 'fail'; // No results from fuzzy search either
302 }
303 }
304 echo wp_json_encode($response);
305 wp_die();
306 }
307
308
309 add_action( 'wp_ajax_wpbo_search_site', 'wpbo_search_site' );
310 add_action( 'wp_ajax_nopriv_wpbo_search_site', 'wpbo_search_site' );
311
312 if ( ! function_exists( 'qcld_wpbot_modified_keyword' ) ) {
313 function qcld_wpbot_modified_keyword( $keyword ) {
314 $keyword = rtrim( $keyword, '!' );
315 $pattern = '/[?\/]/';
316 $strings = preg_split( $pattern, $keyword );
317 $strings = array_filter( array_map( 'trim', $strings ) );
318 $keyword = rtrim( $strings[0], '!' );
319 return htmlspecialchars_decode( $keyword );
320 }
321 }
322
323 add_action( 'wp_ajax_wpbo_search_responseby_intent', 'qcld_wpbo_search_responseby_intent' );
324 add_action( 'wp_ajax_nopriv_wpbo_search_responseby_intent', 'qcld_wpbo_search_responseby_intent' );
325
326 if( !function_exists( 'wpbo_search_site_pagination' )){
327
328 function wpbo_search_site_pagination() {
329 global $wpdb;
330
331 // Verify nonce for security
332 $p_nonce = isset($_POST['nonce']) ? sanitize_text_field(wp_unslash($_POST['nonce'])) : '';
333 if ( ! wp_verify_nonce( $p_nonce, 'wp_chatbot' ) && ! wp_verify_nonce( $p_nonce, 'qcsecretbotnonceval123qc' ) ) {
334 wp_send_json_error( array( 'message' => 'Security check failed' ) );
335 wp_die();
336 }
337
338 // Sanitize and validate inputs
339 $keyword = isset( $_POST['keyword'] ) ? sanitize_text_field(wp_unslash($_POST['keyword'])) : '';
340 $post_type = isset( $_POST['type'] ) ? sanitize_text_field(wp_unslash($_POST['type'])) : 'post';
341 $page = isset($_POST['page']) ? absint( wp_unslash($_POST['page']) ) : 0;
342
343 // Validate post type against allowed types
344 $allowed_post_types = array( 'post', 'page', 'product' );
345 if ( ! in_array( $post_type, $allowed_post_types, true ) ) {
346 $post_type = 'post';
347 }
348
349 $enable_post_types = get_option( 'wppt_post_types' );
350 $load_more = maybe_unserialize( get_option( 'qlcd_wp_chatbot_load_more' ) );
351
352 if ( is_array( $load_more ) && isset( $load_more[ get_locale() ] ) ) {
353 $load_more = $load_more[ get_locale() ];
354 }
355 if ( is_array( $load_more ) && ! empty( $load_more ) ) {
356 $load_more = $load_more[ array_rand( $load_more ) ];
357 }
358 $searchlimit = ( get_option( 'wppt_number_of_result' ) == '' ? 5 : absint( get_option( 'wppt_number_of_result' ) ) );
359 $orderby = ( get_option( 'wppt_result_orderby' ) == '' ? 'none' : get_option( 'wppt_result_orderby' ) );
360 $order = ( get_option( 'wppt_result_order' ) == '' ? 'ASC' : get_option( 'wppt_result_order' ) );
361 $thumb = ( get_option( 'wpbot_search_image_size' ) ? get_option( 'wpbot_search_image_size' ) : 'thumbnail' );
362 // order by setup
363 $new_window = get_option( 'wpbot_search_result_new_window' );
364
365 $total_items = absint( get_option( 'wppt_number_of_result' ) );
366 if ( $total_items < 1 ) {
367 $total_items = 5;
368 }
369
370 $searchkeyword = qcld_wpbot_modified_keyword( $keyword );
371
372 $response = array();
373 $response['status'] = 'fail';
374 $response['html'] = '';
375
376 // Use prepared statements to prevent SQL injection
377 if ( get_option( 'active_advance_query' ) != '1' ) {
378 // Simple query - search in post_title only
379 $total_results = $wpdb->get_results( // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
380 $wpdb->prepare(
381 "SELECT * FROM {$wpdb->prefix}posts
382 WHERE post_type = %s
383 AND post_status = 'publish'
384 AND post_title LIKE %s
385 ORDER BY ID DESC",
386 $post_type,
387 '%' . $wpdb->esc_like( $searchkeyword ) . '%'
388 ));
389 } else {
390 // Advanced query - search in both post_title and post_content
391 $total_results = $wpdb->get_results( // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
392 $wpdb->prepare(
393 "SELECT * FROM " . $wpdb->prefix . "posts
394 WHERE post_type = %s
395 AND post_status = %s
396 AND (post_title REGEXP %s OR post_content REGEXP %s)
397 ORDER BY ID DESC",
398 $post_type,
399 'publish',
400 '[[:<:]]' . $searchkeyword . '[[:>:]]',
401 '[[:<:]]' . $searchkeyword . '[[:>:]]'
402 ));
403 }
404
405 if ( ! empty( $total_results ) ) {
406
407 // Validate and sanitize orderby parameter
408 $valid_orderby = array( 'title', 'date', 'modified', 'none', 'rand' );
409 if ( ! in_array( $orderby, $valid_orderby, true ) ) {
410 $orderby = 'none';
411 }
412
413 if ( $orderby == 'title' ) {
414 $orderby = 'post_title';
415 }
416 if ( $orderby == 'date' ) {
417 $orderby = 'post_date';
418 }
419 if ( $orderby == 'modified' ) {
420 $orderby = 'post_modified';
421 }
422
423 // Validate order parameter
424 $order = strtoupper( $order );
425 if ( ! in_array( $order, array( 'ASC', 'DESC' ), true ) ) {
426 $order = 'ASC';
427 }
428
429 // Build query with pagination
430 $offset = absint( $total_items * $page );
431
432 if ( get_option( 'active_advance_query' ) != '1' ) {
433 if ( $orderby != 'none' && $orderby != 'rand' ) {
434 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared, PluginCheck.Security.DirectDB.UnescapedDBParameter
435 $results = $wpdb->get_results( $wpdb->prepare(
436 "SELECT * FROM {$wpdb->prefix}posts
437 WHERE post_type = %s
438 AND post_status = 'publish'
439 AND post_title LIKE %s
440 ORDER BY {$orderby} {$order}
441 LIMIT %d, %d",
442 $post_type,
443 '%' . $wpdb->esc_like( $searchkeyword ) . '%',
444 $offset,
445 $total_items
446 ) );
447 } else {
448 $results = $wpdb->get_results( // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
449 $wpdb->prepare(
450 "SELECT * FROM {$wpdb->prefix}posts
451 WHERE post_type = %s
452 AND post_status = 'publish'
453 AND post_title LIKE %s
454 ORDER BY ID DESC
455 LIMIT %d, %d",
456 $post_type,
457 '%' . $wpdb->esc_like( $searchkeyword ) . '%',
458 $offset,
459 $total_items
460 ));
461 }
462 } else {
463 if ( $orderby != 'none' && $orderby != 'rand' ) {
464 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared, PluginCheck.Security.DirectDB.UnescapedDBParameter
465 $results = $wpdb->get_results( $wpdb->prepare(
466 "SELECT * FROM " . $wpdb->prefix . "posts
467 WHERE post_type = %s
468 AND post_status = %s
469 AND (post_title REGEXP %s OR post_content REGEXP %s)
470 ORDER BY " . $orderby . " " . $order . "
471 LIMIT %d, %d",
472 $post_type,
473 'publish',
474 '[[:<:]]' . $searchkeyword . '[[:>:]]',
475 '[[:<:]]' . $searchkeyword . '[[:>:]]',
476 $offset,
477 $total_items
478 ) );
479 } else {
480 $results = $wpdb->get_results( // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
481 $wpdb->prepare(
482 "SELECT * FROM " . $wpdb->prefix . "posts
483 WHERE post_type = %s
484 AND post_status = %s
485 AND (post_title REGEXP %s OR post_content REGEXP %s)
486 ORDER BY ID DESC
487 LIMIT %d, %d",
488 $post_type,
489 'publish',
490 '[[:<:]]' . $searchkeyword . '[[:>:]]',
491 '[[:<:]]' . $searchkeyword . '[[:>:]]',
492 $offset,
493 $total_items
494 ));
495 }
496 }
497 } else {
498 if ( class_exists( 'SitePress' ) ) {
499 global $sitepress;
500 $selected_lan = isset( $_POST['language'] ) ? sanitize_text_field(wp_unslash($_POST['language'])) : '';
501 $selected_lan = explode( '_', $selected_lan );
502 if ( ! empty( $selected_lan[0] ) ) {
503 $sitepress->switch_lang( $selected_lan[0], true );
504 }
505 }
506
507 $query_arg = array(
508 'post_type' => $post_type,
509 'post_status' => 'publish',
510 'posts_per_page' => $total_items,
511 's' => stripslashes( $keyword ),
512 'paged' => ( $page + 1 ),
513 'orderby' => $orderby,
514 );
515
516 if ( class_exists( 'SitePress' ) ) {
517 global $sitepress;
518 $selected_lan = isset( $_POST['language'] ) ? sanitize_text_field(wp_unslash($_POST['language'])) : '';
519 $selected_lan = explode( '_', $selected_lan );
520 if ( ! empty( $selected_lan[0] ) ) {
521 $sitepress->switch_lang( $selected_lan[0], true );
522 }
523 }
524
525 $query_arg['suppress_filters'] = true;
526 if ( $orderby != 'none' && $orderby != 'rand' ) {
527 $query_arg['order'] = $order;
528 }
529
530 $totalresults = new WP_Query(
531 array(
532 'post_type' => $post_type,
533 'post_status' => 'publish',
534 's' => stripslashes( $keyword ),
535 )
536 );
537 $resultss = new WP_Query( $query_arg );
538 $total_results = $totalresults->posts;
539 $resultss = new WP_Query( $query_arg );
540 $results = $resultss->posts;
541 }
542
543 if ( ! empty( $total_results ) ) {
544
545 $selected_lan = isset( $_POST['language'] ) ? sanitize_text_field(wp_unslash($_POST['language'])) : '';
546 $urlss = get_option( 'wpbotml_url_urls' ) ? get_option( 'wpbotml_url_urls' ) : '';
547 $imagesize = ( get_option( 'wpbot_search_image_size' ) != '' ? get_option( 'wpbot_search_image_size' ) : 'thumbnail' );
548
549 $response['html'] .= '<div class="wpb-search-result">';
550
551 foreach ( $total_results as $result ) {
552
553 if ( $result->post_type == 'product' ) {
554 if ( ! class_exists( 'WooCommerce' ) ) {
555 continue;
556 }
557 }
558
559 $featured_img_url = get_the_post_thumbnail_url( $result->ID, $thumb );
560 $excerpt = '';
561 if ( isset( $result->ID ) ) {
562 $post_obj = get_post( $result->ID );
563 if ( $post_obj ) {
564 if ( has_excerpt( $result->ID ) ) {
565 $excerpt = get_the_excerpt( $result->ID );
566 } else {
567 $content = $post_obj->post_content;
568
569 // Remove ALL WPBakery shortcodes (paired + self-closing)
570 $content = preg_replace( '/\[vc_[^\]]*\](.*?)\[\/vc_[^\]]*\]/s', '$1', $content ); // paired
571 $content = preg_replace( '/\[vc_[^\]]*\]/s', '', $content ); // self-closing
572 $content = preg_replace('/\[\/?[\w\-]+[^\]]*\]/', '', $content);
573 // Extra: remove any leftover [] shortcodes (just in case)
574 $content = strip_shortcodes( $content );
575
576 // Run through normal WP content filters
577 $content_filtered = apply_filters( 'the_content', $content );
578
579 // Strip HTML tags, then trim
580 $excerpt = wp_trim_words( wp_strip_all_tags( $content_filtered ), 20, '...' );
581 }
582 }
583 }
584
585
586 $response['html'] .= '<div class="wpbot_card_wraper">';
587 $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 ) . '"' : '' ) . '>';
588 if ( $featured_img_url != '' ) {
589 $response['html'] .= '<img src="' . esc_url_raw( $featured_img_url ) . '" />';
590 }
591
592 $response['html'] .= '<div class="wpbot_card_caption ' . ( $featured_img_url == '' ? 'wpbot_card_caption_saas' : '' ) . '">';
593 $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>';
594 $response['html'] .= '<p class="wpbot_card_description">' . esc_html( $excerpt ) . '</p>';
595 if ( $result->post_type == 'product' ) {
596 if ( class_exists( 'WooCommerce' ) ) {
597 $product = wc_get_product( $result->ID );
598 $response['html'] .= '<p class="wpbot_product_price">' . get_woocommerce_currency_symbol() . $product->get_price_html() . '</p>';
599 }
600 }
601 $response['html'] .= '</div>';
602 $response['html'] .= '</a></div>';
603 $response['html'] .= '</div>';
604
605 }
606
607
608 $response['html'] .= '</div>';
609 $response['status'] = 'success';
610
611 }
612 wp_reset_query();
613
614 if ( $response['status'] != 'success' ) {
615 $texts = maybe_unserialize( get_option( 'qlcd_wp_chatbot_no_result' ) );
616 $selected_lan = isset( $_POST['language'] ) ? sanitize_text_field(wp_unslash($_POST['language'])) : '';
617 if ( ! empty( $texts ) && is_array( $texts ) && isset( $texts[ $selected_lan ][0] ) ) {
618 $texts = str_replace( "\'", "'", $texts[ $selected_lan ][0] );
619 $response['html'] = array( $texts );
620 } else {
621 $response['html'] = array( 'No results found' );
622 }
623 }
624 wp_send_json( $response );
625 die();
626 }
627
628 }
629
630
631
632 add_action( 'wp_ajax_wpbo_search_site_pagination', 'wpbo_search_site_pagination' );
633 add_action( 'wp_ajax_nopriv_wpbo_search_site_pagination', 'wpbo_search_site_pagination' );
634 function qcld_wpbo_search_responseby_intent(){
635
636 global $wpdb;
637
638 $keyword = isset( $_POST['keyword'] ) ? sanitize_text_field(wp_unslash($_POST['keyword'])) : '';
639
640 $table = $wpdb->prefix.'wpbot_response';
641
642 $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
643
644 $response = array('status'=>'fail');
645
646 if(!empty($result)){
647
648 $response['status'] = 'success';
649 $response['html'] = $result->response;
650
651 }
652
653 echo wp_json_encode($response);
654
655 die();
656
657 }
658 function qcld_wb_chatbot_email_subscription() {
659
660 global $wpdb;
661 $table = $wpdb->prefix . 'wpbot_subscription';
662
663 $name = sanitize_text_field( $_POST['name'] );// phpcs:ignore WordPress.Security.NonceVerification.Missing
664 $email = sanitize_email( $_POST['email'] );// phpcs:ignore WordPress.Security.NonceVerification.Missing
665 $url = esc_url_raw( $_POST['url'] );// phpcs:ignore WordPress.Security.NonceVerification.Missing
666 $user_agent = sanitize_text_field( $_SERVER['HTTP_USER_AGENT'] );// phpcs:ignore WordPress.Security.NonceVerification.Missing
667
668 if ( isset( $_POST['phone'] ) && $_POST['phone'] != '' ) {// phpcs:ignore WordPress.Security.NonceVerification.Missing
669
670 $phone = sanitize_text_field( $_POST['phone'] );// phpcs:ignore WordPress.Security.NonceVerification.Missing
671 if ( $email != '' ) {
672
673 $email_exists = $wpdb->get_row( $wpdb->prepare( "select * from %i where 1 and email = %s", $table, $email ) ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter
674 if ( ! empty( $email_exists ) ) {
675 $wpdb->update( // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
676 $table,
677 array(
678 'phone' => $phone,
679 ),
680 array( 'email' => $email ),
681 array(
682 '%s',
683 ),
684 array( '%s' )
685 );
686 } else {
687 $wpdb->insert( // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery
688 $table,
689 array(
690 'date' => current_time( 'mysql' ),
691 'name' => $name,
692 'email' => $email,
693 'phone' => $phone,
694 'url' => $url,
695 'user_agent' => $user_agent,
696 )
697 );
698 }
699 } else {
700 $wpdb->insert( // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery
701 $table,
702 array(
703 'date' => current_time( 'mysql' ),
704 'name' => $name,
705 'email' => $email,
706 'phone' => $phone,
707 'url' => $url,
708 'user_agent' => $user_agent,
709 )
710 );
711 }
712 $response['status'] = 'success';
713 echo json_encode( $response );
714 die();
715
716 } else {
717
718 $response = array();
719 $response['status'] = 'fail';
720
721 $email_exists = $wpdb->get_row( $wpdb->prepare( "select * from %i where 1 and email = %s", $table, $email ) ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter
722 if ( empty( $email_exists ) ) {
723
724 $wpdb->insert( // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery
725 $table,
726 array(
727 'date' => current_time( 'mysql' ),
728 'name' => $name,
729 'email' => $email,
730 'url' => $url,
731 'user_agent' => $user_agent,
732 )
733 );
734 $response['status'] = 'success';
735 $texts = maybe_unserialize( get_option( 'qlcd_wp_email_subscription_success' ) );
736 if ( is_array( $texts ) && isset( $texts[ get_wpbot_locale() ] ) ) {
737 $texts = $texts[ get_wpbot_locale() ];
738 }
739 if ( is_array( $texts ) && ! empty( $texts ) ) {
740 $response['msg'] = $texts[ array_rand( $texts ) ];
741 } elseif ( is_string( $texts ) && ! empty( $texts ) ) {
742 $response['msg'] = $texts;
743 } else {
744 $response['msg'] = 'Thank you for subscribing.';
745 }
746
747 } else {
748 $texts = maybe_unserialize( get_option( 'qlcd_wp_email_already_subscribe' ) );
749
750 if ( is_array( $texts ) && isset( $texts[ get_wpbot_locale() ] ) ) {
751 $texts = $texts[ get_wpbot_locale() ];
752 }
753
754 if ( is_array( $texts ) && ! empty( $texts ) ) {
755 $response['msg'] = $texts[ array_rand( $texts ) ];
756 } elseif ( is_string( $texts ) && ! empty( $texts ) ) {
757 $response['msg'] = $texts;
758 } else {
759 $response['msg'] = 'You have already subscribed!';
760 }
761 }
762
763 do_action( 'qcld_mailing_list_subscription_success', $name, $email );
764
765 if ( get_option( 'qc_email_subscription_offer' ) == 1 ) {
766
767 $response['status'] = 'success';
768
769 if ( get_option( 'qlcd_wp_email_subscription_offer_subject' ) ) {
770 $offertextss = maybe_unserialize( get_option( 'qlcd_wp_email_subscription_offer_subject' ) );
771 if ( is_array( $offertextss ) && isset( $offertextss[ get_wpbot_locale() ] ) ) {
772 $offertextss = $offertextss[ get_wpbot_locale() ];
773 }
774 if ( is_array( $offertextss ) && ! empty( $offertextss ) ) {
775 $subject = str_replace( '%%username%%', $name, $offertextss[ array_rand( $offertextss ) ] );
776 } elseif ( is_string( $offertextss ) && ! empty( $offertextss ) ) {
777 $subject = str_replace( '%%username%%', $name, $offertextss );
778 } else {
779 $subject = 'Email subscription offer';
780 }
781
782 } else {
783 $subject = 'Email subscription offer';
784 }
785
786 // Extract Domain
787 $url = get_site_url();
788 $url = parse_url( $url );
789 $domain = $url['host'];
790 $toEmail = $email;
791 $fromEmail = 'wordpress@' . $domain;
792 $fromname = ( get_option( 'qlcd_wp_chatbot_from_name' ) ? get_option( 'qlcd_wp_chatbot_from_name' ) : 'WordPress' );
793
794 if ( get_option( 'qlcd_wp_chatbot_from_email' ) && get_option( 'qlcd_wp_chatbot_from_email' ) != '' ) {
795 $fromEmail = get_option( 'qlcd_wp_chatbot_from_email' );
796 }
797
798 $replyto = $fromEmail;
799
800 if ( get_option( 'qlcd_wp_chatbot_reply_to_email' ) && get_option( 'qlcd_wp_chatbot_reply_to_email' ) != '' ) {
801 $replyto = get_option( 'qlcd_wp_chatbot_reply_to_email' );
802 }
803
804 // Starting messaging and status.
805 $offertexts = maybe_unserialize( get_option( 'qlcd_wp_email_subscription_offer' ) );
806 if ( is_array( $offertexts ) && isset( $offertexts[ get_wpbot_locale() ] ) ) {
807 $offertexts = $offertexts[ get_wpbot_locale() ];
808 }
809 // build email body.
810 $bodyContent = '';
811 $bodyContent .= '<p><strong>' . esc_html__( 'Offer Details', 'wpchatbot' ) . ':</strong></p><hr>';
812 if ( is_array( $offertexts ) && ! empty( $offertexts ) ) {
813 $bodyContent .= '<p>' . str_replace( '%%username%%', $name, $offertexts[ array_rand( $offertexts ) ] ) . '</p>';
814 } elseif ( is_string( $offertexts ) && ! empty( $offertexts ) ) {
815 $bodyContent .= '<p>' . str_replace( '%%username%%', $name, $offertexts ) . '</p>';
816 } else {
817 $bodyContent .= '<p></p>';
818 }
819 $bodyContent .= '<p>' . esc_html__( 'Mail Generated on', 'wpchatbot' ) . ': ' . current_time( 'F j, Y, g:i a' ) . '</p>';
820 $to = $toEmail;
821 $body = $bodyContent;
822
823 $headers = array();
824 $headers[] = 'Content-Type: text/html; charset=UTF-8';
825 $headers[] = 'From: ' . $fromname . ' <' . $fromEmail . '>';
826 $headers[] = 'Reply-To: ' . $fromname . ' <' . ( $replyto ) . '>';
827 wp_mail( $to, $subject, $body, $headers );
828 $response['email'] = 'Send! to ' . $to . ' from ' . $fromEmail;
829
830 }
831
832 echo json_encode( $response );
833
834 die();
835 }
836 }
837
838 add_action( 'wp_ajax_qcld_wb_chatbot_email_subscription', 'qcld_wb_chatbot_email_subscription' );
839 add_action( 'wp_ajax_nopriv_qcld_wb_chatbot_email_subscription', 'qcld_wb_chatbot_email_subscription' );
840 add_action( 'admin_post_wpbprint.csv', 'qcld_wpb_export_email_csv' );
841
842 if ( ! function_exists( 'qcld_wpbd_array2csv' ) ) {
843 function qcld_wpbd_array2csv( array &$array ) {
844 if ( count( $array ) == 0 ) {
845 return null;
846 }
847 ob_start();
848 $df = fopen( 'php://output', 'w' );
849 fputcsv( $df, array( 'Name', 'Email' ), ',', '"', '\\' );
850 foreach ( $array as $row ) {
851 fputcsv( $df, $row, ',', '"', '\\' );
852 }
853 fclose( $df );
854 return ob_get_clean();
855 }
856 }
857
858 function qcld_wpb_export_email_csv() {
859 global $wpdb;
860 $table = $wpdb->prefix . 'wpbot_subscription';
861
862 if ( ! current_user_can( 'manage_options' ) ) {
863 return;
864 }
865
866 $emails = $wpdb->get_results( $wpdb->prepare( "select * from %i WHERE %d", $table, 1 ) ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter
867 $childArray = array();
868 foreach ( $emails as $email ) {
869 $innerArray = array();
870 $innerArray[0] = $email->name;
871 $innerArray[1] = $email->email;
872 array_push( $childArray, $innerArray );
873 }
874 qcld_wpbd_download_send_headers( 'wpb_email_lists_' . current_time( 'Y-m-d' ) . '.csv' );
875
876 $result = qcld_wpbd_array2csv( $childArray );
877
878 print $result; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
879 die();
880 }
881 function qcld_wpbd_download_send_headers( $filename ) {
882 // disable caching
883 $now = gmdate( 'D, d M Y H:i:s' );
884 header( 'Expires: Tue, 03 Jul 2001 06:00:00 GMT' );
885 header( 'Cache-Control: max-age=0, no-cache, must-revalidate, proxy-revalidate' );
886 header( "Last-Modified: {$now} GMT" );
887
888 // force download
889 header( 'Content-Type: application/force-download' );
890
891 // disposition / encoding on response body
892 header( "Content-Disposition: attachment;filename={$filename}" );
893 header( 'Content-Transfer-Encoding: binary' );
894 }
895 add_action( 'wp_ajax_wpbo_search_response_catlist', 'wpbo_search_response_catlist' );
896 add_action( 'wp_ajax_nopriv_wpbo_search_response_catlist', 'wpbo_search_response_catlist' );
897
898 if( !function_exists( 'wpbo_search_response_catlist' )){
899 function wpbo_search_response_catlist(){
900 global $wpdb;
901 $table = $wpdb->prefix.'wpbot_response_category';
902 $status = array('status'=>'fail');
903 $results = $wpdb->get_results($wpdb->prepare("SELECT * FROM %i", $table)); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
904 $response_result = array();
905
906 if(!empty($results)){
907 foreach($results as $result){
908
909 $response_result[] = array('name'=>$result->name);
910
911 }
912 }
913
914 if(!empty($response_result)){
915
916 $status = array('status'=>'success', 'data'=>$response_result);
917
918
919 }
920
921 echo wp_json_encode($status);
922
923 die();
924
925 }
926 }
927 add_action( 'wp_ajax_wpbo_search_response', 'qcld_wpbo_search_response' );
928 add_action( 'wp_ajax_nopriv_wpbo_search_response', 'qcld_wpbo_search_response' );
929
930
931
932 function qcld_wpbo_search_response(){
933
934 global $wpdb;
935 $keyword = isset( $_POST['keyword'] ) ? (sanitize_text_field(wp_unslash($_POST['keyword']))) : '';
936 $strid = isset( $_POST['strid'] ) ? (sanitize_text_field(wp_unslash($_POST['strid']))) : '';
937 $table = $wpdb->prefix.'wpbot_response';
938
939
940 $response_result = array();
941
942 $status = array('status'=>'fail', 'multiple'=>false);
943 $field = "ID";
944 if(($strid != '') && empty($response_result)){
945 $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
946 if(!empty($results)){
947 foreach($results as $result){
948
949 $response_result[] = array('id'=>$result->id,'query'=>$result->query, 'response'=>$result->response, 'score'=>1);
950
951 }
952 }
953 }
954 $field = "query";
955 $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
956
957
958 if(!empty($results)){
959 foreach($results as $result){
960
961 $response_result[] = array('id'=>$result->id,'query'=>$result->query, 'response'=>$result->response, 'score'=>1);
962
963 }
964 }
965
966 $field = "category";
967 if(empty($response_result)){
968 $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
969
970
971 if(!empty($results)){
972 foreach($results as $result){
973 $response_result[] = array('id'=>$result->id,'query'=>$result->query, 'response'=>$result->response, 'score'=>1);
974 }
975 if(count($response_result)>1){
976 $status = array('status'=>'success','category'=> true, 'multiple'=>true, 'data'=>$response_result);
977 }else{
978 $status = array('status'=>'success', 'category'=> true, 'multiple'=>false, 'data'=>$response_result);
979 }
980
981 echo wp_json_encode($status);
982
983 die();
984 }
985
986 }
987
988 if(class_exists('Qcld_str_pro')){
989 if(get_option('qc_bot_str_remove_stopwords') && get_option('qc_bot_str_remove_stopwords')==1){
990 $keyword = qcld_strpro_remove_stopwords($keyword);
991 }
992 }
993
994
995 if(empty($response_result)){
996
997 $fields = get_option('qc_bot_str_fields');
998
999 $allowed_fields = array('query', 'keyword', 'response');
1000 $valid_fields = array();
1001
1002 if($fields && !empty($fields) && is_array($fields)){
1003 foreach($fields as $field){
1004 if(in_array($field, $allowed_fields)){
1005 $valid_fields[] = '`' . $field . '`';
1006 }
1007 }
1008 }
1009
1010 if(!empty($valid_fields)){
1011 $qfields = implode(', ', $valid_fields);
1012 }else{
1013 $qfields = '`query`,`keyword`,`response`';
1014 }
1015
1016
1017
1018 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared, PluginCheck.Security.DirectDB.UnescapedDBParameter
1019 $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) );
1020
1021 $weight = get_option('qc_bot_str_weight')!=''?get_option('qc_bot_str_weight'):'0.4';
1022
1023 if(!empty($results)){
1024 $max_score = max(array_column($results, 'score'));
1025 if ($max_score <= 0) {
1026 $max_score = 1; // Set to 1 to avoid division by zero
1027 }
1028 foreach($results as $result){
1029 if(($result->score/$max_score) >= $weight){
1030 $response_result[] = array('id'=>$result->id,'query'=>$result->query, 'response'=>$result->response, 'score'=>$result->score);
1031 }
1032 }
1033 }
1034 }
1035 $field = "keyword";
1036 if( empty( $response_result ) ){
1037
1038 $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
1039
1040
1041 if(!empty($results)){
1042 foreach($results as $result){
1043 $response_result[] = array('id'=>$result->id,'query'=>$result->query, 'response'=>$result->response, 'score'=>1);
1044 }
1045 }
1046 }
1047 if(!empty($response_result)){
1048
1049 if(count($response_result)>1){
1050 $status = array('status'=>'success', 'multiple'=>true, 'data'=>$response_result);
1051 }else{
1052 $status = array('status'=>'success', 'multiple'=>false, 'data'=>$response_result);
1053 }
1054
1055 }
1056 if(empty($result->query)){
1057 $status = array('status'=>'fail', 'multiple'=>false, 'data'=>$response_result);
1058 }
1059 if(empty($status['data']) || (isset($status['status']) && $status['status']==='fail')){
1060 // Check for space before question mark and try again.
1061 if(preg_match('/ \?$/', $keyword)){
1062 $keyword2 = preg_replace('/ \?$/', '?', $keyword);
1063 // Try again with new keyword.
1064 // Repeat the main search logic with $keyword2.
1065 $response_result = array();
1066 $field = "query";
1067 $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
1068 if(!empty($results)){
1069 foreach($results as $result){
1070 $response_result[] = array('id'=>$result->id,'query'=>$result->query, 'response'=>$result->response, 'score'=>1);
1071 }
1072 if(count($response_result)>1){
1073 $status = array('status'=>'success', 'multiple'=>true, 'data'=>$response_result);
1074 }else{
1075 $status = array('status'=>'success', 'multiple'=>false, 'data'=>$response_result);
1076 }
1077 }else{
1078 $status = array('status'=>'fail', 'multiple'=>false, 'data'=>[]);
1079 }
1080 }
1081 }
1082 if(empty($status['data']) || (isset($status['status']) && $status['status']==='fail')){
1083 // Try a partial match if still nothing found.
1084 if(empty($status['data'])) {
1085 $keyword_like = '%' . preg_replace('/[\\s\\?]+/', '%', $keyword) . '%';
1086 $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
1087 $response_result = array();
1088 if(!empty($results)){
1089 foreach($results as $result){
1090 $response_result[] = array('id'=>$result->id,'query'=>$result->query, 'response'=>$result->response, 'score'=>1);
1091 }
1092 if(count($response_result)>1){
1093 $status = array('status'=>'success', 'multiple'=>true, 'data'=>$response_result);
1094 }else{
1095 $status = array('status'=>'success', 'multiple'=>false, 'data'=>$response_result);
1096 }
1097 } else {
1098 $status = array('status'=>'fail', 'multiple'=>false, 'data'=>[], 'message'=>'Sorry, I found nothing');
1099 }
1100 }
1101 }
1102 if(empty($status['data'])){
1103 $status = array('status'=>'fail', 'multiple'=>false, 'data'=>[], 'message'=>'no result found');
1104 }
1105 echo wp_json_encode($status);
1106
1107 die();
1108
1109 }
1110
1111 function qcld_strpro_remove_stopwords($keyword){
1112
1113 if(get_option('qlcd_wp_chatbot_stop_words') && get_option('qlcd_wp_chatbot_stop_words')!=''){
1114 $commonWords = explode(',', get_option('qlcd_wp_chatbot_stop_words'));
1115 return preg_replace('/\b('.implode('|',$commonWords).')\b/','',$keyword);
1116 }else{
1117 return $keyword;
1118 }
1119
1120
1121
1122 }