cache = array(); } /** * Search for the user query * * 1. Sanitize the string * 2. Strip stop words * 3. Fetch the posts using the new string * * @since 1.0.0 * @param string $q The phrase to search for */ public function search( $q ){ global $wpdb; //Is it in the cache? If (array_key_exists( $q, $this->cache )){ return $this->cache[$q]; } $s = $wpdb->prepare('%s', $q); $post_ids = apply_filters( 'als_found_post_ids', $this->posts_with( $s, $q ), $s); if (!is_array($post_ids)){ $post_ids = array(); } if( 3 < strlen($s)){ $this->log_query( $s, count($post_ids)); } $this->cache[$s] = $post_ids; return $post_ids; } /** * Uses MySQL's fulltext to search for posts containing the search string * * * @since 1.0.0 * @param string $s sanitised string to search for * @param string $q unsanitised string to search for * @return array with ids of posts arranged according to relevance */ private function posts_with( $s ){ global $wpdb; $posts = array(); $post_types = array_unique(als_index_post_types()); $title_weight = intval(get_option('als_title_weight',15)); $content_weight = intval(get_option('als_content_weight',1)); $q = $wpdb->prepare('%s', als_remove_punct(als_remove_modifiers($s))); $order_by = 'post__in'; $order = 'ORDER BY score DESC'; $score_field = "(((MATCH(post_title) AGAINST($q) * $title_weight) + (MATCH(post_title,post_content) AGAINST($q) * $content_weight)) + (IF(comment_count = 0, 0, log(comment_count)+0.5)) + (log(DATEDIFF(NOW(), post_modified)+1)) "; // Weight based on post types $score_field .= '+('; foreach($post_types as $type){ $type = strtolower($type); $weight = "als_{$type}_weight"; $weight = get_option($weight, 1); $score_field .= "((post_type IN('$type'))*$weight)+"; } $score_field .= '0)) as score'; //Simple way to take care of final + //Filter by post type $new_array = array(); foreach( $post_types as $type ){ $new_array[] = "'$type'"; } $post_types = implode(',', $new_array); $restrictions = "WHERE MATCH(post_title, post_content) AGAINST ($q IN BOOLEAN MODE) "; $restrictions .= "AND post_type in($post_types) AND post_status='publish'"; //The final sql statement $sql = "SELECT ID, $score_field FROM {$wpdb->posts} $restrictions ORDER BY score DESC LIMIT 100"; $results = $wpdb->query($sql); $results = $wpdb->last_result; //Here is a workaround(for the time being) foreach($results as $single){ $posts[] = $single->ID; } return $posts; } /** * Save the search term with its results * * * @since 1.0.0 * @param string $s array of words * @param int $count number of results */ private function log_query( $s, $count = 0 ){ global $wpdb; $searches_log_table = $wpdb->prefix . "als_log"; $count = intval($count); $modified = $wpdb->prepare("(%s)", als_remove_punct(als_remove_modifiers($s))); $original = $wpdb->prepare("(%s)", $s); $exists = "SELECT searches as searches FROM $searches_log_table WHERE LOWER(query)=LOWER($original)"; $exists = $wpdb->get_results($exists); if(count($exists) < 1) { $sql = "INSERT IGNORE INTO $searches_log_table (query, modified, hits) VALUES ($original, $modified,$count)"; return $wpdb->query($sql); } else { $searches = intval($exists[0]->searches) + 1; $sql = "UPDATE $searches_log_table SET searches=$searches, hits=$count WHERE LOWER(query)=LOWER($original)"; return $wpdb->query($sql); } } }