Relevanssi – A Better Search - Version 4.7.1

Version Description

  • New feature: New filter hook relevanssi_post_content_after_shortcodes filters the post content after shortcodes have been processed but before the HTML tags are stripped.
  • Minor fix: Adds more backwards compatibility for the relevanssi_indexing_restriction change.
Download this release

Release Info

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

Code changes from version 4.7.0 to 4.7.1

lib/common.php CHANGED
@@ -671,6 +671,7 @@ function relevanssi_remove_punct( $a ) {
671
 
672
  $replacement_array = array(
673
  'ß' => 'ss',
 
674
  '·' => '',
675
  '…' => '',
676
  '€' => '',
@@ -755,13 +756,6 @@ function relevanssi_remove_punct( $a ) {
755
  */
756
  function relevanssi_prevent_default_request( $request, $query ) {
757
  if ( $query->is_search ) {
758
- if ( isset( $query->query_vars['post_type'] ) && isset( $query->query_vars['post_status'] ) ) {
759
- if ( 'attachment' === $query->query_vars['post_type'] && 'inherit,private' === $query->query_vars['post_status'] ) {
760
- // This is a media library search; do not meddle.
761
- return $request;
762
- }
763
- }
764
-
765
  if ( in_array( $query->query_vars['post_type'], array( 'topic', 'reply' ), true ) ) {
766
  // This is a BBPress search; do not meddle.
767
  return $request;
@@ -1375,7 +1369,7 @@ function relevanssi_switch_blog( $new_blog, $prev_blog ) {
1375
  * @return string The link with the parameter added.
1376
  */
1377
  function relevanssi_add_highlight( $permalink, $link_post = null ) {
1378
- $highlight_docs = get_option( 'relevanssi_highlight_docs' );
1379
  $query = get_search_query();
1380
  if ( isset( $highlight_docs ) && 'off' !== $highlight_docs && ! empty( $query ) ) {
1381
  $frontpage_id = intval( get_option( 'page_on_front' ) );
@@ -1939,3 +1933,43 @@ function relevanssi_remove_page_builder_shortcodes( $content ) {
1939
  $content = preg_replace( $search_array, ' ', $content );
1940
  return $content;
1941
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
671
 
672
  $replacement_array = array(
673
  'ß' => 'ss',
674
+ '₂' => '2',
675
  '·' => '',
676
  '…' => '',
677
  '€' => '',
756
  */
757
  function relevanssi_prevent_default_request( $request, $query ) {
758
  if ( $query->is_search ) {
 
 
 
 
 
 
 
759
  if ( in_array( $query->query_vars['post_type'], array( 'topic', 'reply' ), true ) ) {
760
  // This is a BBPress search; do not meddle.
761
  return $request;
1369
  * @return string The link with the parameter added.
1370
  */
1371
  function relevanssi_add_highlight( $permalink, $link_post = null ) {
1372
+ $highlight_docs = get_option( 'relevanssi_highlight_docs', 'off' );
1373
  $query = get_search_query();
1374
  if ( isset( $highlight_docs ) && 'off' !== $highlight_docs && ! empty( $query ) ) {
1375
  $frontpage_id = intval( get_option( 'page_on_front' ) );
1933
  $content = preg_replace( $search_array, ' ', $content );
1934
  return $content;
1935
  }
1936
+
1937
+ /**
1938
+ * Blocks Relevanssi from the admin searches on specific post types.
1939
+ *
1940
+ * This function is added to relevanssi_search_ok, relevanssi_admin_search_ok,
1941
+ * and relevanssi_prevent_default_request hooks. When a search is made with
1942
+ * one of the listed post types, these filters will get a false response, which
1943
+ * means Relevanssi won't search and won't block the default request.
1944
+ *
1945
+ * @see relevanssi_prevent_default_request
1946
+ * @see relevanssi_search
1947
+ *
1948
+ * @param boolean $allow Should the admin search be allowed.
1949
+ * @param WP_Query $query The query object.
1950
+ */
1951
+ function relevanssi_block_on_admin_searches( $allow, $query ) {
1952
+ $blocked_post_types = array(
1953
+ 'rc_blocks', // Reusable Content Blocks.
1954
+ );
1955
+ /**
1956
+ * Filters the post types that are blocked in the admin search.
1957
+ *
1958
+ * In some cases you may want to enable Relevanssi in the admin backend,
1959
+ * but don't want Relevanssi to search certain post types. To block
1960
+ * Relevanssi from a specific post type, add the post type to this filter.
1961
+ *
1962
+ * @param array List of post types Relevanssi shouldn't try searching.
1963
+ */
1964
+ $blocked_post_types = apply_filters(
1965
+ 'relevanssi_admin_search_blocked_post_types',
1966
+ $blocked_post_types
1967
+ );
1968
+ if (
1969
+ isset( $query->query_vars['post_type'] ) &&
1970
+ in_array( $query->query_vars['post_type'], $blocked_post_types, true )
1971
+ ) {
1972
+ $allow = false;
1973
+ }
1974
+ return $allow;
1975
+ }
lib/compatibility/gutenberg.php CHANGED
@@ -58,7 +58,27 @@ function relevanssi_gutenberg_block_rendering( $content ) {
58
  $output = '';
59
 
60
  foreach ( $blocks as $block ) {
61
- if ( ! isset( $block['attrs']['className'] ) || strstr( $block['attrs']['className'], 'relevanssi_noindex' ) === false ) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
62
  $output .= render_block( $block );
63
  }
64
  }
58
  $output = '';
59
 
60
  foreach ( $blocks as $block ) {
61
+ /**
62
+ * Filters the Gutenberg block before it is rendered.
63
+ *
64
+ * If the block is non-empty after the filter and it's className
65
+ * parameter is not 'relevanssi_noindex', it will be passed on to the
66
+ * render_block() function for rendering.
67
+ *
68
+ * @see render_block
69
+ *
70
+ * @param array $block The Gutenberg block element.
71
+ */
72
+ $block = apply_filters( 'relevanssi_block_to_render', $block );
73
+
74
+ if ( ! $block ) {
75
+ continue;
76
+ }
77
+
78
+ if (
79
+ ! isset( $block['attrs']['className'] )
80
+ || false === strstr( $block['attrs']['className'], 'relevanssi_noindex' )
81
+ ) {
82
  $output .= render_block( $block );
83
  }
84
  }
lib/compatibility/polylang.php CHANGED
@@ -17,9 +17,9 @@ add_filter( 'relevanssi_hits_filter', 'relevanssi_polylang_term_filter' );
17
  /**
18
  * Removes the Polylang language filters.
19
  *
20
- * If the Polylang allow all option is enabled ('relevanssi_polylang_all_languages'),
21
- * removes the Polylang language filter. By default Polylang filters the languages
22
- * using a taxonomy query.
23
  *
24
  * @param object $query WP_Query object we need to clean up.
25
  */
@@ -75,10 +75,10 @@ function relevanssi_polylang_filter( $query ) {
75
  /**
76
  * Allows taxonomy terms in language-restricted searches.
77
  *
78
- * This is a bit of a hack, where the language taxonomy WHERE clause is modified on
79
- * the go to allow all posts with the post ID -1 (which means taxonomy terms and
80
- * users). This may break suddenly in updates, but I haven't come up with a better
81
- * way so far.
82
  *
83
  * @param string $where The WHERE clause to modify.
84
  *
@@ -87,6 +87,8 @@ function relevanssi_polylang_filter( $query ) {
87
  * @since 2.1.6
88
  */
89
  function relevanssi_polylang_where_include_terms( $where ) {
 
 
90
  $current_language = substr( get_locale(), 0, 2 );
91
  if ( function_exists( 'pll_current_language' ) ) {
92
  $current_language = pll_current_language();
@@ -94,7 +96,11 @@ function relevanssi_polylang_where_include_terms( $where ) {
94
  $languages = get_terms( array( 'taxonomy' => 'language' ) );
95
  $language_id = 0;
96
  foreach ( $languages as $language ) {
97
- if ( ! is_wp_error( $language ) && $language instanceof WP_Term && $language->slug === $current_language ) {
 
 
 
 
98
  $language_id = intval( $language->term_id );
99
  break;
100
  }
@@ -103,9 +109,10 @@ function relevanssi_polylang_where_include_terms( $where ) {
103
  if ( 0 !== $language_id ) {
104
  // Do a simple search-and-replace to modify the query.
105
  $where = preg_replace( '/\s+/', ' ', $where );
 
106
  $where = str_replace(
107
- "AND relevanssi.doc IN (SELECT DISTINCT(tr.object_id) FROM wp_term_relationships AS tr WHERE tr.term_taxonomy_id IN ($language_id))",
108
- "AND (relevanssi.doc IN (SELECT DISTINCT(tr.object_id) FROM wp_term_relationships AS tr WHERE tr.term_taxonomy_id IN ($language_id)) OR (relevanssi.doc = -1))",
109
  $where
110
  );
111
  }
@@ -115,9 +122,10 @@ function relevanssi_polylang_where_include_terms( $where ) {
115
  /**
116
  * Filters out taxonomy terms in the wrong language.
117
  *
118
- * If all languages are not allowed, this filter goes through the results and removes
119
- * the taxonomy terms in the wrong language. This can't be done in the original query
120
- * because the term language information is slightly hard to find.
 
121
  *
122
  * @param array $hits The found posts are in $hits[0].
123
  *
@@ -149,7 +157,10 @@ function relevanssi_polylang_term_filter( $hits ) {
149
  if ( -1 === $hit->ID && isset( $hit->term_id ) ) {
150
  $term_id = intval( $hit->term_id );
151
  $translations = pll_get_term_translations( $term_id );
152
- if ( isset( $translations[ $current_language ] ) && $translations[ $current_language ] === $term_id ) {
 
 
 
153
  $accepted_hits[] = $original_hit;
154
  }
155
  } else {
17
  /**
18
  * Removes the Polylang language filters.
19
  *
20
+ * If the Polylang allow all option ('relevanssi_polylang_all_languages') is
21
+ * enabled this removes the Polylang language filter. By default Polylang
22
+ * filters the languages using a taxonomy query.
23
  *
24
  * @param object $query WP_Query object we need to clean up.
25
  */
75
  /**
76
  * Allows taxonomy terms in language-restricted searches.
77
  *
78
+ * This is a bit of a hack, where the language taxonomy WHERE clause is modified
79
+ * on the go to allow all posts with the post ID -1 (which means taxonomy terms
80
+ * and users). This may break suddenly in updates, but I haven't come up with a
81
+ * better way so far.
82
  *
83
  * @param string $where The WHERE clause to modify.
84
  *
87
  * @since 2.1.6
88
  */
89
  function relevanssi_polylang_where_include_terms( $where ) {
90
+ global $wpdb;
91
+
92
  $current_language = substr( get_locale(), 0, 2 );
93
  if ( function_exists( 'pll_current_language' ) ) {
94
  $current_language = pll_current_language();
96
  $languages = get_terms( array( 'taxonomy' => 'language' ) );
97
  $language_id = 0;
98
  foreach ( $languages as $language ) {
99
+ if (
100
+ ! is_wp_error( $language ) &&
101
+ $language instanceof WP_Term &&
102
+ $language->slug === $current_language
103
+ ) {
104
  $language_id = intval( $language->term_id );
105
  break;
106
  }
109
  if ( 0 !== $language_id ) {
110
  // Do a simple search-and-replace to modify the query.
111
  $where = preg_replace( '/\s+/', ' ', $where );
112
+ $where = preg_replace( '/\(\s/', '(', $where );
113
  $where = str_replace(
114
+ "AND relevanssi.doc IN (SELECT DISTINCT(tr.object_id) FROM {$wpdb->prefix}term_relationships AS tr WHERE tr.term_taxonomy_id IN ($language_id))",
115
+ "AND (relevanssi.doc IN ( SELECT DISTINCT(tr.object_id) FROM {$wpdb->prefix}term_relationships AS tr WHERE tr.term_taxonomy_id IN ($language_id)) OR (relevanssi.doc = -1))",
116
  $where
117
  );
118
  }
122
  /**
123
  * Filters out taxonomy terms in the wrong language.
124
  *
125
+ * If all languages are not allowed, this filter goes through the results and
126
+ * removes the taxonomy terms in the wrong language. This can't be done in the
127
+ * original query because the term language information is slightly hard to
128
+ * find.
129
  *
130
  * @param array $hits The found posts are in $hits[0].
131
  *
157
  if ( -1 === $hit->ID && isset( $hit->term_id ) ) {
158
  $term_id = intval( $hit->term_id );
159
  $translations = pll_get_term_translations( $term_id );
160
+ if (
161
+ isset( $translations[ $current_language ] ) &&
162
+ $translations[ $current_language ] === $term_id
163
+ ) {
164
  $accepted_hits[] = $original_hit;
165
  }
166
  } else {
lib/compatibility/seopress.php CHANGED
@@ -22,12 +22,13 @@ add_filter( 'relevanssi_indexing_restriction', 'relevanssi_seopress_exclude' );
22
  * @param boolean $do_not_index True, if the post shouldn't be indexed.
23
  * @param integer $post_id The post ID number.
24
  *
25
- * @return boolean True, if the post shouldn't be indexed.
 
26
  */
27
  function relevanssi_seopress_noindex( $do_not_index, $post_id ) {
28
  $noindex = get_post_meta( $post_id, '_seopress_robots_index', true );
29
  if ( 'yes' === $noindex ) {
30
- $do_not_index = true;
31
  }
32
  return $do_not_index;
33
  }
@@ -38,10 +39,22 @@ function relevanssi_seopress_noindex( $do_not_index, $post_id ) {
38
  * Adds a MySQL query restriction that blocks posts that have the SEOPress
39
  * "noindex" setting set to "1" from indexing.
40
  *
41
- * @param string $restriction The MySQL query restriction to modify.
 
42
  */
43
  function relevanssi_seopress_exclude( $restriction ) {
44
  global $wpdb;
45
- $restriction .= " AND post.ID NOT IN (SELECT post_id FROM $wpdb->postmeta WHERE meta_key = '_seopress_robots_index' AND meta_value = 'yes' ) ";
 
 
 
 
 
 
 
 
 
 
 
46
  return $restriction;
47
  }
22
  * @param boolean $do_not_index True, if the post shouldn't be indexed.
23
  * @param integer $post_id The post ID number.
24
  *
25
+ * @return string|boolean If the post shouldn't be indexed, this returns
26
+ * 'seopress'. The value may also be a boolean.
27
  */
28
  function relevanssi_seopress_noindex( $do_not_index, $post_id ) {
29
  $noindex = get_post_meta( $post_id, '_seopress_robots_index', true );
30
  if ( 'yes' === $noindex ) {
31
+ $do_not_index = 'SEOPress';
32
  }
33
  return $do_not_index;
34
  }
39
  * Adds a MySQL query restriction that blocks posts that have the SEOPress
40
  * "noindex" setting set to "1" from indexing.
41
  *
42
+ * @param array $restriction An array with two values: 'mysql' for the MySQL
43
+ * query restriction to modify, 'reason' for the reason of restriction.
44
  */
45
  function relevanssi_seopress_exclude( $restriction ) {
46
  global $wpdb;
47
+ // Backwards compatibility code for 2.8.0, remove at some point.
48
+ if ( is_string( $restriction ) ) {
49
+ $restriction = array(
50
+ 'mysql' => $restriction,
51
+ 'reason' => '',
52
+ );
53
+ }
54
+
55
+ $restriction['mysql'] .= " AND post.ID NOT IN (SELECT post_id FROM
56
+ $wpdb->postmeta WHERE meta_key = '_seopress_robots_index'
57
+ AND meta_value = 'yes' ) ";
58
+ $restriction['reason'] .= 'SEOPress';
59
  return $restriction;
60
  }
lib/compatibility/woocommerce.php CHANGED
@@ -15,12 +15,20 @@ add_filter( 'relevanssi_indexing_restriction', 'relevanssi_woocommerce_restricti
15
  /**
16
  * Applies the WooCommerce product visibility filter.
17
  *
18
- * @param string $restriction The restriction clause.
19
- *
20
- * @return string The restriction clause with the WC filter added, if necessary.
21
  */
22
  function relevanssi_woocommerce_restriction( $restriction ) {
23
- $restriction .= relevanssi_woocommerce_indexing_filter();
 
 
 
 
 
 
 
 
 
24
  return $restriction;
25
  }
26
 
15
  /**
16
  * Applies the WooCommerce product visibility filter.
17
  *
18
+ * @param array $restriction An array with two values: 'mysql' for the MySQL
19
+ * query restriction to modify, 'reason' for the reason of restriction.
 
20
  */
21
  function relevanssi_woocommerce_restriction( $restriction ) {
22
+ // Backwards compatibility code for 2.8.0, remove at some point.
23
+ if ( is_string( $restriction ) ) {
24
+ $restriction = array(
25
+ 'mysql' => $restriction,
26
+ 'reason' => '',
27
+ );
28
+ }
29
+
30
+ $restriction['mysql'] .= relevanssi_woocommerce_indexing_filter();
31
+ $restriction['reason'] .= 'WooCommerce';
32
  return $restriction;
33
  }
34
 
lib/compatibility/yoast-seo.php CHANGED
@@ -21,12 +21,13 @@ add_filter( 'relevanssi_indexing_restriction', 'relevanssi_yoast_exclude' );
21
  * @param boolean $do_not_index True, if the post shouldn't be indexed.
22
  * @param integer $post_id The post ID number.
23
  *
24
- * @return boolean True, if the post shouldn't be indexed.
 
25
  */
26
  function relevanssi_yoast_noindex( $do_not_index, $post_id ) {
27
  $noindex = get_post_meta( $post_id, '_yoast_wpseo_meta-robots-noindex', true );
28
  if ( '1' === $noindex ) {
29
- $do_not_index = true;
30
  }
31
  return $do_not_index;
32
  }
@@ -37,10 +38,23 @@ function relevanssi_yoast_noindex( $do_not_index, $post_id ) {
37
  * Adds a MySQL query restriction that blocks posts that have the Yoast SEO
38
  * "noindex" setting set to "1" from indexing.
39
  *
40
- * @param string $restriction The MySQL query restriction to modify.
 
41
  */
42
  function relevanssi_yoast_exclude( $restriction ) {
43
  global $wpdb;
44
- $restriction .= " AND post.ID NOT IN (SELECT post_id FROM $wpdb->postmeta WHERE meta_key = '_yoast_wpseo_meta-robots-noindex' AND meta_value = '1' ) ";
 
 
 
 
 
 
 
 
 
 
 
 
45
  return $restriction;
46
  }
21
  * @param boolean $do_not_index True, if the post shouldn't be indexed.
22
  * @param integer $post_id The post ID number.
23
  *
24
+ * @return string|boolean If the post shouldn't be indexed, this returns
25
+ * 'yoast_seo'. The value may also be a boolean.
26
  */
27
  function relevanssi_yoast_noindex( $do_not_index, $post_id ) {
28
  $noindex = get_post_meta( $post_id, '_yoast_wpseo_meta-robots-noindex', true );
29
  if ( '1' === $noindex ) {
30
+ $do_not_index = 'Yoast SEO';
31
  }
32
  return $do_not_index;
33
  }
38
  * Adds a MySQL query restriction that blocks posts that have the Yoast SEO
39
  * "noindex" setting set to "1" from indexing.
40
  *
41
+ * @param array $restriction An array with two values: 'mysql' for the MySQL
42
+ * query restriction to modify, 'reason' for the reason of restriction.
43
  */
44
  function relevanssi_yoast_exclude( $restriction ) {
45
  global $wpdb;
46
+
47
+ // Backwards compatibility code for 2.8.0, remove at some point.
48
+ if ( is_string( $restriction ) ) {
49
+ $restriction = array(
50
+ 'mysql' => $restriction,
51
+ 'reason' => '',
52
+ );
53
+ }
54
+
55
+ $restriction['mysql'] .= " AND post.ID NOT IN (SELECT post_id FROM
56
+ $wpdb->postmeta WHERE meta_key = '_yoast_wpseo_meta-robots-noindex'
57
+ AND meta_value = '1' ) ";
58
+ $restriction['reason'] .= ' Yoast SEO';
59
  return $restriction;
60
  }
lib/excerpts-highlights.php CHANGED
@@ -58,7 +58,7 @@ function relevanssi_do_excerpt( $t_post, $query, $excerpt_length = null, $excerp
58
  }
59
  $post = $t_post; // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited
60
 
61
- $remove_stopwords = true;
62
 
63
  /**
64
  * Filters the search query before excerpt-building.
@@ -88,7 +88,10 @@ function relevanssi_do_excerpt( $t_post, $query, $excerpt_length = null, $excerp
88
  } else {
89
  $untokenized_terms = array_filter( explode( ' ', $query ) );
90
  }
91
- $terms = array_merge( array_flip( $untokenized_terms ), $terms );
 
 
 
92
 
93
  // These shortcodes cause problems with Relevanssi excerpts.
94
  $problem_shortcodes = array( 'layerslider', 'responsive-flipbook', 'breadcrumb', 'robogallery', 'gravityview', 'wp_show_posts' );
@@ -102,9 +105,7 @@ function relevanssi_do_excerpt( $t_post, $query, $excerpt_length = null, $excerp
102
  * @param array $problem_shortcodes Array of problematic shortcode names.
103
  */
104
  $problem_shortcodes = apply_filters( 'relevanssi_disable_shortcodes_excerpt', $problem_shortcodes );
105
- foreach ( $problem_shortcodes as $shortcode ) {
106
- remove_shortcode( $shortcode );
107
- }
108
 
109
  /**
110
  * Filters the post content before 'the_content'.
@@ -118,6 +119,9 @@ function relevanssi_do_excerpt( $t_post, $query, $excerpt_length = null, $excerp
118
  */
119
  $content = apply_filters( 'relevanssi_pre_excerpt_content', $post->post_content, $post, $query );
120
 
 
 
 
121
  // Add the custom field content.
122
  if ( 'on' === get_option( 'relevanssi_excerpt_custom_fields' ) ) {
123
  $content .= relevanssi_get_custom_field_content( $post->ID );
@@ -450,7 +454,7 @@ function relevanssi_highlight_terms( $content, $query, $in_docs = false ) {
450
  $min_word_length = 1;
451
  }
452
 
453
- $remove_stopwords = true;
454
  $terms = array_keys(
455
  relevanssi_tokenize(
456
  $query,
@@ -459,27 +463,27 @@ function relevanssi_highlight_terms( $content, $query, $in_docs = false ) {
459
  )
460
  );
461
 
462
- if ( is_array( $query ) ) {
463
- $untokenized_terms = array_filter(
464
- $query,
465
- function( $value ) use ( $min_word_length ) {
466
- if ( relevanssi_strlen( $value ) > $min_word_length ) {
467
- return true;
468
- }
 
 
 
 
 
469
  return false;
470
  }
471
- );
472
- } else {
473
- $untokenized_terms = array_filter(
474
- explode( ' ', $query ),
475
- function( $value ) use ( $min_word_length ) {
476
- if ( relevanssi_strlen( $value ) > $min_word_length ) {
477
- return true;
478
- }
479
- return false;
480
  }
481
- );
482
- }
 
 
483
  $terms = array_unique( array_merge( $untokenized_terms, $terms ) );
484
  array_walk( $terms, 'relevanssi_array_walk_trim' ); // Numeric search terms begin with a space.
485
 
@@ -503,9 +507,9 @@ function relevanssi_highlight_terms( $content, $query, $in_docs = false ) {
503
 
504
  usort( $terms, 'relevanssi_strlen_sort' );
505
 
506
- $word_boundaries_available = true;
507
  if ( 'on' === get_option( 'relevanssi_word_boundaries', 'off' ) ) {
508
- $word_boundaries_available = false;
509
  }
510
 
511
  $content = html_entity_decode( $content, ENT_QUOTES, 'UTF-8' );
@@ -1116,7 +1120,7 @@ function relevanssi_add_accent_variations( $word ) {
1116
  $escaped = false;
1117
  for ( $i = 0; $i < $len; $i++ ) {
1118
  $char = relevanssi_substr( $word, $i, 1 );
1119
- if ( '\\' === $char ) {
1120
  $escaped = true;
1121
  continue;
1122
  }
58
  }
59
  $post = $t_post; // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited
60
 
61
+ $remove_stopwords = 'body';
62
 
63
  /**
64
  * Filters the search query before excerpt-building.
88
  } else {
89
  $untokenized_terms = array_filter( explode( ' ', $query ) );
90
  }
91
+ $untokenized_terms = array_flip(
92
+ relevanssi_remove_stopwords_from_array( $untokenized_terms )
93
+ );
94
+ $terms = array_merge( $untokenized_terms, $terms );
95
 
96
  // These shortcodes cause problems with Relevanssi excerpts.
97
  $problem_shortcodes = array( 'layerslider', 'responsive-flipbook', 'breadcrumb', 'robogallery', 'gravityview', 'wp_show_posts' );
105
  * @param array $problem_shortcodes Array of problematic shortcode names.
106
  */
107
  $problem_shortcodes = apply_filters( 'relevanssi_disable_shortcodes_excerpt', $problem_shortcodes );
108
+ array_walk( $problem_shortcodes, 'remove_shortcode' );
 
 
109
 
110
  /**
111
  * Filters the post content before 'the_content'.
119
  */
120
  $content = apply_filters( 'relevanssi_pre_excerpt_content', $post->post_content, $post, $query );
121
 
122
+ $pattern = get_shortcode_regex( $problem_shortcodes );
123
+ $content = preg_replace_callback( "/$pattern/", 'strip_shortcode_tag', $content );
124
+
125
  // Add the custom field content.
126
  if ( 'on' === get_option( 'relevanssi_excerpt_custom_fields' ) ) {
127
  $content .= relevanssi_get_custom_field_content( $post->ID );
454
  $min_word_length = 1;
455
  }
456
 
457
+ $remove_stopwords = 'body';
458
  $terms = array_keys(
459
  relevanssi_tokenize(
460
  $query,
463
  )
464
  );
465
 
466
+ if ( ! is_array( $query ) ) {
467
+ $query = explode( ' ', $query );
468
+ }
469
+
470
+ $body_stopwords = function_exists( 'relevanssi_fetch_body_stopwords' )
471
+ ? relevanssi_fetch_body_stopwords()
472
+ : array();
473
+
474
+ $untokenized_terms = array_filter(
475
+ $query,
476
+ function( $value ) use ( $min_word_length, $body_stopwords ) {
477
+ if ( in_array( $value, $body_stopwords, true ) ) {
478
  return false;
479
  }
480
+ if ( relevanssi_strlen( $value ) > $min_word_length ) {
481
+ return true;
 
 
 
 
 
 
 
482
  }
483
+ return false;
484
+ }
485
+ );
486
+
487
  $terms = array_unique( array_merge( $untokenized_terms, $terms ) );
488
  array_walk( $terms, 'relevanssi_array_walk_trim' ); // Numeric search terms begin with a space.
489
 
507
 
508
  usort( $terms, 'relevanssi_strlen_sort' );
509
 
510
+ $word_boundaries_available = false;
511
  if ( 'on' === get_option( 'relevanssi_word_boundaries', 'off' ) ) {
512
+ $word_boundaries_available = true;
513
  }
514
 
515
  $content = html_entity_decode( $content, ENT_QUOTES, 'UTF-8' );
1120
  $escaped = false;
1121
  for ( $i = 0; $i < $len; $i++ ) {
1122
  $char = relevanssi_substr( $word, $i, 1 );
1123
+ if ( '\\' === $char && ! $escaped ) {
1124
  $escaped = true;
1125
  continue;
1126
  }
lib/indexing.php CHANGED
@@ -117,9 +117,25 @@ function relevanssi_generate_indexing_query( $valid_status, $extend = false, $re
117
  *
118
  * @param string The WHERE restriction.
119
  *
120
- * @return string The modified WHERE restriction.
 
121
  */
122
- $restriction = apply_filters( 'relevanssi_indexing_restriction', $restriction );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
123
 
124
  if ( ! $extend ) {
125
  $q = "SELECT post.ID
@@ -135,7 +151,7 @@ function relevanssi_generate_indexing_query( $valid_status, $extend = false, $re
135
  )
136
  ))
137
  AND post.ID NOT IN (SELECT post_id FROM $wpdb->postmeta WHERE meta_key = '_relevanssi_hide_post' AND meta_value = 'on')
138
- $restriction ORDER BY post.ID DESC $limit";
139
  } else {
140
  $processed_post_filter = 'r.doc is null';
141
  if ( 'noindex' !== get_option( 'relevanssi_internal_links', 'noindex' ) ) {
@@ -159,7 +175,7 @@ function relevanssi_generate_indexing_query( $valid_status, $extend = false, $re
159
  )
160
  )
161
  AND post.ID NOT IN (SELECT post_id FROM $wpdb->postmeta WHERE meta_key = '_relevanssi_hide_post' AND meta_value = 'on')
162
- $restriction ORDER BY post.ID DESC $limit";
163
  }
164
 
165
  /**
@@ -443,6 +459,11 @@ function relevanssi_index_doc( $index_post, $remove_first = false, $custom_field
443
  if ( $previous_post || $post_was_null ) {
444
  $post = $previous_post; // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited
445
  }
 
 
 
 
 
446
  return 'hide';
447
  }
448
  }
@@ -460,14 +481,21 @@ function relevanssi_index_doc( $index_post, $remove_first = false, $custom_field
460
  *
461
  * Allows you to filter whether a post is indexed or not.
462
  *
463
- * @param boolean If true, the post is not indexed. Default false.
464
- * @param int The post ID.
 
 
465
  */
466
- if ( true === apply_filters( 'relevanssi_do_not_index', false, $post->ID ) ) {
 
467
  // Filter says no.
 
 
 
468
  if ( $debug ) {
469
- relevanssi_debug_echo( 'relevanssi_do_not_index returned true.' );
470
  }
 
471
  $index_this_post = false;
472
  }
473
 
@@ -558,6 +586,8 @@ function relevanssi_index_doc( $index_post, $remove_first = false, $custom_field
558
  $wpdb->query( $query ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
559
  }
560
 
 
 
561
  if ( $previous_post || $post_was_null ) {
562
  $post = $previous_post; // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited
563
  }
@@ -609,7 +639,14 @@ function relevanssi_index_taxonomy_terms( &$insert_data, $post_id, $taxonomy, $d
609
  * @param int The post ID.
610
  */
611
  $term_string = apply_filters( 'relevanssi_tag_before_tokenize', trim( $term_string ), $post_term, $taxonomy, $post_id );
612
- $term_tokens = relevanssi_tokenize( $term_string, true, $min_word_length );
 
 
 
 
 
 
 
613
  if ( count( $term_tokens ) > 0 ) {
614
  foreach ( $term_tokens as $token => $count ) {
615
  $n++;
@@ -794,11 +831,19 @@ function relevanssi_insert_edit( $post_id ) {
794
  $index_this_post = true;
795
 
796
  /* Documented in lib/indexing.php. */
797
- $restriction = apply_filters( 'relevanssi_indexing_restriction', '' );
798
- if ( ! empty( $restriction ) ) {
 
 
 
 
 
 
799
  // Check the indexing restriction filter: if the post passes the filter, this
800
  // should return the post ID.
801
- $is_unrestricted = $wpdb->get_var( "SELECT ID FROM $wpdb->posts AS post WHERE ID = $post_id $restriction" ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared,WordPress.DB.PreparedSQL.InterpolatedNotPrepared
 
 
802
  if ( ! $is_unrestricted ) {
803
  $index_this_post = false;
804
  }
@@ -816,6 +861,11 @@ function relevanssi_insert_edit( $post_id ) {
816
  } else {
817
  // The post isn't supposed to be indexed anymore, remove it from index.
818
  relevanssi_remove_doc( $post_id );
 
 
 
 
 
819
  $return_value = 'removed';
820
  }
821
 
@@ -1440,6 +1490,17 @@ function relevanssi_index_content( &$insert_data, $post, $min_word_length, $debu
1440
  remove_shortcode( 'noindex' );
1441
  add_shortcode( 'noindex', 'relevanssi_noindex_shortcode' );
1442
 
 
 
 
 
 
 
 
 
 
 
 
1443
  $contents = relevanssi_strip_invisibles( $contents );
1444
 
1445
  // Premium feature for better control over internal links.
@@ -1449,7 +1510,6 @@ function relevanssi_index_content( &$insert_data, $post, $min_word_length, $debu
1449
 
1450
  $contents = preg_replace( '/<[a-zA-Z\/][^>]*>/', ' ', $contents );
1451
  $contents = wp_strip_all_tags( $contents );
1452
- $contents = wp_encode_emoji( $contents );
1453
 
1454
  /**
1455
  * Filters the post content in indexing before tokenization.
@@ -1570,6 +1630,7 @@ function relevanssi_disable_shortcodes() {
1570
  * insert query values before and after the conversion.
1571
  *
1572
  * @global $wpdb The WordPress database interface.
 
1573
  *
1574
  * @param array $insert_data An array of term => data pairs, where data has
1575
  * token counts for the term in different contexts.
@@ -1578,7 +1639,12 @@ function relevanssi_disable_shortcodes() {
1578
  * @return array An array of values clauses for an INSERT query.
1579
  */
1580
  function relevanssi_convert_data_to_values( $insert_data, $post ) {
1581
- global $wpdb;
 
 
 
 
 
1582
 
1583
  /**
1584
  * Sets the indexed post 'type' column in the index.
@@ -1615,6 +1681,10 @@ function relevanssi_convert_data_to_values( $insert_data, $post ) {
1615
  $taxonomy_detail = isset( $data['taxonomy_detail'] ) ? $data['taxonomy_detail'] : '';
1616
  $customfield_detail = isset( $data['customfield_detail'] ) ? $data['customfield_detail'] : '';
1617
 
 
 
 
 
1618
  $term = trim( $term );
1619
 
1620
  $value = $wpdb->prepare(
117
  *
118
  * @param string The WHERE restriction.
119
  *
120
+ * @param array $restriction An array with two values: 'mysql' for the MySQL
121
+ * query restriction to modify, 'reason' for the reason of restriction.
122
  */
123
+ $restriction = apply_filters(
124
+ 'relevanssi_indexing_restriction',
125
+ array(
126
+ 'mysql' => $restriction,
127
+ 'reason' => '',
128
+ )
129
+ );
130
+
131
+ /**
132
+ * Backwards compatibility for the change in filter parameters in Premium
133
+ * 2.8.0 in March 2020. Remove this eventually.
134
+ */
135
+ if ( is_string( $restriction ) ) {
136
+ $restriction['mysql'] = $restriction;
137
+ $restriction['reason'] = 'relevanssi_indexing_restriction filter';
138
+ }
139
 
140
  if ( ! $extend ) {
141
  $q = "SELECT post.ID
151
  )
152
  ))
153
  AND post.ID NOT IN (SELECT post_id FROM $wpdb->postmeta WHERE meta_key = '_relevanssi_hide_post' AND meta_value = 'on')
154
+ {$restriction['mysql']} ORDER BY post.ID DESC $limit";
155
  } else {
156
  $processed_post_filter = 'r.doc is null';
157
  if ( 'noindex' !== get_option( 'relevanssi_internal_links', 'noindex' ) ) {
175
  )
176
  )
177
  AND post.ID NOT IN (SELECT post_id FROM $wpdb->postmeta WHERE meta_key = '_relevanssi_hide_post' AND meta_value = 'on')
178
+ {$restriction['mysql']} ORDER BY post.ID DESC $limit";
179
  }
180
 
181
  /**
459
  if ( $previous_post || $post_was_null ) {
460
  $post = $previous_post; // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited
461
  }
462
+ update_post_meta(
463
+ $post->ID,
464
+ '_relevanssi_noindex_reason',
465
+ __( 'Relevanssi index exclude', 'relevanssi' )
466
+ );
467
  return 'hide';
468
  }
469
  }
481
  *
482
  * Allows you to filter whether a post is indexed or not.
483
  *
484
+ * @param boolean|string If not false, the post is not indexed. The value
485
+ * can be a boolean, or a string containing an explanation for the
486
+ * exclusion. Default false.
487
+ * @param int The post ID.
488
  */
489
+ $do_not_index = apply_filters( 'relevanssi_do_not_index', false, $post->ID );
490
+ if ( $do_not_index ) {
491
  // Filter says no.
492
+ if ( true === $do_not_index ) {
493
+ $do_not_index = __( 'Blocked by a filter function', 'relevanssi' );
494
+ }
495
  if ( $debug ) {
496
+ relevanssi_debug_echo( 'relevanssi_do_not_index says exclude, because: ' . $do_not_index );
497
  }
498
+ update_post_meta( $post->ID, '_relevanssi_noindex_reason', $do_not_index );
499
  $index_this_post = false;
500
  }
501
 
586
  $wpdb->query( $query ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
587
  }
588
 
589
+ delete_post_meta( $post->ID, '_relevanssi_noindex_reason' );
590
+
591
  if ( $previous_post || $post_was_null ) {
592
  $post = $previous_post; // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited
593
  }
639
  * @param int The post ID.
640
  */
641
  $term_string = apply_filters( 'relevanssi_tag_before_tokenize', trim( $term_string ), $post_term, $taxonomy, $post_id );
642
+
643
+ /** This filter is documented in lib/indexing.php */
644
+ $term_tokens = apply_filters(
645
+ 'relevanssi_indexing_tokens',
646
+ relevanssi_tokenize( $term_string, true, $min_word_length ),
647
+ 'taxonomy-' . $taxonomy
648
+ );
649
+
650
  if ( count( $term_tokens ) > 0 ) {
651
  foreach ( $term_tokens as $token => $count ) {
652
  $n++;
831
  $index_this_post = true;
832
 
833
  /* Documented in lib/indexing.php. */
834
+ $restriction = apply_filters(
835
+ 'relevanssi_indexing_restriction',
836
+ array(
837
+ 'mysql' => '',
838
+ 'reason' => '',
839
+ )
840
+ );
841
+ if ( ! empty( $restriction['mysql'] ) ) {
842
  // Check the indexing restriction filter: if the post passes the filter, this
843
  // should return the post ID.
844
+ $is_unrestricted = $wpdb->get_var(
845
+ "SELECT ID FROM $wpdb->posts AS post WHERE ID = $post_id {$restriction['mysql']}" // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared,WordPress.DB.PreparedSQL.InterpolatedNotPrepared
846
+ );
847
  if ( ! $is_unrestricted ) {
848
  $index_this_post = false;
849
  }
861
  } else {
862
  // The post isn't supposed to be indexed anymore, remove it from index.
863
  relevanssi_remove_doc( $post_id );
864
+ update_post_meta(
865
+ $post_id,
866
+ '_relevanssi_noindex_reason',
867
+ trim( $restriction['reason'] )
868
+ );
869
  $return_value = 'removed';
870
  }
871
 
1490
  remove_shortcode( 'noindex' );
1491
  add_shortcode( 'noindex', 'relevanssi_noindex_shortcode' );
1492
 
1493
+ /**
1494
+ * Filters the post content after shortcodes but before HTML stripping.
1495
+ *
1496
+ * @param string $contents The post content.
1497
+ * @param object $post The full post object.
1498
+ */
1499
+ $contents = apply_filters(
1500
+ 'relevanssi_post_content_after_shortcodes',
1501
+ $contents,
1502
+ $post
1503
+ );
1504
  $contents = relevanssi_strip_invisibles( $contents );
1505
 
1506
  // Premium feature for better control over internal links.
1510
 
1511
  $contents = preg_replace( '/<[a-zA-Z\/][^>]*>/', ' ', $contents );
1512
  $contents = wp_strip_all_tags( $contents );
 
1513
 
1514
  /**
1515
  * Filters the post content in indexing before tokenization.
1630
  * insert query values before and after the conversion.
1631
  *
1632
  * @global $wpdb The WordPress database interface.
1633
+ * @global $relevanssi_variables Used for the Relevanssi db table name.
1634
  *
1635
  * @param array $insert_data An array of term => data pairs, where data has
1636
  * token counts for the term in different contexts.
1639
  * @return array An array of values clauses for an INSERT query.
1640
  */
1641
  function relevanssi_convert_data_to_values( $insert_data, $post ) {
1642
+ global $wpdb, $relevanssi_variables;
1643
+
1644
+ $charset = $wpdb->get_col_charset(
1645
+ $relevanssi_variables['relevanssi_table'],
1646
+ 'term'
1647
+ );
1648
 
1649
  /**
1650
  * Sets the indexed post 'type' column in the index.
1681
  $taxonomy_detail = isset( $data['taxonomy_detail'] ) ? $data['taxonomy_detail'] : '';
1682
  $customfield_detail = isset( $data['customfield_detail'] ) ? $data['customfield_detail'] : '';
1683
 
1684
+ if ( 'utf8' === $charset ) {
1685
+ $term = wp_encode_emoji( $term );
1686
+ }
1687
+
1688
  $term = trim( $term );
1689
 
1690
  $value = $wpdb->prepare(
lib/init.php CHANGED
@@ -19,6 +19,9 @@ add_action( 'admin_menu', 'relevanssi_menu' );
19
  // Taking over the search.
20
  add_filter( 'the_posts', 'relevanssi_query', 99, 2 );
21
  add_filter( 'posts_request', 'relevanssi_prevent_default_request', 10, 2 );
 
 
 
22
 
23
  // Post indexing.
24
  add_action( 'wp_insert_post', 'relevanssi_insert_edit', 99, 1 );
@@ -288,6 +291,7 @@ function relevanssi_query_vars( $qv ) {
288
  $qv[] = 'by_date';
289
  $qv[] = 'highlight';
290
  $qv[] = 'posts_per_page';
 
291
 
292
  return $qv;
293
  }
19
  // Taking over the search.
20
  add_filter( 'the_posts', 'relevanssi_query', 99, 2 );
21
  add_filter( 'posts_request', 'relevanssi_prevent_default_request', 10, 2 );
22
+ add_filter( 'relevanssi_search_ok', 'relevanssi_block_on_admin_searches', 10, 2 );
23
+ add_filter( 'relevanssi_admin_search_ok', 'relevanssi_block_on_admin_searches', 10, 2 );
24
+ add_filter( 'relevanssi_prevent_default_request', 'relevanssi_block_on_admin_searches', 10, 2 );
25
 
26
  // Post indexing.
27
  add_action( 'wp_insert_post', 'relevanssi_insert_edit', 99, 1 );
291
  $qv[] = 'by_date';
292
  $qv[] = 'highlight';
293
  $qv[] = 'posts_per_page';
294
+ $qv[] = 'post_parent';
295
 
296
  return $qv;
297
  }
lib/search.php CHANGED
@@ -50,13 +50,6 @@ function relevanssi_query( $posts, $query = false ) {
50
  $search_ok = false; // No search term.
51
  }
52
 
53
- // Disable Relevanssi in the media library search.
54
- if ( $search_ok ) {
55
- if ( 'attachment' === $query->query_vars['post_type'] && 'inherit,private' === $query->query_vars['post_status'] ) {
56
- $search_ok = false;
57
- }
58
- }
59
-
60
  /**
61
  * Filters whether Relevanssi search can be run or not.
62
  *
@@ -132,6 +125,8 @@ function relevanssi_search( $args ) {
132
  $q_no_synonyms = $query_data['query_no_synonyms'];
133
  $phrase_queries = $query_data['phrase_queries'];
134
 
 
 
135
  /**
136
  * Filters whether stopwords are removed from titles.
137
  *
@@ -139,7 +134,7 @@ function relevanssi_search( $args ) {
139
  */
140
  $remove_stopwords = apply_filters( 'relevanssi_remove_stopwords_in_titles', true );
141
 
142
- $terms = relevanssi_tokenize( $q, $remove_stopwords );
143
  $terms = array_keys( $terms ); // Don't care about tf in query.
144
 
145
  if ( function_exists( 'relevanssi_process_terms' ) ) {
@@ -228,8 +223,6 @@ function relevanssi_search( $args ) {
228
 
229
  }
230
 
231
- $min_length = get_option( 'relevanssi_min_word_length' );
232
-
233
  $search_again = false;
234
 
235
  $content_boost = floatval( get_option( 'relevanssi_content_boost', 1 ) ); // Default value, because this option was added late.
@@ -1318,8 +1311,8 @@ function relevanssi_compile_search_args( $query, $q ) {
1318
  }
1319
 
1320
  $parent_query = array();
1321
- if ( isset( $query->query_vars['post_parent'] ) ) {
1322
- $parent_query = array( 'parent in' => array( $query->query_vars['post_parent'] ) );
1323
  }
1324
  if ( isset( $query->query_vars['post_parent__in'] ) && is_array( $query->query_vars['post_parent__in'] ) && ! empty( $query->query_vars['post_parent__in'] ) ) {
1325
  $parent_query = array( 'parent in' => $query->query_vars['post_parent__in'] );
50
  $search_ok = false; // No search term.
51
  }
52
 
 
 
 
 
 
 
 
53
  /**
54
  * Filters whether Relevanssi search can be run or not.
55
  *
125
  $q_no_synonyms = $query_data['query_no_synonyms'];
126
  $phrase_queries = $query_data['phrase_queries'];
127
 
128
+ $min_length = get_option( 'relevanssi_min_word_length' );
129
+
130
  /**
131
  * Filters whether stopwords are removed from titles.
132
  *
134
  */
135
  $remove_stopwords = apply_filters( 'relevanssi_remove_stopwords_in_titles', true );
136
 
137
+ $terms = relevanssi_tokenize( $q, $remove_stopwords, $min_length );
138
  $terms = array_keys( $terms ); // Don't care about tf in query.
139
 
140
  if ( function_exists( 'relevanssi_process_terms' ) ) {
223
 
224
  }
225
 
 
 
226
  $search_again = false;
227
 
228
  $content_boost = floatval( get_option( 'relevanssi_content_boost', 1 ) ); // Default value, because this option was added late.
1311
  }
1312
 
1313
  $parent_query = array();
1314
+ if ( isset( $query->query_vars['post_parent'] ) && '' !== $query->query_vars['post_parent'] ) {
1315
+ $parent_query = array( 'parent in' => array( (int) $query->query_vars['post_parent'] ) );
1316
  }
1317
  if ( isset( $query->query_vars['post_parent__in'] ) && is_array( $query->query_vars['post_parent__in'] ) && ! empty( $query->query_vars['post_parent__in'] ) ) {
1318
  $parent_query = array( 'parent in' => $query->query_vars['post_parent__in'] );
lib/shortcodes.php CHANGED
@@ -32,8 +32,6 @@ add_shortcode( 'searchform', 'relevanssi_search_form' );
32
  * @return string A link to search results.
33
  */
34
  function relevanssi_shortcode( $atts, $content ) {
35
- global $wpdb;
36
-
37
  $attributes = shortcode_atts(
38
  array(
39
  'term' => false,
32
  * @return string A link to search results.
33
  */
34
  function relevanssi_shortcode( $atts, $content ) {
 
 
35
  $attributes = shortcode_atts(
36
  array(
37
  'term' => false,
lib/stopwords.php CHANGED
@@ -303,3 +303,22 @@ function relevanssi_remove_stopword( $term, $verbose = true ) {
303
 
304
  return $success;
305
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
303
 
304
  return $success;
305
  }
306
+
307
+ /**
308
+ * Helper function to remove stopwords from an array.
309
+ *
310
+ * Removes all stopwords from an array of terms. If body stopwords are
311
+ * available, those will also be removed. The terms must be in the array values.
312
+ *
313
+ * @param array $terms An array of terms to clean out.
314
+ *
315
+ * @return array An array of terms with stopwords removed.
316
+ */
317
+ function relevanssi_remove_stopwords_from_array( $terms ) {
318
+ $stopword_list = relevanssi_fetch_stopwords();
319
+ if ( function_exists( 'relevanssi_fetch_body_stopwords' ) ) {
320
+ $stopword_list = array_merge( $stopword_list, relevanssi_fetch_body_stopwords() );
321
+ }
322
+ $terms_without_stops = array_diff( $terms, $stopword_list );
323
+ return $terms_without_stops;
324
+ }
lib/uninstall.php CHANGED
@@ -132,5 +132,8 @@ function relevanssi_uninstall_free() {
132
  delete_option( 'relevanssi_taxonomies_to_index' );
133
  delete_option( 'relevanssi_highlight_docs_external' );
134
 
 
 
 
135
  relevanssi_drop_database_tables();
136
  }
132
  delete_option( 'relevanssi_taxonomies_to_index' );
133
  delete_option( 'relevanssi_highlight_docs_external' );
134
 
135
+ global $wpdb;
136
+ $wpdb->query( "DELETE FROM $wpdb->postmeta WHERE meta_key = '_relevanssi_noindex_reason'" );
137
+
138
  relevanssi_drop_database_tables();
139
  }
readme.txt CHANGED
@@ -5,7 +5,7 @@ Tags: search, relevance, better search
5
  Requires at least: 4.9
6
  Tested up to: 5.4
7
  Requires PHP: 5.6
8
- Stable tag: 4.7.0
9
  License: GPLv2 or later
10
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
11
 
@@ -133,6 +133,10 @@ Each document database is full of useless words. All the little words that appea
133
  * John Calahan for extensive 4.0 beta testing.
134
 
135
  == Changelog ==
 
 
 
 
136
  = 4.7.0 =
137
  * New feature: New filter hook `relevanssi_admin_search_blocked_post_types` makes it easy to block Relevanssi from searching a specific post type in the admin dashboard. There's built-in support for Reusable Content Blocks `rc_blocks` post type, for example.
138
  * New feature: The reason why a post is not indexed is now stored in the `_relevanssi_noindex_reason` custom field.
@@ -170,6 +174,9 @@ Each document database is full of useless words. All the little words that appea
170
  * Minor fix: Indexing did not adjust the number of posts indexed at one go like it should.
171
 
172
  == Upgrade notice ==
 
 
 
173
  = 4.7.0 =
174
  * The `relevanssi_indexing_restriction` filter hook has been changed, stopwords are handled in a different way in excerpts.
175
 
5
  Requires at least: 4.9
6
  Tested up to: 5.4
7
  Requires PHP: 5.6
8
+ Stable tag: 4.7.1
9
  License: GPLv2 or later
10
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
11
 
133
  * John Calahan for extensive 4.0 beta testing.
134
 
135
  == Changelog ==
136
+ = 4.7.1 =
137
+ * New feature: New filter hook `relevanssi_post_content_after_shortcodes` filters the post content after shortcodes have been processed but before the HTML tags are stripped.
138
+ * Minor fix: Adds more backwards compatibility for the `relevanssi_indexing_restriction` change.
139
+
140
  = 4.7.0 =
141
  * New feature: New filter hook `relevanssi_admin_search_blocked_post_types` makes it easy to block Relevanssi from searching a specific post type in the admin dashboard. There's built-in support for Reusable Content Blocks `rc_blocks` post type, for example.
142
  * New feature: The reason why a post is not indexed is now stored in the `_relevanssi_noindex_reason` custom field.
174
  * Minor fix: Indexing did not adjust the number of posts indexed at one go like it should.
175
 
176
  == Upgrade notice ==
177
+ = 4.7.1 =
178
+ * Improved backwards compatibility for the `relevanssi_indexing_restriction` filter hook change.
179
+
180
  = 4.7.0 =
181
  * The `relevanssi_indexing_restriction` filter hook has been changed, stopwords are handled in a different way in excerpts.
182
 
relevanssi.php CHANGED
@@ -13,7 +13,7 @@
13
  * Plugin Name: Relevanssi
14
  * Plugin URI: https://www.relevanssi.com/
15
  * Description: This plugin replaces WordPress search with a relevance-sorting search.
16
- * Version: 4.7.0
17
  * Author: Mikko Saari
18
  * Author URI: http://www.mikkosaari.fi/
19
  * Text Domain: relevanssi
@@ -65,7 +65,7 @@ $relevanssi_variables['database_version'] = 5;
65
  $relevanssi_variables['file'] = __FILE__;
66
  $relevanssi_variables['plugin_dir'] = plugin_dir_path( __FILE__ );
67
  $relevanssi_variables['plugin_basename'] = plugin_basename( __FILE__ );
68
- $relevanssi_variables['plugin_version'] = '4.7.0';
69
 
70
  require_once 'lib/admin-ajax.php';
71
  require_once 'lib/common.php';
13
  * Plugin Name: Relevanssi
14
  * Plugin URI: https://www.relevanssi.com/
15
  * Description: This plugin replaces WordPress search with a relevance-sorting search.
16
+ * Version: 4.7.1
17
  * Author: Mikko Saari
18
  * Author URI: http://www.mikkosaari.fi/
19
  * Text Domain: relevanssi
65
  $relevanssi_variables['file'] = __FILE__;
66
  $relevanssi_variables['plugin_dir'] = plugin_dir_path( __FILE__ );
67
  $relevanssi_variables['plugin_basename'] = plugin_basename( __FILE__ );
68
+ $relevanssi_variables['plugin_version'] = '4.7.1';
69
 
70
  require_once 'lib/admin-ajax.php';
71
  require_once 'lib/common.php';