| 1 | <?php |
|---|
| 2 | /** |
|---|
| 3 | * WordPress API for searching. |
|---|
| 4 | * |
|---|
| 5 | * @package WordPress |
|---|
| 6 | * @subpackage Search |
|---|
| 7 | */ |
|---|
| 8 | |
|---|
| 9 | /** |
|---|
| 10 | * Search API |
|---|
| 11 | * An API that is loaded for search related actions |
|---|
| 12 | * The class contains various functions for outputing to WordPress and doing the necessary legwork for common search functions |
|---|
| 13 | * (pagination, trimming content for display, options and filtering, etc) |
|---|
| 14 | */ |
|---|
| 15 | class WP_Search |
|---|
| 16 | { |
|---|
| 17 | |
|---|
| 18 | var $plugin = NULL; //Reference to the active search plugin |
|---|
| 19 | var $flags = array(); // Array of search parameters |
|---|
| 20 | var $custom_options = array(); // Options array to edit in the admin control panel |
|---|
| 21 | |
|---|
| 22 | /** |
|---|
| 23 | * Constructor |
|---|
| 24 | * This function creates a new filter 'search_load' so that search plugins can call it and load their class object into "$this->plugin". |
|---|
| 25 | */ |
|---|
| 26 | function WP_Search() { |
|---|
| 27 | // Check if the plugin is loaded before we try to load this class to it |
|---|
| 28 | if( $this->plugin == NULL ) { |
|---|
| 29 | $this->plugin = apply_filters( 'search_load', array() ); |
|---|
| 30 | $this->plugin->flags =& $this->create_flags(); |
|---|
| 31 | $this->plugin->parent =& $this; |
|---|
| 32 | } |
|---|
| 33 | |
|---|
| 34 | if( $this->plugin->options['advanced'] == 1 && $_GET['advancedsearch'] == "1" ) |
|---|
| 35 | add_filter( 'template_redirect', array( &$this, 'advanced_search_wrapper' ) ); |
|---|
| 36 | if( $this->plugin->options['advanced'] == 1 ) |
|---|
| 37 | add_filter( 'get_search_form', array( &$this, 'advanced_link' ) ); |
|---|
| 38 | |
|---|
| 39 | $this->custom_options = unserialize( get_option( "searchapi_custom_options" ) ); |
|---|
| 40 | |
|---|
| 41 | /** |
|---|
| 42 | * Config Warning |
|---|
| 43 | * Shows a warning if you need to configure additonal settings |
|---|
| 44 | */ |
|---|
| 45 | function config_warning() { |
|---|
| 46 | echo "<div id='message' class='updated fade'><p><strong>" . __('The search system is almost ready.' ) . "</strong> ".sprintf( __ ( '<a href="%1$s">You must fill out a few additional configuration fields before the search engine can be used.</a>'), "options-general.php?page=search/search.php" ) . "</p></div>"; |
|---|
| 47 | } |
|---|
| 48 | |
|---|
| 49 | // Should we show the above notice? |
|---|
| 50 | if( is_array( $this->custom_options ) && ( count ( $this->custom_options ) > 0 ) ) { |
|---|
| 51 | foreach( $this->custom_options as $setting ) { |
|---|
| 52 | if( $setting['required'] == 1 ) { |
|---|
| 53 | if( ! trim( get_option( $setting['id'] ) ) ) { |
|---|
| 54 | add_action('admin_notices', 'config_warning'); |
|---|
| 55 | break; |
|---|
| 56 | } |
|---|
| 57 | } |
|---|
| 58 | } |
|---|
| 59 | } |
|---|
| 60 | } |
|---|
| 61 | |
|---|
| 62 | |
|---|
| 63 | /** |
|---|
| 64 | * Initialize Search |
|---|
| 65 | * This function overloads the template outputer so that we can replace the content with our search results. We do this so the legacy search template or older search stuff |
|---|
| 66 | * doesn't load instead. This function calls execute_search which does the bulk of the work for this class. |
|---|
| 67 | * @see search_api::execute_search() |
|---|
| 68 | */ |
|---|
| 69 | function init_search() { |
|---|
| 70 | add_filter( 'template_redirect', array( &$this, 'execute_search' ) ); |
|---|
| 71 | } |
|---|
| 72 | |
|---|
| 73 | /** |
|---|
| 74 | * Build Options |
|---|
| 75 | * This function takes a list of custom options a plugin might have (a search api key, a charset string, etc) so that you can edit them from the control panel |
|---|
| 76 | * @param array $options An array of options stored in arrays containing ids, values, titles and descriptions |
|---|
| 77 | */ |
|---|
| 78 | function build_options( $options, $help = '' ) { |
|---|
| 79 | global $wpdb; |
|---|
| 80 | |
|---|
| 81 | foreach( $options as $option ) { |
|---|
| 82 | add_option( esc_attr__ ( $option['id'] ) , esc_attr__ ( $option['value'] ) ); |
|---|
| 83 | } |
|---|
| 84 | |
|---|
| 85 | update_option( "searchapi_custom_options", serialize( $options ) ); |
|---|
| 86 | update_option( "searchapi_help", $wpdb->escape( $help ) ); |
|---|
| 87 | } |
|---|
| 88 | |
|---|
| 89 | /** |
|---|
| 90 | * Options Admin Menu |
|---|
| 91 | * This function creates a menu under "settings" for search settings if the search plugin has any |
|---|
| 92 | */ |
|---|
| 93 | function options_admin_menu() { |
|---|
| 94 | if( is_array ( $this->custom_options ) ) { |
|---|
| 95 | add_options_page ( |
|---|
| 96 | __("Search Settings"), |
|---|
| 97 | __("Search Settings"), |
|---|
| 98 | 'manage_options', |
|---|
| 99 | __FILE__, |
|---|
| 100 | array( &$this, "options_admin_page" ) |
|---|
| 101 | ); |
|---|
| 102 | } |
|---|
| 103 | } |
|---|
| 104 | |
|---|
| 105 | /** |
|---|
| 106 | * Options Admin Page |
|---|
| 107 | * This function takes creates a page for editing search settings |
|---|
| 108 | */ |
|---|
| 109 | function options_admin_page() { |
|---|
| 110 | global $wpdb; |
|---|
| 111 | echo "<div class='wrap'><h2>" . __( "Search Settings " ) . "</h2>"; |
|---|
| 112 | |
|---|
| 113 | if( get_option( 'searchapi_help' ) ) |
|---|
| 114 | echo "<div id='message' class='update fade'>\n" . stripslashes( get_option( 'searchapi_help' ) ) . "</div>\n"; |
|---|
| 115 | |
|---|
| 116 | // Update settings |
|---|
| 117 | if( $_REQUEST['submit'] ) { |
|---|
| 118 | $ok = false; |
|---|
| 119 | |
|---|
| 120 | foreach( $this->custom_options as $option ) { |
|---|
| 121 | if( !empty( $_REQUEST[$option['id']] ) ) { |
|---|
| 122 | update_option( $wpdb->escape( $option['id'] ), $wpdb->escape ( $_REQUEST[$option['id']] ) ); |
|---|
| 123 | $ok = true; |
|---|
| 124 | } |
|---|
| 125 | } |
|---|
| 126 | |
|---|
| 127 | if( $ok == true ) |
|---|
| 128 | echo "<div id='message' class='update fade'><p>" . __("Options Saved") . "</p></div>"; |
|---|
| 129 | else |
|---|
| 130 | echo "<div id='message' class='error fade'><p>" . __("Failed to save options.") . "</p></div>"; |
|---|
| 131 | } |
|---|
| 132 | |
|---|
| 133 | // Display the form |
|---|
| 134 | echo "<form method='post'>\n"; |
|---|
| 135 | |
|---|
| 136 | foreach( $this->custom_options as $option ) { |
|---|
| 137 | echo "<p><label for='{$option['id']}'> " . esc_html__( $option['title'] ) . ": \n"; |
|---|
| 138 | if( !empty( $option['desc'] ) ) |
|---|
| 139 | echo "<br /> " . esc_html__( $option['desc'] ) . "<br />"; |
|---|
| 140 | echo "<input type='text' name='{$option['id']}' value='" . esc_attr__( stripslashes( get_option( $option['id'] ) ) ) ."' /></label></p>"; |
|---|
| 141 | } |
|---|
| 142 | |
|---|
| 143 | echo "<input type='submit' name='submit' class='button-primary' value='Save Settings' /></form>"; |
|---|
| 144 | |
|---|
| 145 | echo "</div>"; |
|---|
| 146 | } |
|---|
| 147 | |
|---|
| 148 | /** |
|---|
| 149 | * Pagination |
|---|
| 150 | * This function takes the total number of results from a set and calculates how many pages is needed to display X (WordPress's posts per page option) results per page. |
|---|
| 151 | * @param int $total The total number of results from a query |
|---|
| 152 | * @return string HTML output containing the pagination links |
|---|
| 153 | */ |
|---|
| 154 | function pagination( $total ) { |
|---|
| 155 | // Only go through the pagination code if the search plugin calls for it |
|---|
| 156 | if( $this->plugin->options['pagination'] == 1 ) { |
|---|
| 157 | |
|---|
| 158 | // Load some required variables such as the total results, the total needed pages and variable place holders. |
|---|
| 159 | if( $total > 0 ) |
|---|
| 160 | $pages = ceil( $total / get_option( 'posts_per_page' ) ); |
|---|
| 161 | |
|---|
| 162 | if( empty ( $_GET['pg'] ) ) |
|---|
| 163 | $_GET['pg'] = 1; |
|---|
| 164 | |
|---|
| 165 | $pages = $pages ? $pages : 1; |
|---|
| 166 | $links = ""; |
|---|
| 167 | |
|---|
| 168 | // Grab the current URL (minus the query string) since search pages can have many query strings |
|---|
| 169 | $current = "http" . ( empty( $_SERVER["HTTPS"] ) ? "": ( $_SERVER["HTTPS"]=='on' ) ? "s": "" )."://" . esc_attr__( $_SERVER["HTTP_HOST"] ) . esc_attr__( $_SERVER["REQUEST_URI"] ); |
|---|
| 170 | $current = preg_replace( "/&pg=([0-9]+)/i", "", $current ); |
|---|
| 171 | |
|---|
| 172 | // Create the previous, next and number links |
|---|
| 173 | if( $_GET['pg'] > 1 ) |
|---|
| 174 | $previous_link = "<span class=\"searchpglink\"><a href=\"".$current."&pg=".($_GET['pg'] - 1)."\"><</a></span> "; |
|---|
| 175 | |
|---|
| 176 | if( $_GET['pg'] < $pages ) |
|---|
| 177 | $next_link = " <span class=\"searchpglink\"><a href=\"".$current."&pg=".($_GET['pg'] + 1)."\">></a></span>"; |
|---|
| 178 | |
|---|
| 179 | if( $pages > 1 ) { |
|---|
| 180 | for( $i = 0, $j = $pages - 1; $i <= $j; ++$i ) { |
|---|
| 181 | $pagenum = $i+1; |
|---|
| 182 | $page = ceil( $pagenum ); |
|---|
| 183 | |
|---|
| 184 | if ( $pagenum < ( $_GET['pg'] - 4 ) ) { |
|---|
| 185 | $i = $_GET['pg'] - 6; |
|---|
| 186 | continue; |
|---|
| 187 | } |
|---|
| 188 | |
|---|
| 189 | if ( $page == $_GET['pg'] ) |
|---|
| 190 | $links .= " <span class=\"searchpgcurrent\">{$page}</span>"; // this is the current page, no need for a link |
|---|
| 191 | else { |
|---|
| 192 | $links .= " <span class=\"searchpglink\"><a href=\"".$current."&pg=".$page."\" title=\"$page\">$page</a></span>"; |
|---|
| 193 | if ( $pagenum > ( $_GET['pg'] + 4 ) ) |
|---|
| 194 | break; |
|---|
| 195 | } |
|---|
| 196 | } |
|---|
| 197 | } |
|---|
| 198 | } |
|---|
| 199 | |
|---|
| 200 | // FILTER: search_pagination Allows you to edit the output of the pagination links |
|---|
| 201 | return apply_filters('search_pagination', $previous_link . $links . $next_link); |
|---|
| 202 | } |
|---|
| 203 | |
|---|
| 204 | /** |
|---|
| 205 | * Advanced Search Wrapper |
|---|
| 206 | * This function creates a "virtual" page which is used to display all the advanced search form HTML. The short code [advsearch] is replaced with output from |
|---|
| 207 | * the advanced_search function here. |
|---|
| 208 | * @see search_api::advanced_search() |
|---|
| 209 | * @global class WordPress DB Abstraction Layer |
|---|
| 210 | */ |
|---|
| 211 | function advanced_search_wrapper() { |
|---|
| 212 | global $wp_query; |
|---|
| 213 | |
|---|
| 214 | // set "the loop" to nothing |
|---|
| 215 | $wp_query->posts = NULL; |
|---|
| 216 | |
|---|
| 217 | // Create a blank "result set" for the wordpress query object |
|---|
| 218 | $object = new stdClass(); |
|---|
| 219 | $object->post_title = __( "Advanced Search" ); |
|---|
| 220 | $object->post_content = "[advsearch]"; |
|---|
| 221 | |
|---|
| 222 | $wp_query->posts[0] = $object; |
|---|
| 223 | |
|---|
| 224 | // replace the advsearch shortcode with the form, and then return the page template |
|---|
| 225 | add_shortcode( 'advsearch', array( &$this, 'advanced_search' ) ); |
|---|
| 226 | |
|---|
| 227 | // Return the template |
|---|
| 228 | $template = get_page_template(); |
|---|
| 229 | |
|---|
| 230 | if ( $template ) |
|---|
| 231 | include $template; |
|---|
| 232 | else |
|---|
| 233 | include(TEMPLATEPATH . "/index.php"); |
|---|
| 234 | |
|---|
| 235 | exit; |
|---|
| 236 | } |
|---|
| 237 | |
|---|
| 238 | /** |
|---|
| 239 | * Advanced Link |
|---|
| 240 | * This function returns a link to the advanced search form. If additonal output is passed to it then that is also returned. |
|---|
| 241 | * @param string $output Output to be returned, usually passed from get_search_form or another WordPress search |
|---|
| 242 | * @return string HTML output containing an advanced search link |
|---|
| 243 | */ |
|---|
| 244 | function advanced_link( $output = '' ) { |
|---|
| 245 | // output usually comes from get_search-form |
|---|
| 246 | if( !empty( $output ) ) |
|---|
| 247 | $html = $output; |
|---|
| 248 | |
|---|
| 249 | // return a link to the advanced search form |
|---|
| 250 | $html .= "<small><a href='index.php?advancedsearch=1'>". __( "Advanced Search" ) . "</a></small>"; |
|---|
| 251 | |
|---|
| 252 | // FILTER: search_advanced_link Allows you to edit the output of the advanced link and the search in the sidebar (using the filter get_search_template) |
|---|
| 253 | return apply_filters('search_advanced_link', $html); |
|---|
| 254 | } |
|---|
| 255 | |
|---|
| 256 | /** |
|---|
| 257 | * Advanced Search |
|---|
| 258 | * This function generates HTML for an avanced search form (author, categories, etc). This function is outputed using a WordPress short code. |
|---|
| 259 | * @return string HTML output for an advanced search form |
|---|
| 260 | */ |
|---|
| 261 | function advanced_search() { |
|---|
| 262 | |
|---|
| 263 | // Content type picker |
|---|
| 264 | $option_output = "<br /> " . __( "Search:" ) ." <input type='checkbox' name='types[]' value='posts' /> " . __( "Posts" ) ." <input type='checkbox' name='types[]' value='pages' /> " . __( "Pages" ) ." <input type='checkbox' name='types[]' value='comments' /> " . __( "Comments " ) ."<br />"; |
|---|
| 265 | |
|---|
| 266 | // author text box |
|---|
| 267 | $author_output .= "<br />" . __( "Author:" ) ." <input type='text' value='' name=\"author\" />"; |
|---|
| 268 | |
|---|
| 269 | // category and tag/taxonomy selector (multiple choice box) |
|---|
| 270 | $tax_output = ""; |
|---|
| 271 | |
|---|
| 272 | foreach( get_object_taxonomies('post') as $taxonomy ) { |
|---|
| 273 | $data = get_taxonomy( $taxonomy ); |
|---|
| 274 | |
|---|
| 275 | if( $data->name == "category" ) |
|---|
| 276 | $tax_output = "<br /> <br /> " . __( "Categories: " ) ."<br /><br />" . str_replace( "name='cat'", "name='cats[]' multiple='multiple' size='10'", wp_dropdown_categories( 'hierarchical=1&echo=0' ) ); |
|---|
| 277 | |
|---|
| 278 | else { |
|---|
| 279 | $terms = get_terms( $data->name ); |
|---|
| 280 | |
|---|
| 281 | if( count ( $terms ) != 0 ) { |
|---|
| 282 | $tax_output .= "<br /> <br /> " . $data->label . "<br /><br /><select name='tags[]' multiple='multiple' size='10'>"; |
|---|
| 283 | foreach( $terms as $term ) { |
|---|
| 284 | $tax_output .= "<option value='".$term->term_id."'>" . $term->name . '</option>'; |
|---|
| 285 | } |
|---|
| 286 | $tax_output .= "</select>"; |
|---|
| 287 | } |
|---|
| 288 | } |
|---|
| 289 | } |
|---|
| 290 | |
|---|
| 291 | // Month Picker, created once and used for start and end dates |
|---|
| 292 | $month_picker = "<option value=''>" . __( 'Select Month' ) . "</option> |
|---|
| 293 | <option value='1'>" . __( 'January' ) . "</option> |
|---|
| 294 | <option value='2'>" . __( 'February' ) . "</option> |
|---|
| 295 | <option value='3'>" . __( 'March' ) . "</option> |
|---|
| 296 | <option value='4'>" . __( 'April' ) . "</option> |
|---|
| 297 | <option value='5'>" . __( 'May' ) . "</option> |
|---|
| 298 | <option value='6'>" . __( 'June' ) . "</option> |
|---|
| 299 | <option value='7'>" . __( 'July' ) . "</option> |
|---|
| 300 | <option value='8'>" . __( 'August' ) . "</option> |
|---|
| 301 | <option value='9'>" . __( 'September' ) . "</option> |
|---|
| 302 | <option value='10'>" . __( 'October' ) . "</option> |
|---|
| 303 | <option value='11'>" . __( 'November' ) . "</option> |
|---|
| 304 | <option value='12'>" . __( 'December' ) . "</option>"; |
|---|
| 305 | |
|---|
| 306 | // Start date dropdowns |
|---|
| 307 | $date_output = "<br /><br />" . __( 'From' ) . "<br /> <select name='startMonth'>{$month_picker}</select> |
|---|
| 308 | <select name='startYear'> <option value=\"\">" . __( 'Select Year' ) . "</option> |
|---|
| 309 | " . str_replace( get_option( "siteurl" ) . "/?m=", "", wp_get_archives( 'type=yearly&format=option&show_post_count=0&echo=0') ) . "</select> |
|---|
| 310 | <select name='startDay'> <option value=\"\">" . __( 'Select Day' ) . "</option>"; |
|---|
| 311 | |
|---|
| 312 | for ( $i = 1; $i <= 31; $i++ ) { |
|---|
| 313 | $date_output .= "<option value='{$i}'>{$i}</option>"; |
|---|
| 314 | } |
|---|
| 315 | |
|---|
| 316 | $date_output .= "</select>"; |
|---|
| 317 | |
|---|
| 318 | // End date dropdowns |
|---|
| 319 | $date_output .= "<br />" . __( 'to' ) . "<br /> <select name='endMonth'>{$month_picker}</select> |
|---|
| 320 | <select name='endYear'> <option value=\"\">" . __( 'Select Year' ) . "</option> |
|---|
| 321 | " . str_replace( get_option( "siteurl" ) . "/?m=", "", wp_get_archives( 'type=yearly&format=option&show_post_count=0&echo=0' ) ) . "</select> |
|---|
| 322 | <select name='endDay'> <option value=\"\">" . __( 'Select Day' ) . "</option>"; |
|---|
| 323 | |
|---|
| 324 | for ( $i = 1; $i <= 31; $i++ ) { |
|---|
| 325 | $date_output .= "<option value='{$i}'>{$i}</option>"; |
|---|
| 326 | } |
|---|
| 327 | |
|---|
| 328 | $date_output .= "</select>"; |
|---|
| 329 | |
|---|
| 330 | // Return the final output |
|---|
| 331 | |
|---|
| 332 | // FILTER: search_advanced Allows you to edit the output of the advanced search page |
|---|
| 333 | return apply_filters( 'search_advanced', "<br /><form method='get' id='result_search_form' action='' style='text-align: left;'> |
|---|
| 334 | <input type='text' value='{$this->flags['string']}' name='s' id='results' size='50' /> |
|---|
| 335 | {$option_output} |
|---|
| 336 | {$author_output} |
|---|
| 337 | {$tax_output} |
|---|
| 338 | {$date_output} |
|---|
| 339 | <p><input type='submit' id='searchsubmit' value='" . __( 'Search' ) . "' /></p> |
|---|
| 340 | </form>" ); |
|---|
| 341 | } |
|---|
| 342 | |
|---|
| 343 | /** |
|---|
| 344 | * Create Flags |
|---|
| 345 | * Cleans up input from the query string and sticks it in an easier to digest format for search plugins |
|---|
| 346 | * @return array An array of search parameters |
|---|
| 347 | */ |
|---|
| 348 | function create_flags() { |
|---|
| 349 | global $wpdb; |
|---|
| 350 | // Clean up and separate the terms |
|---|
| 351 | $this->flags['string'] = $wpdb->escape( $_GET['s'] ); |
|---|
| 352 | preg_match_all( '/".*?("|$)|((?<=[\\s",+])|^)[^\\s",+]+/', $this->flags['string'], $matches ); |
|---|
| 353 | $this->flags['terms'] = array_map( create_function( '$a', 'return trim($a, "\\"\'\\n\\r ");' ), $matches[0] ); |
|---|
| 354 | |
|---|
| 355 | // Clean up the start and end dates |
|---|
| 356 | |
|---|
| 357 | $this->flags['startYear'] = intval( $_GET['startYear'] ); |
|---|
| 358 | $this->flags['startMonth'] = intval( $_GET['startMonth'] ); |
|---|
| 359 | $this->flags['startDay'] = intval( $_GET['startDay'] ); |
|---|
| 360 | |
|---|
| 361 | $this->flags['endYear'] = intval( $_GET['endYear'] ); |
|---|
| 362 | $this->flags['endMonth'] = intval( $_GET['endMonth'] ); |
|---|
| 363 | $this->flags['endDay'] = intval( $_GET['endDay'] ); |
|---|
| 364 | |
|---|
| 365 | // Clean up the author flag |
|---|
| 366 | $this->flags['author'] = $wpdb->escape( $_GET['authors'] ); |
|---|
| 367 | |
|---|
| 368 | // Clean up categories |
|---|
| 369 | if( is_array( $_GET['cats'] ) ) { |
|---|
| 370 | foreach( $_GET['cats'] as $i ) |
|---|
| 371 | $this->flags['categories'][] = intval( $i ); |
|---|
| 372 | } |
|---|
| 373 | |
|---|
| 374 | // Clean up tags |
|---|
| 375 | if( is_array( $_GET['tags'] ) ) { |
|---|
| 376 | foreach( $_GET['tags'] as $i ) |
|---|
| 377 | $this->flags['tags'][] = intval( $i ); |
|---|
| 378 | } |
|---|
| 379 | |
|---|
| 380 | // Clean up the content types (all, posts, pages, comments) |
|---|
| 381 | if( is_array( $_GET['types'] ) ) { |
|---|
| 382 | foreach( $_GET['types'] as $i ) { |
|---|
| 383 | $this->flags['types'][] = $wpdb->escape( $i ); |
|---|
| 384 | } |
|---|
| 385 | } |
|---|
| 386 | |
|---|
| 387 | // Build our sort by/order by flag |
|---|
| 388 | $this->flags['sort'] = "relevance"; |
|---|
| 389 | if( $_GET['sort'] == "date" ) |
|---|
| 390 | $this->flags['sort'] = "date"; |
|---|
| 391 | elseif( $_GET['sort'] == "alpha" ) |
|---|
| 392 | $this->flags['sort'] = "alpha"; |
|---|
| 393 | |
|---|
| 394 | |
|---|
| 395 | // Decide ascending or decesnding |
|---|
| 396 | $this->flags['sorttype'] = "DESC"; |
|---|
| 397 | if( $_GET['sorttype'] == "ASC" ) |
|---|
| 398 | $this->flags['sorttype'] = "ASC"; |
|---|
| 399 | |
|---|
| 400 | // decie which page we are on |
|---|
| 401 | $this->flags['page'] = 1; |
|---|
| 402 | if( !empty( $_GET['pg'] ) ) |
|---|
| 403 | $this->flags['page'] = intval( $_GET['pg'] ); |
|---|
| 404 | |
|---|
| 405 | // return a mass array of all the flags/query strings |
|---|
| 406 | // FILTER: search_flags Allows you to make any changes to the search flags array |
|---|
| 407 | return apply_filters( 'search_flags', $this->flags ); |
|---|
| 408 | } |
|---|
| 409 | |
|---|
| 410 | |
|---|
| 411 | /** |
|---|
| 412 | * Result Search Box |
|---|
| 413 | * This function generates HTML for options to be displayed on a search result page. This includes options for filtering by type, reordering results and an |
|---|
| 414 | * advanced search link |
|---|
| 415 | * @return string HTML output for the various form controls |
|---|
| 416 | */ |
|---|
| 417 | function result_search_box( ) { |
|---|
| 418 | $output = ""; |
|---|
| 419 | |
|---|
| 420 | // Return filters if the feature is enabled. flters are for filtering by content type (posts, pages, comments) |
|---|
| 421 | if( $this->plugin->options['filters'] == 1 ) { |
|---|
| 422 | $option_output = "<br />"; |
|---|
| 423 | |
|---|
| 424 | if( is_array( $this->flags['types'] ) ) { |
|---|
| 425 | if( in_array( 'posts', $this->flags['types'] ) ) |
|---|
| 426 | $checked['post'] = ' checked="checked"'; |
|---|
| 427 | |
|---|
| 428 | if( in_array( 'pages', $this->flags['types'] ) ) |
|---|
| 429 | $checked['page'] = ' checked="checked"'; |
|---|
| 430 | |
|---|
| 431 | if( in_array( 'comments', $this->flags['types'] ) ) |
|---|
| 432 | $checked['comment'] = ' checked="checked"'; |
|---|
| 433 | } |
|---|
| 434 | |
|---|
| 435 | // all three types are searched at once |
|---|
| 436 | else { |
|---|
| 437 | $checked['post'] = ' checked="checked"'; |
|---|
| 438 | $checked['page'] = ' checked="checked"'; |
|---|
| 439 | $checked['comment'] = ' checked="checked"'; |
|---|
| 440 | } |
|---|
| 441 | |
|---|
| 442 | // Find the current url for use within javascript (the switch sort and switch sort type dropdowns) |
|---|
| 443 | $current_url = "http" . ( empty( $_SERVER["HTTPS"] ) ? "": ( $_SERVER["HTTPS"]=='on' ) ? "s": "" )."://" . ( $_SERVER["HTTP_HOST"] ) . ( $_SERVER["REQUEST_URI"] ); |
|---|
| 444 | |
|---|
| 445 | |
|---|
| 446 | // Start building the options output |
|---|
| 447 | $option_output .= __( 'Search Only:' ) . "<input type='checkbox' name='types[]' value='posts'{$checked['post']} /> " . __( 'Posts' ) . " |
|---|
| 448 | <input type='checkbox' name='types[]' value='pages'{$checked['page']}/> " . __( 'Pages ' ) . " |
|---|
| 449 | <input type='checkbox' name='types[]' value='comments'{$checked['comment']} /> " . __( 'Comments ') . "<br />"; |
|---|
| 450 | } |
|---|
| 451 | |
|---|
| 452 | if( $this->plugin->options['sort'] == 1 ) { |
|---|
| 453 | |
|---|
| 454 | // Decide which sort flag is chosen |
|---|
| 455 | if( $this->flags['sort'] == "date" ) |
|---|
| 456 | $checked['date'] = ' selected="selected"'; |
|---|
| 457 | elseif( $this->flags['sort'] == "alpha" ) |
|---|
| 458 | $checked['alpha'] = ' selected="selected"'; |
|---|
| 459 | elseif( $this->flags['sort'] == "relevance" ) |
|---|
| 460 | $checked['relevance'] = ' selected="selected"'; |
|---|
| 461 | |
|---|
| 462 | // Decide which sort type flag is chosen |
|---|
| 463 | if( $this->flags['sorttype'] == "ASC" ) |
|---|
| 464 | $checked['ASC'] = ' selected="selected"'; |
|---|
| 465 | elseif( $this->flags['sorttype'] == "DESC" ) |
|---|
| 466 | $checked['DESC'] = ' selected="selected"'; |
|---|
| 467 | |
|---|
| 468 | // Start building the options output |
|---|
| 469 | $option_output .= "<script type='text/javascript'> |
|---|
| 470 | function switchSort(value) { |
|---|
| 471 | document.location.href = '" . preg_replace( "/&sort=([A-Za-z]+)/i", "", $current_url ) . "'+'&sort='+value; |
|---|
| 472 | } |
|---|
| 473 | |
|---|
| 474 | function switchSortType(value) { |
|---|
| 475 | document.location.href = '" . preg_replace( "/&sorttype=([A-Za-z]+)/i", "", $current_url ) . "'+'&sorttype='+value; |
|---|
| 476 | } |
|---|
| 477 | </script> |
|---|
| 478 | |
|---|
| 479 | <br /><div style='text-align: right;'>" . __( 'Order results by:' ) . " |
|---|
| 480 | |
|---|
| 481 | <select name='sort' onChange='switchSort(this.options[this.selectedIndex].value);'>\n |
|---|
| 482 | <option value='relevance'{$checked['relevance']}>" . __( 'Relevance' ) . "</option> |
|---|
| 483 | <option value='date'{$checked['date']}>" . __( 'Date' ) . "</option> |
|---|
| 484 | <option value='alpha'{$checked['alpha']}>" . __( 'Alphabetical' ) . "</option> |
|---|
| 485 | </select> |
|---|
| 486 | |
|---|
| 487 | <select name='sorttype' onChange='switchSortType(this.options[this.selectedIndex].value);'>\n |
|---|
| 488 | <option value='ASC'{$checked['ASC']}>" . __( 'Ascending' ) . "</option> |
|---|
| 489 | <option value='DESC'{$checked['DESC']}>" . __( 'Descending' ) . "</option> |
|---|
| 490 | </select></div>"; |
|---|
| 491 | |
|---|
| 492 | } |
|---|
| 493 | |
|---|
| 494 | if( $this->plugin->options['advanced'] == 1 ) |
|---|
| 495 | $advanced = $this->advanced_link(); |
|---|
| 496 | |
|---|
| 497 | // Result Box Output |
|---|
| 498 | $output = "<br /><form method='get' id='resultsearchform' action='' style='text-align: left;'> |
|---|
| 499 | <input type='text' value='" . esc_attr( apply_filters( 'the_search_query', get_search_query() ) ) . "' name='s' id='results' /> |
|---|
| 500 | <input type='submit' id='searchsubmit' value='" . __( 'Search' ) . "' /> |
|---|
| 501 | {$advanced} |
|---|
| 502 | {$option_output} |
|---|
| 503 | </form>"; |
|---|
| 504 | |
|---|
| 505 | // FILTER: search_result_box Allows you to make changes to the filter/order box above the search results |
|---|
| 506 | return apply_filters( 'search_result_box', $output ); |
|---|
| 507 | } |
|---|
| 508 | |
|---|
| 509 | /** |
|---|
| 510 | * Trim Excerpt |
|---|
| 511 | * If a line of text is longer then $chars characters this functon shortens a line of text and returns it with $end at the end. If a line of text is shorter the whole |
|---|
| 512 | * thing is returned. |
|---|
| 513 | * @param string $content The text to shorten |
|---|
| 514 | * @param int $chars The amount of characters to start shortening content at |
|---|
| 515 | * @param string $end The characters to append to the end of the shortend text |
|---|
| 516 | * @return string The shortend text with appended characters OR full already short text |
|---|
| 517 | */ |
|---|
| 518 | function trim_excerpt( $content, $chars = 150, $end = "..." ) { |
|---|
| 519 | $content = substr( strip_tags( trim( $content ) ), 0, $chars ); |
|---|
| 520 | $content = substr( $content, 0, strrpos( $content, ' ' ) ) . $end; |
|---|
| 521 | apply_filters( 'the_excerpt', $content ); |
|---|
| 522 | return $content; |
|---|
| 523 | } |
|---|
| 524 | |
|---|
| 525 | /** |
|---|
| 526 | * Execute Search |
|---|
| 527 | * This function creates a virtual page and then replaces a shortcode [search] with output from another search plugin (the plugin's search() function). This function also |
|---|
| 528 | * outputs all final HTML to the browser for search results. |
|---|
| 529 | * @global class WordPress's DB Abstraction Class |
|---|
| 530 | * @global class WordPress query object (from wp-includes/query.php). used for overloading "the loop" to display in a page. |
|---|
| 531 | */ |
|---|
| 532 | function execute_search() { |
|---|
| 533 | global $wpdb, $wp_query; |
|---|
| 534 | |
|---|
| 535 | // Default the loop to nothing since we are trying to overload the page template |
|---|
| 536 | $wp_query->posts = NULL; |
|---|
| 537 | |
|---|
| 538 | // Try to load the search page which SHOULD contain the short code [search] |
|---|
| 539 | $wp_query->posts = $wpdb->get_results( "SELECT * from {$wpdb->prefix}posts WHERE post_type = 'page' and post_title = 'search'" ); |
|---|
| 540 | |
|---|
| 541 | // Create a virtual page if the search page does not exist |
|---|
| 542 | if( empty( $wp_query->posts[0] ) ) { |
|---|
| 543 | $object = new stdClass(); |
|---|
| 544 | $object->post_title = __( "Search" ); |
|---|
| 545 | $object->post_content = "[search]"; |
|---|
| 546 | $wp_query->posts[0] = $object; |
|---|
| 547 | } |
|---|
| 548 | |
|---|
| 549 | // Parse the shortodes for the loop |
|---|
| 550 | add_shortcode( 'search', array( $this->plugin, 'search' ) ); |
|---|
| 551 | |
|---|
| 552 | // Return the template |
|---|
| 553 | // Return the template |
|---|
| 554 | $template = get_page_template(); |
|---|
| 555 | |
|---|
| 556 | if ( $template ) |
|---|
| 557 | include $template; |
|---|
| 558 | else |
|---|
| 559 | include(TEMPLATEPATH . "/index.php"); |
|---|
| 560 | |
|---|
| 561 | exit; |
|---|
| 562 | } |
|---|
| 563 | |
|---|
| 564 | } |
|---|
| 565 | |
|---|
| 566 | // END SEARCH API |
|---|
| 567 | |
|---|
| 568 | // BEGIN SEARCH INDEX CLASS |
|---|
| 569 | |
|---|
| 570 | /** |
|---|
| 571 | * Search Index |
|---|
| 572 | * This class contains a set of fucntions for "refreshing" (updating) the search index when a piece of content is changed in WordPress. |
|---|
| 573 | * The purpose is to only need to search one table instead of 3+ for different pieces of content, have a standard set of data and make it easier for |
|---|
| 574 | * search libraries like Sphinx to read. |
|---|
| 575 | * @verson 1.0.0 |
|---|
| 576 | */ |
|---|
| 577 | class search_index { |
|---|
| 578 | |
|---|
| 579 | function search_index() { |
|---|
| 580 | add_filter( 'delete_post', array( &$this, 'delete_post' ) ); |
|---|
| 581 | add_filter( 'delete_comment', array( &$this, 'delete_comment' ) ); |
|---|
| 582 | add_filter( 'save_post', array( &$this, 'save_post' ) ); |
|---|
| 583 | add_filter( 'comment_post', array( &$this, 'comment_post' ) ); |
|---|
| 584 | add_filter( 'edit_comment', array( &$this, 'edit_comment' ) ); |
|---|
| 585 | add_filter( 'wp_set_comment_status', array( &$this, 'edit_comment' ) ); |
|---|
| 586 | } |
|---|
| 587 | /** |
|---|
| 588 | * Delete Post |
|---|
| 589 | * This function is ran when a post or a page is deleted from WordPress. The post or page is then also removed from being searched. |
|---|
| 590 | * This function can be hooked into with the hook 'refreshed_search_index' |
|---|
| 591 | * @param int $id The id of the post or page being deleted |
|---|
| 592 | * @global object WordPress Database Abstraction Layer |
|---|
| 593 | */ |
|---|
| 594 | function delete_post( $id ) { |
|---|
| 595 | global $wpdb; |
|---|
| 596 | $wpdb->query( "DELETE FROM {$wpdb->prefix}search_index WHERE type = 'post' OR type = 'page' AND object = '" . $wpdb->escape( $id ) . "'" ); |
|---|
| 597 | do_action( 'refreshed_search_index' ); |
|---|
| 598 | } |
|---|
| 599 | |
|---|
| 600 | /** |
|---|
| 601 | * Delete Comment |
|---|
| 602 | * This function is ran when a comment is deleted from WordPress. The comment is then also removed from being searched. |
|---|
| 603 | * This function can be hooked into with the hook 'refreshed_search_index' |
|---|
| 604 | * @param int $id The id of the comment being deleted |
|---|
| 605 | * @global object WordPress Database Abstraction Layer |
|---|
| 606 | */ |
|---|
| 607 | function delete_comment( $id ) { |
|---|
| 608 | global $wpdb; |
|---|
| 609 | $wpdb->query( "DELETE FROM {$wpdb->prefix}search_index WHERE type = 'comment' AND object = '" . intval( $id ) . "'" ); |
|---|
| 610 | do_action( 'refreshed_search_index' ); |
|---|
| 611 | } |
|---|
| 612 | |
|---|
| 613 | /** |
|---|
| 614 | * Save Post |
|---|
| 615 | * This function is ran when a page or post is saved or created in WordPress. The data or changed data is then made avaiable for searching. |
|---|
| 616 | * This function can be hooked into with the hook 'refreshed_search_index' |
|---|
| 617 | * @param int $id The id of the page or post |
|---|
| 618 | * @global object WordPress Database Abstraction Layer |
|---|
| 619 | */ |
|---|
| 620 | function save_post( $id ) { |
|---|
| 621 | global $wpdb; |
|---|
| 622 | |
|---|
| 623 | $post = $wpdb->get_results ( "SELECT * from {$wpdb->prefix}posts WHERE ID = '" . intval( $id ) . "'" ); |
|---|
| 624 | |
|---|
| 625 | // print_r($post); |
|---|
| 626 | if( $post[0]->post_type != "revision" ) |
|---|
| 627 | { |
|---|
| 628 | $type = $post[0]->post_type; |
|---|
| 629 | |
|---|
| 630 | // Do we have an index for this (are we updating?) or are we creating |
|---|
| 631 | $idx = $wpdb->get_results( "SELECT * from {$wpdb->prefix}search_index WHERE object = '" . intval( $post[0]->ID ) . "' AND ( type = 'post' OR type='page' ) " ); |
|---|
| 632 | |
|---|
| 633 | // Build a string of categories and tags that this object belongs to |
|---|
| 634 | |
|---|
| 635 | $cats = ","; |
|---|
| 636 | $tags = ","; |
|---|
| 637 | |
|---|
| 638 | $terms = $wpdb->get_results( "SELECT r.term_taxonomy_id,t.taxonomy,r.object_id from $wpdb->term_relationships r LEFT JOIN $wpdb->term_taxonomy t ON(t.term_taxonomy_id=r.term_taxonomy_id) WHERE r.object_id = '" . intval( $post[0]->ID ) . "'" ); |
|---|
| 639 | |
|---|
| 640 | foreach( $terms as $term ) { |
|---|
| 641 | if( $term->taxonomy == "category" ) |
|---|
| 642 | $cats .= intval( $term->term_taxonomy_id ) . ","; |
|---|
| 643 | else |
|---|
| 644 | $tags .= intval( $term->term_taxonomy_id ) . ","; |
|---|
| 645 | } |
|---|
| 646 | |
|---|
| 647 | // Find which author created this object |
|---|
| 648 | $authors = $wpdb->get_results( "SELECT display_name FROM $wpdb->users WHERE ID = '" . intval( $post[0]->post_author ) ."'" ); |
|---|
| 649 | $author = $authors[0]->display_name; |
|---|
| 650 | |
|---|
| 651 | // Can this item be searched yet? |
|---|
| 652 | if( $post[0]->post_status == "publish" && empty( $post[0]->post_password ) ) |
|---|
| 653 | $protected = "0"; |
|---|
| 654 | else |
|---|
| 655 | $protected = "1"; |
|---|
| 656 | |
|---|
| 657 | // update |
|---|
| 658 | if( !empty( $idx[0]->id ) ) { |
|---|
| 659 | $wpdb->query( "UPDATE {$wpdb->prefix}search_index SET title = '" . $wpdb->escape( $post[0]->post_title ) . "', content = '" . $wpdb->escape( $post[0]->post_content ) . "', post_date = '" . $wpdb->escape( $post[0]->post_date ) . "', parent = '', categories = '" . $wpdb->escape ( $cats ) . "', tags = '" . $wpdb->escape( $tags ) . "', author = '" . $wpdb->escape ( $author ) . "', type = '" . $wpdb->escape( $type ) . "', protected = '" . $wpdb->escape ( $protected ) . "' WHERE object = '" . intval( $post[0]->ID ) . "'" ); |
|---|
| 660 | } |
|---|
| 661 | |
|---|
| 662 | // create new |
|---|
| 663 | else { |
|---|
| 664 | $wpdb->query( "INSERT INTO {$wpdb->prefix}search_index (object, title, content, post_date, parent, categories, tags, author, type, protected) |
|---|
| 665 | VALUES ( |
|---|
| 666 | '" . intval( $id ) . "', '" . $wpdb->escape( $post[0]->post_title ) . "', '" . $wpdb->escape( $post[0]->post_content ) . "', '" . $wpdb->escape( $post[0]->post_date ) . "', '0', '" . $wpdb->escape( $cat ) . "', '" . $wpdb->escape( $tags ) . "', '" . $wpdb->escape( $author ) . "', '" . $wpdb->escape( $type ) . "', '" . $wpdb->escape( $protected ) . "' |
|---|
| 667 | );" ); |
|---|
| 668 | |
|---|
| 669 | } |
|---|
| 670 | do_action( 'refreshed_search_index' ); |
|---|
| 671 | } |
|---|
| 672 | } |
|---|
| 673 | |
|---|
| 674 | /** |
|---|
| 675 | * Comment Post |
|---|
| 676 | * This function is ran when a comment is made on a post in WordPress. The comment is made avaiable for searching. |
|---|
| 677 | * This function can be hooked into with the hook 'refreshed_search_index' |
|---|
| 678 | * @param int $id The id of the of the comment |
|---|
| 679 | * @global object WordPress Database Abstraction Layer |
|---|
| 680 | */ |
|---|
| 681 | function comment_post( $id ) { |
|---|
| 682 | global $wpdb; |
|---|
| 683 | |
|---|
| 684 | // Load the comment |
|---|
| 685 | $comment = $wpdb->get_results( "SELECT * from {$wpdb->prefix}comments WHERE comment_ID = '" . intval( $id ) . "'" ); |
|---|
| 686 | |
|---|
| 687 | // Load the straight post data |
|---|
| 688 | $post = $wpdb->get_results( "SELECT * from {$wpdb->prefix}posts WHERE ID = '" . intval( $comment[0]->comment_post_ID ) . "'" ); |
|---|
| 689 | |
|---|
| 690 | // Load a string of the cats the comment is in |
|---|
| 691 | $cat = ","; |
|---|
| 692 | $cats = $wpdb->get_results( "SELECT term_taxonomy_id from $wpdb->term_relationships WHERE object_id = '" . intval( $comment[0]->comment_post_ID ) . "'" ); |
|---|
| 693 | |
|---|
| 694 | foreach( $cats[0] as $catz ) { |
|---|
| 695 | $cat .= $catz.","; |
|---|
| 696 | } |
|---|
| 697 | |
|---|
| 698 | // Can we search this comment? |
|---|
| 699 | if( $comment[0]->comment_approved == 1 ) |
|---|
| 700 | $protected = 0; |
|---|
| 701 | else |
|---|
| 702 | $protected = 1; |
|---|
| 703 | |
|---|
| 704 | // create the index entry |
|---|
| 705 | $wpdb->query( "INSERT INTO {$wpdb->prefix}search_index (object, title, content, post_date, parent, categories, author, type, protected) |
|---|
| 706 | VALUES ( |
|---|
| 707 | '" . intval( $comment[0]->comment_ID ) . "', '', '" . $wpdb->escape( $comment[0]->comment_content ) . "', '" . $wpdb->escape( $comment[0]->comment_date ) . "', '". intval( $post[0]->ID ) ."', '" . $wpdb->escape( $cat ) . "', '" . $wpdb->escape( $comment[0]->comment_author ) . "', 'comment', '" . $wpdb->escape( $protected ) . "' |
|---|
| 708 | );" ); |
|---|
| 709 | |
|---|
| 710 | do_action( 'refreshed_search_index' ); |
|---|
| 711 | } |
|---|
| 712 | |
|---|
| 713 | |
|---|
| 714 | /** |
|---|
| 715 | * Edit Comment |
|---|
| 716 | * This function is ran when a comment is changed. The updated comment is made avaiable for searching. |
|---|
| 717 | * This function can be hooked into with the hook 'refreshed_search_index' |
|---|
| 718 | * @param int $id The id of the of the comment |
|---|
| 719 | * @param string $status The status of the comment (closed, etc) |
|---|
| 720 | * @global object WordPress Database Abstraction Layer |
|---|
| 721 | */ |
|---|
| 722 | function edit_comment( $id, $status = '' ) { |
|---|
| 723 | global $wpdb; |
|---|
| 724 | |
|---|
| 725 | // Load the comment data |
|---|
| 726 | $comment = $wpdb->get_results( "SELECT * from {$wpdb->prefix}comments WHERE comment_ID = '" . intval( $id ) . "'" ); |
|---|
| 727 | |
|---|
| 728 | // Load the post data for this comment |
|---|
| 729 | $post = $wpdb->get_results( "SELECT * from {$wpdb->prefix}posts WHERE ID = '" . intval( $comment[0]->comment_post_ID ) . "'" ); |
|---|
| 730 | |
|---|
| 731 | // Load a string of the categories the comment is in |
|---|
| 732 | $cat = ","; |
|---|
| 733 | $cats = $wpdb->get_results( "SELECT term_taxonomy_id from $wpdb->term_relationships WHERE object_id = '". intval( $post[0]->ID ) . "'" ); |
|---|
| 734 | |
|---|
| 735 | if( is_array( $cats[0] ) ) |
|---|
| 736 | { |
|---|
| 737 | foreach( $cats[0] as $catz ) { |
|---|
| 738 | $cat .= $catz->term_taxonomy_id.","; |
|---|
| 739 | } |
|---|
| 740 | } |
|---|
| 741 | |
|---|
| 742 | // see if we can search this comment |
|---|
| 743 | if( $comment[0]->comment_approved ) |
|---|
| 744 | $protected = 0; |
|---|
| 745 | else |
|---|
| 746 | $protected = 1; |
|---|
| 747 | |
|---|
| 748 | // update the entry |
|---|
| 749 | $wpdb->query( "UPDATE {$wpdb->prefix}search_index SET title = '', content = '" . $wpdb->escape( $comment[0]->comment_content ) . "', post_date = '" . $wpdb->escape( $comment[0]->comment_date ) . "', parent = '" . intval( $post[0]->ID ) . "', categories = '" . $wpdb->escape( $cat ) . "', author = '" . $wpdb->escape( $comment[0]->comment_author ) . "', protected = '" . $wpdb->escape( $protected ) . "' WHERE object = '" . intval( $id ) . "' AND type = 'comment'" ); |
|---|
| 750 | |
|---|
| 751 | do_action( 'refreshed_search_index' ); |
|---|
| 752 | } |
|---|
| 753 | |
|---|
| 754 | /** |
|---|
| 755 | * Refresh All |
|---|
| 756 | * This function is database resource intensive. It clears out the entire search index and rebuilds it. |
|---|
| 757 | * This function can be hooked into with the hook 'refreshed_search_index' |
|---|
| 758 | * @global object WordPress Database Abstraction Layer |
|---|
| 759 | */ |
|---|
| 760 | function all() { |
|---|
| 761 | global $wpdb; |
|---|
| 762 | |
|---|
| 763 | // delete the current index |
|---|
| 764 | $wpdb->query( "DELETE FROM {$wpdb->prefix}search_index" ); |
|---|
| 765 | |
|---|
| 766 | // Load all the posts and pages stored within WordPress |
|---|
| 767 | $posts = $wpdb->get_results( "SELECT * from {$wpdb->prefix}posts" ); |
|---|
| 768 | |
|---|
| 769 | foreach( $posts as $post ) { |
|---|
| 770 | // don't search revisions |
|---|
| 771 | if( $post->post_type == "page" || $post->post_type == "post" ) { |
|---|
| 772 | |
|---|
| 773 | // Build a string of categories and tags that this object belongs to |
|---|
| 774 | $cats = ","; |
|---|
| 775 | $tags = ","; |
|---|
| 776 | |
|---|
| 777 | $terms = $wpdb->get_results( "SELECT r.term_taxonomy_id,t.taxonomy,r.object_id from $wpdb->term_relationships r LEFT JOIN $wpdb->term_taxonomy t ON(t.term_taxonomy_id=r.term_taxonomy_id) WHERE r.object_id = '" . intval( $post->ID ) . "'" ); |
|---|
| 778 | |
|---|
| 779 | foreach( $terms as $term ) { |
|---|
| 780 | if( $term->taxonomy == "category" ) |
|---|
| 781 | $cats .= intval( $term->term_taxonomy_id ) . ","; |
|---|
| 782 | else |
|---|
| 783 | $tags .= intval( $term->term_taxonomy_id ) . ","; |
|---|
| 784 | } |
|---|
| 785 | |
|---|
| 786 | // find the author |
|---|
| 787 | $authors = $wpdb->get_results( "SELECT display_name FROM $wpdb->users WHERE ID = '" . intval( $post->post_author ) . "'" ); |
|---|
| 788 | $author = $authors[0]->display_name; |
|---|
| 789 | |
|---|
| 790 | // Can we search this item? |
|---|
| 791 | if( $post->post_status == "publish" && empty( $post->post_password ) ) |
|---|
| 792 | $protected = "0"; |
|---|
| 793 | else |
|---|
| 794 | $protected = "1"; |
|---|
| 795 | |
|---|
| 796 | // Create the entry in the search index |
|---|
| 797 | $wpdb->query( "INSERT INTO {$wpdb->prefix}search_index (object, title, content, post_date, parent, categories, tags, author, type, protected) |
|---|
| 798 | VALUES ( |
|---|
| 799 | '". intval( $post->ID ) . "', '" . $wpdb->escape( $post->post_title ) . "', '" . $wpdb->escape( $post->post_content ) . "', '" . $wpdb->escape( $post->post_date ) . "', '0', '" . $wpdb->escape( $cats ) . "', '" . $wpdb->escape( $tags ) . "', '" . $wpdb->escape( $author ) . "', '" . $wpdb->escape( $post->post_type ) . "', '" . $wpdb->escape( $protected ) . "' |
|---|
| 800 | );" ); |
|---|
| 801 | |
|---|
| 802 | do_action( 'refreshed_search_index' ); |
|---|
| 803 | } |
|---|
| 804 | } |
|---|
| 805 | |
|---|
| 806 | // Load up the comments for insertion now |
|---|
| 807 | $comments = $wpdb->get_results( "SELECT * from {$wpdb->prefix}comments" ); |
|---|
| 808 | |
|---|
| 809 | foreach($comments as $comment) { |
|---|
| 810 | // load the post data |
|---|
| 811 | $post = $wpdb->get_results( "SELECT * from {$wpdb->prefix}posts WHERE ID = '" . intval( $comment->comment_post_ID ) . "'" ); |
|---|
| 812 | |
|---|
| 813 | // load a string of categories that the comment is in |
|---|
| 814 | $cat = ","; |
|---|
| 815 | $cats = $wpdb->get_results( "SELECT term_taxonomy_id from $wpdb->term_relationships WHERE object_id = '" . intval( $comment->comment_post_ID ) . "'" ); |
|---|
| 816 | |
|---|
| 817 | foreach( $cats as $catz ) { |
|---|
| 818 | $cat .= intval( $catz->term_taxonomy_id ) . ","; |
|---|
| 819 | } |
|---|
| 820 | |
|---|
| 821 | // is the comment searchable |
|---|
| 822 | if( $comment->comment_approved ) |
|---|
| 823 | $protected = 0; |
|---|
| 824 | else |
|---|
| 825 | $protected = 1; |
|---|
| 826 | |
|---|
| 827 | // create the search index row |
|---|
| 828 | $wpdb->query( "INSERT INTO {$wpdb->prefix}search_index (object, title, content, post_date, parent, categories, author, type, protected) |
|---|
| 829 | VALUES ( |
|---|
| 830 | '" . intval( $comment->comment_ID ) . "', '', '" . $wpdb->escape( $comment->comment_content ) . "', '" . $wpdb->escape( $comment->comment_date ) . "', '" . intval( $post[0]->ID ) . "', '" . $wpdb->escape( $cat ) . "', '" . $wpdb->escape( $comment->comment_author ) . "', 'comment', '" . $wpdb->escape( $protected ) . "' |
|---|
| 831 | );" ); |
|---|
| 832 | } |
|---|
| 833 | |
|---|
| 834 | } |
|---|
| 835 | } |
|---|
| 836 | // END SEARCH INDEX |
|---|
| 837 | |
|---|
| 838 | function load_search_api() { |
|---|
| 839 | global $wpsearch; |
|---|
| 840 | $wpsearch = new WP_Search(); |
|---|
| 841 | add_action( 'admin_menu', array( &$wpsearch, 'options_admin_menu' ) ); |
|---|
| 842 | } |
|---|
| 843 | |
|---|
| 844 | if ( ! isset($wpsearch) ) { |
|---|
| 845 | add_action( 'plugins_loaded', 'load_search_api' ); |
|---|
| 846 | } |
|---|
| 847 | |
|---|
| 848 | |
|---|
| 849 | // Load the search index and have WordPress call the functions if we have indexing enabled |
|---|
| 850 | if( $wpsearch->plugin->options['index'] == 1 ) |
|---|
| 851 | $index = new search_index(); |
|---|
| 852 | |
|---|
| 853 | ?> |
|---|