Relevanssi – A Better Search - Version 3.5.9

Version Description

  • Improved the way highlighting handles HTML tags, especially when highlighting on post pages.
  • The throttle limit setting was removed from the settings page for causing trouble. If you need to change it, update relevanssi_throttle_limit option directly.
  • Relevanssi didn't support tax_queries with field set to name. That works now.
  • Much faster way of showing the 25 most common words in the index. If you've disabled this feature because it was so slow, try enabling it - you might be surprised!
Download this release

Release Info

Developer msaari
Plugin Icon 128x128 Relevanssi – A Better Search
Version 3.5.9
Comparing to
See all releases

Code changes from version 3.5.8 to 3.5.9

lib/common.php CHANGED
@@ -740,4 +740,16 @@ function relevanssi_strlen($s) {
740
  return strlen( $s );
741
  }
742
 
 
 
 
 
 
 
 
 
 
 
 
 
743
  ?>
740
  return strlen( $s );
741
  }
742
 
743
+ /* If WP_CLI is available, print out the debug notice as a WP_CLI::log(), otherwise
744
+ * just echo.
745
+ */
746
+ function relevanssi_debug_echo($s) {
747
+ if ( defined( 'WP_CLI' ) && WP_CLI ) {
748
+ WP_CLI::log($s);
749
+ }
750
+ else {
751
+ echo $s . "\n";
752
+ }
753
+ }
754
+
755
  ?>
