PluginProbe
WPBot – AI ChatBot for Live Support, Lead Generation, WordPress Automation, AI Services / 0.9.0
WPBot – AI ChatBot for Live Support, Lead Generation, WordPress Automation, AI Services v0.9.0
8.7.8 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 All 534 releases
chatbot / includes / class-wpwbot-table.php

class-wpwbot-table.php in WPBot – AI ChatBot for Live Support, Lead Generation, WordPress Automation, AI Services 0.9.0, at includes/class-wpwbot-table.php

465 lines 18.2 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 if ( ! defined( 'ABSPATH' ) ) {
3 exit;
4 }
5 if ( ! class_exists( 'wpwBot_Table' ) ) :
6 /**
7 * Class for plugin index table
8 */
9 class wpwBot_Table {
10 /**
11 * @var wpwBot_Table Index table name
12 */
13 private $table_name;
14 /**
15 * Constructor
16 */
17 public function __construct() {
18 global $wpdb;
19 $this->table_name = $wpdb->prefix . QCLD_wpCHATBOT_INDEX_TABLE;
20 add_action( 'wp_insert_post', array( $this, 'update_table' ), 10, 3 );
21
22 if ( defined('wpCOMMERCE_VERSION') ) {
23 if ( version_compare( wpCOMMERCE_VERSION, '3.0', ">=" ) ) {
24 add_action( 'wpcommerce_variable_product_sync_data', array( $this, 'variable_product_changed' ) );
25 } else {
26 add_action( 'wpcommerce_variable_product_sync', array( $this, 'variable_product_changed' ), 10, 2 );
27 }
28 }
29
30 add_action( 'wp_ajax_qcld-wp-chabot-reindex', array( $this, 'reindex_table' ) );
31 add_action( 'wp_ajax_qcld-wp-chabot-cancel-index', array( $this, 'cancel_reindex' ) );
32 }
33 /*
34 * Reindex plugin table
35 */
36 public function reindex_table( $return = false ) {
37 global $wpdb;
38 $index_meta = get_option( 'wp_chatbot_index_meta', false );
39 $status = false;
40 // No current index going on. Let's start over
41 if ( false === $index_meta ) {
42 $status = 'start';
43 $index_meta = array(
44 'offset' => 0,
45 'start' => true,
46 );
47 $wpdb->query("DROP TABLE IF EXISTS {$this->table_name}");
48 $this->create_table();
49 $index_meta['found_posts'] = $this->get_number_of_products();
50 } else if ( ! empty( $index_meta['site_stack'] ) && $index_meta['offset'] >= $index_meta['found_posts'] ) {
51 $status = 'start';
52 $index_meta['start'] = true;
53 $index_meta['offset'] = 0;
54 $index_meta['current_site'] = array_shift( $index_meta['site_stack'] );
55 } else {
56 $index_meta['start'] = false;
57 }
58 $index_meta = apply_filters( 'wp_chatbot_index_meta', $index_meta );
59 $posts_per_page = apply_filters( 'wp_chatbot_index_posts_per_page', 30 );
60 $args = array(
61 'posts_per_page' => $posts_per_page,
62 'fields' => 'ids',
63 'post_type' => 'product',
64 'post_status' => 'publish',
65 'offset' => $index_meta['offset'],
66 'ignore_sticky_posts' => true,
67 'suppress_filters' => true,
68 'no_found_rows' => 1,
69 'orderby' => 'ID',
70 'order' => 'DESC',
71 );
72 $posts = get_posts( $args );
73 if ( $status !== 'start' ) {
74 if ( $posts && count( $posts ) > 0 ) {
75 $queued_posts = array();
76 foreach( $posts as $post_id ) {
77 $queued_posts[] = absint( $post_id );
78 }
79 $this->fill_table( $queued_posts );
80 $index_meta['offset'] = absint( $index_meta['offset'] + $posts_per_page );
81 if ( $index_meta['offset'] >= $index_meta['found_posts'] ) {
82 $index_meta['offset'] = $index_meta['found_posts'];
83 }
84 update_option( 'wp_chatbot_index_meta', $index_meta );
85 } else {
86 // We are done (with this site)
87 $index_meta['offset'] = (int) count( $posts );
88 delete_option( 'wp_chatbot_index_meta' );
89 update_option( 'wp_chatbot_index_count', 1 );
90 }
91 } else {
92 update_option( 'wp_chatbot_index_meta', $index_meta );
93 }
94 if ( $return ) {
95 return $index_meta;
96 } else {
97 wp_send_json_success( $index_meta );
98 }
99 }
100 /*
101 * Get total number of products
102 */
103 private function get_number_of_products() {
104 $args = array(
105 'posts_per_page' => -1,
106 'fields' => 'ids',
107 'post_type' => 'product',
108 'post_status' => 'publish',
109 'ignore_sticky_posts' => true,
110 'suppress_filters' => true,
111 'no_found_rows' => 1,
112 'orderby' => 'ID',
113 'order' => 'DESC',
114 );
115 $posts = get_posts( $args );
116 if ( $posts && count( $posts ) > 0 ) {
117 $count = count( $posts );
118 } else {
119 $count = 0;
120 }
121 return $count;
122 }
123 /*
124 * Check if index table exist
125 */
126 private function is_table_not_exist() {
127 global $wpdb;
128 return ( $wpdb->get_var( "SHOW TABLES LIKE '{$this->table_name}'" ) != $this->table_name );
129 }
130 /*
131 * Create index table
132 */
133 private function create_table() {
134 global $wpdb;
135 $charset_collate = $wpdb->get_charset_collate();
136 $sql = "CREATE TABLE {$this->table_name} (
137 id BIGINT(20) UNSIGNED NOT NULL DEFAULT 0,
138 term VARCHAR(50) NOT NULL DEFAULT 0,
139 term_source VARCHAR(20) NOT NULL DEFAULT 0,
140 type VARCHAR(50) NOT NULL DEFAULT 0,
141 count BIGINT(20) UNSIGNED NOT NULL DEFAULT 0,
142 in_stock INT(11) NOT NULL DEFAULT 0,
143 visibility VARCHAR(20) NOT NULL DEFAULT 0,
144 lang VARCHAR(20) NOT NULL DEFAULT 0
145 ) $charset_collate;";
146 require_once( ABSPATH . 'wp-admin/includes/upgrade.php' );
147 dbDelta( $sql );
148 }
149 /*
150 * Insert data into the index table
151 */
152 private function fill_table( $posts ) {
153 foreach ( $posts as $found_post_id ) {
154 $data = array();
155 $data['terms'] = array();
156 $data['id'] = $found_post_id;
157 $product = wc_get_product( $data['id'] );
158 if( ! is_a( $product, 'WC_Product' ) ) {
159 continue;
160 }
161 $data['in_stock'] = method_exists( $product, 'get_stock_status' ) ? ( ( $product->get_stock_status() === 'outofstock' ) ? 0 : 1 ) : ( method_exists( $product, 'is_in_stock' ) ? $product->is_in_stock() : 1 );
162 $data['visibility'] = method_exists( $product, 'get_catalog_visibility' ) ? $product->get_catalog_visibility() : ( method_exists( $product, 'get_visibility' ) ? $product->get_visibility() : 'visible' );
163 $data['lang'] = '';
164 $sku = $product->get_sku();
165 $title = apply_filters( 'the_title', get_the_title( $data['id'] ) );
166 $content = apply_filters( 'the_content', get_post_field( 'post_content', $data['id'] ) );
167 $excerpt = get_post_field( 'post_excerpt', $data['id'] );
168 $cat_names = $this->get_terms_names_list( $data['id'], 'product_cat' );
169 $tag_names = $this->get_terms_names_list( $data['id'], 'product_tag' );
170 // Get all child products if exists
171 if ( $product->is_type( 'variable' ) && class_exists( 'WC_Product_Variation' ) ) {
172 if ( sizeof( $product->get_children() ) > 0 ) {
173 foreach ( $product->get_children() as $child_id ) {
174 $variation_product = new WC_Product_Variation( $child_id );
175 $variation_sku = $variation_product->get_sku();
176 $variation_desc = '';
177 if ( method_exists( $variation_product, 'get_description' ) ) {
178 $variation_desc = $variation_product->get_description();
179 }
180 if ( $variation_sku ) {
181 $sku = $sku . ' ' . $variation_sku;
182 }
183 if ( $variation_desc ) {
184 $content = $content . ' ' . $variation_desc;
185 }
186 }
187 }
188 }
189 // WP 4.2 emoji strip
190 if ( function_exists( 'wp_encode_emoji' ) ) {
191 $content = wp_encode_emoji( $content );
192 }
193 $content = $this->strip_shortcodes( $content );
194 $excerpt = $this->strip_shortcodes( $excerpt );
195 $data['terms']['title'] = $this->extract_terms( $title );
196 $data['terms']['content'] = $this->extract_terms( $content );
197 $data['terms']['excerpt'] = $this->extract_terms( $excerpt );
198 $data['terms']['sku'] = $this->extract_terms( $sku );
199 $data['terms']['category'] = $this->extract_terms( $cat_names );
200 $data['terms']['tag'] = $this->extract_terms( $tag_names );
201 //Insert data into table
202 $this->insert_into_table( $data );
203 }
204 }
205 /*
206 * Scrap all product data and insert to table
207 */
208 private function insert_into_table( $data ) {
209 global $wpdb;
210 $values = array();
211 foreach( $data['terms'] as $source => $all_terms ) {
212 foreach ( $all_terms as $term => $count ) {
213 if ( ! $term ) {
214 continue;
215 }
216 $value = $wpdb->prepare(
217 "(%d, %s, %s, %s, %d, %d, %s, %s)",
218 $data['id'], $term, $source, 'product', $count, $data['in_stock'], $data['visibility'], $data['lang']
219 );
220 $values[] = $value;
221 }
222 }
223 if ( count( $values ) > 0 ) {
224 $values = implode( ', ', $values );
225 $query = "INSERT IGNORE INTO {$this->table_name}
226 (`id`, `term`, `term_source`, `type`, `count`, `in_stock`, `visibility`, `lang`)
227 VALUES $values
228 ";
229 $wpdb->query( $query );
230 }
231 }
232 /*
233 * Update index table
234 */
235 public function update_table( $post_id, $post, $update ) {
236 global $wpdb;
237 if ( $this->is_table_not_exist() ) {
238 $this->create_table();
239 }
240 $slug = 'product';
241 if ( $slug != $post->post_type ) {
242 return;
243 }
244 $wpdb->delete( $this->table_name, array( 'id' => $post_id ) );
245 $posts = get_posts( array(
246 'posts_per_page' => -1,
247 'fields' => 'ids',
248 'post_type' => 'product',
249 'post_status' => 'publish',
250 'suppress_filters' => false,
251 'no_found_rows' => 1,
252 'include' => $post_id
253 ) );
254 $this->fill_table( $posts );
255 }
256 /*
257 * Fires when products terms are changed
258 */
259 public function term_changed( $term_id, $tt_id, $taxonomy ) {
260 if ( $taxonomy === 'product_cat' || $taxonomy === 'product_tag' ) {
261 }
262 }
263 /*
264 * Fires when products variations are changed
265 */
266 public function variable_product_changed( $product, $children = null ) {
267 global $wpdb;
268 $product_id = '';
269
270 if ( $this->is_table_not_exist() ) {
271 $this->create_table();
272 }
273
274 if ( is_object( $product ) ) {
275 $product_id = $product->get_id();
276 } else {
277 $product_id = $product;
278 }
279 $wpdb->delete( $this->table_name, array( 'id' => $product_id ) );
280 $posts = get_posts( array(
281 'posts_per_page' => -1,
282 'fields' => 'ids',
283 'post_type' => 'product',
284 'post_status' => 'publish',
285 'suppress_filters' => false,
286 'no_found_rows' => 1,
287 'include' => $product_id
288 ) );
289 $this->fill_table( $posts );
290 }
291 /*
292 * Cancel index
293 */
294 public function cancel_reindex() {
295 delete_option( 'wp_chatbot_index_meta' );
296 wp_send_json_success( 'Deleted!' );
297 }
298 /*
299 * Strip shortcodes
300 */
301 private function strip_shortcodes( $content ) {
302 $content = preg_replace( '#\[[^\]]+\]#', '', $content );
303 return $content;
304 }
305 /*
306 * Extract terms from content
307 */
308 private function extract_terms( $str ) {
309 $stopwords = str_replace('\\', '', get_option('qlcd_wp_chatbot_stop_words'));
310 $str = $this->html2txt( $str );
311 // Avoid single A-Z.
312
313 $special_cars = $this->get_special_chars();
314 $str = str_replace( $special_cars, "", $str );
315 $str = str_replace( array(
316 "ˇ",
317 "°",
318 "Ë›",
319 "Ëť",
320 "¸",
321 "§",
322 "=",
323 "¨",
324 "’",
325 "‘",
326 "”",
327 "“",
328 "„",
329 "´",
330 "—",
331 "–",
332 "Ă—",
333 '&#8217;',
334 "&nbsp;",
335 chr( 194 ) . chr( 160 )
336 ), " ", $str );
337 $str = str_replace( 'Ăź', 'ss', $str );
338 $str = preg_replace( '/[[:space:]]+/', ' ', $str );
339 // Most objects except unicode characters
340 $str = preg_replace( '/[\x00-\x08\x0B\x0C\x0E-\x1F\x80-\x9F]/u', '', $str );
341 // Line feeds, carriage returns, tabs
342 $str = preg_replace( '/[\x00-\x1F\x80-\x9F]/u', '', $str );
343 if ( function_exists( 'mb_strtolower' ) ) {
344 $str = mb_strtolower( $str );
345 } else {
346 $str = strtolower( $str );
347 }
348 $str = preg_replace( '/^[a-z]$/i', "", $str );
349 $str = trim( preg_replace( '/\s+/', ' ', $str ) );
350 $str_array = array_count_values( explode( ' ', $str ) );
351 if ( $stopwords && $str_array && ! empty( $str_array ) ) {
352 $stopwords_array = explode( ',', $stopwords );
353 if ( $stopwords_array && ! empty( $stopwords_array ) ) {
354 $stopwords_array = array_map( 'trim', $stopwords_array );
355 foreach ( $str_array as $str_word => $str_count ) {
356 if ( in_array( $str_word, $stopwords_array ) ) {
357 unset( $str_array[$str_word] );
358 }
359 }
360 }
361 }
362 return $str_array;
363 }
364 /*
365 * Removes scripts, styles, html tags
366 */
367 public function html2txt( $str ) {
368 $search = array(
369 '@<script[^>]*?>.*?</script>@si',
370 '@<[\/\!]*?[^<>]*?>@si',
371 '@<style[^>]*?>.*?</style>@siU',
372 '@<![\s\S]*?--[ \t\n\r]*>@'
373 );
374 $str = preg_replace( $search, '', $str );
375 $str = esc_attr( $str );
376 $str = stripslashes( $str );
377 $str = str_replace( array( "\r", "\n" ), ' ', $str );
378 $str = str_replace( array(
379 "·",
380 "…",
381 "€",
382 "&shy;"
383 ), "", $str );
384 return $str;
385 }
386 /*
387 * Get special characters that must be striped
388 */
389 public function get_special_chars() {
390 $chars = array(
391 '-',
392 '_',
393 '|',
394 '+',
395 '`',
396 '~',
397 '!',
398 '@',
399 '#',
400 '$',
401 '%',
402 '^',
403 '&',
404 '*',
405 '(',
406 ')',
407 '\\',
408 '?',
409 ';',
410 ':',
411 "'",
412 '"',
413 ".",
414 ",",
415 "<",
416 ">",
417 "{",
418 "}",
419 "/",
420 "[",
421 "]",
422 );
423 return apply_filters( 'wp_chatbot_special_chars', $chars );
424 }
425 /*
426 * Get string with current product terms ids
427 *
428 * @return string List of terms ids
429 */
430 private function get_terms_list( $id, $taxonomy ) {
431 $terms = get_the_terms( $id, $taxonomy );
432 if ( is_wp_error( $terms ) ) {
433 return '';
434 }
435 if ( empty( $terms ) ) {
436 return '';
437 }
438 $cats_array_temp = array();
439 foreach ( $terms as $term ) {
440 $cats_array_temp[] = $term->term_id;
441 }
442 return implode( ', ', $cats_array_temp );
443 }
444 /*
445 * Get string with current product terms names
446 *
447 * @return string List of terms names
448 */
449 private function get_terms_names_list( $id, $taxonomy ) {
450 $terms = get_the_terms( $id, $taxonomy );
451 if ( is_wp_error( $terms ) ) {
452 return '';
453 }
454 if ( empty( $terms ) ) {
455 return '';
456 }
457 $cats_array_temp = array();
458 foreach ( $terms as $term ) {
459 $cats_array_temp[] = $term->name;
460 }
461 return implode( ', ', $cats_array_temp );
462 }
463 }
464 endif;
465 new wpwBot_Table();