prefix . 'als_log'; $response = $wpdb->get_col( "SELECT modified FROM $table WHERE LOWER(modified) LIKE LOWER('$q%') LIMIT $count"); if( !is_array($response) ){ $response = array(); } return $response; } /** * Fetch query suggestions from post titles * * * @param $q the user query that should be used to fetch suggestions * @param $count the number of suggestions to fetch * * @since 2.3.3 * * @return array */ function als_post_titles_suggest( $q='',$count = 5 ) { global $wpdb; $response= $wpdb->get_col( "SELECT post_title FROM $wpdb->posts WHERE LOWER(post_title) LIKE LOWER('$q%') AND post_status='publish' LIMIT $count"); if( !is_array($response) ){ $response = array("No suggestions"); } return $response; } /** * Checks whether or not we should use custom snippets * * @since 1.0.0 * @return bool */ function als_use_custom_snippets() { return ( get_option('als_custom_excerpt', 'yes') == 'yes' // Has the user enabled custom snippets && isset( $_GET['s'] ) // Are we on the search page && is_main_query() // Is this the main query && in_the_loop() // Are we in the loop ); } /** * Highlights a search snippet * * @since 1.0.0 * @return string */ function als_snippet_highlight( $text, $words ) { foreach( $words as $word ) { $text=preg_replace("/($word)(?![^<]*>)/i", "\${1}", $text); } return $text; } /** * Finds the locations of the words in a snippet * * @since 1.0.0 * @return array */ function als_word_locations( $text, $words ) { $locations = array(); foreach ($words as $word) { $wordlen = strlen($word); $loc = stripos( $text, $word); while ( $loc !== false ) { $locations[] = $loc; $loc = stripos( $text, $word, $loc + $wordlen); } } $locations = array_unique($locations); sort( $locations ); return $locations; } /** * Finds the locations of the words in a snippet * * @since 1.0.0 * @return array */ function als_snippet_location( $word_positions = array() ) { $radius = als_snippet_radius(); $words_in_radius = 0; $best_radius = array( 0, $radius * 2 ); $start_pos = 0; $end_post = $radius * 2; if (! is_array( $word_positions ) ) $word_positions = array(); if (!isset($word_positions[0])) return $best_radius; //Loop through all words to extract the best word range foreach ( $word_positions as $position ) { //Fetch possible ranges for this word position $ranges = als_word_ranges( $position ); //Get the best position $best_range = als_best_range( $ranges, $word_positions ); //Check if its better than what we currently have if ( $best_range[0] > $words_in_radius ) { $words_in_radius = $best_range[0]; $best_radius = $best_range[1]; } } return $best_radius; } /** * Gets best range from a group of ranges * * @since 1.0.0 * @return array */ function als_best_range( $ranges, $word_positions ) { $words_in_range = 0; $best_range = $ranges[0]; foreach ( $ranges as $range ) { $start = $range[0]; $end = $range[1]; $range = range( $start, $end ); $_words_in_range = count ( array_intersect( $word_positions, $range) ); if ( $_words_in_range > $words_in_range ) { $words_in_range = $_words_in_range; $best_range = array($start, $end); } } return array( $words_in_range, $best_range ); } /** * Gets possible word ranges * * @since 1.0.0 * @return array */ function als_word_ranges( $position ) { $radius = als_snippet_radius(); $half_radius = ceil($radius / 2); $ranges = array( array ( $position - $radius, $position + $radius), array ( $position - $half_radius, $position + $radius + $half_radius), array ( $position - $half_radius - $radius, $position + $half_radius), ); //Make sure no start range is less than 0 if ( $ranges[0][0] < 0) { $ranges[0][1] = $ranges[0][1] + $radius -$position ; $ranges[0][0] = 0; } if ( $ranges[1][0] < 0) { $ranges[1][1] = $ranges[1][1] + $half_radius -$position; $ranges[1][0] = 0; } if ( $ranges[2][0] < 0) { $ranges[2][1] = $ranges[2][1] + $half_radius + $radius -$position; $ranges[2][0] = 0; } return $ranges; } /** * Gets radius of a search snippet * * @since 1.0.0 * @return array */ function als_snippet_radius() { $radius = ceil( absint (get_option('als_excerpt_length', 200) / 2)); if( $radius < strlen( $_GET['s'] ) ) return strlen( $_GET['s'] ); //Radius should not be less than the search term return $radius; } /** * Extracts a snippet from text * * @since 1.0.0 * @return array */ function als_extract_snippet( $content='', $words=array(), $radius = 60 ) { $snippet = false; $word_locations = als_word_locations( $content, $words ); $snippet_location = als_snippet_location( $word_locations ); $snippet = substr($content,$snippet_location[0] , $snippet_location[1]) . '...'; //If no word was found in the content... if( !$snippet ) $snippet = substr( $content, 0, $radius * 2 ); return $snippet; } /** * Extracts a snippet from text * * @since 1.0.0 * @return array */ function als_content_to_snippet( $content, $query ) { //Convert search term to individual words and sort them $s_words = als_tokenize( $query ); $s2_words = als_prepare( $query ); $words = array_unique ( array_merge( $s_words, $s2_words)); $content = do_shortcode( $content ); //Strip html tags $content = wp_strip_all_tags ($content, true); //Radius of our snippet $radius = als_snippet_radius(); //Extract the snippet $excerpt = als_extract_snippet( $content, $words, $radius ); //If we are not highlighting; return our excerpt if ( get_option('als_highlight_term', 'yes') != 'yes'){ return $excerpt; } return als_snippet_highlight( $excerpt, $words ); } /** * Provides ajax search results * * @param $q The query to crawl for * * @since 1.0.0 * * @return array containing post title, url, link, and excerpt */ function als_get_ajax_results($q) { global $post; if(!$q){ return; } //Get a list of matching post ids $results = als_search($q); $args = array( 'numberposts' => 10, 'post_type' => array_unique(als_index_post_types()), ); if ( count($results) > 0 ){ $args['include'] = $results; $args['orderby'] = 'post__in'; } else { $args['s'] = $q; } $posts = get_posts( $args ); $return = array(); foreach ($posts as $_post ){ //Assign this post to the global post object setup_postdata($_post); $post = $_post; //Prepare the return fields $return[] = array( 'title' => get_the_title(), 'ID' => get_the_ID(), 'url' => get_permalink(), 'snippet' => '', ); } return $return; } /** * Clean variables using sanitize_text_field. * @param string|array $var text to be cleaned * @return string|array * @ since 1.0.0 */ function als_clean( $var ) { return is_array( $var ) ? array_map( 'als_clean', $var ) : sanitize_text_field( $var ); } /** * Validates the array type search filters * * @param $array the array to validate * * @return bool true on validate or false on invalid value * @ since 2.0.0 **/ function als_is_array( $array ) { if(is_array($array) AND count($array)!=0) { return true; } return false; } /** * Validates the string filters for searches * * @param $array the array to validate * * @return bool true on validate or false on invalid value * @ since 2.0.0 **/ function als_is_string( $string ) { if(!is_null($string) AND strlen($string) !=0) { return true; } return false; } /** * Get's a given search modifier from a search term * * @param $modifier the modifier eg intittle: * @param $q the query * * @return bool true on validate or false on invalid value * @ since 2.0.0 **/ function als_query_modifier( $modifier, $q ) { // the value to be modified starts with a quote, we use it as our delimeter // Otherwise, we use spaces as delimiters $is_quoted = false; $start = stripos($q, $modifier); $regex = $modifier . '([\'"]{1})'; $q = stripslashes($q); //Took me 4 hours to realise that the query has been escaped with slashes if($start === false){ return false; // end early to save resources } else if(preg_match("/$regex/i", $q, $matches)){ $is_quoted = true; $quote=$matches[1]; } $regex = '/\b' . $modifier . '(.+?)\s/i'; //captures the value assigned to a modifier if($is_quoted){ $regex = '/\b' . $modifier . $quote . '(.+?)' . $quote .'/i'; //captures a quoted value assigned to a modifier } $q .= ' ';//To accomodate the space (\s) in the first regex if(preg_match($regex , $q, $matches)) return $matches[1]; return false; } /** * Removes modifiers from a search query * * @param $q the query * * @return bool true on validate or false on invalid value * @ since 2.0.0 **/ function als_remove_modifiers( $q ) { $modifiers = apply_filters('als_remove_modifiers', array("+", "-", "~", "<", ">", "*", "author_in:", "author:", "author_not_in:", "cat:", "category:", "tagged:", "post_types:", "before:", "after:")); return str_ireplace($modifiers, '', $q); } /** * Returns a list of stopwords * * * @return array * @ since 2.3.3 **/ function als_get_stopwords( ) { //Als instance $als_instance = als_lite_instance(); $stop_words = file_get_contents($als_instance->includes_path . 'stopwords.txt'); $stop_words = strtolower(als_remove_punct($stop_words)); return explode(' ', $stop_words); } //Removes stopwords from a list of words function als_remove_stopwords( $words ){ return array_diff( $words, als_get_stopwords() ); } /** * Returns how many seconds/mins/hours/days/weeks/months ago * * * @param $past an earlier date * @param $current the later date, defaults to now() * * @since 1.0.0 * * @return array */ function als_date_diff($past, $current=false) { if(!$current){ $current=date('Y-m-d h:i:s'); } $past = strtotime($past); $current = strtotime($current); $diff = abs($past - $current); if ($diff<60) { Return ($diff . __(' Seconds ago.', 'als')); } if ($diff>=60 && $diff<(60*60)) { $diff = ceil($diff / 60); Return ($diff . __(' Minutes ago.', 'als')); } if ($diff>=(60*60) && $diff<(60*60*24)) { $diff = ceil($diff / (60*60)); Return ($diff . __(' Hours ago.', 'als')); } if ($diff>=(60*60*24) && $diff<(60*60*24*7)) { $diff = ceil($diff / (60*60*24)); Return ($diff . __(' Days ago.', 'als')); } if ($diff>=(60*60*24*7) && $diff<(60*60*24*7*4)) { $diff = ceil($diff / (60*60*24*7)); Return ($diff . __(' Weeks ago.', 'als')); } if ($diff>=(60*60*24*7*4) && $diff<(60*60*24*7*4*12)) { $diff = ceil($diff / (60*60*24*7*4)); Return ($diff . __(' Months ago.', 'als')); } $diff = ceil($diff / (60*60*24*7*4*12)); Return ($diff . __(' Years ago.', 'als')); } /** * Fetches the registered post types * * @param $array whether to return an array or string. Set true to return an array * @since 1.0.0 * * @return array/string */ function als_post_types( $array=false ) { $args = array( 'exclude_from_search' => false, 'public' => true, ); $post_types = get_post_types($args); if(!$array) { return (implode(', ', $post_types)); } return $post_types; } //Stems a word function als_stem( $word ) { return ALS_PorterStemmer::Stem($word); } //Prepares a string for indexing / searching function als_prepare( $text ){ //Get a list of words $words = als_tokenize( $text ); //Remove stopwords $words = als_remove_stopwords( $words ); //Stem the words and return return array_map( 'als_stem', $words ); } //Tokenizes a string into words function als_tokenize( $text ){ return explode( ' ', als_normalize( $text ) ); } //Nomarlizes a string function als_normalize( $text ){ //Remove accents $text = remove_accents( $text ); //Convert to lowecase $text = strtolower( $text ); //Delete non alphanumeric characters except spaces //$text = preg_replace( '/^\da-z ]', '', $text ); Some languages dont use alphanumeric chars //Remove punctutions and return return als_remove_punct( $text ); } //Removes punctuations function als_remove_punct($a) { if (!is_string($a)) return ""; // In case something sends a non-string here. $a = preg_replace ('/<[^>]*>/', ' ', $a); $a = str_replace("\r", '', $a); // --- replace with empty space $a = str_replace("\n", ' ', $a); // --- replace with space $a = str_replace("\t", ' ', $a); // --- replace with space $a = stripslashes($a); $a = str_replace('ß', 'ss', $a); $a = str_replace("·", ' ', $a); $a = str_replace("…", ' ', $a); $a = str_replace("€", '', $a); $a = str_replace("­", '', $a); $a = str_replace(chr(194) . chr(160), ' ', $a); $a = str_replace(" ", ' ', $a); $a = str_replace('’', ' ', $a); $a = str_replace("'", '', $a); $a = str_replace("’", ' ', $a); $a = str_replace("‘", ' ', $a); $a = str_replace("”", ' ', $a); $a = str_replace("“", ' ', $a); $a = str_replace("„", ' ', $a); $a = str_replace("´", ' ', $a); $a = str_replace("—", ' ', $a); $a = str_replace("–", ' ', $a); $a = str_replace("×", ' ', $a); $a = preg_replace('/[[:punct:]]+/u', ' ', $a); $a = preg_replace('/[[:space:]]+/', ' ', $a); $a = trim($a); return $a; } //Runs a search and returns matching ids function als_search( $q ){ $instance = als_lite_instance(); $search_engine = $instance->search; return $search_engine->search( $q ); }