lib/excerpts-highlights.php CHANGED
@@ -25,6 +25,7 @@ function relevanssi_do_excerpt($t_post, $query) {
25
  remove_shortcode('layerslider');
26
  remove_shortcode('responsive-flipbook');
27
  remove_shortcode('breadcrumb');
 
28
 
29
  $content = apply_filters('relevanssi_pre_excerpt_content', $post->post_content, $post, $query);
30
  $content = apply_filters('the_content', $content);
@@ -194,7 +195,8 @@ function relevanssi_highlight_in_docs($content) {
194
  // Local search
195
  if (isset($query['s'])) {
196
  $q = relevanssi_add_synonyms($query['s']);
197
- $highlighted_content = relevanssi_highlight_terms($content, $q);
 
198
  if (!empty($highlighted_content)) $content = $highlighted_content;
199
  // Sometimes the content comes back empty; until I figure out why, this tries to be a solution.
200
  }
@@ -208,7 +210,7 @@ function relevanssi_highlight_in_docs($content) {
208
  return $content;
209
  }
210
 
211
- function relevanssi_highlight_terms($excerpt, $query) {
212
  $type = get_option("relevanssi_highlight");
213
  if ("none" == $type) {
214
  return $excerpt;
@@ -336,11 +338,7 @@ function relevanssi_highlight_terms($excerpt, $query) {
336
  }
337
 
338
  $excerpt = relevanssi_remove_nested_highlights($excerpt, $start_emp_token, $end_emp_token);
339
-
340
- /*
341
- $excerpt = htmlentities($excerpt, ENT_QUOTES, 'UTF-8');
342
- // return the HTML entities that were stripped before
343
- */
344
 
345
  $excerpt = str_replace($start_emp_token, $start_emp, $excerpt);
346
  $excerpt = str_replace($end_emp_token, $end_emp, $excerpt);
@@ -359,6 +357,61 @@ function relevanssi_replace_punctuation($a) {
359
  return $a;
360
  }
361
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
362
  function relevanssi_remove_nested_highlights($s, $a, $b) {
363
  $offset = 0;
364
  $string = "";
25
  remove_shortcode('layerslider');
26
  remove_shortcode('responsive-flipbook');
27
  remove_shortcode('breadcrumb');
28
+ remove_shortcode('maxmegamenu');
29
 
30
  $content = apply_filters('relevanssi_pre_excerpt_content', $post->post_content, $post, $query);
31
  $content = apply_filters('the_content', $content);
195
  // Local search
196
  if (isset($query['s'])) {
197
  $q = relevanssi_add_synonyms($query['s']);
198
+ $in_docs = true;
199
+ $highlighted_content = relevanssi_highlight_terms($content, $q, $in_docs);
200
  if (!empty($highlighted_content)) $content = $highlighted_content;
201
  // Sometimes the content comes back empty; until I figure out why, this tries to be a solution.
202
  }
210
  return $content;
211
  }
212
 
213
+ function relevanssi_highlight_terms($excerpt, $query, $in_docs = false) {
214
  $type = get_option("relevanssi_highlight");
215
  if ("none" == $type) {
216
  return $excerpt;
338
  }
339
 
340
  $excerpt = relevanssi_remove_nested_highlights($excerpt, $start_emp_token, $end_emp_token);
341
+ $excerpt = relevanssi_fix_entities($excerpt, $in_docs);
 
 
 
 
342
 
343
  $excerpt = str_replace($start_emp_token, $start_emp, $excerpt);
344
  $excerpt = str_replace($end_emp_token, $end_emp, $excerpt);
357
  return $a;
358
  }
359
 
360
+ function relevanssi_fix_entities($excerpt, $in_docs) {
361
+ if (!$in_docs) {
362
+ // For excerpts, use htmlentities()
363
+ $excerpt = htmlentities($excerpt, ENT_QUOTES, 'UTF-8');
364
+
365
+ // Except for allowed tags, which are turned back into tags.
366
+ $tags = get_option('relevanssi_excerpt_allowable_tags', '');
367
+ $tags = trim(str_replace("<", " <", $tags));
368
+ $tags = explode(" ", $tags);
369
+ $tags = relevanssi_generate_closing_tags($tags);
370
+
371
+ $tags_entitied = htmlentities(implode(" ", $tags), ENT_QUOTES, 'UTF-8');
372
+ $tags_entitied = explode(" ", $tags_entitied);
373
+
374
+ $excerpt = str_replace($tags_entitied, $tags, $excerpt);
375
+ }
376
+ else {
377
+ // Running htmlentities() for whole posts tends to ruin things.
378
+ // However, we want to run htmlentities() for anything inside
379
+ // <pre> and <code> tags.
380
+ $excerpt = relevanssi_entities_inside($excerpt, "code");
381
+ $excerpt = relevanssi_entities_inside($excerpt, "pre");
382
+ }
383
+ return $excerpt;
384
+ }
385
+
386
+ function relevanssi_entities_inside($excerpt, $tag) {
387
+ $hits = preg_match_all('/<' . $tag . '>(.*?)<\/' . $tag . '>/im', $excerpt, $matches);
388
+ if ($hits > 0) {
389
+ $replacements = array();
390
+ foreach ($matches[1] as $match) {
391
+ if (!empty($match)) $replacements[] = "<xxx" . $tag . ">" . htmlentities($match, ENT_QUOTES, 'UTF-8') . "</xxx" . $tag . ">";
392
+ }
393
+ if (!empty($replacements)) {
394
+ for ($i = 0; $i < count($replacements); $i++) {
395
+ $patterns[] = "/<" . $tag . ">(.*?)<\/" . $tag . ">/im";
396
+ }
397
+ $excerpt = preg_replace($patterns, $replacements, $excerpt, 1);
398
+ }
399
+ $excerpt = str_replace("xxx" . $tag, $tag, $excerpt);
400
+ }
401
+ return $excerpt;
402
+ }
403
+
404
+ function relevanssi_generate_closing_tags($tags) {
405
+ $closing_tags = array();
406
+ foreach ($tags as $tag) {
407
+ $a = str_replace("<", "</", $tag);
408
+ $b = str_replace(">", "/>", $tag);
409
+ $closing_tags[] = $a;
410
+ $closing_tags[] = $b;
411
+ }
412
+ return array_merge($tags, $closing_tags);
413
+ }
414
+
415
  function relevanssi_remove_nested_highlights($s, $a, $b) {
416
  $offset = 0;
417
  $string = "";
lib/indexing.php CHANGED
@@ -1,6 +1,6 @@
1
  <?php
2
 
3
- function relevanssi_build_index($extend = false) {
4
  if (function_exists('wp_suspend_cache_addition'))
5
  wp_suspend_cache_addition(true); // Thanks to Julien Mession
6
 
@@ -13,6 +13,7 @@ function relevanssi_build_index($extend = false) {
13
  $types = get_option("relevanssi_index_post_types");
14
  if (!is_array($types)) $types = array();
15
  foreach ($types as $type) {
 
16
  array_push($post_types, "'$type'");
17
  }
18
 
@@ -41,7 +42,7 @@ function relevanssi_build_index($extend = false) {
41
 
42
  if (!$extend) {
43
  // truncate table first
44
- $wpdb->query("TRUNCATE TABLE $relevanssi_table");
45
 
46
  if (function_exists('relevanssi_index_taxonomies')) {
47
  if (get_option('relevanssi_index_taxonomies') == 'on') {
@@ -55,6 +56,13 @@ function relevanssi_build_index($extend = false) {
55
  }
56
  }
57
 
 
 
 
 
 
 
 
58
  $q = "SELECT post.ID
59
  FROM $wpdb->posts post
60
  LEFT JOIN $wpdb->posts parent ON (post.post_parent=parent.ID)
@@ -67,13 +75,17 @@ function relevanssi_build_index($extend = false) {
67
  OR (post.post_parent=0)
68
  )
69
  ))
70
- $restriction";
71
 
72
  update_option('relevanssi_index', '');
73
  }
74
  else {
75
  // extending, so no truncate and skip the posts already in the index
76
  $limit = get_option('relevanssi_index_limit', 200);
 
 
 
 
77
  if (is_numeric($limit) && $limit > 0) {
78
  $size = $limit;
79
  $limit = " LIMIT $limit";
@@ -105,26 +117,40 @@ function relevanssi_build_index($extend = false) {
105
  do_action('relevanssi_pre_indexing_query');
106
  $content = $wpdb->get_results($q);
107
 
 
108
  foreach ($content as $post) {
109
- $n += relevanssi_index_doc($post->ID, false, $custom_fields, true);
110
- // n calculates the number of insert queries
 
111
  // $bypassglobalpost set to true, because at this point global $post should be NULL, but in some cases it is not
 
 
112
  }
 
113
 
114
  $wpdb->query("ANALYZE TABLE $relevanssi_table");
115
  // To prevent empty indices
116
 
117
- echo '<div id="message" class="updated fade"><p>'
118
- . __((($size == 0) || (count($content) < $size)) ? "Indexing complete!" : "More to index...", "relevanssi")
119
- . '</p></div>';
 
 
 
 
 
 
 
120
  update_option('relevanssi_indexed', 'done');
121
 
122
- // We always want to run this on init, if the index is finishd building.
123
  $D = $wpdb->get_var("SELECT COUNT(DISTINCT(relevanssi.doc)) FROM $relevanssi_table AS relevanssi");
124
  update_option( 'relevanssi_doc_count', $D);
125
 
126
  if (function_exists('wp_suspend_cache_addition'))
127
  wp_suspend_cache_addition(false); // Thanks to Julien Mession
 
 
128
  }
129
 
130
  // BEGIN modified by renaissancehack
@@ -142,7 +168,7 @@ function relevanssi_build_index($extend = false) {
142
  - Quick edit:
143
  global $post is an array, $indexpost is the ID of current revision.
144
  */
145
- function relevanssi_index_doc($indexpost, $remove_first = false, $custom_fields = false, $bypassglobalpost = false) {
146
  global $wpdb, $post, $relevanssi_variables;
147
  $relevanssi_table = $relevanssi_variables['relevanssi_table'];
148
  $post_was_null = false;
@@ -185,7 +211,7 @@ function relevanssi_index_doc($indexpost, $remove_first = false, $custom_fields
185
  // At this point we should have something in $post; if not, quit.
186
  if ($post_was_null) $post = null;
187
  if ($previous_post) $post = $previous_post;
188
- return;
189
  }
190
 
191
  // Finally fetch the post again by ID. Complicated, yes, but unless we do this, we might end
@@ -194,9 +220,10 @@ function relevanssi_index_doc($indexpost, $remove_first = false, $custom_fields
194
 
195
  if (function_exists('relevanssi_hide_post')) {
196
  if (relevanssi_hide_post($post->ID)) {
 
197
  if ($post_was_null) $post = null;
198
  if ($previous_post) $post = $previous_post;
199
- return;
200
  }
201
  }
202
 
@@ -209,6 +236,7 @@ function relevanssi_index_doc($indexpost, $remove_first = false, $custom_fields
209
 
210
  if (true == apply_filters('relevanssi_do_not_index', false, $post->ID)) {
211
  // filter says no
 
212
  $index_this_post = false;
213
  }
214
 
@@ -218,6 +246,7 @@ function relevanssi_index_doc($indexpost, $remove_first = false, $custom_fields
218
  if (function_exists('relevanssi_remove_item')) {
219
  relevanssi_remove_item($post->ID, 'post');
220
  }
 
221
  }
222
 
223
  // This needs to be here, after the call to relevanssi_remove_doc(), because otherwise
@@ -225,7 +254,7 @@ function relevanssi_index_doc($indexpost, $remove_first = false, $custom_fields
225
  if (!$index_this_post) {
226
  if ($post_was_null) $post = null;
227
  if ($previous_post) $post = $previous_post;
228
- return;
229
  }
230
 
231
  $n = 0;
@@ -237,11 +266,13 @@ function relevanssi_index_doc($indexpost, $remove_first = false, $custom_fields
237
 
238
  //Added by OdditY - INDEX COMMENTS of the POST ->
239
  if ("none" != get_option("relevanssi_index_comments")) {
 
240
  $pcoms = relevanssi_get_comments($post->ID);
241
  if ($pcoms != "") {
242
  $pcoms = relevanssi_strip_invisibles($pcoms);
243
  $pcoms = preg_replace('/<[a-zA-Z\/][^>]*>/', ' ', $pcoms);
244
  $pcoms = strip_tags($pcoms);
 
245
  $pcoms = relevanssi_tokenize($pcoms, true, $min_word_length);
246
  if (count($pcoms) > 0) {
247
  foreach ($pcoms as $pcom => $count) {
@@ -257,6 +288,7 @@ function relevanssi_index_doc($indexpost, $remove_first = false, $custom_fields
257
 
258
  // Then process all taxonomies, if any.
259
  foreach ($taxonomies as $taxonomy) {
 
260
  $insert_data = relevanssi_index_taxonomy_terms($post, $taxonomy, $insert_data);
261
  }
262
 
@@ -265,6 +297,7 @@ function relevanssi_index_doc($indexpost, $remove_first = false, $custom_fields
265
  $auth = $post->post_author;
266
  $display_name = $wpdb->get_var("SELECT display_name FROM $wpdb->users WHERE ID=$auth");
267
  $names = relevanssi_tokenize($display_name, false, $min_word_length);
 
268
  foreach($names as $name => $count) {
269
  isset($insert_data[$name]['author']) ? $insert_data[$name]['author'] += $count : $insert_data[$name]['author'] = $count;
270
  }
@@ -280,6 +313,7 @@ function relevanssi_index_doc($indexpost, $remove_first = false, $custom_fields
280
  }
281
  $custom_fields = apply_filters('relevanssi_index_custom_fields', $custom_fields);
282
  if (is_array($custom_fields)) {
 
283
  $custom_fields = array_unique($custom_fields); // no reason to index duplicates
284
  foreach ($custom_fields as $field) {
285
  if ($remove_underscore_fields) {
@@ -291,6 +325,8 @@ function relevanssi_index_doc($indexpost, $remove_first = false, $custom_fields
291
  // Quick hack : allow indexing of PODS relationship custom fields // TMV
292
  if (is_array($value) && isset($value['post_title'])) $value = $value['post_title'];
293
  relevanssi_index_acf($insert_data, $post->ID, $field, $value);
 
 
294
  $value_tokens = relevanssi_tokenize($value, true, $min_word_length);
295
  foreach ($value_tokens as $token => $count) {
296
  isset($insert_data[$token]['customfield']) ? $insert_data[$token]['customfield'] += $count : $insert_data[$token]['customfield'] = $count;
@@ -304,6 +340,7 @@ function relevanssi_index_doc($indexpost, $remove_first = false, $custom_fields
304
  }
305
 
306
  if (isset($post->post_excerpt) && ("on" == get_option("relevanssi_index_excerpt") || "attachment" == $post->post_type)) { // include excerpt for attachments which use post_excerpt for captions - modified by renaissancehack
 
307
  $excerpt_tokens = relevanssi_tokenize($post->post_excerpt, true, $min_word_length);
308
  foreach ($excerpt_tokens as $token => $count) {
309
  isset($insert_data[$token]['excerpt']) ? $insert_data[$token]['excerpt'] += $count : $insert_data[$token]['excerpt'] = $count;
@@ -311,14 +348,17 @@ function relevanssi_index_doc($indexpost, $remove_first = false, $custom_fields
311
  }
312
 
313
  if (function_exists('relevanssi_index_mysql_columns')) {
 
314
  $insert_data = relevanssi_index_mysql_columns($insert_data, $post->ID);
315
  }
316
 
317
  $index_titles = true;
318
  if (!empty($post->post_title)) {
319
  if (apply_filters('relevanssi_index_titles', $index_titles)) {
 
320
  $filtered_title = apply_filters('relevanssi_post_title_before_tokenize', $post->post_title, $post);
321
  $titles = relevanssi_tokenize(apply_filters('the_title', $filtered_title, $post->ID), apply_filters('relevanssi_remove_stopwords_in_titles', true), $min_word_length);
 
322
 
323
  if (count($titles) > 0) {
324
  foreach ($titles as $title => $count) {
@@ -331,16 +371,20 @@ function relevanssi_index_doc($indexpost, $remove_first = false, $custom_fields
331
 
332
  $index_content = true;
333
  if (apply_filters('relevanssi_index_content', $index_content)) {
 
334
  remove_shortcode('noindex');
335
  add_shortcode('noindex', 'relevanssi_noindex_shortcode_indexing');
336
 
337
  $contents = apply_filters('relevanssi_post_content', $post->post_content, $post);
 
338
 
339
  // Allow user to add extra content for Relevanssi to index
340
  // Thanks to Alexander Gieg
341
  $additional_content = trim(apply_filters('relevanssi_content_to_index', '', $post));
342
- if ('' != $additional_content)
343
  $contents .= ' '.$additional_content;
 
 
344
 
345
  if ('on' == get_option('relevanssi_expand_shortcodes')) {
346
  if (function_exists("do_shortcode")) {
@@ -393,6 +437,8 @@ function relevanssi_index_doc($indexpost, $remove_first = false, $custom_fields
393
  remove_shortcode('woocommerce_thankyou');
394
  remove_shortcode('woocommerce_lost_password');
395
  remove_shortcode('woocommerce_edit_address');
 
 
396
 
397
  $post_before_shortcode = $post;
398
  $contents = do_shortcode($contents);
@@ -428,6 +474,8 @@ function relevanssi_index_doc($indexpost, $remove_first = false, $custom_fields
428
  $contents = apply_filters('relevanssi_post_content_before_tokenize', $contents, $post);
429
  $contents = relevanssi_tokenize($contents, true, $min_word_length);
430
 
 
 
431
  if (count($contents) > 0) {
432
  foreach ($contents as $content => $count) {
433
  $n++;
@@ -472,6 +520,7 @@ function relevanssi_index_doc($indexpost, $remove_first = false, $custom_fields
472
  $values = implode(', ', $values);
473
  $query = "INSERT IGNORE INTO $relevanssi_table (doc, term, term_reverse, content, title, comment, tag, link, author, category, excerpt, taxonomy, customfield, type, taxonomy_detail, customfield_detail, mysqlcolumn)
474
  VALUES $values";
 
475
  $wpdb->query($query);
476
  }
477
 
@@ -751,4 +800,14 @@ function relevanssi_index_acf(&$insert_data, $post_id, $field_name, $field_value
751
  $insert_data[$value]['customfield']++;
752
  }
753
  }
 
 
 
 
 
 
 
 
 
 
754
  ?>
1
  <?php
2
 
3
+ function relevanssi_build_index($extend = false, $verbose = true, $post_limit = null) {
4
  if (function_exists('wp_suspend_cache_addition'))
5
  wp_suspend_cache_addition(true); // Thanks to Julien Mession
6
 
13
  $types = get_option("relevanssi_index_post_types");
14
  if (!is_array($types)) $types = array();
15
  foreach ($types as $type) {
16
+ if ($type == "bogus") continue;
17
  array_push($post_types, "'$type'");
18
  }
19
 
42
 
43
  if (!$extend) {
44
  // truncate table first
45
+ relevanssi_truncate_index();
46
 
47
  if (function_exists('relevanssi_index_taxonomies')) {
48
  if (get_option('relevanssi_index_taxonomies') == 'on') {
56
  }
57
  }
58
 
59
+ // if post limit parameter is present, numeric and > 0, use that
60
+ $limit = "";
61
+ if (isset($post_limit) && is_numeric($post_limit) && $post_limit > 0) {
62
+ $size = $post_limit;
63
+ $limit = " LIMIT $post_limit";
64
+ }
65
+
66
  $q = "SELECT post.ID
67
  FROM $wpdb->posts post
68
  LEFT JOIN $wpdb->posts parent ON (post.post_parent=parent.ID)
75
  OR (post.post_parent=0)
76
  )
77
  ))
78
+ $restriction $limit";
79
 
80
  update_option('relevanssi_index', '');
81
  }
82
  else {
83
  // extending, so no truncate and skip the posts already in the index
84
  $limit = get_option('relevanssi_index_limit', 200);
85
+
86
+ // if post limit parameter is present, numeric and > 0, use that
87
+ if (isset($post_limit) && is_numeric($post_limit) && $post_limit > 0) $limit = $post_limit;
88
+
89
  if (is_numeric($limit) && $limit > 0) {
90
  $size = $limit;
91
  $limit = " LIMIT $limit";
117
  do_action('relevanssi_pre_indexing_query');
118
  $content = $wpdb->get_results($q);
119
 
120
+ if ( defined( 'WP_CLI' ) && WP_CLI ) $progress = \WP_CLI\Utils\make_progress_bar( 'Indexing posts', count($content) );
121
  foreach ($content as $post) {
122
+ $result = relevanssi_index_doc($post->ID, false, $custom_fields, true);
123
+ if (is_numeric($result) && $result > 0) $n++;
124
+ // n calculates the number of posts indexed
125
  // $bypassglobalpost set to true, because at this point global $post should be NULL, but in some cases it is not
126
+
127
+ if ( defined( 'WP_CLI' ) && WP_CLI ) $progress->tick();
128
  }
129
+ if ( defined( 'WP_CLI' ) && WP_CLI ) $progress->finish();
130
 
131
  $wpdb->query("ANALYZE TABLE $relevanssi_table");
132
  // To prevent empty indices
133
 
134
+ $complete = false;
135
+ if ($verbose) {
136
+ echo '<div id="message" class="updated fade"><p>'
137
+ . __((($size == 0) || (count($content) < $size)) ? "Indexing complete!" : "More to index...", "relevanssi")
138
+ . '</p></div>';
139
+ }
140
+ else {
141
+ if (($size == 0) || (count($content) < $size)) $complete = true;
142
+ }
143
+
144
  update_option('relevanssi_indexed', 'done');
145
 
146
+ // We always want to run this on init, if the index is finished building.
147
  $D = $wpdb->get_var("SELECT COUNT(DISTINCT(relevanssi.doc)) FROM $relevanssi_table AS relevanssi");
148
  update_option( 'relevanssi_doc_count', $D);
149
 
150
  if (function_exists('wp_suspend_cache_addition'))
151
  wp_suspend_cache_addition(false); // Thanks to Julien Mession
152
+
153
+ return array($complete, $n);
154
  }
155
 
156
  // BEGIN modified by renaissancehack
168
  - Quick edit:
169
  global $post is an array, $indexpost is the ID of current revision.
170
  */
171
+ function relevanssi_index_doc($indexpost, $remove_first = false, $custom_fields = false, $bypassglobalpost = false, $debug = false) {
172
  global $wpdb, $post, $relevanssi_variables;
173
  $relevanssi_table = $relevanssi_variables['relevanssi_table'];
174
  $post_was_null = false;
211
  // At this point we should have something in $post; if not, quit.
212
  if ($post_was_null) $post = null;
213
  if ($previous_post) $post = $previous_post;
214
+ return -1;
215
  }
216
 
217
  // Finally fetch the post again by ID. Complicated, yes, but unless we do this, we might end
220
 
221
  if (function_exists('relevanssi_hide_post')) {
222
  if (relevanssi_hide_post($post->ID)) {
223
+ if ($debug) relevanssi_debug_echo("relevanssi_hide_post() returned true.");
224
  if ($post_was_null) $post = null;
225
  if ($previous_post) $post = $previous_post;
226
+ return "hide";
227
  }
228
  }
229
 
236
 
237
  if (true == apply_filters('relevanssi_do_not_index', false, $post->ID)) {
238
  // filter says no
239
+ if ($debug) relevanssi_debug_echo("relevanssi_do_not_index returned true.");
240
  $index_this_post = false;
241
  }
242
 
246
  if (function_exists('relevanssi_remove_item')) {
247
  relevanssi_remove_item($post->ID, 'post');
248
  }
249
+ if ($debug) relevanssi_debug_echo("Removed the post from the index.");
250
  }
251
 
252
  // This needs to be here, after the call to relevanssi_remove_doc(), because otherwise
254
  if (!$index_this_post) {
255
  if ($post_was_null) $post = null;
256
  if ($previous_post) $post = $previous_post;
257
+ return "donotindex";
258
  }
259
 
260
  $n = 0;
266
 
267
  //Added by OdditY - INDEX COMMENTS of the POST ->
268
  if ("none" != get_option("relevanssi_index_comments")) {
269
+ if ($debug) relevanssi_debug_echo("Indexing comments.");
270
  $pcoms = relevanssi_get_comments($post->ID);
271
  if ($pcoms != "") {
272
  $pcoms = relevanssi_strip_invisibles($pcoms);
273
  $pcoms = preg_replace('/<[a-zA-Z\/][^>]*>/', ' ', $pcoms);
274
  $pcoms = strip_tags($pcoms);
275
+ if ($debug) relevanssi_debug_echo("Comment content: $pcoms");
276
  $pcoms = relevanssi_tokenize($pcoms, true, $min_word_length);
277
  if (count($pcoms) > 0) {
278
  foreach ($pcoms as $pcom => $count) {
288
 
289
  // Then process all taxonomies, if any.
290
  foreach ($taxonomies as $taxonomy) {
291
+ if ($debug) relevanssi_debug_echo("Indexing taxonomy terms for $taxonomy");
292
  $insert_data = relevanssi_index_taxonomy_terms($post, $taxonomy, $insert_data);
293
  }
294
 
297
  $auth = $post->post_author;
298
  $display_name = $wpdb->get_var("SELECT display_name FROM $wpdb->users WHERE ID=$auth");
299
  $names = relevanssi_tokenize($display_name, false, $min_word_length);
300
+ if ($debug) relevanssi_debug_echo("Indexing post author as: " . implode(" ", array_keys($names)));
301
  foreach($names as $name => $count) {
302
  isset($insert_data[$name]['author']) ? $insert_data[$name]['author'] += $count : $insert_data[$name]['author'] = $count;
303
  }
313
  }
314
  $custom_fields = apply_filters('relevanssi_index_custom_fields', $custom_fields);
315
  if (is_array($custom_fields)) {
316
+ if ($debug) relevanssi_debug_echo("Custom fields to index: " . implode(", ", $custom_fields));
317
  $custom_fields = array_unique($custom_fields); // no reason to index duplicates
318
  foreach ($custom_fields as $field) {
319
  if ($remove_underscore_fields) {
325
  // Quick hack : allow indexing of PODS relationship custom fields // TMV
326
  if (is_array($value) && isset($value['post_title'])) $value = $value['post_title'];
327
  relevanssi_index_acf($insert_data, $post->ID, $field, $value);
328
+ if ($debug) relevanssi_debug_echo("\tKey: " . $field . " – value: " . $value);
329
+
330
  $value_tokens = relevanssi_tokenize($value, true, $min_word_length);
331
  foreach ($value_tokens as $token => $count) {
332
  isset($insert_data[$token]['customfield']) ? $insert_data[$token]['customfield'] += $count : $insert_data[$token]['customfield'] = $count;
340
  }
341
 
342
  if (isset($post->post_excerpt) && ("on" == get_option("relevanssi_index_excerpt") || "attachment" == $post->post_type)) { // include excerpt for attachments which use post_excerpt for captions - modified by renaissancehack
343
+ if ($debug) relevanssi_debug_echo("Indexing post excerpt: $post->post_excerpt");
344
  $excerpt_tokens = relevanssi_tokenize($post->post_excerpt, true, $min_word_length);
345
  foreach ($excerpt_tokens as $token => $count) {
346
  isset($insert_data[$token]['excerpt']) ? $insert_data[$token]['excerpt'] += $count : $insert_data[$token]['excerpt'] = $count;
348
  }
349
 
350
  if (function_exists('relevanssi_index_mysql_columns')) {
351
+ if ($debug) relevanssi_debug_echo("Indexing MySQL columns.");
352
  $insert_data = relevanssi_index_mysql_columns($insert_data, $post->ID);
353
  }
354
 
355
  $index_titles = true;
356
  if (!empty($post->post_title)) {
357
  if (apply_filters('relevanssi_index_titles', $index_titles)) {
358
+ if ($debug) relevanssi_debug_echo("Indexing post title.");
359
  $filtered_title = apply_filters('relevanssi_post_title_before_tokenize', $post->post_title, $post);
360
  $titles = relevanssi_tokenize(apply_filters('the_title', $filtered_title, $post->ID), apply_filters('relevanssi_remove_stopwords_in_titles', true), $min_word_length);
361
+ if ($debug) relevanssi_debug_echo("\tTitle, tokenized: " . implode(" ", array_keys($titles)));
362
 
363
  if (count($titles) > 0) {
364
  foreach ($titles as $title => $count) {
371
 
372
  $index_content = true;
373
  if (apply_filters('relevanssi_index_content', $index_content)) {
374
+ if ($debug) relevanssi_debug_echo("Indexing post content.");
375
  remove_shortcode('noindex');
376
  add_shortcode('noindex', 'relevanssi_noindex_shortcode_indexing');
377
 
378
  $contents = apply_filters('relevanssi_post_content', $post->post_content, $post);
379
+ if ($debug) relevanssi_debug_echo("\tPost content after relevanssi_post_content:\n$contents");
380
 
381
  // Allow user to add extra content for Relevanssi to index
382
  // Thanks to Alexander Gieg
383
  $additional_content = trim(apply_filters('relevanssi_content_to_index', '', $post));
384
+ if ('' != $additional_content) {
385
  $contents .= ' '.$additional_content;
386
+ if ($debug) relevanssi_debug_echo("\tAdditional content from relevanssi_content_to_index:\n$contents");
387
+ }
388
 
389
  if ('on' == get_option('relevanssi_expand_shortcodes')) {
390
  if (function_exists("do_shortcode")) {
437
  remove_shortcode('woocommerce_thankyou');
438
  remove_shortcode('woocommerce_lost_password');
439
  remove_shortcode('woocommerce_edit_address');
440
+ remove_shortcode('tc_process_payment');
441
+ remove_shortcode('maxmegamenu'); // Max Mega Menu
442
 
443
  $post_before_shortcode = $post;
444
  $contents = do_shortcode($contents);
474
  $contents = apply_filters('relevanssi_post_content_before_tokenize', $contents, $post);
475
  $contents = relevanssi_tokenize($contents, true, $min_word_length);
476
 
477
+ if ($debug) relevanssi_debug_echo("\tContent, tokenized:\n" . implode(" ", array_keys($contents)));
478
+
479
  if (count($contents) > 0) {
480
  foreach ($contents as $content => $count) {
481
  $n++;
520
  $values = implode(', ', $values);
521
  $query = "INSERT IGNORE INTO $relevanssi_table (doc, term, term_reverse, content, title, comment, tag, link, author, category, excerpt, taxonomy, customfield, type, taxonomy_detail, customfield_detail, mysqlcolumn)
522
  VALUES $values";
523
+ if ($debug) relevanssi_debug_echo("Final indexing query:\n\t$query");
524
  $wpdb->query($query);
525
  }
526
 
800
  $insert_data[$value]['customfield']++;
801
  }
802
  }
803
+
804
+ /**
805
+ * Truncates the Relevanssi index.
806
+ */
807
+ function relevanssi_truncate_index() {
808
+ global $wpdb, $relevanssi_variables;
809
+ $relevanssi_table = $relevanssi_variables['relevanssi_table'];
810
+ return $wpdb->query("TRUNCATE TABLE $relevanssi_table");
811
+ }
812
+
813
  ?>
lib/interface.php CHANGED
@@ -67,7 +67,7 @@ function relevanssi_options() {
67
  relevanssi_options_form();
68
 
69
  if (apply_filters('relevanssi_display_common_words', true))
70
- relevanssi_common_words();
71
 
72
  echo "<div style='clear:both'></div>";
73
 
@@ -86,7 +86,8 @@ function relevanssi_search_stats() {
86
  check_admin_referer('relevanssi_reset_logs', '_relresnonce');
87
  if (isset($_REQUEST['relevanssi_reset_code'])) {
88
  if ($_REQUEST['relevanssi_reset_code'] == 'reset') {
89
- relevanssi_truncate_logs();
 
90
  }
91
  }
92
  }
@@ -117,13 +118,22 @@ function relevanssi_search_stats() {
117
  relevanssi_sidebar();
118
  }
119
 
120
- function relevanssi_truncate_logs() {
121
  global $wpdb, $relevanssi_variables;
122
 
123
  $query = "TRUNCATE " . $relevanssi_variables['log_table'];
124
- $wpdb->query($query);
125
 
126
- echo "<div id='relevanssi-warning' class='updated fade'>" . __('Logs clear!', 'relevanssi') . "</div>";
 
 
 
 
 
 
 
 
 
127
  }
128
 
129
  function update_relevanssi_options() {
@@ -292,7 +302,6 @@ function update_relevanssi_options() {
292
  if (isset($_REQUEST['relevanssi_disable_or_fallback'])) update_option('relevanssi_disable_or_fallback', $_REQUEST['relevanssi_disable_or_fallback']);
293
  if (isset($_REQUEST['relevanssi_respect_exclude'])) update_option('relevanssi_respect_exclude', $_REQUEST['relevanssi_respect_exclude']);
294
  if (isset($_REQUEST['relevanssi_throttle'])) update_option('relevanssi_throttle', $_REQUEST['relevanssi_throttle']);
295
- if (isset($_REQUEST['relevanssi_throttle_limit'])) update_option('relevanssi_throttle_limit', $_REQUEST['relevanssi_throttle_limit']);
296
  if (isset($_REQUEST['relevanssi_wpml_only_current'])) update_option('relevanssi_wpml_only_current', $_REQUEST['relevanssi_wpml_only_current']);
297
  if (isset($_REQUEST['relevanssi_word_boundaries'])) update_option('relevanssi_word_boundaries', $_REQUEST['relevanssi_word_boundaries']);
298
  if (isset($_REQUEST['relevanssi_default_orderby'])) update_option('relevanssi_default_orderby', $_REQUEST['relevanssi_default_orderby']);
@@ -369,37 +378,48 @@ function relevanssi_remove_all_stopwords() {
369
  printf(__("<div id='message' class='updated fade'><p>Stopwords removed! Remember to re-index.</p></div>", "relevanssi"), $term);
370
  }
371
 
372
- function relevanssi_remove_stopword($term) {
373
  global $wpdb, $relevanssi_variables;
374
 
375
  $q = $wpdb->prepare("DELETE FROM " . $relevanssi_variables['stopword_table'] . " WHERE stopword=%s", $term);
376
  $success = $wpdb->query($q);
377
 
378
  if ($success) {
379
- echo "<div id='message' class='updated fade'><p>";
380
- printf(__("Term '%s' removed from stopwords! Re-index to get it back to index.", "relevanssi"), stripslashes($term));
381
- echo "</p></div>";
 
 
 
 
 
382
  }
383
  else {
384
- echo "<div id='message' class='updated fade'><p>";
385
- printf(__("Couldn't remove term '%s' from stopwords!", "relevanssi"), stripslashes($term));
386
- echo "</p></div>";
 
 
 
 
 
387
  }
388
  }
389
 
390
- function relevanssi_common_words() {
391
  global $wpdb, $relevanssi_variables, $wp_version;
392
 
393
  RELEVANSSI_PREMIUM ? $plugin = 'relevanssi-premium' : $plugin = 'relevanssi';
394
 
395
- echo "<div style='float:left; width: 45%'>";
396
-
397
- echo "<h3>" . __("25 most common words in the index", 'relevanssi') . "</h3>";
398
 
399
- echo "<p>" . __("These words are excellent stopword material. A word that appears in most of the posts in the database is quite pointless when searching. This is also an easy way to create a completely new stopword list, if one isn't available in your language. Click the icon after the word to add the word to the stopword list. The word will also be removed from the index, so rebuilding the index is not necessary.", 'relevanssi') . "</p>";
 
400
 
401
- $words = $wpdb->get_results("SELECT COUNT(DISTINCT(doc)) as cnt, term
402
- FROM " . $relevanssi_variables['relevanssi_table'] . " GROUP BY term ORDER BY cnt DESC LIMIT 25");
 
 
403
 
404
  ?>
405
  <form method="post">
@@ -408,26 +428,31 @@ function relevanssi_common_words() {
408
  <ul>
409
  <?php
410
 
411
- if (function_exists("plugins_url")) {
412
- if (version_compare($wp_version, '2.8dev', '>' )) {
413
- $src = plugins_url('delete.png', $relevanssi_variables['file']);
 
 
 
 
414
  }
415
  else {
416
- $src = plugins_url($plugin . '/delete.png');
 
 
 
 
 
 
417
  }
 
 
 
418
  }
419
  else {
420
- // We can't check, so let's assume something sensible
421
- $src = '/wp-content/plugins/' . $plugin . '/delete.png';
422
  }
423
-
424
- foreach ($words as $word) {
425
- $stop = __('Add to stopwords', 'relevanssi');
426
- printf('<li>%s (%d) <input style="padding: 0; margin: 0" type="image" src="%s" alt="%s" name="term" value="%s"/></li>', $word->term, $word->cnt, $src, $stop, $word->term);
427
- }
428
- echo "</ul>\n</form>";
429
-
430
- echo "</div>";
431
  }
432
 
433
  function relevanssi_query_log() {
@@ -860,7 +885,7 @@ function relevanssi_options_form() {
860
  echo '<a href="#options">' . __("Import/export options", "relevanssi") . '</a>';
861
  }
862
  else {
863
- echo '<strong><a href="http://www.relevanssi.com/buy-premium/?utm_source=plugin&utm_medium=link&utm_campaign=buy">' . __('Buy Relevanssi Premium', 'relevanssi') . '</a></strong>';
864
  }
865
  ?>
866
  </p>
@@ -938,13 +963,7 @@ function relevanssi_options_form() {
938
 
939
  <label for='relevanssi_throttle'><?php _e("Limit searches:", "relevanssi"); ?>
940
  <input type='checkbox' name='relevanssi_throttle' id='relevanssi_throttle' <?php echo $throttle ?> /></label><br />
941
- <small><?php _e("If this option is checked, Relevanssi will limit search results to at most 500 results per term. This will improve performance, but may cause some relevant documents to go unfound. However, Relevanssi tries to prioritize the most relevant documents. <strong>This does not work well when sorting results by date.</strong> The throttle can end up cutting off recent posts to favour more relevant posts.", 'relevanssi'); ?></small>
942
-
943
- <br /><br />
944
-
945
- <label for='relevanssi_throttle_limit'><?php _e("Limit:", "relevanssi"); ?>
946
- <input type='text' size='4' name='relevanssi_throttle_limit' id='relevanssi_throttle_limit' value='<?php echo $throttle_limit ?>' /></label><br />
947
- <small><?php printf(__("For better performance, adjust the limit to a smaller number. Adjusting the limit to 100 or 200 should be safe for good results, and might bring a boost in search speed. DO NOT use this feature to limit the number of search results on search results pages, as that will lead to problems. For adjusting the number of search results displayed, see <a href='%s'>this knowledge base entry</a>.", 'relevanssi'), 'http://www.relevanssi.com/knowledge-base/posts-per-page/'); ?></small>
948
 
949
  <br /><br />
950
 
@@ -1128,7 +1147,7 @@ function relevanssi_options_form() {
1128
 
1129
  <label for='relevanssi_hilite_title'><?php _e("Highlight query terms in result titles too:", 'relevanssi'); ?>
1130
  <input type='checkbox' name='relevanssi_hilite_title' id='relevanssi_hilite_title' <?php echo $hititle ?> /></label>
1131
- <small><?php _e("", 'relevanssi'); ?></small>
1132
 
1133
  <br />
1134
 
@@ -1195,7 +1214,7 @@ function relevanssi_options_form() {
1195
  <tr>
1196
  <th><?php _e('Type', 'relevanssi'); ?></th>
1197
  <th><?php _e('Index', 'relevanssi'); ?></th>
1198
- <th><?php _e('Public?', 'relevanssi'); ?></th>
1199
  </tr>
1200
  </thead>
1201
  <?php
@@ -1213,7 +1232,7 @@ function relevanssi_options_form() {
1213
  $checked = '';
1214
  }
1215
  $label = sprintf("%s", $type);
1216
- in_array($type, $public_types) ? $public = __('yes', 'relevanssi') : $public = __('no', 'relevanssi');
1217
 
1218
  echo <<<EOH
1219
  <tr>
@@ -1243,6 +1262,7 @@ EOH;
1243
  </tr>
1244
  </table>
1245
 
 
1246
  <br /><br />
1247
 
1248
  <p><?php _e('Choose taxonomies to index:', 'relevanssi'); ?></p>
67
  relevanssi_options_form();
68
 
69
  if (apply_filters('relevanssi_display_common_words', true))
70
+ relevanssi_common_words(25);
71
 
72
  echo "<div style='clear:both'></div>";
73
 
86
  check_admin_referer('relevanssi_reset_logs', '_relresnonce');
87
  if (isset($_REQUEST['relevanssi_reset_code'])) {
88
  if ($_REQUEST['relevanssi_reset_code'] == 'reset') {
89
+ $verbose = true;
90
+ relevanssi_truncate_logs($verbose);
91
  }
92
  }
93
  }
118
  relevanssi_sidebar();
119
  }
120
 
121
+ function relevanssi_truncate_logs($verbose = true) {
122
  global $wpdb, $relevanssi_variables;
123
 
124
  $query = "TRUNCATE " . $relevanssi_variables['log_table'];
125
+ $result = $wpdb->query($query);
126
 
127
+ if ($verbose) {
128
+ if ($result !== false) {
129
+ echo "<div id='relevanssi-warning' class='updated fade'>" . __('Logs clear!', 'relevanssi') . "</div>";
130
+ }
131
+ else {
132
+ echo "<div id='relevanssi-warning' class='updated fade'>" . __('Clearing the logs failed.', 'relevanssi') . "</div>";
133
+ }
134
+ }
135
+
136
+ return $result;
137
  }
138
 
139
  function update_relevanssi_options() {
302
  if (isset($_REQUEST['relevanssi_disable_or_fallback'])) update_option('relevanssi_disable_or_fallback', $_REQUEST['relevanssi_disable_or_fallback']);
303
  if (isset($_REQUEST['relevanssi_respect_exclude'])) update_option('relevanssi_respect_exclude', $_REQUEST['relevanssi_respect_exclude']);
304
  if (isset($_REQUEST['relevanssi_throttle'])) update_option('relevanssi_throttle', $_REQUEST['relevanssi_throttle']);
 
305
  if (isset($_REQUEST['relevanssi_wpml_only_current'])) update_option('relevanssi_wpml_only_current', $_REQUEST['relevanssi_wpml_only_current']);
306
  if (isset($_REQUEST['relevanssi_word_boundaries'])) update_option('relevanssi_word_boundaries', $_REQUEST['relevanssi_word_boundaries']);
307
  if (isset($_REQUEST['relevanssi_default_orderby'])) update_option('relevanssi_default_orderby', $_REQUEST['relevanssi_default_orderby']);
378
  printf(__("<div id='message' class='updated fade'><p>Stopwords removed! Remember to re-index.</p></div>", "relevanssi"), $term);
379
  }
380
 
381
+ function relevanssi_remove_stopword($term, $verbose = true) {
382
  global $wpdb, $relevanssi_variables;
383
 
384
  $q = $wpdb->prepare("DELETE FROM " . $relevanssi_variables['stopword_table'] . " WHERE stopword=%s", $term);
385
  $success = $wpdb->query($q);
386
 
387
  if ($success) {
388
+ if ($verbose) {
389
+ echo "<div id='message' class='updated fade'><p>";
390
+ printf(__("Term '%s' removed from stopwords! Re-index to get it back to index.", "relevanssi"), stripslashes($term));
391
+ echo "</p></div>";
392
+ }
393
+ else {
394
+ return true;
395
+ }
396
  }
397
  else {
398
+ if ($verbose) {
399
+ echo "<div id='message' class='updated fade'><p>";
400
+ printf(__("Couldn't remove term '%s' from stopwords!", "relevanssi"), stripslashes($term));
401
+ echo "</p></div>";
402
+ }
403
+ else {
404
+ return false;
405
+ }
406
  }
407
  }
408
 
409
+ function relevanssi_common_words($limit = 25, $wp_cli = false) {
410
  global $wpdb, $relevanssi_variables, $wp_version;
411
 
412
  RELEVANSSI_PREMIUM ? $plugin = 'relevanssi-premium' : $plugin = 'relevanssi';
413
 
414
+ if (!is_numeric($limit)) $limit = 25;
 
 
415
 
416
+ $words = $wpdb->get_results("SELECT COUNT(*) as cnt, term FROM " . $relevanssi_variables['relevanssi_table'] . " GROUP BY term ORDER BY cnt DESC LIMIT $limit");
417
+ // Clean: $limit is numeric.
418
 
419
+ if (!$wp_cli) {
420
+ echo "<div style='float:left; width: 45%'>";
421
+ echo "<h3>" . __("25 most common words in the index", 'relevanssi') . "</h3>";
422
+ echo "<p>" . __("These words are excellent stopword material. A word that appears in most of the posts in the database is quite pointless when searching. This is also an easy way to create a completely new stopword list, if one isn't available in your language. Click the icon after the word to add the word to the stopword list. The word will also be removed from the index, so rebuilding the index is not necessary.", 'relevanssi') . "</p>";
423
 
424
  ?>
425
  <form method="post">
428
  <ul>
429
  <?php
430
 
431
+ if (function_exists("plugins_url")) {
432
+ if (version_compare($wp_version, '2.8dev', '>' )) {
433
+ $src = plugins_url('delete.png', $relevanssi_variables['file']);
434
+ }
435
+ else {
436
+ $src = plugins_url($plugin . '/delete.png');
437
+ }
438
  }
439
  else {
440
+ // We can't check, so let's assume something sensible
441
+ $src = '/wp-content/plugins/' . $plugin . '/delete.png';
442
+ }
443
+
444
+ foreach ($words as $word) {
445
+ $stop = __('Add to stopwords', 'relevanssi');
446
+ printf('<li>%s (%d) <input style="padding: 0; margin: 0" type="image" src="%s" alt="%s" name="term" value="%s"/></li>', $word->term, $word->cnt, $src, $stop, $word->term);
447
  }
448
+ echo "</ul>\n</form>";
449
+
450
+ echo "</div>";
451
  }
452
  else {
453
+ // WP CLI gets the list of words
454
+ return $words;
455
  }
 
 
 
 
 
 
 
 
456
  }
457
 
458
  function relevanssi_query_log() {
885
  echo '<a href="#options">' . __("Import/export options", "relevanssi") . '</a>';
886
  }
887
  else {
888
+ echo '<strong><a href="https://www.relevanssi.com/buy-premium/?utm_source=plugin&utm_medium=link&utm_campaign=buy">' . __('Buy Relevanssi Premium', 'relevanssi') . '</a></strong>';
889
  }
890
  ?>
891
  </p>
963
 
964
  <label for='relevanssi_throttle'><?php _e("Limit searches:", "relevanssi"); ?>
965
  <input type='checkbox' name='relevanssi_throttle' id='relevanssi_throttle' <?php echo $throttle ?> /></label><br />
966
+ <small><?php _e("If this option is checked, Relevanssi will limit search results to at most 500 results per term (this number can be adjusted by changing the 'relevanssi_throttle_limit' option). This will improve performance, but may cause some relevant documents to go unfound. However, Relevanssi tries to prioritize the most relevant documents. <strong>This does not work when sorting results by date.</strong> The throttle can end up cutting off recent posts to favour more relevant posts.", 'relevanssi'); ?></small>
 
 
 
 
 
 
967
 
968
  <br /><br />
969
 
1147
 
1148
  <label for='relevanssi_hilite_title'><?php _e("Highlight query terms in result titles too:", 'relevanssi'); ?>
1149
  <input type='checkbox' name='relevanssi_hilite_title' id='relevanssi_hilite_title' <?php echo $hititle ?> /></label>
1150
+ <small><?php _e("Highlight hits in titles of the search results. This doesn't work automatically but requires you to replace the_title() on the template with relevanssi_the_title().", 'relevanssi'); ?></small>
1151
 
1152
  <br />
1153
 
1214
  <tr>
1215
  <th><?php _e('Type', 'relevanssi'); ?></th>
1216
  <th><?php _e('Index', 'relevanssi'); ?></th>
1217
+ <th><?php _e('Excluded from search?', 'relevanssi'); ?></th>
1218
  </tr>
1219
  </thead>
1220
  <?php
1232
  $checked = '';
1233
  }
1234
  $label = sprintf("%s", $type);
1235
+ in_array($type, $public_types) ? $public = __('no', 'relevanssi') : $public = __('yes', 'relevanssi');
1236
 
1237
  echo <<<EOH
1238
  <tr>
1262
  </tr>
1263
  </table>
1264
 
1265
+ <p><?php printf(__('If you choose to index a post type that is excluded from the search, you may need to uncheck the "%s" option.', 'relevanssi'), __('Respect exclude_from_search for custom post types', 'relevanssi')); ?></p>
1266
  <br /><br />
1267
 
1268
  <p><?php _e('Choose taxonomies to index:', 'relevanssi'); ?></p>
lib/search.php CHANGED
@@ -115,6 +115,7 @@ function relevanssi_search($args) {
115
  $numeric_slugs[] = $slug;
116
  }
117
  else {
 
118
  $term_id = $term->term_id;
119
  $slug_in = "'$slug'";
120
  }
@@ -130,6 +131,50 @@ function relevanssi_search($args) {
130
  }
131
  if (!empty($numeric_slugs)) $row['field'] = 'id';
132
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
133
  if ($row['field'] == 'id' || $row['field'] == 'term_id') {
134
  $id = $row['terms'];
135
  $term_id = $id;
@@ -168,7 +213,7 @@ function relevanssi_search($args) {
168
  }
169
 
170
  if (!isset($row['include_children']) || $row['include_children'] == true) {
171
- if (!$using_term_tax_id) {
172
  if (!is_array($term_id)) {
173
  $term_id = array($term_id);
174
  }
@@ -179,15 +224,17 @@ function relevanssi_search($args) {
179
  $term_id = $term_tax_id;
180
  }
181
  }
182
- foreach ($term_id as $t_id) {
183
- if ($using_term_tax_id) {
184
- $t_term = get_term_by('term_taxonomy_id', $t_id, $row['taxonomy']);
185
- $t_id = $t_term->ID;
186
- }
187
- $kids = get_term_children($t_id, $row['taxonomy']);
188
- foreach ($kids as $kid) {
189
- $term = get_term_by('id', $kid, $row['taxonomy']);
190
- $term_tax_id[] = relevanssi_get_term_tax_id('id', $kid, $row['taxonomy']);
 
 
191
  }
192
  }
193
  }
@@ -378,6 +425,7 @@ function relevanssi_search($args) {
378
 
379
  $remove_stopwords = apply_filters('relevanssi_remove_stopwords_in_titles', true);
380
  if (function_exists('wp_encode_emoji')) $q = wp_encode_emoji($q);
 
381
  if ($sentence) {
382
  $q = str_replace('"', '', $q);
383
  $q = '"' . $q . '"';
@@ -740,7 +788,6 @@ function relevanssi_search($args) {
740
  }
741
 
742
  if (!isset($doc_weight)) $no_matches = true;
743
-
744
  if ($no_matches) {
745
  if ($search_again) {
746
  // no hits even with fuzzy search!
@@ -804,6 +851,9 @@ function relevanssi_search($args) {
804
  if ($operator == "AND" AND get_option('relevanssi_disable_or_fallback') != 'on') {
805
  $or_args = $args;
806
  $or_args['operator'] = "OR";
 
 
 
807
  $or_args['q'] = relevanssi_add_synonyms($q);
808
  $return = relevanssi_search($or_args);
809
  extract($return);
@@ -1177,21 +1227,22 @@ function relevanssi_do_query(&$query) {
1177
  $expost = null;
1178
  }
1179
 
 
 
 
 
 
1180
  $operator = "";
1181
  if (function_exists('relevanssi_set_operator')) {
1182
  $operator = relevanssi_set_operator($query);
1183
  $operator = strtoupper($operator); // just in case
1184
  }
1185
  if ($operator != "OR" && $operator != "AND") $operator = get_option("relevanssi_implicit_operator");
 
1186
 
1187
  isset($query->query_vars['orderby']) ? $orderby = $query->query_vars['orderby'] : $orderby = null;
1188
  isset($query->query_vars['order']) ? $order = $query->query_vars['order'] : $order = null;
1189
 
1190
- $sentence = false;
1191
- if (isset($query->query_vars['sentence']) && !empty($query->query_vars['sentence'])) {
1192
- $sentence = true;
1193
- }
1194
-
1195
  $fields = "";
1196
  if (!empty($query->query_vars['fields'])) {
1197
  if ($query->query_vars['fields'] == 'ids') {
@@ -1239,7 +1290,7 @@ function relevanssi_do_query(&$query) {
1239
  $hits = $hits_filters_applied[0];
1240
 
1241
  $query->found_posts = sizeof($hits);
1242
- if ($query->query_vars["posts_per_page"] == 0) {
1243
  // assume something sensible to prevent "division by zero error";
1244
  $query->query_vars["posts_per_page"] = -1;
1245
  }
@@ -1258,14 +1309,14 @@ function relevanssi_do_query(&$query) {
1258
  $make_excerpts = get_option('relevanssi_excerpts');
1259
  if ($query->is_admin) $make_excerpts = false;
1260
 
1261
- if ($query->query_vars['paged'] > 0) {
1262
  $wpSearch_low = ($query->query_vars['paged'] - 1) * $query->query_vars["posts_per_page"];
1263
  }
1264
  else {
1265
  $wpSearch_low = 0;
1266
  }
1267
 
1268
- if ($query->query_vars["posts_per_page"] == -1) {
1269
  $wpSearch_high = sizeof($hits);
1270
  }
1271
  else {
115
  $numeric_slugs[] = $slug;
116
  }
117
  else {
118
+ $slug = sanitize_title($slug);
119
  $term_id = $term->term_id;
120
  $slug_in = "'$slug'";
121
  }
131
  }
132
  if (!empty($numeric_slugs)) $row['field'] = 'id';
133
  }
134
+ if ($row['field'] == 'name') {
135
+ $name = $row['terms'];
136
+ $numeric_names = array();
137
+ $name_in = null;
138
+ if (is_array($name)) {
139
+ $names = array();
140
+ $term_id = array();
141
+ foreach ($name as $t_name) {
142
+ $term = get_term_by('name', $t_name, $row['taxonomy']);
143
+ if (!$term && is_numeric($t_names)) {
144
+ $numeric_names[] = "'$t_name'";
145
+ }
146
+ else {
147
+ $t_name = sanitize_title($t_name);
148
+ $term_id[] = $term->term_id;
149
+ $names[] = "'$t_name'";
150
+ }
151
+ }
152
+ if (!empty($names)) $name_in = implode(',', $names);
153
+ }
154
+ else {
155
+ $term = get_term_by('name', $name, $row['taxonomy']);
156
+ if (!$term && is_numeric($name)) {
157
+ $numeric_slugs[] = $name;
158
+ }
159
+ else {
160
+ if (isset($term->term_id)) {
161
+ $name = sanitize_title($name);
162
+ $term_id = $term->term_id;
163
+ $name_in = "'$name'";
164
+ }
165
+ }
166
+ }
167
+ if (!empty($name_in)) {
168
+ $row_taxonomy = sanitize_text_field($row['taxonomy']);
169
+ $tt_q = "SELECT tt.term_taxonomy_id
170
+ FROM $wpdb->term_taxonomy AS tt
171
+ LEFT JOIN $wpdb->terms AS t ON (tt.term_id=t.term_id)
172
+ WHERE tt.taxonomy = '$row_taxonomy' AND t.name IN ($name_in)";
173
+ // Clean: $row_taxonomy is sanitized, each name in $name_in is sanitized
174
+ $term_tax_id = $wpdb->get_col($tt_q);
175
+ }
176
+ if (!empty($numeric_names)) $row['field'] = 'id';
177
+ }
178
  if ($row['field'] == 'id' || $row['field'] == 'term_id') {
179
  $id = $row['terms'];
180
  $term_id = $id;
213
  }
214
 
215
  if (!isset($row['include_children']) || $row['include_children'] == true) {
216
+ if (!$using_term_tax_id && isset($term_id)) {
217
  if (!is_array($term_id)) {
218
  $term_id = array($term_id);
219
  }
224
  $term_id = $term_tax_id;
225
  }
226
  }
227
+ if (isset($term_id) && is_array($term_id)) {
228
+ foreach ($term_id as $t_id) {
229
+ if ($using_term_tax_id) {
230
+ $t_term = get_term_by('term_taxonomy_id', $t_id, $row['taxonomy']);
231
+ $t_id = $t_term->ID;
232
+ }
233
+ $kids = get_term_children($t_id, $row['taxonomy']);
234
+ foreach ($kids as $kid) {
235
+ $term = get_term_by('id', $kid, $row['taxonomy']);
236
+ $term_tax_id[] = relevanssi_get_term_tax_id('id', $kid, $row['taxonomy']);
237
+ }
238
  }
239
  }
240
  }
425
 
426
  $remove_stopwords = apply_filters('relevanssi_remove_stopwords_in_titles', true);
427
  if (function_exists('wp_encode_emoji')) $q = wp_encode_emoji($q);
428
+
429
  if ($sentence) {
430
  $q = str_replace('"', '', $q);
431
  $q = '"' . $q . '"';
788
  }
789
 
790
  if (!isset($doc_weight)) $no_matches = true;
 
791
  if ($no_matches) {
792
  if ($search_again) {
793
  // no hits even with fuzzy search!
851
  if ($operator == "AND" AND get_option('relevanssi_disable_or_fallback') != 'on') {
852
  $or_args = $args;
853
  $or_args['operator'] = "OR";
854
+ global $wp_query;
855
+ $wp_query->set("operator", "OR");
856
+
857
  $or_args['q'] = relevanssi_add_synonyms($q);
858
  $return = relevanssi_search($or_args);
859
  extract($return);
1227
  $expost = null;
1228
  }
1229
 
1230
+ $sentence = false;
1231
+ if (isset($query->query_vars['sentence']) && !empty($query->query_vars['sentence'])) {
1232
+ $sentence = true;
1233
+ }
1234
+
1235
  $operator = "";
1236
  if (function_exists('relevanssi_set_operator')) {
1237
  $operator = relevanssi_set_operator($query);
1238
  $operator = strtoupper($operator); // just in case
1239
  }
1240
  if ($operator != "OR" && $operator != "AND") $operator = get_option("relevanssi_implicit_operator");
1241
+ $query->set("operator", $operator);
1242
 
1243
  isset($query->query_vars['orderby']) ? $orderby = $query->query_vars['orderby'] : $orderby = null;
1244
  isset($query->query_vars['order']) ? $order = $query->query_vars['order'] : $order = null;
1245
 
 
 
 
 
 
1246
  $fields = "";
1247
  if (!empty($query->query_vars['fields'])) {
1248
  if ($query->query_vars['fields'] == 'ids') {
1290
  $hits = $hits_filters_applied[0];
1291
 
1292
  $query->found_posts = sizeof($hits);
1293
+ if (!isset($query->query_vars["posts_per_page"]) || $query->query_vars["posts_per_page"] == 0) {
1294
  // assume something sensible to prevent "division by zero error";
1295
  $query->query_vars["posts_per_page"] = -1;
1296
  }
1309
  $make_excerpts = get_option('relevanssi_excerpts');
1310
  if ($query->is_admin) $make_excerpts = false;
1311
 
1312
+ if (isset($query->query_vars['paged']) && $query->query_vars['paged'] > 0) {
1313
  $wpSearch_low = ($query->query_vars['paged'] - 1) * $query->query_vars["posts_per_page"];
1314
  }
1315
  else {
1316
  $wpSearch_low = 0;
1317
  }
1318
 
1319
+ if (!isset($query->query_vars["posts_per_page"]) || $query->query_vars["posts_per_page"] == -1) {
1320
  $wpSearch_high = sizeof($hits);
1321
  }
1322
  else {
lib/uninstall.php CHANGED
@@ -25,8 +25,6 @@ function relevanssi_clear_database_tables() {
25
  $sql = "DROP TABLE $log_table";
26
  $wpdb->query($sql);
27
  }
28
-
29
- echo '<div id="message" class="updated fade"><p>' . __("Data wiped clean, you can now delete the plugin.", "relevanssi") . '</p></div>';
30
  }
31
 
32
  ?>
25
  $sql = "DROP TABLE $log_table";
26
  $wpdb->query($sql);
27
  }
 
 
28
  }
29
 
30
  ?>
readme.txt CHANGED
@@ -1,10 +1,10 @@
1
  === Relevanssi - A Better Search ===
2
  Contributors: msaari
3
- Donate link: http://www.relevanssi.com/buy-premium/
4
  Tags: search, relevance, better search
5
  Requires at least: 4.0
6
- Tested up to: 4.7.3
7
- Stable tag: 3.5.8
8
  License: GPLv2 or later
9
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
10
 
@@ -14,7 +14,7 @@ Relevanssi replaces the default search with a partial-match search that sorts re
14
 
15
  Relevanssi replaces the standard WordPress search with a better search engine, with lots of features and configurable options. You'll get better results, better presentation of results - your users will thank you.
16
 
17
- This is the free version of Relevanssi. There's also Relevanssi Premium, which has added features, including Multisite support. This free version does not work properly on Multisite. For more information about Premium, see [Relevanssi.com](http://www.relevanssi.com/).
18
 
19
  = Key features =
20
  * Search results sorted in the order of relevance, not by date.
@@ -51,12 +51,13 @@ Relevanssi is available in two versions, regular and Premium. Regular Relevanssi
51
  * Let the user choose between AND and OR searches, use + and - operator (AND and NOT).
52
  * Highlighting search terms for visitors from external search engines.
53
  * Export and import settings.
 
54
 
55
  = Relevanssi in Facebook =
56
- You can find [Relevanssi in Facebook](http://www.facebook.com/relevanssi). Become a fan to follow the development of the plugin, I'll post updates on bugs, new features and new versions to the Facebook page.
57
 
58
  = Other search plugins =
59
- Relevanssi owes a lot to [wpSearch](http://wordpress.org/extend/plugins/wpsearch/) by Kenny Katzgrau. Relevanssi was built to replace wpSearch, when it started to fail.
60
 
61
  Search Unleashed is a popular search plugin, but it hasn't been updated since 2010. Relevanssi is in active development and does what Search Unleashed does.
62
 
@@ -77,7 +78,7 @@ If it seems the plugin doesn't work after an update, the first thing to try is d
77
  = Changes to templates =
78
  None necessary! Relevanssi uses the standard search form and doesn't usually need any changes in the search results template.
79
 
80
- If the search does not bring any results, your theme probably has a query_posts() call in the search results template. That throws Relevanssi off. For more information, see [The most important Relevanssi debugging trick](http://www.relevanssi.com/knowledge-base/query_posts/).
81
 
82
  = How to index =
83
  Check the options to make sure they're to your liking, then click "Save indexing options and build the index". If everything's fine, you'll see the Relevanssi options screen again with a message "Indexing successful!"
@@ -98,7 +99,7 @@ To avoid trouble, use the function like this:
98
  See Frequently Asked Questions for more instructions on what you can do with Relevanssi.
99
 
100
  = The advanced hacker option =
101
- If you're doing something unusual with your search and Relevanssi doesn't work, try using `relevanssi_do_query()`. See [Knowledge Base](http://www.relevanssi.com/knowledge-base/relevanssi_do_query/).
102
 
103
  = Uninstalling =
104
  To uninstall the plugin remove the plugin using the normal WordPress plugin management tools (from the Plugins page, first Deactivate, then Delete). If you remove the plugin files manually, the database tables and options will remain.
@@ -111,13 +112,13 @@ Some plugins cause problems when indexing documents. These are generally plugins
111
  == Frequently Asked Questions ==
112
 
113
  = Knowledge Base =
114
- You can find solutions and answers at the [Relevanssi Knowledge Base](http://www.relevanssi.com/category/knowledge-base/).
115
 
116
  = Relevanssi doesn't work =
117
  If you the results don't change after installing and activating Relevanssi, the most likely reason is that you have a call to `query_posts()` on your search results template. This confuses Relevanssi. Try removing the query_posts call and see what happens.
118
 
119
  = Searching for words with ampersands or hyphens doesn't work =
120
- Please read [Words with punctuation can't be found](http://www.relevanssi.com/knowledge-base/words-ampersands-cant-found/). This is a Relevanssi feature, but you can circumvent it with a simple filter function.
121
 
122
  = Where are the user search logs? =
123
  See the top of the admin menu. There's 'User searches'. There. If the logs are empty, please note showing the results needs at least MySQL 5.
@@ -267,6 +268,12 @@ Each document database is full of useless words. All the little words that appea
267
 
268
  == Changelog ==
269
 
 
 
 
 
 
 
270
  = 3.5.8 =
271
  * Did you mean function had a XSS vulnerability, which is now removed.
272
  * Minimum word length wasn't applied to titles in indexing. It is now fixed. If you think this is a problem, rebuild the index.
@@ -591,7 +598,7 @@ Each document database is full of useless words. All the little words that appea
591
  = 3.0.2 =
592
  * AFTER UPGRADING FROM 2.x: Make sure you deactivate and reactivate Relevanssi in order to make the database changes happen.
593
  * Fixed the "Cannot use a scalar value as an array" bug in indexing.
594
- * Role-Scoper users: in order to make Relevanssi work with Role-Scoper, replace the Relevanssi helper file in Role-Scoper with [this file](http://www.relevanssi.com/relevanssi-helper-front_rs.txt).
595
  * Removed an error message about set_time_limit() under safe_mode.
596
  * Jetpack Contact Form shortcode caused problems when indexing. Relevanssi will now simply remove the shortcode before indexing.
597
  * Fixed errors caused by / characters in highlighting.
@@ -708,7 +715,7 @@ Each document database is full of useless words. All the little words that appea
708
  * A call to a non-existing function in 2.9.2 made all sorts of mess. This release fixes all problems with broken loops. I'm sorry about the bug.
709
 
710
  = 2.9.2 =
711
- * It's now possible to adjust the number of search results per page. See [Changing posts_per_page](http://www.relevanssi.com/knowledge-base/posts-per-page/) for instructions.
712
  * Somebody reported revisions appearing in the search results. Added an extra check to prevent that.
713
  * Improved the indexing procedure to prevent MySQL errors from appearing and to streamline the process.
714
  * Improved the way custom post types can be handled in indexing.
@@ -717,7 +724,7 @@ Each document database is full of useless words. All the little words that appea
717
  = 2.9.1 =
718
  * It is now possible to change the default result order from relevance to post date.
719
  * Fixed a bug that caused wrong $post object to be set in indexing.
720
- * Added a new hook `relevanssi_excerpt_content`; see [Knowledge Base](http://www.relevanssi.com/category/knowledge-base/) for details.
721
 
722
  = 2.9 =
723
  * Fixed a bug that caused Cyrillic searches in the log to get corrupted.
@@ -1035,6 +1042,9 @@ Each document database is full of useless words. All the little words that appea
1035
 
1036
  == Upgrade notice ==
1037
 
 
 
 
1038
  = 3.5.8 =
1039
  * Fix for a XSS vulnerability.
1040
 
@@ -1114,4 +1124,4 @@ Each document database is full of useless words. All the little words that appea
1114
  * WordPress 3.7 compatibility, couple of minor bug fixes.
1115
 
1116
  = 3.1.8 =
1117
- Recommended for users of WPML and BBpress. Category exclusions and restrictions are also fixed.
1
  === Relevanssi - A Better Search ===
2
  Contributors: msaari
3
+ Donate link: https://www.relevanssi.com/buy-premium/
4
  Tags: search, relevance, better search
5
  Requires at least: 4.0
6
+ Tested up to: 4.7.4
7
+ Stable tag: 3.5.9
8
  License: GPLv2 or later
9
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
10
 
14
 
15
  Relevanssi replaces the standard WordPress search with a better search engine, with lots of features and configurable options. You'll get better results, better presentation of results - your users will thank you.
16
 
17
+ This is the free version of Relevanssi. There's also Relevanssi Premium, which has added features, including Multisite support. This free version does not work properly on Multisite. For more information about Premium, see [Relevanssi.com](https://www.relevanssi.com/).
18
 
19
  = Key features =
20
  * Search results sorted in the order of relevance, not by date.
51
  * Let the user choose between AND and OR searches, use + and - operator (AND and NOT).
52
  * Highlighting search terms for visitors from external search engines.
53
  * Export and import settings.
54
+ * [WP CLI commands](https://www.relevanssi.com/user-manual/wp-cli/).
55
 
56
  = Relevanssi in Facebook =
57
+ You can find [Relevanssi in Facebook](https://www.facebook.com/relevanssi). Become a fan to follow the development of the plugin, I'll post updates on bugs, new features and new versions to the Facebook page.
58
 
59
  = Other search plugins =
60
+ Relevanssi owes a lot to [wpSearch](https://wordpress.org/extend/plugins/wpsearch/) by Kenny Katzgrau. Relevanssi was built to replace wpSearch, when it started to fail.
61
 
62
  Search Unleashed is a popular search plugin, but it hasn't been updated since 2010. Relevanssi is in active development and does what Search Unleashed does.
63
 
78
  = Changes to templates =
79
  None necessary! Relevanssi uses the standard search form and doesn't usually need any changes in the search results template.
80
 
81
+ If the search does not bring any results, your theme probably has a query_posts() call in the search results template. That throws Relevanssi off. For more information, see [The most important Relevanssi debugging trick](https://www.relevanssi.com/knowledge-base/query_posts/).
82
 
83
  = How to index =
84
  Check the options to make sure they're to your liking, then click "Save indexing options and build the index". If everything's fine, you'll see the Relevanssi options screen again with a message "Indexing successful!"
99
  See Frequently Asked Questions for more instructions on what you can do with Relevanssi.
100
 
101
  = The advanced hacker option =
102
+ If you're doing something unusual with your search and Relevanssi doesn't work, try using `relevanssi_do_query()`. See [Knowledge Base](https://www.relevanssi.com/knowledge-base/relevanssi_do_query/).
103
 
104
  = Uninstalling =
105
  To uninstall the plugin remove the plugin using the normal WordPress plugin management tools (from the Plugins page, first Deactivate, then Delete). If you remove the plugin files manually, the database tables and options will remain.
112
  == Frequently Asked Questions ==
113
 
114
  = Knowledge Base =
115
+ You can find solutions and answers at the [Relevanssi Knowledge Base](https://www.relevanssi.com/category/knowledge-base/).
116
 
117
  = Relevanssi doesn't work =
118
  If you the results don't change after installing and activating Relevanssi, the most likely reason is that you have a call to `query_posts()` on your search results template. This confuses Relevanssi. Try removing the query_posts call and see what happens.
119
 
120
  = Searching for words with ampersands or hyphens doesn't work =
121
+ Please read [Words with punctuation can't be found](https://www.relevanssi.com/knowledge-base/words-ampersands-cant-found/). This is a Relevanssi feature, but you can circumvent it with a simple filter function.
122
 
123
  = Where are the user search logs? =
124
  See the top of the admin menu. There's 'User searches'. There. If the logs are empty, please note showing the results needs at least MySQL 5.
268
 
269
  == Changelog ==
270
 
271
+ = 3.5.9 =
272
+ * Improved the way highlighting handles HTML tags, especially when highlighting on post pages.
273
+ * The throttle limit setting was removed from the settings page for causing trouble. If you need to change it, update `relevanssi_throttle_limit` option directly.
274
+ * Relevanssi didn't support tax_queries with `field` set to `name`. That works now.
275
+ * Much faster way of showing the 25 most common words in the index. If you've disabled this feature because it was so slow, try enabling it - you might be surprised!
276
+
277
  = 3.5.8 =
278
  * Did you mean function had a XSS vulnerability, which is now removed.
279
  * Minimum word length wasn't applied to titles in indexing. It is now fixed. If you think this is a problem, rebuild the index.
598
  = 3.0.2 =
599
  * AFTER UPGRADING FROM 2.x: Make sure you deactivate and reactivate Relevanssi in order to make the database changes happen.
600
  * Fixed the "Cannot use a scalar value as an array" bug in indexing.
601
+ * Role-Scoper users: in order to make Relevanssi work with Role-Scoper, replace the Relevanssi helper file in Role-Scoper with [this file](https://www.relevanssi.com/relevanssi-helper-front_rs.txt).
602
  * Removed an error message about set_time_limit() under safe_mode.
603
  * Jetpack Contact Form shortcode caused problems when indexing. Relevanssi will now simply remove the shortcode before indexing.
604
  * Fixed errors caused by / characters in highlighting.
715
  * A call to a non-existing function in 2.9.2 made all sorts of mess. This release fixes all problems with broken loops. I'm sorry about the bug.
716
 
717
  = 2.9.2 =
718
+ * It's now possible to adjust the number of search results per page. See [Changing posts_per_page](https://www.relevanssi.com/knowledge-base/posts-per-page/) for instructions.
719
  * Somebody reported revisions appearing in the search results. Added an extra check to prevent that.
720
  * Improved the indexing procedure to prevent MySQL errors from appearing and to streamline the process.
721
  * Improved the way custom post types can be handled in indexing.
724
  = 2.9.1 =
725
  * It is now possible to change the default result order from relevance to post date.
726
  * Fixed a bug that caused wrong $post object to be set in indexing.
727
+ * Added a new hook `relevanssi_excerpt_content`; see [Knowledge Base](https://www.relevanssi.com/category/knowledge-base/) for details.
728
 
729
  = 2.9 =
730
  * Fixed a bug that caused Cyrillic searches in the log to get corrupted.
1042
 
1043
  == Upgrade notice ==
1044
 
1045
+ = 3.5.9 =
1046
+ * Improvements in highlighting and taxonomy searches.
1047
+
1048
  = 3.5.8 =
1049
  * Fix for a XSS vulnerability.
1050
 
1124
  * WordPress 3.7 compatibility, couple of minor bug fixes.
1125
 
1126
  = 3.1.8 =
1127
+ * Recommended for users of WPML and BBpress. Category exclusions and restrictions are also fixed.
relevanssi.php CHANGED
@@ -3,7 +3,7 @@
3
  Plugin Name: Relevanssi
4
  Plugin URI: http://www.relevanssi.com/
5
  Description: This plugin replaces WordPress search with a relevance-sorting search.
6
- Version: 3.5.8
7
  Author: Mikko Saari
8
  Author URI: http://www.mikkosaari.fi/
9
  */
@@ -375,10 +375,10 @@ function relevanssi_sidebar() {
375
  <p>Do you want more features? Support Relevanssi development? Get a
376
  better search experience for your users?</p>
377
 
378
- <p><strong>Go Premium!</strong> Buy Relevanssi Premium. See <a href="http://www.relevanssi.com/features/?utm_source=plugin&utm_medium=link&utm_campaign=features">feature
379
- comparison</a> and <a href="http://www.relevanssi.com/buy-premium/?utm_source=plugin&utm_medium=link&utm_campaign=license">license prices</a>.</p>
380
 
381
- <p><strong><a href="http://www.relevanssi.com/buy-premium/?utm_source=plugin&utm_medium=link&utm_campaign=license">Buy Premium now &raquo;</a></strong></p>
382
 
383
  <p>Use the coupon <strong>FREE2017</strong> to get 20% off the price (valid through 2017).</p>
384
  </div>
@@ -400,6 +400,7 @@ comparison</a> and <a href="http://www.relevanssi.com/buy-premium/?utm_source=pl
400
  - Index and search user profile pages<br />
401
  - Index and search taxonomy term pages<br />
402
  - Import and export options<br />
 
403
  - And more!
404
  </p>
405
  </div>
@@ -411,7 +412,7 @@ comparison</a> and <a href="http://www.relevanssi.com/buy-premium/?utm_source=pl
411
  <h3 class="hndle"><span>Relevanssi on Facebook</span></h3>
412
  <div class="inside">
413
  <div style="float: left; margin-right: 5px"><img src="$facebooklogo" width="45" height="43" alt="Facebook" /></div>
414
- <p><a href="http://www.facebook.com/relevanssi">Check
415
  out the Relevanssi page on Facebook</a> for news and updates about your favourite plugin.</p>
416
  </div>
417
  </div>
@@ -424,7 +425,7 @@ comparison</a> and <a href="http://www.relevanssi.com/buy-premium/?utm_source=pl
424
  <p>For Relevanssi support, see:</p>
425
 
426
  <p>- <a href="http://wordpress.org/tags/relevanssi?forum_id=10">WordPress.org forum</a><br />
427
- - <a href="http://www.relevanssi.com/category/knowledge-base/?utm_source=plugin&utm_medium=link&utm_campaign=kb">Knowledge base</a></p>
428
  </div>
429
  </div>
430
  </div>
3
  Plugin Name: Relevanssi
4
  Plugin URI: http://www.relevanssi.com/
5
  Description: This plugin replaces WordPress search with a relevance-sorting search.
6
+ Version: 3.5.9
7
  Author: Mikko Saari
8
  Author URI: http://www.mikkosaari.fi/
9
  */
375
  <p>Do you want more features? Support Relevanssi development? Get a
376
  better search experience for your users?</p>
377
 
378
+ <p><strong>Go Premium!</strong> Buy Relevanssi Premium. See <a href="https://www.relevanssi.com/features/?utm_source=plugin&utm_medium=link&utm_campaign=features">feature
379
+ comparison</a> and <a href="https://www.relevanssi.com/buy-premium/?utm_source=plugin&utm_medium=link&utm_campaign=license">license prices</a>.</p>
380
 
381
+ <p><strong><a href="https://www.relevanssi.com/buy-premium/?utm_source=plugin&utm_medium=link&utm_campaign=license">Buy Premium now &raquo;</a></strong></p>
382
 
383
  <p>Use the coupon <strong>FREE2017</strong> to get 20% off the price (valid through 2017).</p>
384
  </div>
400
  - Index and search user profile pages<br />
401
  - Index and search taxonomy term pages<br />
402
  - Import and export options<br />
403
+ - WP CLI commands<br />
404
  - And more!
405
  </p>
406
  </div>
412
  <h3 class="hndle"><span>Relevanssi on Facebook</span></h3>
413
  <div class="inside">
414
  <div style="float: left; margin-right: 5px"><img src="$facebooklogo" width="45" height="43" alt="Facebook" /></div>
415
+ <p><a href="https://www.facebook.com/relevanssi">Check
416
  out the Relevanssi page on Facebook</a> for news and updates about your favourite plugin.</p>
417
  </div>
418
  </div>
425
  <p>For Relevanssi support, see:</p>
426
 
427
  <p>- <a href="http://wordpress.org/tags/relevanssi?forum_id=10">WordPress.org forum</a><br />
428
+ - <a href="https://www.relevanssi.com/category/knowledge-base/?utm_source=plugin&utm_medium=link&utm_campaign=kb">Knowledge base</a></p>
429
  </div>
430
  </div>
431
  </div>