| 1 | <?php |
|---|
| 2 | /** |
|---|
| 3 | * The MySQL search plugin uses the WordPress "Search API" to enable basic MySQL fulltext searching. |
|---|
| 4 | * @author Justin Shreve <jshreve4@kent.edu> |
|---|
| 5 | * @version 1.1.0 |
|---|
| 6 | */ |
|---|
| 7 | |
|---|
| 8 | /* |
|---|
| 9 | Plugin Name: MySQL FullText Search Plugin |
|---|
| 10 | Plugin URI: http://wordpress.org/ |
|---|
| 11 | Description: MySQL FullText Search functionality for WordPress |
|---|
| 12 | Author: Justin Shreve |
|---|
| 13 | Version: 1.1.0 |
|---|
| 14 | */ |
|---|
| 15 | |
|---|
| 16 | /** |
|---|
| 17 | * MySQL Search |
|---|
| 18 | * Takes information from the search api and uses it to query the search index table. |
|---|
| 19 | * @version 1.1.0 |
|---|
| 20 | */ |
|---|
| 21 | class mysql_search |
|---|
| 22 | { |
|---|
| 23 | /** |
|---|
| 24 | * Results |
|---|
| 25 | * Contains an array of MySQL results from a search |
|---|
| 26 | * @var array a list of results from a search |
|---|
| 27 | */ |
|---|
| 28 | var $results = array(); |
|---|
| 29 | |
|---|
| 30 | /** |
|---|
| 31 | * Flags |
|---|
| 32 | * An array of search parameters |
|---|
| 33 | * @var array search parameters |
|---|
| 34 | */ |
|---|
| 35 | var $flags = array(); |
|---|
| 36 | |
|---|
| 37 | /** |
|---|
| 38 | * Options |
|---|
| 39 | * Options specific to each search plugin. You can enable/disable advanced search, search page filters, pagination and search index support. |
|---|
| 40 | * @var array options to be used by the search api |
|---|
| 41 | */ |
|---|
| 42 | var $options = array( |
|---|
| 43 | 'advanced' => 1, |
|---|
| 44 | 'filters' => 1, |
|---|
| 45 | 'pagination' => 1, |
|---|
| 46 | 'sort' => 1, |
|---|
| 47 | 'index' => 1, |
|---|
| 48 | ); |
|---|
| 49 | |
|---|
| 50 | /** |
|---|
| 51 | * MySQL Search (Constructor) |
|---|
| 52 | * This function passes along the options array to the search api |
|---|
| 53 | */ |
|---|
| 54 | function mysql_search() { |
|---|
| 55 | $this->parent->options =& $this->options; |
|---|
| 56 | } |
|---|
| 57 | |
|---|
| 58 | /** |
|---|
| 59 | * Search |
|---|
| 60 | * This function pulls everything from the API and database together. It loads the pagination function, the filter code, calls the results function and outputs the |
|---|
| 61 | * results. |
|---|
| 62 | * @return string Final search output |
|---|
| 63 | */ |
|---|
| 64 | function search() |
|---|
| 65 | { |
|---|
| 66 | // Query the database and format results |
|---|
| 67 | $total = $this->find_results(); |
|---|
| 68 | |
|---|
| 69 | if( $this->flags['page'] > 1 ) |
|---|
| 70 | $start = intval ( ( ( $this->flags['page'] - 1 ) * get_option( 'posts_per_page' ) ) + 1 ); |
|---|
| 71 | else |
|---|
| 72 | $start = 1; |
|---|
| 73 | |
|---|
| 74 | // Return the results |
|---|
| 75 | if( $total > 0 ) |
|---|
| 76 | { |
|---|
| 77 | // FILTER: search_results_start Starts the results output |
|---|
| 78 | $result_html = apply_filters( 'search_results_start', "<ol class=\"searchresults\" start=\"{$start}\">\n" ); |
|---|
| 79 | |
|---|
| 80 | foreach( $this->results as $results ) { |
|---|
| 81 | // Result is a post |
|---|
| 82 | if( $results->type == "post" ) { |
|---|
| 83 | // FILTER: search_post_result Lets you change a single row for result output |
|---|
| 84 | $result_html .= apply_filters( 'search_post_result', "<li><strong class='result_type'>" . __( 'Post ' ) . "</strong>: <a href=\"" . get_permalink( $results->object ) . "\" class='result_title'>" . $results->title . "</a>\n<p class=\"result_summary\">". $this->parent->trim_excerpt( $results->content ) ."</p></li>" ); |
|---|
| 85 | } |
|---|
| 86 | // Result is a page |
|---|
| 87 | elseif( $results->type == "page" ) { |
|---|
| 88 | // FILTER: search_page_result Lets you change a single row for result output |
|---|
| 89 | $result_html .= apply_filters( 'search_page_result', "<li><strong class='result_type'>" . __( 'Page ' ) . "</strong>: <a href=\"" . get_permalink ( $results->object ) . "\" class='result_title'>" . $results->title . "</a>\n<p class=\"result_summary\">". $this->parent->trim_excerpt( $results->content ) ."</p></li>" ); |
|---|
| 90 | } |
|---|
| 91 | // Result is a comment |
|---|
| 92 | else { |
|---|
| 93 | // FILTER: search_comment_result Lets you change a single row for result output |
|---|
| 94 | $result_html .= apply_filters( 'search_comment_result', "<li><strong class='result_type'>" . __( 'Comment ' ) . "</strong>: <a href=\"" . get_comment_link( $results->object ) . "\" class='result_title'>" . get_the_title( $results->parent ) ."</a>\n<p class=\"result_summary\">" . $this->parent->trim_excerpt( $results->content ) ."</p></li>" ); |
|---|
| 95 | } |
|---|
| 96 | } |
|---|
| 97 | |
|---|
| 98 | // FILTER: search_results_start Ends the results output |
|---|
| 99 | $result_html .= apply_filters( 'search_results_end', "</ol>\n" ); |
|---|
| 100 | } |
|---|
| 101 | |
|---|
| 102 | // No results error |
|---|
| 103 | else { |
|---|
| 104 | // FILTER: search_no_results Allows you to change the error message when no results are returned |
|---|
| 105 | $result_html .= apply_filters( 'search_no_results', "<h2>" . __( ' There are no results for this seach.' ) . "</h2>" ); |
|---|
| 106 | } |
|---|
| 107 | |
|---|
| 108 | // Return the search output |
|---|
| 109 | // FILTER: search_results Allows you to edit the results |
|---|
| 110 | return apply_filters( 'search_results', $this->parent->result_search_box() . $result_html . $this->parent->pagination( $total ) ); |
|---|
| 111 | } |
|---|
| 112 | |
|---|
| 113 | /** |
|---|
| 114 | * Find Results |
|---|
| 115 | * This function is what physically queries the database and does the search using the flags given to us from the search API |
|---|
| 116 | * @global object WordPress Database Abstraction Layer |
|---|
| 117 | * @return int The number of results |
|---|
| 118 | */ |
|---|
| 119 | function find_results() |
|---|
| 120 | { |
|---|
| 121 | global $wpdb; |
|---|
| 122 | |
|---|
| 123 | // Start off our query and our counting of results query |
|---|
| 124 | $start = "SELECT *,MATCH( content,title ) AGAINST( '{$this->flags[string]}') as ranking FROM {$wpdb->prefix}search_index WHERE MATCH ( content,title ) AGAINST('{$this->flags[string]}' IN BOOLEAN MODE) AND protected = '0'"; |
|---|
| 125 | $cstart = "SELECT COUNT(*) as total FROM {$wpdb->prefix}search_index WHERE MATCH ( content,title ) AGAINST('{$this->flags[string]}' IN BOOLEAN MODE) AND protected = '0'"; |
|---|
| 126 | |
|---|
| 127 | // Add in any date flags |
|---|
| 128 | if( !empty( $this->flags['startYear'] ) ) |
|---|
| 129 | $sql .= " AND YEAR(post_date) >= " . $this->flags['startYear']; |
|---|
| 130 | if ( !empty( $this->flags['startMonth'] ) ) |
|---|
| 131 | $sql .= " AND MONTH(post_date) >= " . $this->flags['startMonth']; |
|---|
| 132 | if ( !empty( $this->flags['startDay'] ) ) |
|---|
| 133 | $sql .= " AND DAYOFMONTH(post_date) >= " . $this->flags['startDay']; |
|---|
| 134 | |
|---|
| 135 | if( !empty( $this->flags['endYear'] ) ) |
|---|
| 136 | $sql .= " AND YEAR(post_date) <= " . $this->flags['endYear']; |
|---|
| 137 | if ( !empty( $this->flags['endMonth'] ) ) |
|---|
| 138 | $sql .= " AND MONTH(post_date) <= " . $this->flags['endMonth']; |
|---|
| 139 | if ( !empty( $this->flags['endDay'] ) ) |
|---|
| 140 | $sql .= " AND DAYOFMONTH(post_date) <= " . $this->flags['endDay']; |
|---|
| 141 | |
|---|
| 142 | // add in the author flag |
|---|
| 143 | if( !empty( $this->flags['author'] ) ) |
|---|
| 144 | $sql .= " AND author LIKE '%".$this->flags['author']."%'"; |
|---|
| 145 | |
|---|
| 146 | // keep going and do the category flags |
|---|
| 147 | if( is_array( $this->flags['categories'] ) ) |
|---|
| 148 | { |
|---|
| 149 | $sql .= " AND ("; |
|---|
| 150 | foreach( $this->flags['categories'] as $category ) |
|---|
| 151 | { |
|---|
| 152 | $sql .= " categories LIKE '%,{$category},%' OR "; |
|---|
| 153 | } |
|---|
| 154 | $sql = substr( $sql, 0, -3 ) . ")"; |
|---|
| 155 | } |
|---|
| 156 | |
|---|
| 157 | |
|---|
| 158 | // keep going and do the category flags |
|---|
| 159 | if( is_array( $this->flags['tags'] ) ) |
|---|
| 160 | { |
|---|
| 161 | $sql .= " AND ("; |
|---|
| 162 | foreach( $this->flags['tags'] as $tag ) |
|---|
| 163 | { |
|---|
| 164 | $sql .= " tags LIKE '%,{$tag},%' OR "; |
|---|
| 165 | } |
|---|
| 166 | $sql = substr( $sql, 0, -3 ) . ")"; |
|---|
| 167 | } |
|---|
| 168 | |
|---|
| 169 | |
|---|
| 170 | |
|---|
| 171 | // Figure out what type of data we are looking for |
|---|
| 172 | if( is_array( $this->flags['types'] ) ) { |
|---|
| 173 | if( in_array( 'posts', $this->flags['types'] ) && !in_array( 'pages', $this->flags['types'] ) && !in_array( 'comments', $this->flags['types'] ) ) |
|---|
| 174 | $sql .= " AND type = 'post'"; |
|---|
| 175 | elseif( in_array( 'pages', $this->flags['types'] ) && !in_array( 'posts', $this->flags['types'] ) && !in_array( 'comments', $this->flags['types'] ) ) |
|---|
| 176 | $sql .= " AND type = 'page'"; |
|---|
| 177 | elseif( in_array( 'comments', $this->flags['types'] ) && !in_array( 'posts', $this->flags['types'] ) && !in_array( 'pages', $this->flags['types'] ) ) |
|---|
| 178 | $sql .= " AND type = 'comment'"; |
|---|
| 179 | elseif( in_array( 'posts', $this->flags['types'] ) && in_array( 'pages', $this->flags['types'] ) && !in_array( 'comments', $this->flags['types'] ) ) |
|---|
| 180 | $sql .= " AND (type = 'post' OR type = 'page')"; |
|---|
| 181 | elseif( in_array( 'posts', $this->flags['types'] ) && !in_array( 'pages', $this->flags['types'] ) && in_array( 'comments', $this->flags['types'] ) ) |
|---|
| 182 | $sql .= " AND (type = 'post' OR type = 'comment')"; |
|---|
| 183 | elseif( !in_array( 'posts', $this->flags['types'] ) && in_array( 'pages', $this->flags['types'] ) && in_array( 'comments', $this->flags['types'] ) ) |
|---|
| 184 | $sql .= " AND (type = 'page' OR type = 'comment')"; |
|---|
| 185 | } |
|---|
| 186 | |
|---|
| 187 | // How many results do we have total? |
|---|
| 188 | // FILTER: search_count_find_results Allows you do manage the sql query |
|---|
| 189 | $count = $wpdb->get_results( apply_filters( "search_count_find_results", $cstart . $sql ) ); |
|---|
| 190 | |
|---|
| 191 | // how we are ordering the data |
|---|
| 192 | if( $this->flags['sort'] == "alpha" ) |
|---|
| 193 | $sql .= " ORDER BY title ".$this->flags['sorttype']; |
|---|
| 194 | elseif( $this->flags['sort'] == "date" ) |
|---|
| 195 | $sql .= " ORDER BY post_date ".$this->flags['sorttype']; |
|---|
| 196 | |
|---|
| 197 | // Add in the pagination data for the LIMIT part of the query |
|---|
| 198 | $sql .= " LIMIT " . ( $this->flags['page'] - 1 ) * get_option( 'posts_per_page' ) . ",".get_option('posts_per_page').";"; |
|---|
| 199 | |
|---|
| 200 | // store the results in an array |
|---|
| 201 | // FILTER: search_find_results Allows you do manage the sql query |
|---|
| 202 | $this->results = $wpdb->get_results( apply_filters( "search_find_results", $start . $sql ) ); |
|---|
| 203 | |
|---|
| 204 | // return the total number of results |
|---|
| 205 | return $count[0]->total; |
|---|
| 206 | } |
|---|
| 207 | } |
|---|
| 208 | |
|---|
| 209 | if( function_exists( "do_search_load" ) ) { |
|---|
| 210 | echo '<div id="message" class="updated fade"><p>'; |
|---|
| 211 | _e('You may only have one search plugin using the search api enabled at a time. Please disable the active search plugin first.'); |
|---|
| 212 | echo '</p>'; |
|---|
| 213 | die; |
|---|
| 214 | } |
|---|
| 215 | else { |
|---|
| 216 | /** |
|---|
| 217 | * Search Load |
|---|
| 218 | * This function is ran by a filter in the search API. |
|---|
| 219 | * @return object The search plugin object (the class in this file) |
|---|
| 220 | */ |
|---|
| 221 | function do_search_load() { |
|---|
| 222 | return new mysql_search(); |
|---|
| 223 | } |
|---|
| 224 | } |
|---|
| 225 | |
|---|
| 226 | register_activation_hook( __FILE__, 'mysql_activate_self' ); |
|---|
| 227 | |
|---|
| 228 | /** |
|---|
| 229 | * Activate Self |
|---|
| 230 | * This function refreshes the search index when the plugin is activated |
|---|
| 231 | */ |
|---|
| 232 | function mysql_activate_self() { |
|---|
| 233 | global $index; |
|---|
| 234 | $index->all(); |
|---|
| 235 | update_option( 'searchapi_custom_options', '' ); |
|---|
| 236 | update_option( 'searchapi_help', '' ); |
|---|
| 237 | update_option( 'searchapi_plugin', "search/mysql.php" ); |
|---|
| 238 | } |
|---|
| 239 | |
|---|
| 240 | // Tell the above function to run in the search api |
|---|
| 241 | add_filter('search_load', 'do_search_load' ); |
|---|
| 242 | ?> |
|---|