Relevanssi – A Better Search - Version 4.3.3

Version Description

  • New feature: New filter hook relevanssi_indexing_adjust can be used to stop Relevanssi from adjusting the number of posts indexed at once during the indexing.
  • New feature: New filter hook relevanssi_acf_field_value filters ACF field values before they are indexed.
  • New feature: New filter hook relevanssi_disabled_shortcodes filters the array containing shortcodes that are disabled when indexing.
  • Removed feature: The relevanssi_indexing_limit option wasn't really used anymore, so it has been removed.
  • Changed behaviour: Indexing exclusions from Yoast SEO and SEOPress are applied in a different way in the indexing, making for a smoother indexing process.
  • Changed behaviour: WP Table Reloaded support has been removed; you really shouldn't be using WP Table Reloaded anymore.
  • Minor fix: Relevanssi won't choke on ACF fields with array or object values anymore.
  • Minor fix: Relevanssi uninstall process left couple of Relevanssi options in the database.
  • Minor fix: WPML language filter didn't work when fields was set to ids or id=>parent.
Download this release

Release Info

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

Code changes from version 4.3.2 to 4.3.3

lib/admin-ajax.php CHANGED
@@ -372,6 +372,9 @@ function relevanssi_admin_search_debugging_info( $query ) {
372
  $result .= '<ul style="list-style: disc; margin-left: 1.5em">';
373
  foreach ( $wp_filter[ $filter ] as $priority => $functions ) {
374
  foreach ( $functions as $function ) {
 
 
 
375
  $result .= "<li>$priority: " . $function['function'] . '</li>';
376
  }
377
  }
372
  $result .= '<ul style="list-style: disc; margin-left: 1.5em">';
373
  foreach ( $wp_filter[ $filter ] as $priority => $functions ) {
374
  foreach ( $functions as $function ) {
375
+ if ( $function['function'] instanceof Closure ) {
376
+ $function['function'] = 'Anonymous function';
377
+ }
378
  $result .= "<li>$priority: " . $function['function'] . '</li>';
379
  }
380
  }
lib/admin_scripts.js CHANGED
@@ -178,6 +178,7 @@ jQuery(document).ready(function($) {
178
  offset: 0,
179
  total_seconds: 0,
180
  limit: relevanssi_params.indexing_limit,
 
181
  extend: true,
182
  security: nonce.indexing_nonce
183
  }
@@ -201,6 +202,7 @@ function process_indexing_step(args) {
201
  total: args.total,
202
  offset: args.offset,
203
  limit: args.limit,
 
204
  extend: args.extend,
205
  security: args.security
206
  },
@@ -251,25 +253,22 @@ function process_indexing_step(args) {
251
  "relevanssi_estimated"
252
  ).innerHTML = estimated_time
253
 
254
- /*console.log("total time: " + total_seconds);
255
- console.log("estimated time: " + Math.round(total_seconds / response.percentage * 100));
256
- console.log("estimated remaining: " + Math.round((total_seconds / response.percentage * 100) - total_seconds));
257
- console.log("estimated formatted: " + estimated_time);
258
- */
259
- if (time_seconds < 2) {
260
- args.limit = args.limit * 2
261
- // current limit can be indexed in less than two seconds; double the limit
262
- } else if (time_seconds < 5) {
263
- args.limit += 5
264
- // current limit can be indexed in less than five seconds; up the limit
265
- } else if (time_seconds > 20) {
266
- args.limit = Math.round(args.limit / 2)
267
- if (args.limit < 1) args.limit = 1
268
- // current limit takes more than twenty seconds; halve the limit
269
- } else if (time_seconds > 10) {
270
- args.limit -= 5
271
- if (args.limit < 1) args.limit = 1
272
- // current limit takes more than ten seconds; reduce the limit
273
  }
274
 
275
  var results_textarea = document.getElementById("results")
@@ -293,6 +292,7 @@ function process_indexing_step(args) {
293
  offset: response.offset,
294
  total_seconds: args.total_seconds,
295
  limit: args.limit,
 
296
  extend: args.extend,
297
  security: args.security
298
  }
178
  offset: 0,
179
  total_seconds: 0,
180
  limit: relevanssi_params.indexing_limit,
181
+ adjust: relevanssi_params.indexing_adjust,
182
  extend: true,
183
  security: nonce.indexing_nonce
184
  }
202
  total: args.total,
203
  offset: args.offset,
204
  limit: args.limit,
205
+ adjust: args.adjust,
206
  extend: args.extend,
207
  security: args.security
208
  },
253
  "relevanssi_estimated"
254
  ).innerHTML = estimated_time
255
 
256
+ if (args.adjust) {
257
+ if (time_seconds < 2) {
258
+ args.limit = args.limit * 2
259
+ // current limit can be indexed in less than two seconds; double the limit
260
+ } else if (time_seconds < 5) {
261
+ args.limit += 5
262
+ // current limit can be indexed in less than five seconds; up the limit
263
+ } else if (time_seconds > 20) {
264
+ args.limit = Math.round(args.limit / 2)
265
+ if (args.limit < 1) args.limit = 1
266
+ // current limit takes more than twenty seconds; halve the limit
267
+ } else if (time_seconds > 10) {
268
+ args.limit -= 5
269
+ if (args.limit < 1) args.limit = 1
270
+ // current limit takes more than ten seconds; reduce the limit
271
+ }
 
 
 
272
  }
273
 
274
  var results_textarea = document.getElementById("results")
292
  offset: response.offset,
293
  total_seconds: args.total_seconds,
294
  limit: args.limit,
295
+ adjust: args.adjust,
296
  extend: args.extend,
297
  security: args.security
298
  }
lib/common.php CHANGED
@@ -1672,3 +1672,14 @@ function relevanssi_get_forbidden_taxonomies() {
1672
  'product_visibility', // WooCommerce.
1673
  );
1674
  }
 
 
 
 
 
 
 
 
 
 
 
1672
  'product_visibility', // WooCommerce.
1673
  );
1674
  }
1675
+
1676
+ /**
1677
+ * Returns "off".
1678
+ *
1679
+ * Useful for returning "off" to filters easily.
1680
+ *
1681
+ * @return string A string with value "off".
1682
+ */
1683
+ function relevanssi_return_off() {
1684
+ return 'off';
1685
+ }
lib/compatibility/acf.php CHANGED
@@ -39,37 +39,74 @@ function relevanssi_acf_relationship_fields( $search_ok ) {
39
  * @param int $post_id The post ID.
40
  * @param string $field_name Name of the field.
41
  * @param string $field_value The field value.
 
 
42
  */
43
  function relevanssi_index_acf( &$insert_data, $post_id, $field_name, $field_value ) {
44
  if ( ! is_admin() ) {
45
  include_once ABSPATH . 'wp-admin/includes/plugin.php'; // Otherwise is_plugin_active() will cause a fatal error.
46
  }
47
  if ( ! function_exists( 'is_plugin_active' ) ) {
48
- return;
49
  }
50
  if ( ! is_plugin_active( 'advanced-custom-fields/acf.php' ) && ! is_plugin_active( 'advanced-custom-fields-pro/acf.php' ) ) {
51
- return;
52
  }
53
  if ( ! function_exists( 'get_field_object' ) ) {
54
- return; // ACF is active, but not loaded.
55
  }
56
 
57
  $field_object = get_field_object( $field_name, $post_id );
58
  if ( ! isset( $field_object['choices'] ) ) {
59
- return; // Not a "select" field.
60
  }
61
  if ( is_array( $field_value ) ) {
62
- return; // Not handled (currently).
63
  }
64
  if ( ! isset( $field_object['choices'][ $field_value ] ) ) {
65
- return; // Value does not exist.
66
  }
67
 
68
- $value = $field_object['choices'][ $field_value ];
69
- if ( $value ) {
70
- if ( ! isset( $insert_data[ $value ]['customfield'] ) ) {
71
- $insert_data[ $value ]['customfield'] = 0;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
72
  }
73
- $insert_data[ $value ]['customfield']++;
74
  }
 
 
75
  }
39
  * @param int $post_id The post ID.
40
  * @param string $field_name Name of the field.
41
  * @param string $field_value The field value.
42
+ *
43
+ * @return int Number of tokens indexed.
44
  */
45
  function relevanssi_index_acf( &$insert_data, $post_id, $field_name, $field_value ) {
46
  if ( ! is_admin() ) {
47
  include_once ABSPATH . 'wp-admin/includes/plugin.php'; // Otherwise is_plugin_active() will cause a fatal error.
48
  }
49
  if ( ! function_exists( 'is_plugin_active' ) ) {
50
+ return 0;
51
  }
52
  if ( ! is_plugin_active( 'advanced-custom-fields/acf.php' ) && ! is_plugin_active( 'advanced-custom-fields-pro/acf.php' ) ) {
53
+ return 0;
54
  }
55
  if ( ! function_exists( 'get_field_object' ) ) {
56
+ return 0; // ACF is active, but not loaded.
57
  }
58
 
59
  $field_object = get_field_object( $field_name, $post_id );
60
  if ( ! isset( $field_object['choices'] ) ) {
61
+ return 0; // Not a "select" field.
62
  }
63
  if ( is_array( $field_value ) ) {
64
+ return 0; // Not handled (currently).
65
  }
66
  if ( ! isset( $field_object['choices'][ $field_value ] ) ) {
67
+ return 0; // Value does not exist.
68
  }
69
 
70
+ $n = 0;
71
+
72
+ /**
73
+ * Filters the field value before it is used to save the insert data.
74
+ *
75
+ * The value is used as an array key, so it needs to be an integer or a
76
+ * string. If your custom field values are arrays or objects, use this
77
+ * filter hook to convert them into strings.
78
+ *
79
+ * @param any The ACF field value.
80
+ * @param string The ACF field name.
81
+ * @param int The post ID.
82
+ *
83
+ * @return string|int The field value.
84
+ */
85
+ $value = apply_filters(
86
+ 'relevanssi_acf_field_value',
87
+ $field_object['choices'][ $field_value ],
88
+ $field_name,
89
+ $post_id
90
+ );
91
+
92
+ if ( $value && ( is_integer( $value ) || is_string( $value ) ) ) {
93
+ $min_word_length = get_option( 'relevanssi_min_word_length', 3 );
94
+
95
+ /** This filter is documented in lib/indexing.php */
96
+ $value_tokens = apply_filters( 'relevanssi_indexing_tokens', relevanssi_tokenize( $value, true, $min_word_length ), 'custom_field' );
97
+ foreach ( $value_tokens as $token => $count ) {
98
+ $n++;
99
+ if ( ! isset( $insert_data[ $token ]['customfield'] ) ) {
100
+ $insert_data[ $token ]['customfield'] = 0;
101
+ }
102
+ $insert_data[ $token ]['customfield'] += $count;
103
+
104
+ // Premium indexes more detail about custom fields.
105
+ if ( function_exists( 'relevanssi_customfield_detail' ) ) {
106
+ $insert_data = relevanssi_customfield_detail( $insert_data, $token, $count, $field_name );
107
+ }
108
  }
 
109
  }
110
+
111
+ return $n;
112
  }
lib/compatibility/polylang.php CHANGED
@@ -87,9 +87,12 @@ function relevanssi_polylang_filter( $query ) {
87
  * @since 2.1.6
88
  */
89
  function relevanssi_polylang_where_include_terms( $where ) {
90
- $current_language = pll_current_language();
91
- $languages = get_terms( array( 'taxonomy' => 'language' ) );
92
- $language_id = 0;
 
 
 
93
  foreach ( $languages as $language ) {
94
  if ( ! is_wp_error( $language ) && $language instanceof WP_Term && $language->slug === $current_language ) {
95
  $language_id = intval( $language->term_id );
@@ -125,8 +128,11 @@ function relevanssi_polylang_where_include_terms( $where ) {
125
  function relevanssi_polylang_term_filter( $hits ) {
126
  $polylang_allow_all = get_option( 'relevanssi_polylang_all_languages' );
127
  if ( 'on' !== $polylang_allow_all ) {
128
- $current_language = pll_current_language();
129
- $accepted_hits = array();
 
 
 
130
  foreach ( $hits[0] as $hit ) {
131
  if ( -1 === $hit->ID && isset( $hit->term_id ) ) {
132
  $term_id = intval( $hit->term_id );
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();
93
+ }
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 );
128
  function relevanssi_polylang_term_filter( $hits ) {
129
  $polylang_allow_all = get_option( 'relevanssi_polylang_all_languages' );
130
  if ( 'on' !== $polylang_allow_all ) {
131
+ $current_language = substr( get_locale(), 0, 2 );
132
+ if ( function_exists( 'pll_current_language' ) ) {
133
+ $current_language = pll_current_language();
134
+ }
135
+ $accepted_hits = array();
136
  foreach ( $hits[0] as $hit ) {
137
  if ( -1 === $hit->ID && isset( $hit->term_id ) ) {
138
  $term_id = intval( $hit->term_id );
lib/compatibility/seopress.php CHANGED
@@ -12,6 +12,7 @@
12
  */
13
 
14
  add_filter( 'relevanssi_do_not_index', 'relevanssi_seopress_noindex', 10, 2 );
 
15
 
16
  /**
17
  * Blocks indexing of posts marked "noindex" in the SEOPress settings.
@@ -30,3 +31,17 @@ function relevanssi_seopress_noindex( $do_not_index, $post_id ) {
30
  }
31
  return $do_not_index;
32
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
12
  */
13
 
14
  add_filter( 'relevanssi_do_not_index', 'relevanssi_seopress_noindex', 10, 2 );
15
+ add_filter( 'relevanssi_indexing_restriction', 'relevanssi_seopress_exclude' );
16
 
17
  /**
18
  * Blocks indexing of posts marked "noindex" in the SEOPress settings.
31
  }
32
  return $do_not_index;
33
  }
34
+
35
+ /**
36
+ * Excludes the "noindex" posts from Relevanssi indexing.
37
+ *
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
+ }
lib/compatibility/tablepress.php ADDED
@@ -0,0 +1,30 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * /lib/compatibility/tablepress.php
4
+ *
5
+ * TablePress compatibility features.
6
+ *
7
+ * @package Relevanssi
8
+ * @author Mikko Saari
9
+ * @license https://wordpress.org/about/gpl/ GNU General Public License
10
+ * @see https://www.relevanssi.com/
11
+ */
12
+
13
+ /**
14
+ * Enables TablePress shortcodes for Relevanssi indexing.
15
+ *
16
+ * @return null|object The TablePress controller.
17
+ */
18
+ function relevanssi_enable_tablepress_shortcodes() {
19
+ $my_tablepress_controller = null;
20
+ if ( defined( 'TABLEPRESS_ABSPATH' ) ) {
21
+ if ( ! isset( TablePress::$model_options ) ) {
22
+ include_once TABLEPRESS_ABSPATH . 'classes/class-model.php';
23
+ include_once TABLEPRESS_ABSPATH . 'models/model-options.php';
24
+ TablePress::$model_options = new TablePress_Options_Model();
25
+ }
26
+ $my_tablepress_controller = TablePress::load_controller( 'frontend' );
27
+ $my_tablepress_controller->init_shortcodes();
28
+ }
29
+ return $my_tablepress_controller;
30
+ }
lib/compatibility/wpml.php CHANGED
@@ -33,9 +33,16 @@ function relevanssi_wpml_filter( $data ) {
33
  $current_blog_language = get_bloginfo( 'language' );
34
  $filtered_hits = array();
35
  foreach ( $data[0] as $hit ) {
36
- if ( is_integer( $hit ) ) {
 
37
  // In case "fields" is set to "ids", fetch the post object we need.
38
- $hit = get_post( $hit );
 
 
 
 
 
 
39
  }
40
 
41
  if ( isset( $hit->blog_id ) ) {
@@ -63,16 +70,16 @@ function relevanssi_wpml_filter( $data ) {
63
  // This is a post in a translated post type.
64
  if ( intval( $hit->ID ) === intval( $id ) ) {
65
  // The post exists in the current language, and can be included.
66
- $filtered_hits[] = $hit;
67
  }
68
  } else {
69
  // This is not a translated post type, so include all posts.
70
- $filtered_hits[] = $hit;
71
  }
72
  } elseif ( get_bloginfo( 'language' ) === $current_blog_language ) {
73
  // If there is no WPML but the target blog has identical language with current blog,
74
  // we use the hits. Note en-US is not identical to en-GB!
75
- $filtered_hits[] = $hit;
76
  }
77
 
78
  if ( isset( $hit->blog_id ) ) {
33
  $current_blog_language = get_bloginfo( 'language' );
34
  $filtered_hits = array();
35
  foreach ( $data[0] as $hit ) {
36
+ $original_hit = $hit;
37
+ if ( is_numeric( $hit ) ) {
38
  // In case "fields" is set to "ids", fetch the post object we need.
39
+ $original_hit = $hit;
40
+ $hit = get_post( $hit );
41
+ }
42
+ if ( ! isset( $hit->post_content ) ) {
43
+ // The "fields" is set to "id=>parent".
44
+ $original_hit = $hit;
45
+ $hit = get_post( $hit->ID );
46
  }
47
 
48
  if ( isset( $hit->blog_id ) ) {
70
  // This is a post in a translated post type.
71
  if ( intval( $hit->ID ) === intval( $id ) ) {
72
  // The post exists in the current language, and can be included.
73
+ $filtered_hits[] = $original_hit;
74
  }
75
  } else {
76
  // This is not a translated post type, so include all posts.
77
+ $filtered_hits[] = $original_hit;
78
  }
79
  } elseif ( get_bloginfo( 'language' ) === $current_blog_language ) {
80
  // If there is no WPML but the target blog has identical language with current blog,
81
  // we use the hits. Note en-US is not identical to en-GB!
82
+ $filtered_hits[] = $original_hit;
83
  }
84
 
85
  if ( isset( $hit->blog_id ) ) {
lib/compatibility/yoast-seo.php CHANGED
@@ -11,6 +11,7 @@
11
  */
12
 
13
  add_filter( 'relevanssi_do_not_index', 'relevanssi_yoast_noindex', 10, 2 );
 
14
 
15
  /**
16
  * Blocks indexing of posts marked "noindex" in the Yoast SEO settings.
@@ -29,3 +30,17 @@ function relevanssi_yoast_noindex( $do_not_index, $post_id ) {
29
  }
30
  return $do_not_index;
31
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
11
  */
12
 
13
  add_filter( 'relevanssi_do_not_index', 'relevanssi_yoast_noindex', 10, 2 );
14
+ add_filter( 'relevanssi_indexing_restriction', 'relevanssi_yoast_exclude' );
15
 
16
  /**
17
  * Blocks indexing of posts marked "noindex" in the Yoast SEO settings.
30
  }
31
  return $do_not_index;
32
  }
33
+
34
+ /**
35
+ * Excludes the "noindex" posts from Relevanssi indexing.
36
+ *
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
+ }
lib/contextual-help.php CHANGED
@@ -28,9 +28,9 @@ function relevanssi_admin_help() {
28
  '<li>' . sprintf( __( "To adjust the post order, you can use the %1\$s query parameter. With %1\$s, you can use multiple layers of different sorting methods. See <a href='%2\$s'>WordPress Codex</a> for more details on using arrays for orderby.", 'relevanssi' ), '<code>orderby</code>', 'https://codex.wordpress.org/Class_Reference/WP_Query#Order_.26_Orderby_Parameters' ) . '</li>' .
29
  '<li>' . __( "Inside-word matching is disabled by default, because it increases garbage results that don't really match the search term. If you want to enable it, add the following function to your theme functions.php:", 'relevanssi' ) .
30
  '<pre>add_filter( \'relevanssi_fuzzy_query\', \'rlv_partial_inside_words\' );
31
- function rlv_partial_inside_words( $query ) {
32
- return "(term LIKE \'%#term#%\')";
33
- }</pre></li>' .
34
  // Translators: %s is 'Uncheck this if you use non-ASCII characters' option name.
35
  '<li>' . sprintf( __( 'To get inside-word highlights, uncheck the "%s" option. That has a side-effect of enabling the inside-word highlights.', 'relevanssi' ), __( 'Uncheck this if you use non-ASCII characters', 'relevanssi' ) ) . '</li>' .
36
  // Translators: %s is 'relevanssi_throttle_limit'.
28
  '<li>' . sprintf( __( "To adjust the post order, you can use the %1\$s query parameter. With %1\$s, you can use multiple layers of different sorting methods. See <a href='%2\$s'>WordPress Codex</a> for more details on using arrays for orderby.", 'relevanssi' ), '<code>orderby</code>', 'https://codex.wordpress.org/Class_Reference/WP_Query#Order_.26_Orderby_Parameters' ) . '</li>' .
29
  '<li>' . __( "Inside-word matching is disabled by default, because it increases garbage results that don't really match the search term. If you want to enable it, add the following function to your theme functions.php:", 'relevanssi' ) .
30
  '<pre>add_filter( \'relevanssi_fuzzy_query\', \'rlv_partial_inside_words\' );
31
+ function rlv_partial_inside_words( $query ) {
32
+ return "(relevanssi.term LIKE \'%#term#%\')";
33
+ }</pre></li>' .
34
  // Translators: %s is 'Uncheck this if you use non-ASCII characters' option name.
35
  '<li>' . sprintf( __( 'To get inside-word highlights, uncheck the "%s" option. That has a side-effect of enabling the inside-word highlights.', 'relevanssi' ), __( 'Uncheck this if you use non-ASCII characters', 'relevanssi' ) ) . '</li>' .
36
  // Translators: %s is 'relevanssi_throttle_limit'.
lib/indexing.php CHANGED
@@ -126,6 +126,7 @@ function relevanssi_generate_indexing_query( $valid_status, $extend = false, $re
126
  OR (post.post_parent=0)
127
  )
128
  ))
 
129
  $restriction ORDER BY post.ID DESC $limit";
130
  } else {
131
  $q = "SELECT post.ID
@@ -144,6 +145,7 @@ function relevanssi_generate_indexing_query( $valid_status, $extend = false, $re
144
  )
145
  )
146
  )
 
147
  $restriction ORDER BY post.ID DESC $limit";
148
  }
149
 
@@ -233,7 +235,7 @@ function relevanssi_valid_status_array() {
233
  * @param boolean|int $extend_offset If numeric, offsets the indexing by that
234
  * amount. If true, doesn't truncate the index before indexing. If false, truncates
235
  * index before indexing. Default false.
236
- * @param boolean $verbose If true, echoes out information. Default true.
237
  * @param int $post_limit How many posts to index. Default null, no limit.
238
  * @param boolean $is_ajax If true, indexing is done in AJAX context.
239
  * Default false.
@@ -243,104 +245,51 @@ function relevanssi_valid_status_array() {
243
  * posts indexed. Outside AJAX context, these values are returned as an array in
244
  * format of array(completed, posts indexed).
245
  */
246
- function relevanssi_build_index( $extend_offset = false, $verbose = true, $post_limit = null, $is_ajax = false ) {
247
  global $wpdb, $relevanssi_variables;
248
  $relevanssi_table = $relevanssi_variables['relevanssi_table'];
249
 
250
  // Thanks to Julien Mession. This speeds up indexing a lot.
251
  wp_suspend_cache_addition( true );
252
 
253
- // The values generated by these functions are safe to use for MySQL.
254
- $restriction = relevanssi_post_type_restriction();
255
- $valid_status = relevanssi_valid_status_array();
256
-
257
- $n = 0;
258
- $size = 0;
259
-
260
  if ( false === $extend_offset ) {
261
  // Truncate the index first.
262
  relevanssi_truncate_index();
263
 
264
- // Premium feature: index taxonomy terms.
265
- if ( function_exists( 'relevanssi_index_taxonomies' ) ) {
266
- if ( 'on' === get_option( 'relevanssi_index_taxonomies' ) ) {
267
- relevanssi_index_taxonomies();
268
- }
269
- }
270
-
271
- // Premium feature: index user profiles.
272
- if ( function_exists( 'relevanssi_index_users' ) ) {
273
- if ( 'on' === get_option( 'relevanssi_index_users' ) ) {
274
- relevanssi_index_users();
275
- }
276
- }
277
-
278
- // Premium feature: index post type archives.
279
- if ( function_exists( 'relevanssi_index_post_type_archives' ) ) {
280
- if ( 'on' === get_option( 'relevanssi_index_post_type_archives' ) ) {
281
- relevanssi_index_post_type_archives();
282
- }
283
  }
284
 
285
- // If $post_limit parameter is present, numeric and > 0, use that.
286
- $limit = '';
287
- if ( isset( $post_limit ) && is_numeric( $post_limit ) && $post_limit > 0 ) {
288
- $size = $post_limit;
289
- $limit = " LIMIT $post_limit";
290
- }
291
-
292
- $query = relevanssi_generate_indexing_query( $valid_status, $extend_offset, $restriction, $limit );
293
-
294
  update_option( 'relevanssi_index', '' );
295
- } elseif ( ! is_numeric( $extend_offset ) ) {
296
- // Extending, so do not truncate and skip the posts already in the index.
297
- $limit = get_option( 'relevanssi_index_limit', 200 );
298
-
299
- // If $post_limit parameter is present, numeric and > 0, use that.
300
- if ( isset( $post_limit ) && is_numeric( $post_limit ) && $post_limit > 0 ) {
301
- $limit = $post_limit;
302
- }
303
-
304
- if ( is_numeric( $limit ) && $limit > 0 ) {
305
- $size = $limit;
306
- $limit = " LIMIT $limit";
307
- } else {
308
- $limit = '';
309
- }
310
-
311
- $extend = true;
312
- $query = relevanssi_generate_indexing_query( $valid_status, $extend, $restriction, $limit );
313
- } else { // $extend_offset is numeric.
314
- // Extending, so do not truncate and skip the posts already in the index.
315
- $limit = get_option( 'relevanssi_index_limit', 200 );
316
-
317
- // If $post_limit parameter is present, numeric and > 0, use that.
318
- if ( isset( $post_limit ) && is_numeric( $post_limit ) && $post_limit > 0 ) {
319
- $limit = $post_limit;
320
- }
321
 
322
- if ( is_numeric( $limit ) && $limit > 0 ) {
323
- $size = $limit;
324
- $limit = " LIMIT $limit OFFSET $extend_offset";
325
- } else {
326
- $limit = '';
327
- }
328
 
329
- // Extend is set to false, because $limit now has LIMIT and OFFSET.
330
- $extend = false;
331
- $query = relevanssi_generate_indexing_query( $valid_status, $extend, $restriction, $limit );
332
- }
333
 
334
- $custom_fields = relevanssi_get_custom_fields();
 
 
 
 
 
335
 
336
  /* This action documented earlier in lib/indexing.php. */
337
  do_action( 'relevanssi_pre_indexing_query' );
338
- $content = $wpdb->get_results( $query ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
339
 
 
340
  if ( defined( 'WP_CLI' ) && WP_CLI && function_exists( 'relevanssi_generate_progress_bar' ) ) {
 
341
  $progress = relevanssi_generate_progress_bar( 'Indexing posts', count( $content ) );
 
342
  }
343
 
 
 
 
344
  $remove_first = false;
345
  $bypass_global_post = true; // $bypassglobalpost set to true, because at this
346
  // point global $post should be null, but in some cases it is not.
@@ -351,29 +300,28 @@ function relevanssi_build_index( $extend_offset = false, $verbose = true, $post_
351
  $n++;
352
  }
353
  if ( defined( 'WP_CLI' ) && WP_CLI && $progress ) {
 
354
  $progress->tick();
 
355
  }
356
  }
357
  if ( defined( 'WP_CLI' ) && WP_CLI && $progress ) {
 
358
  $progress->finish();
 
359
  }
360
 
361
  // To prevent empty indices.
362
  $wpdb->query( "ANALYZE TABLE $relevanssi_table" ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared,WordPress.DB.PreparedSQL.InterpolatedNotPrepared
363
 
364
  $complete = false;
 
 
365
  if ( ( 0 === $size ) || ( count( $content ) < $size ) ) {
366
- $message = __( 'Indexing complete!', 'relevanssi' );
367
  $complete = true;
368
- } else {
369
- $message = __( 'More to index...', 'relevanssi' );
370
- }
371
- if ( $verbose ) {
372
- printf( '<div id="message" class="updated fade"><p>%s</p></div>', esc_html( $message ) );
373
  }
374
 
375
- update_option( 'relevanssi_indexed', 'done' );
376
-
377
  // Update the document count variable.
378
  relevanssi_update_doc_count();
379
 
@@ -414,74 +362,41 @@ function relevanssi_build_index( $extend_offset = false, $verbose = true, $post_
414
  * @param boolean $remove_first If true, remove the post from the index
415
  * before indexing. Default false.
416
  * @param array $custom_fields The custom fields that are indexed for the
417
- * post.
418
  * @param boolean $bypass_global_post If true, do not use the global $post object.
419
  * Default false.
420
  * @param boolean $debug If true, echo out debugging information.
421
  * Default false.
422
  */
423
- function relevanssi_index_doc( $index_post, $remove_first = false, $custom_fields = false, $bypass_global_post = false, $debug = false ) {
424
  global $wpdb, $post, $relevanssi_variables;
425
  $relevanssi_table = $relevanssi_variables['relevanssi_table'];
426
- $post_was_null = false;
427
  $previous_post = null;
428
 
429
  // Check if this is a Jetpack Contact Form entry.
430
  if ( isset( $_REQUEST['contact-form-id'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification
431
- return;
432
  }
433
 
434
- if ( $bypass_global_post ) {
435
- // If $bypass_global_post is set, relevanssi_index_doc() will index the post
436
- // object or post ID as specified in $index_post.
437
- if ( isset( $post ) ) {
438
- $previous_post = $post;
439
- } else {
440
- $post_was_null = true;
441
- }
442
-
443
- if ( is_object( $index_post ) ) {
444
- $post = $index_post; // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited
445
- } else {
446
- $post = get_post( $index_post ); // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited
447
- }
448
- } else {
449
- // Quick edit has an array in the global $post, so fetch the post ID for the
450
- // post to edit.
451
- if ( is_array( $post ) ) {
452
- $post = get_post( $post['ID'] ); // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited
453
- }
454
-
455
- if ( empty( $post ) ) {
456
- // No $post set, so we need to use $indexpost, if it's a post object.
457
- $post_was_null = true;
458
- if ( is_object( $index_post ) ) {
459
- $post = $index_post; // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited
460
- } else {
461
- $post = get_post( $index_post ); // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited
462
- }
463
- } else {
464
- // $post was set, let's grab the previous value in case we need it
465
- $previous_post = $post;
466
- }
467
  }
468
 
469
- if ( null === $post ) {
470
- // At this point we should have something in $post; if not, quit.
471
- if ( $post_was_null ) {
472
- $post = null; // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited
473
- }
474
- if ( $previous_post ) {
475
- $post = $previous_post; // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited
476
- }
477
- return -1;
478
  }
479
 
480
  // Finally fetch the post again by ID. Complicated, yes, but unless we do this,
481
  // we might end up indexing the post before the updates come in.
482
- $post = get_post( $post->ID ); // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited
483
 
484
  if ( null === $post ) {
 
 
 
 
485
  return -1;
486
  }
487
 
@@ -491,10 +406,7 @@ function relevanssi_index_doc( $index_post, $remove_first = false, $custom_field
491
  if ( $debug ) {
492
  relevanssi_debug_echo( 'relevanssi_hide_post() returned true.' );
493
  }
494
- if ( $post_was_null ) {
495
- $post = null; // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited
496
- }
497
- if ( $previous_post ) {
498
  $post = $previous_post; // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited
499
  }
500
  return 'hide';
@@ -504,11 +416,8 @@ function relevanssi_index_doc( $index_post, $remove_first = false, $custom_field
504
  $index_this_post = false;
505
  $post->indexing_content = true;
506
 
507
- $index_types = get_option( 'relevanssi_index_post_types' );
508
- if ( ! is_array( $index_types ) ) {
509
- $index_types = array();
510
- }
511
- if ( in_array( $post->post_type, $index_types, true ) ) {
512
  $index_this_post = true;
513
  }
514
 
@@ -542,10 +451,7 @@ function relevanssi_index_doc( $index_post, $remove_first = false, $custom_field
542
  // This needs to be here, after the call to relevanssi_remove_doc(), because
543
  // otherwise a post that's in the index but shouldn't be there won't get removed.
544
  if ( ! $index_this_post ) {
545
- if ( $post_was_null ) {
546
- $post = null; // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited
547
- }
548
- if ( $previous_post ) {
549
  $post = $previous_post; // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited
550
  }
551
  return 'donotindex';
@@ -566,161 +472,26 @@ function relevanssi_index_doc( $index_post, $remove_first = false, $custom_field
566
  $insert_data = array();
567
 
568
  if ( 'none' !== get_option( 'relevanssi_index_comments' ) ) {
569
- if ( $debug ) {
570
- relevanssi_debug_echo( 'Indexing comments.' );
571
- }
572
- $post_comments = relevanssi_get_comments( $post->ID );
573
- if ( ! empty( $post_comments ) ) {
574
- $post_comments = relevanssi_strip_invisibles( $post_comments );
575
- $post_comments = preg_replace( '/<[a-zA-Z\/][^>]*>/', ' ', $post_comments );
576
- $post_comments = wp_strip_all_tags( $post_comments );
577
- if ( $debug ) {
578
- relevanssi_debug_echo( "Comment content: $post_comments" );
579
- }
580
- /**
581
- * Filters the indexing tokens before they are added to the $insert_data.
582
- *
583
- * @param array An array of token-frequency pairs.
584
- * @param string The context of the tokens (eg. 'content', 'title').
585
- *
586
- * @return array The filtered tokens.
587
- */
588
- $post_comments_tokens = apply_filters( 'relevanssi_indexing_tokens', relevanssi_tokenize( $post_comments, true, $min_word_length ), 'comments' );
589
- if ( count( $post_comments_tokens ) > 0 ) {
590
- foreach ( $post_comments_tokens as $token => $count ) {
591
- $n++;
592
- $insert_data[ $token ]['comment'] = $count;
593
- }
594
- }
595
- }
596
  }
597
 
598
- // Process taxonomies.
599
  $taxonomies = get_option( 'relevanssi_index_taxonomies_list', array() );
600
  foreach ( $taxonomies as $taxonomy ) {
601
- if ( $debug ) {
602
- relevanssi_debug_echo( "Indexing taxonomy terms for $taxonomy" );
603
- }
604
- $insert_data = relevanssi_index_taxonomy_terms( $post, $taxonomy, $insert_data );
605
  }
606
 
607
- // Index post author.
608
  if ( 'on' === get_option( 'relevanssi_index_author' ) ) {
609
- $author_id = $post->post_author;
610
- $display_name = get_the_author_meta( 'display_name', $author_id );
611
- /** This filter is documented in common/indexing.php */
612
- $name_tokens = apply_filters( 'relevanssi_indexing_tokens', relevanssi_tokenize( $display_name, false, $min_word_length ), 'author' );
613
- if ( $debug ) {
614
- relevanssi_debug_echo( 'Indexing post author as: ' . implode( ' ', array_keys( $name_tokens ) ) );
615
- }
616
- foreach ( $name_tokens as $token => $count ) {
617
- if ( isset( $insert_data[ $token ]['author'] ) ) {
618
- $insert_data[ $token ]['author'] += $count;
619
- } else {
620
- $insert_data[ $token ]['author'] = $count;
621
- }
622
- }
623
- }
624
-
625
- // Indexing custom fields.
626
- $remove_underscore_fields = false;
627
- if ( isset( $custom_fields ) && 'all' === $custom_fields ) {
628
- $custom_fields = get_post_custom_keys( $post->ID );
629
- }
630
- if ( isset( $custom_fields ) && 'visible' === $custom_fields ) {
631
- $custom_fields = get_post_custom_keys( $post->ID );
632
- $remove_underscore_fields = true;
633
  }
634
- /**
635
- * Filters the list of custom fields to index before indexing.
636
- *
637
- * @param array $custom_fields List of custom field names.
638
- * @param int $post->ID The post ID.
639
- */
640
- $custom_fields = apply_filters( 'relevanssi_index_custom_fields', $custom_fields, $post->ID );
641
- if ( is_array( $custom_fields ) ) {
642
- if ( $debug ) {
643
- relevanssi_debug_echo( 'Custom fields to index: ' . implode( ', ', $custom_fields ) );
644
- }
645
- $custom_fields = array_unique( $custom_fields );
646
-
647
- // Premium includes some support for ACF repeater fields.
648
- $repeater_fields = array();
649
- if ( function_exists( 'relevanssi_add_repeater_fields' ) ) {
650
- relevanssi_add_repeater_fields( $custom_fields, $post->ID );
651
- }
652
-
653
- foreach ( $custom_fields as $field ) {
654
- if ( $remove_underscore_fields ) {
655
- if ( '_relevanssi_pdf_content' !== $field && '_' === substr( $field, 0, 1 ) ) {
656
- // We always want to index _relevanssi_pdf_content.
657
- continue;
658
- }
659
- }
660
-
661
- /**
662
- * Filters the custom field value before indexing.
663
- *
664
- * @param array Custom field values.
665
- * @param string $field The custom field name.
666
- * @param int $post->ID The post ID.
667
- */
668
- $values = apply_filters( 'relevanssi_custom_field_value', get_post_meta( $post->ID, $field, false ), $field, $post->ID );
669
-
670
- if ( empty( $values ) || ! is_array( $values ) ) {
671
- continue;
672
- }
673
-
674
- foreach ( $values as $value ) {
675
- // Quick hack : allow indexing of PODS relationship custom fields // TMV.
676
- if ( is_array( $value ) && isset( $value['post_title'] ) ) {
677
- $value = $value['post_title'];
678
- }
679
-
680
- if ( function_exists( 'relevanssi_index_acf' ) ) {
681
- // Handle ACF fields. Only defined when ACF is active.
682
- relevanssi_index_acf( $insert_data, $post->ID, $field, $value );
683
- }
684
-
685
- // Flatten other arrays.
686
- if ( is_array( $value ) ) {
687
- $value = relevanssi_flatten_array( $value );
688
- }
689
 
690
- if ( $debug ) {
691
- relevanssi_debug_echo( "\tKey: " . $field . ' – value: ' . $value );
692
- }
693
- /** This filter is documented in common/indexing.php */
694
- $value_tokens = apply_filters( 'relevanssi_indexing_tokens', relevanssi_tokenize( $value, true, $min_word_length ), 'custom_field' );
695
- foreach ( $value_tokens as $token => $count ) {
696
- if ( ! isset( $insert_data[ $token ]['customfield'] ) ) {
697
- $insert_data[ $token ]['customfield'] = 0;
698
- }
699
- $insert_data[ $token ]['customfield'] += $count;
700
-
701
- // Premium indexes more detail about custom fields.
702
- if ( function_exists( 'relevanssi_customfield_detail' ) ) {
703
- $insert_data = relevanssi_customfield_detail( $insert_data, $token, $count, $field );
704
- }
705
- }
706
- }
707
- }
708
- }
709
 
710
- // Indexing excerpts.
711
- if ( isset( $post->post_excerpt ) && ( 'on' === get_option( 'relevanssi_index_excerpt' ) || 'attachment' === $post->post_type ) ) {
712
- // Include excerpt for attachments which use post_excerpt for captions - modified by renaissancehack.
713
- if ( $debug ) {
714
- relevanssi_debug_echo( "Indexing post excerpt: $post->post_excerpt" );
715
- }
716
- /** This filter is documented in common/indexing.php */
717
- $excerpt_tokens = apply_filters( 'relevanssi_indexing_tokens', relevanssi_tokenize( $post->post_excerpt, true, $min_word_length ), 'excerpt' );
718
- foreach ( $excerpt_tokens as $token => $count ) {
719
- if ( ! isset( $insert_data[ $token ]['excerpt'] ) ) {
720
- $insert_data[ $token ]['excerpt'] = 0;
721
- }
722
- $insert_data[ $token ]['excerpt'] += $count;
723
- }
724
  }
725
 
726
  // Premium can index arbitrary MySQL columns.
@@ -739,301 +510,10 @@ function relevanssi_index_doc( $index_post, $remove_first = false, $custom_field
739
  $insert_data = relevanssi_index_pdf_for_parent( $insert_data, $post->ID );
740
  }
741
 
742
- $index_titles = true;
743
- if ( ! empty( $post->post_title ) ) {
744
- /**
745
- * If this filter returns false, titles are not indexed at all.
746
- *
747
- * @param boolean Return false to prevent titles from being indexed. Default true.
748
- */
749
- if ( apply_filters( 'relevanssi_index_titles', $index_titles ) ) {
750
- if ( $debug ) {
751
- relevanssi_debug_echo( 'Indexing post title.' );
752
- }
753
- /** This filter is documented in wp-includes/post-template.php */
754
- $filtered_title = apply_filters( 'the_title', $post->post_title, $post->ID );
755
- /**
756
- * Filters the title before tokenizing and indexing.
757
- *
758
- * @param string $post->post_title The title.
759
- * @param object $post The full post object.
760
- */
761
- $filtered_title = apply_filters( 'relevanssi_post_title_before_tokenize', $filtered_title, $post );
762
- /**
763
- * Filters whether stopwords should be removed from titles in tokenizing or not.
764
- *
765
- * @param boolean If true, remove stopwords. Default true.
766
- */
767
- $title_tokens = relevanssi_tokenize( $filtered_title, apply_filters( 'relevanssi_remove_stopwords_in_titles', true ), $min_word_length );
768
- /** This filter is documented in common/indexing.php */
769
- $title_tokens = apply_filters( 'relevanssi_indexing_tokens', $title_tokens, 'title' );
770
-
771
- if ( $debug ) {
772
- relevanssi_debug_echo( "\tTitle, tokenized: " . implode( ' ', array_keys( $title_tokens ) ) );
773
- }
774
-
775
- if ( count( $title_tokens ) > 0 ) {
776
- foreach ( $title_tokens as $token => $count ) {
777
- $n++;
778
- if ( ! isset( $insert_data[ $token ]['title'] ) ) {
779
- $insert_data[ $token ]['title'] = 0;
780
- }
781
- $insert_data[ $token ]['title'] += $count;
782
- }
783
- }
784
- }
785
- }
786
-
787
- // Content indexing.
788
- $index_content = true;
789
- /**
790
- * If this filter returns false, post content is not indexed at all.
791
- *
792
- * @param boolean Return false to prevent post content from being indexed. Default true.
793
- */
794
- if ( apply_filters( 'relevanssi_index_content', $index_content ) ) {
795
- if ( $debug ) {
796
- relevanssi_debug_echo( 'Indexing post content.' );
797
- }
798
- remove_shortcode( 'noindex' );
799
- add_shortcode( 'noindex', 'relevanssi_noindex_shortcode_indexing' );
800
-
801
- /**
802
- * Filters the post content before indexing.
803
- *
804
- * @param string $post->post_content The post content.
805
- * @param object $post The full post object.
806
- */
807
- $contents = apply_filters( 'relevanssi_post_content', $post->post_content, $post );
808
- if ( $debug ) {
809
- relevanssi_debug_echo( "\tPost content after relevanssi_post_content:\n$contents" );
810
- }
811
- /**
812
- * Can be used to add extra content to the post before indexing.
813
- *
814
- * @author Alexander Gieg
815
- *
816
- * @param string The additional content.
817
- * @param object $post The post object.
818
- */
819
- $additional_content = trim( apply_filters( 'relevanssi_content_to_index', '', $post ) );
820
- if ( ! empty( $additional_content ) ) {
821
- $contents .= ' ' . $additional_content;
822
- if ( $debug ) {
823
- relevanssi_debug_echo( "\tAdditional content from relevanssi_content_to_index:\n$additional_content" );
824
- }
825
- }
826
-
827
- if ( 'on' === get_option( 'relevanssi_expand_shortcodes' ) ) {
828
- if ( function_exists( 'do_shortcode' ) ) {
829
- // WP Table Reloaded support.
830
- if ( defined( 'WP_TABLE_RELOADED_ABSPATH' ) ) {
831
- include_once WP_TABLE_RELOADED_ABSPATH . 'controllers/controller-frontend.php';
832
- $my_wp_table_reloaded = new WP_Table_Reloaded_Controller_Frontend();
833
- }
834
- // TablePress support.
835
- if ( defined( 'TABLEPRESS_ABSPATH' ) ) {
836
- if ( ! isset( TablePress::$model_options ) ) {
837
- include_once TABLEPRESS_ABSPATH . 'classes/class-model.php';
838
- include_once TABLEPRESS_ABSPATH . 'models/model-options.php';
839
- TablePress::$model_options = new TablePress_Options_Model();
840
- }
841
- $my_tablepress_controller = TablePress::load_controller( 'frontend' );
842
- $my_tablepress_controller->init_shortcodes();
843
- }
844
-
845
- $default_disables = array(
846
- 'contact-form', // Jetpack Contact Form causes an error message.
847
- 'starrater', // GD Star Rating rater shortcode causes problems.
848
- 'responsive-flipbook', // Responsive Flipbook causes problems.
849
- 'avatar_upload', // WP User Avatar is incompatible.
850
- 'product_categories', // A problematic WooCommerce shortcode.
851
- 'recent_products', // A problematic WooCommerce shortcode.
852
- 'php', // PHP Code for Posts.
853
- 'watupro', // Watu PRO doesn't co-operate.
854
- 'starbox', // Starbox shortcode breaks Relevanssi.
855
- 'cfdb-save-form-post', // Contact Form DB.
856
- 'cfdb-datatable',
857
- 'cfdb-table',
858
- 'cfdb-json',
859
- 'cfdb-value',
860
- 'cfdb-count',
861
- 'cfdb-html',
862
- 'woocommerce_cart', // WooCommerce.
863
- 'woocommerce_checkout',
864
- 'woocommerce_order_tracking',
865
- 'woocommerce_my_account',
866
- 'woocommerce_edit_account',
867
- 'woocommerce_change_password',
868
- 'woocommerce_view_order',
869
- 'woocommerce_logout',
870
- 'woocommerce_pay',
871
- 'woocommerce_thankyou',
872
- 'woocommerce_lost_password',
873
- 'woocommerce_edit_address',
874
- 'tc_process_payment',
875
- 'maxmegamenu', // Max Mega Menu.
876
- 'searchandfilter', // Search and Filter.
877
- 'downloads', // Easy Digital Downloads.
878
- 'download_history',
879
- 'purchase_history',
880
- 'download_checkout',
881
- 'purchase_link',
882
- 'download_cart',
883
- 'edd_profile_editor',
884
- 'edd_login',
885
- 'edd_register',
886
- 'swpm_protected', // Simple Membership Partially Protected content.
887
- 'gravityform', // Gravity Forms.
888
- 'sdm_latest_downloads', // SDM Simple Download Monitor.
889
- 'slimstat', // Slimstat Analytics.
890
- );
891
-
892
- $disable_shortcodes = get_option( 'relevanssi_disable_shortcodes' );
893
- $shortcodes = explode( ',', $disable_shortcodes );
894
- $shortcodes = array_unique( array_merge( $shortcodes, $default_disables ) );
895
- foreach ( $shortcodes as $shortcode ) {
896
- if ( empty( $shortcode ) ) {
897
- continue;
898
- }
899
- remove_shortcode( trim( $shortcode ) );
900
- add_shortcode( $shortcode, '__return_empty_string' );
901
- }
902
-
903
- $post_before_shortcode = $post;
904
- $contents = do_shortcode( $contents );
905
- $post = $post_before_shortcode; // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited
906
-
907
- if ( defined( 'TABLEPRESS_ABSPATH' ) ) {
908
- unset( $my_tablepress_controller );
909
- }
910
- if ( defined( 'WP_TABLE_RELOADED_ABSPATH' ) ) {
911
- unset( $my_wp_table_reloaded );
912
- }
913
- }
914
- } else {
915
- $contents = strip_shortcodes( $contents );
916
- }
917
-
918
- remove_shortcode( 'noindex' );
919
- add_shortcode( 'noindex', 'relevanssi_noindex_shortcode' );
920
-
921
- $contents = relevanssi_strip_invisibles( $contents );
922
-
923
- // Premium feature for better control over internal links.
924
- if ( function_exists( 'relevanssi_process_internal_links' ) ) {
925
- $contents = relevanssi_process_internal_links( $contents, $post->ID );
926
- }
927
-
928
- $contents = preg_replace( '/<[a-zA-Z\/][^>]*>/', ' ', $contents );
929
- $contents = wp_strip_all_tags( $contents );
930
- if ( function_exists( 'wp_encode_emoji' ) ) {
931
- $contents = wp_encode_emoji( $contents );
932
- }
933
- /**
934
- * Filters the post content in indexing before tokenization.
935
- *
936
- * @param string $contents The post content.
937
- * @param object $post The full post object.
938
- */
939
- $contents = apply_filters( 'relevanssi_post_content_before_tokenize', $contents, $post );
940
- /** This filter is documented in common/indexing.php */
941
- $content_tokens = apply_filters( 'relevanssi_indexing_tokens', relevanssi_tokenize( $contents, 'body', $min_word_length ), 'content' );
942
- if ( $debug ) {
943
- relevanssi_debug_echo( "\tContent, tokenized:\n" . implode( ' ', array_keys( $content_tokens ) ) );
944
- }
945
-
946
- if ( count( $content_tokens ) > 0 ) {
947
- foreach ( $content_tokens as $token => $count ) {
948
- $n++;
949
- if ( ! isset( $insert_data[ $token ]['content'] ) ) {
950
- $insert_data[ $token ]['content'] = 0;
951
- }
952
- $insert_data[ $token ]['content'] += $count;
953
- }
954
- }
955
- }
956
-
957
- /**
958
- * Sets the indexed post 'type' column in the index.
959
- *
960
- * Default value is 'post', but other common values include 'attachment',
961
- * 'user' and taxonomy name.
962
- *
963
- * @param string Type value.
964
- * @param object The post object for the current post.
965
- */
966
- $type = apply_filters( 'relevanssi_index_get_post_type', 'post', $post );
967
-
968
- /**
969
- * Filters the indexing data before it is converted to INSERT queries.
970
- *
971
- * @param array $insert_data All the tokens and their counts.
972
- * @param object $post The post object.
973
- */
974
- $insert_data = apply_filters( 'relevanssi_indexing_data', $insert_data, $post );
975
-
976
- $values = array();
977
- foreach ( $insert_data as $term => $data ) {
978
- $fields = array( 'content', 'title', 'comment', 'tag', 'link', 'author', 'category', 'excerpt', 'taxonomy', 'customfield', 'mysqlcolumn' );
979
- foreach ( $fields as $field ) {
980
- if ( ! isset( $data[ $field ] ) ) {
981
- $data[ $field ] = 0;
982
- }
983
- }
984
- if ( ! isset( $data['taxonomy_detail'] ) ) {
985
- $data['taxonomy_detail'] = '';
986
- }
987
- if ( ! isset( $data['customfield_detail'] ) ) {
988
- $data['customfield_detail'] = '';
989
- }
990
- $content = $data['content'];
991
- $title = $data['title'];
992
- $comment = $data['comment'];
993
- $tag = $data['tag'];
994
- $link = $data['link'];
995
- $author = $data['author'];
996
- $category = $data['category'];
997
- $excerpt = $data['excerpt'];
998
- $taxonomy = $data['taxonomy'];
999
- $customfield = $data['customfield'];
1000
- $mysqlcolumn = $data['mysqlcolumn'];
1001
- $taxonomy_detail = $data['taxonomy_detail'];
1002
- $customfield_detail = $data['customfield_detail'];
1003
-
1004
- $term = trim( $term );
1005
-
1006
- $value = $wpdb->prepare(
1007
- '(%d, %s, REVERSE(%s), %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %s, %s, %s, %d)',
1008
- $post->ID,
1009
- $term,
1010
- $term,
1011
- $content,
1012
- $title,
1013
- $comment,
1014
- $tag,
1015
- $link,
1016
- $author,
1017
- $category,
1018
- $excerpt,
1019
- $taxonomy,
1020
- $customfield,
1021
- $type,
1022
- $taxonomy_detail,
1023
- $customfield_detail,
1024
- $mysqlcolumn
1025
- );
1026
 
1027
- array_push( $values, $value );
1028
- }
1029
-
1030
- /**
1031
- * Filters the INSERT query VALUES sections before they are inserted in the INSERT query.
1032
- *
1033
- * @param array $values Value sets.
1034
- * @param object $post The post object.
1035
- */
1036
- $values = apply_filters( 'relevanssi_indexing_values', $values, $post );
1037
 
1038
  if ( ! empty( $values ) ) {
1039
  $values = implode( ', ', $values );
@@ -1044,10 +524,7 @@ function relevanssi_index_doc( $index_post, $remove_first = false, $custom_field
1044
  $wpdb->query( $query ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
1045
  }
1046
 
1047
- if ( $post_was_null ) {
1048
- $post = null; // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited
1049
- }
1050
- if ( $previous_post ) {
1051
  $post = $previous_post; // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited
1052
  }
1053
 
@@ -1059,36 +536,48 @@ function relevanssi_index_doc( $index_post, $remove_first = false, $custom_field
1059
  *
1060
  * @since 1.8
1061
  *
1062
- * @param object $post Post object, default null.
1063
- * @param string $taxonomy Taxonomy name, default empty string.
1064
- * @param array $insert_data Insert query data array.
 
1065
  *
1066
- * @return array Updated insert query data array.
1067
  */
1068
- function relevanssi_index_taxonomy_terms( $post = null, $taxonomy = '', $insert_data ) {
1069
- $n = 0;
1070
-
1071
- if ( null === $post || empty( $taxonomy ) ) {
1072
- return $insert_data;
1073
  }
1074
 
 
 
1075
  $min_word_length = get_option( 'relevanssi_min_word_length', 3 );
1076
- $post_taxonomy_terms = get_the_terms( $post->ID, $taxonomy );
1077
 
1078
  if ( false === $post_taxonomy_terms ) {
1079
- return $insert_data;
1080
  }
1081
 
1082
- $tag_string = '';
1083
- foreach ( $post_taxonomy_terms as $post_tag ) {
1084
- if ( is_object( $post_tag ) ) {
1085
- $tag_string .= $post_tag->name . ' ';
1086
  }
1087
  }
1088
- $tag_string = apply_filters( 'relevanssi_tag_before_tokenize', trim( $tag_string ) );
1089
- $tag_tokens = relevanssi_tokenize( $tag_string, true, $min_word_length );
1090
- if ( count( $tag_tokens ) > 0 ) {
1091
- foreach ( $tag_tokens as $token => $count ) {
 
 
 
 
 
 
 
 
 
 
 
1092
  $n++;
1093
 
1094
  switch ( $taxonomy ) {
@@ -1116,7 +605,8 @@ function relevanssi_index_taxonomy_terms( $post = null, $taxonomy = '', $insert_
1116
  $insert_data[ $token ]['taxonomy_detail'] = wp_json_encode( $tax_detail );
1117
  }
1118
  }
1119
- return $insert_data;
 
1120
  }
1121
 
1122
  /**
@@ -1514,3 +1004,642 @@ function relevanssi_index_get_post_type( $type, $post ) {
1514
  }
1515
  return $type;
1516
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
126
  OR (post.post_parent=0)
127
  )
128
  ))
129
+ AND post.ID NOT IN (SELECT post_id FROM $wpdb->postmeta WHERE meta_key = '_relevanssi_hide_post' AND meta_value = 'on')
130
  $restriction ORDER BY post.ID DESC $limit";
131
  } else {
132
  $q = "SELECT post.ID
145
  )
146
  )
147
  )
148
+ AND post.ID NOT IN (SELECT post_id FROM $wpdb->postmeta WHERE meta_key = '_relevanssi_hide_post' AND meta_value = 'on')
149
  $restriction ORDER BY post.ID DESC $limit";
150
  }
151
 
235
  * @param boolean|int $extend_offset If numeric, offsets the indexing by that
236
  * amount. If true, doesn't truncate the index before indexing. If false, truncates
237
  * index before indexing. Default false.
238
+ * @param boolean $verbose Not used anymore, kept for backwards compatibility.
239
  * @param int $post_limit How many posts to index. Default null, no limit.
240
  * @param boolean $is_ajax If true, indexing is done in AJAX context.
241
  * Default false.
245
  * posts indexed. Outside AJAX context, these values are returned as an array in
246
  * format of array(completed, posts indexed).
247
  */
248
+ function relevanssi_build_index( $extend_offset = false, $verbose = null, $post_limit = null, $is_ajax = false ) {
249
  global $wpdb, $relevanssi_variables;
250
  $relevanssi_table = $relevanssi_variables['relevanssi_table'];
251
 
252
  // Thanks to Julien Mession. This speeds up indexing a lot.
253
  wp_suspend_cache_addition( true );
254
 
 
 
 
 
 
 
 
255
  if ( false === $extend_offset ) {
256
  // Truncate the index first.
257
  relevanssi_truncate_index();
258
 
259
+ // Taxonomy term, user profile and post type archive indexing.
260
+ if ( function_exists( 'relevanssi_premium_indexing' ) ) {
261
+ relevanssi_premium_indexing();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
262
  }
263
 
 
 
 
 
 
 
 
 
 
264
  update_option( 'relevanssi_index', '' );
265
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
266
 
267
+ $indexing_query_args = relevanssi_indexing_query_args( $extend_offset, $post_limit );
 
 
 
 
 
268
 
269
+ // The values generated by these functions are safe to use for MySQL.
270
+ $restriction = relevanssi_post_type_restriction();
271
+ $valid_status = relevanssi_valid_status_array();
 
272
 
273
+ $query = relevanssi_generate_indexing_query(
274
+ $valid_status,
275
+ $indexing_query_args['extend'],
276
+ $restriction,
277
+ $indexing_query_args['limit']
278
+ );
279
 
280
  /* This action documented earlier in lib/indexing.php. */
281
  do_action( 'relevanssi_pre_indexing_query' );
 
282
 
283
+ $content = $wpdb->get_results( $query ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
284
  if ( defined( 'WP_CLI' ) && WP_CLI && function_exists( 'relevanssi_generate_progress_bar' ) ) {
285
+ // @codeCoverageIgnoreStart
286
  $progress = relevanssi_generate_progress_bar( 'Indexing posts', count( $content ) );
287
+ // @codeCoverageIgnoreEnd
288
  }
289
 
290
+ $custom_fields = relevanssi_get_custom_fields();
291
+
292
+ $n = 0;
293
  $remove_first = false;
294
  $bypass_global_post = true; // $bypassglobalpost set to true, because at this
295
  // point global $post should be null, but in some cases it is not.
300
  $n++;
301
  }
302
  if ( defined( 'WP_CLI' ) && WP_CLI && $progress ) {
303
+ // @codeCoverageIgnoreStart
304
  $progress->tick();
305
+ // @codeCoverageIgnoreEnd
306
  }
307
  }
308
  if ( defined( 'WP_CLI' ) && WP_CLI && $progress ) {
309
+ // @codeCoverageIgnoreStart
310
  $progress->finish();
311
+ // @codeCoverageIgnoreEnd
312
  }
313
 
314
  // To prevent empty indices.
315
  $wpdb->query( "ANALYZE TABLE $relevanssi_table" ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared,WordPress.DB.PreparedSQL.InterpolatedNotPrepared
316
 
317
  $complete = false;
318
+ $size = $indexing_query_args['size'];
319
+
320
  if ( ( 0 === $size ) || ( count( $content ) < $size ) ) {
 
321
  $complete = true;
322
+ update_option( 'relevanssi_indexed', 'done' );
 
 
 
 
323
  }
324
 
 
 
325
  // Update the document count variable.
326
  relevanssi_update_doc_count();
327
 
362
  * @param boolean $remove_first If true, remove the post from the index
363
  * before indexing. Default false.
364
  * @param array $custom_fields The custom fields that are indexed for the
365
+ * post. Default an empty string.
366
  * @param boolean $bypass_global_post If true, do not use the global $post object.
367
  * Default false.
368
  * @param boolean $debug If true, echo out debugging information.
369
  * Default false.
370
  */
371
+ function relevanssi_index_doc( $index_post, $remove_first = false, $custom_fields = '', $bypass_global_post = false, $debug = false ) {
372
  global $wpdb, $post, $relevanssi_variables;
373
  $relevanssi_table = $relevanssi_variables['relevanssi_table'];
374
+ $post_was_null = true;
375
  $previous_post = null;
376
 
377
  // Check if this is a Jetpack Contact Form entry.
378
  if ( isset( $_REQUEST['contact-form-id'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification
379
+ return -1;
380
  }
381
 
382
+ if ( isset( $post ) ) {
383
+ $post_was_null = false;
384
+ $previous_post = $post;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
385
  }
386
 
387
+ if ( empty( $post ) || $bypass_global_post ) {
388
+ $post = is_object( $index_post ) ? $index_post : get_post( $index_post ); // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited
 
 
 
 
 
 
 
389
  }
390
 
391
  // Finally fetch the post again by ID. Complicated, yes, but unless we do this,
392
  // we might end up indexing the post before the updates come in.
393
+ $post = isset( $post->ID ) ? get_post( $post->ID ) : null; // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited
394
 
395
  if ( null === $post ) {
396
+ // At this point we should have something in $post; if not, quit.
397
+ if ( $previous_post || $post_was_null ) {
398
+ $post = $previous_post; // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited
399
+ }
400
  return -1;
401
  }
402
 
406
  if ( $debug ) {
407
  relevanssi_debug_echo( 'relevanssi_hide_post() returned true.' );
408
  }
409
+ if ( $previous_post || $post_was_null ) {
 
 
 
410
  $post = $previous_post; // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited
411
  }
412
  return 'hide';
416
  $index_this_post = false;
417
  $post->indexing_content = true;
418
 
419
+ $index_types = get_option( 'relevanssi_index_post_types', array() );
420
+ if ( is_array( $index_types ) && in_array( $post->post_type, $index_types, true ) ) {
 
 
 
421
  $index_this_post = true;
422
  }
423
 
451
  // This needs to be here, after the call to relevanssi_remove_doc(), because
452
  // otherwise a post that's in the index but shouldn't be there won't get removed.
453
  if ( ! $index_this_post ) {
454
+ if ( $previous_post || $post_was_null ) {
 
 
 
455
  $post = $previous_post; // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited
456
  }
457
  return 'donotindex';
472
  $insert_data = array();
473
 
474
  if ( 'none' !== get_option( 'relevanssi_index_comments' ) ) {
475
+ $n += relevanssi_index_comments( $insert_data, $post->ID, $min_word_length, $debug );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
476
  }
477
 
 
478
  $taxonomies = get_option( 'relevanssi_index_taxonomies_list', array() );
479
  foreach ( $taxonomies as $taxonomy ) {
480
+ $n += relevanssi_index_taxonomy_terms( $insert_data, $post->ID, $taxonomy, $debug );
 
 
 
481
  }
482
 
 
483
  if ( 'on' === get_option( 'relevanssi_index_author' ) ) {
484
+ $n += relevanssi_index_author( $insert_data, $post->post_author, $min_word_length, $debug );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
485
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
486
 
487
+ $n += relevanssi_index_custom_fields( $insert_data, $post->ID, $custom_fields, $min_word_length, $debug );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
488
 
489
+ if (
490
+ isset( $post->post_excerpt )
491
+ && ( 'on' === get_option( 'relevanssi_index_excerpt' ) || 'attachment' === $post->post_type )
492
+ ) {
493
+ // Attachment caption is stored in the excerpt.
494
+ $n += relevanssi_index_excerpt( $insert_data, $post->post_excerpt, $min_word_length, $debug );
 
 
 
 
 
 
 
 
495
  }
496
 
497
  // Premium can index arbitrary MySQL columns.
510
  $insert_data = relevanssi_index_pdf_for_parent( $insert_data, $post->ID );
511
  }
512
 
513
+ $n += relevanssi_index_title( $insert_data, $post, $min_word_length, $debug );
514
+ $n += relevanssi_index_content( $insert_data, $post, $min_word_length, $debug );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
515
 
516
+ $values = relevanssi_convert_data_to_values( $insert_data, $post );
 
 
 
 
 
 
 
 
 
517
 
518
  if ( ! empty( $values ) ) {
519
  $values = implode( ', ', $values );
524
  $wpdb->query( $query ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
525
  }
526
 
527
+ if ( $previous_post || $post_was_null ) {
 
 
 
528
  $post = $previous_post; // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited
529
  }
530
 
536
  *
537
  * @since 1.8
538
  *
539
+ * @param array $insert_data Insert query data array, modified here.
540
+ * @param int $post_id The indexed post ID.
541
+ * @param string $taxonomy Taxonomy name.
542
+ * @param boolean $debug If true, print out debugging notices.
543
  *
544
+ * @return int The number of new tokens added.
545
  */
546
+ function relevanssi_index_taxonomy_terms( &$insert_data, $post_id, $taxonomy, $debug ) {
547
+ if ( $debug ) {
548
+ relevanssi_debug_echo( "Indexing taxonomy terms for $taxonomy" );
 
 
549
  }
550
 
551
+ $n = 0;
552
+
553
  $min_word_length = get_option( 'relevanssi_min_word_length', 3 );
554
+ $post_taxonomy_terms = get_the_terms( $post_id, $taxonomy );
555
 
556
  if ( false === $post_taxonomy_terms ) {
557
+ return $n;
558
  }
559
 
560
+ $term_string = '';
561
+ foreach ( $post_taxonomy_terms as $post_term ) {
562
+ if ( is_object( $post_term ) ) {
563
+ $term_string .= $post_term->name . ' ';
564
  }
565
  }
566
+ if ( $debug ) {
567
+ relevanssi_debug_echo( "Taxonomy term content for $taxonomy: $term_string" );
568
+ }
569
+ /**
570
+ * Filters the taxonomy term content before indexing.
571
+ *
572
+ * @param string The taxonomy term content.
573
+ * @param string The taxonomy term name.
574
+ * @param string The taxonomy.
575
+ * @param int The post ID.
576
+ */
577
+ $term_string = apply_filters( 'relevanssi_tag_before_tokenize', trim( $term_string ), $post_term, $taxonomy, $post_id );
578
+ $term_tokens = relevanssi_tokenize( $term_string, true, $min_word_length );
579
+ if ( count( $term_tokens ) > 0 ) {
580
+ foreach ( $term_tokens as $token => $count ) {
581
  $n++;
582
 
583
  switch ( $taxonomy ) {
605
  $insert_data[ $token ]['taxonomy_detail'] = wp_json_encode( $tax_detail );
606
  }
607
  }
608
+
609
+ return $n;
610
  }
611
 
612
  /**
1004
  }
1005
  return $type;
1006
  }
1007
+
1008
+ /**
1009
+ * Sets the indexing MySQL LIMIT parameter and other parameters.
1010
+ *
1011
+ * @param boolean|int $extend_offset If numeric, offsets the indexing by that
1012
+ * amount. If true, doesn't truncate the index before indexing. If false,
1013
+ * truncates index before indexing. Default false.
1014
+ * @param int $post_limit How many posts to index. Default null, no
1015
+ * limit.
1016
+ *
1017
+ * @return array Array with the LIMIT clause in 'limit', the extend boolean in
1018
+ * 'extend' and the size integer in 'size'.
1019
+ */
1020
+ function relevanssi_indexing_query_args( $extend_offset, $post_limit ) {
1021
+ $size = 0;
1022
+ $limit = '';
1023
+ $extend = false;
1024
+
1025
+ // If $post_limit parameter is present, numeric and > 0, use that.
1026
+ if ( isset( $post_limit ) && is_numeric( $post_limit ) && $post_limit > 0 ) {
1027
+ $size = $post_limit;
1028
+ $limit = " LIMIT $post_limit";
1029
+ }
1030
+
1031
+ if ( false === $extend_offset ) {
1032
+ $extend = false;
1033
+ } elseif ( ! is_numeric( $extend_offset ) ) {
1034
+ // Extending, so do not truncate and skip the posts already in the index.
1035
+ if ( ! $limit ) {
1036
+ // CLI request with no limit specified.
1037
+ $size = 200;
1038
+ $limit = ' LIMIT 200';
1039
+ }
1040
+
1041
+ $extend = true;
1042
+ } else { // $extend_offset is numeric.
1043
+ if ( ! $limit ) {
1044
+ // CLI request with no limit specified.
1045
+ $size = 200;
1046
+ $limit = ' LIMIT 200';
1047
+ }
1048
+
1049
+ if ( ! empty( $limit ) ) {
1050
+ $limit .= " OFFSET $extend_offset";
1051
+ }
1052
+
1053
+ // Extend is set to false, because $limit now has LIMIT and OFFSET.
1054
+ $extend = false;
1055
+ }
1056
+
1057
+ return array(
1058
+ 'limit' => $limit,
1059
+ 'extend' => $extend,
1060
+ 'size' => $size,
1061
+ );
1062
+ }
1063
+
1064
+ /**
1065
+ * Creates indexing queries for the comment content.
1066
+ *
1067
+ * @param array $insert_data The INSERT query data. Modified here.
1068
+ * @param int $post_id The indexed post ID.
1069
+ * @param int $min_word_length The minimum word length.
1070
+ * @param boolean $debug If true, print out debug notices.
1071
+ *
1072
+ * @return int The number of tokens added to the data.
1073
+ */
1074
+ function relevanssi_index_comments( &$insert_data, $post_id, $min_word_length, $debug ) {
1075
+ $n = 0;
1076
+ if ( $debug ) {
1077
+ relevanssi_debug_echo( 'Indexing comments.' );
1078
+ }
1079
+ $post_comments = relevanssi_get_comments( $post_id );
1080
+ if ( ! empty( $post_comments ) ) {
1081
+ $post_comments = relevanssi_strip_invisibles( $post_comments );
1082
+ $post_comments = preg_replace( '/<[a-zA-Z\/][^>]*>/', ' ', $post_comments );
1083
+ $post_comments = wp_strip_all_tags( $post_comments );
1084
+ if ( $debug ) {
1085
+ relevanssi_debug_echo( "Comment content: $post_comments" );
1086
+ }
1087
+ /**
1088
+ * Filters the indexing tokens before they are added to the $insert_data.
1089
+ *
1090
+ * @param array An array of token-frequency pairs.
1091
+ * @param string The context of the tokens (eg. 'content', 'title').
1092
+ *
1093
+ * @return array The filtered tokens.
1094
+ */
1095
+ $post_comments_tokens = apply_filters(
1096
+ 'relevanssi_indexing_tokens',
1097
+ relevanssi_tokenize( $post_comments, true, $min_word_length ),
1098
+ 'comments'
1099
+ );
1100
+ if ( count( $post_comments_tokens ) > 0 ) {
1101
+ foreach ( $post_comments_tokens as $token => $count ) {
1102
+ $n++;
1103
+ $insert_data[ $token ]['comment'] = $count;
1104
+ }
1105
+ }
1106
+ }
1107
+ return $n;
1108
+ }
1109
+
1110
+ /**
1111
+ * Creates indexing queries for the post author.
1112
+ *
1113
+ * @param array $insert_data The INSERT query data. Modified here.
1114
+ * @param int $post_author The post author id.
1115
+ * @param int $min_word_length The minimum word length.
1116
+ * @param boolean $debug If true, print out debug notices.
1117
+ *
1118
+ * @return int The number of tokens added to the data.
1119
+ */
1120
+ function relevanssi_index_author( &$insert_data, $post_author, $min_word_length, $debug ) {
1121
+ $n = 0;
1122
+ $display_name = get_the_author_meta( 'display_name', $post_author );
1123
+ /** This filter is documented in lib/indexing.php */
1124
+ $name_tokens = apply_filters(
1125
+ 'relevanssi_indexing_tokens',
1126
+ relevanssi_tokenize( $display_name, false, $min_word_length ),
1127
+ 'author'
1128
+ );
1129
+ if ( $debug ) {
1130
+ relevanssi_debug_echo( 'Indexing post author as: ' . implode( ' ', array_keys( $name_tokens ) ) );
1131
+ }
1132
+ foreach ( $name_tokens as $token => $count ) {
1133
+ $n++;
1134
+ if ( ! isset( $insert_data[ $token ]['author'] ) ) {
1135
+ $insert_data[ $token ]['author'] = 0;
1136
+ }
1137
+ $insert_data[ $token ]['author'] += $count;
1138
+ }
1139
+
1140
+ return $n;
1141
+ }
1142
+
1143
+ /**
1144
+ * Creates indexing query data for custom fields.
1145
+ *
1146
+ * @param array $insert_data The INSERT query data. Modified here.
1147
+ * @param int $post_id The indexed post ID.
1148
+ * @param string|array $custom_fields The custom fields to index.
1149
+ * @param int $min_word_length The minimum word length.
1150
+ * @param boolean $debug If true, print out debug notices.
1151
+ *
1152
+ * @return int The number of tokens added to the data.
1153
+ */
1154
+ function relevanssi_index_custom_fields( &$insert_data, $post_id, $custom_fields, $min_word_length, $debug ) {
1155
+ $n = 0;
1156
+
1157
+ $remove_underscore_fields = 'visible' === $custom_fields ? true : false;
1158
+ if ( 'all' === $custom_fields || 'visible' === $custom_fields ) {
1159
+ $custom_fields = get_post_custom_keys( $post_id );
1160
+ }
1161
+
1162
+ /**
1163
+ * Filters the list of custom fields to index before indexing.
1164
+ *
1165
+ * @param array $custom_fields List of custom field names.
1166
+ * @param int $post_id The post ID.
1167
+ */
1168
+ $custom_fields = apply_filters( 'relevanssi_index_custom_fields', $custom_fields, $post_id );
1169
+
1170
+ if ( ! is_array( $custom_fields ) ) {
1171
+ return 0;
1172
+ }
1173
+
1174
+ $custom_fields = array_unique( $custom_fields );
1175
+ if ( $remove_underscore_fields ) {
1176
+ $custom_fields = array_filter(
1177
+ $custom_fields,
1178
+ function( $field ) {
1179
+ if ( '_relevanssi_pdf_content' === $field || '_' !== substr( $field, 0, 1 ) ) {
1180
+ return $field;
1181
+ }
1182
+ }
1183
+ );
1184
+ }
1185
+
1186
+ // Premium includes some support for ACF repeater fields.
1187
+ if ( function_exists( 'relevanssi_add_repeater_fields' ) ) {
1188
+ relevanssi_add_repeater_fields( $custom_fields, $post_id );
1189
+ }
1190
+
1191
+ if ( $debug ) {
1192
+ relevanssi_debug_echo( 'Custom fields to index: ' . implode( ', ', $custom_fields ) );
1193
+ }
1194
+
1195
+ foreach ( $custom_fields as $field ) {
1196
+ /**
1197
+ * Filters the custom field value before indexing.
1198
+ *
1199
+ * @param array Custom field values.
1200
+ * @param string $field The custom field name.
1201
+ * @param int $post_id The post ID.
1202
+ */
1203
+ $values = apply_filters( 'relevanssi_custom_field_value', get_post_meta( $post_id, $field, false ), $field, $post_id );
1204
+
1205
+ if ( empty( $values ) || ! is_array( $values ) ) {
1206
+ continue;
1207
+ }
1208
+
1209
+ foreach ( $values as $value ) {
1210
+ // Quick hack : allow indexing of PODS relationship custom fields // TMV.
1211
+ if ( is_array( $value ) && isset( $value['post_title'] ) ) {
1212
+ $value = $value['post_title'];
1213
+ }
1214
+
1215
+ if ( function_exists( 'relevanssi_index_acf' ) ) {
1216
+ // @codeCoverageIgnoreStart
1217
+ // Handle ACF fields. Only defined when ACF is active.
1218
+ $acf_tokens = relevanssi_index_acf( $insert_data, $post_id, $field, $value );
1219
+ if ( $acf_tokens ) {
1220
+ $n += $acf_tokens;
1221
+ continue;
1222
+ }
1223
+ // @codeCoverageIgnoreEnd
1224
+ }
1225
+
1226
+ // Flatten other arrays.
1227
+ if ( is_array( $value ) ) {
1228
+ $value = relevanssi_flatten_array( $value );
1229
+ }
1230
+
1231
+ if ( $debug ) {
1232
+ relevanssi_debug_echo( "\tKey: " . $field . ' – value: ' . $value );
1233
+ }
1234
+
1235
+ /** This filter is documented in lib/indexing.php */
1236
+ $value_tokens = apply_filters(
1237
+ 'relevanssi_indexing_tokens',
1238
+ relevanssi_tokenize( $value, true, $min_word_length ),
1239
+ 'custom_field'
1240
+ );
1241
+ foreach ( $value_tokens as $token => $count ) {
1242
+ $n++;
1243
+ if ( ! isset( $insert_data[ $token ]['customfield'] ) ) {
1244
+ $insert_data[ $token ]['customfield'] = 0;
1245
+ }
1246
+ $insert_data[ $token ]['customfield'] += $count;
1247
+
1248
+ // Premium indexes more detail about custom fields.
1249
+ if ( function_exists( 'relevanssi_customfield_detail' ) ) {
1250
+ $insert_data = relevanssi_customfield_detail(
1251
+ $insert_data,
1252
+ $token,
1253
+ $count,
1254
+ $field
1255
+ );
1256
+ }
1257
+ }
1258
+ }
1259
+ }
1260
+
1261
+ return $n;
1262
+ }
1263
+
1264
+ /**
1265
+ * Creates indexing queries for the excerpt content.
1266
+ *
1267
+ * @param array $insert_data The INSERT query data. Modified here.
1268
+ * @param string $excerpt The post excerpt to index.
1269
+ * @param int $min_word_length The minimum word length.
1270
+ * @param boolean $debug If true, print out debug notices.
1271
+ *
1272
+ * @return int The number of tokens added to the data.
1273
+ */
1274
+ function relevanssi_index_excerpt( &$insert_data, $excerpt, $min_word_length, $debug ) {
1275
+ $n = 0;
1276
+
1277
+ // Include excerpt for attachments which use post_excerpt for captions - modified by renaissancehack.
1278
+ if ( $debug ) {
1279
+ relevanssi_debug_echo( "Indexing post excerpt: $excerpt" );
1280
+ }
1281
+ /** This filter is documented in common/indexing.php */
1282
+ $excerpt_tokens = apply_filters(
1283
+ 'relevanssi_indexing_tokens',
1284
+ relevanssi_tokenize( $excerpt, true, $min_word_length ),
1285
+ 'excerpt'
1286
+ );
1287
+ foreach ( $excerpt_tokens as $token => $count ) {
1288
+ $n++;
1289
+ if ( ! isset( $insert_data[ $token ]['excerpt'] ) ) {
1290
+ $insert_data[ $token ]['excerpt'] = 0;
1291
+ }
1292
+ $insert_data[ $token ]['excerpt'] += $count;
1293
+ }
1294
+ return $n;
1295
+ }
1296
+
1297
+ /**
1298
+ * Creates indexing queries for post title.
1299
+ *
1300
+ * @param array $insert_data The INSERT query data. Modified here.
1301
+ * @param object $post The post object.
1302
+ * @param int $min_word_length The minimum word length.
1303
+ * @param boolean $debug If true, print out debug notices.
1304
+ *
1305
+ * @return int The number of tokens added to the data.
1306
+ */
1307
+ function relevanssi_index_title( &$insert_data, $post, $min_word_length, $debug ) {
1308
+ $n = 0;
1309
+
1310
+ if ( empty( $post->post_title ) ) {
1311
+ return 0;
1312
+ }
1313
+
1314
+ /**
1315
+ * If this filter returns false, titles are not indexed at all.
1316
+ *
1317
+ * @param boolean Return false to prevent titles from being indexed. Default true.
1318
+ */
1319
+ if ( ! apply_filters( 'relevanssi_index_titles', true ) ) {
1320
+ return 0;
1321
+ }
1322
+
1323
+ if ( $debug ) {
1324
+ relevanssi_debug_echo( 'Indexing post title.' );
1325
+ }
1326
+ /** This filter is documented in wp-includes/post-template.php */
1327
+ $filtered_title = apply_filters( 'the_title', $post->post_title, $post->ID );
1328
+ /**
1329
+ * Filters the title before tokenizing and indexing.
1330
+ *
1331
+ * @param string $post->post_title The title.
1332
+ * @param object $post The full post object.
1333
+ */
1334
+ $filtered_title = apply_filters( 'relevanssi_post_title_before_tokenize', $filtered_title, $post );
1335
+ $title_tokens = relevanssi_tokenize(
1336
+ $filtered_title,
1337
+ /**
1338
+ * Filters whether stopwords should be removed from titles in tokenizing or not.
1339
+ *
1340
+ * @param boolean If true, remove stopwords. Default true.
1341
+ */
1342
+ apply_filters( 'relevanssi_remove_stopwords_in_titles', true ),
1343
+ $min_word_length
1344
+ );
1345
+ /** This filter is documented in lib/indexing.php */
1346
+ $title_tokens = apply_filters( 'relevanssi_indexing_tokens', $title_tokens, 'title' );
1347
+
1348
+ if ( $debug ) {
1349
+ relevanssi_debug_echo( "\tTitle, tokenized: " . implode( ' ', array_keys( $title_tokens ) ) );
1350
+ }
1351
+
1352
+ foreach ( $title_tokens as $token => $count ) {
1353
+ $n++;
1354
+ if ( ! isset( $insert_data[ $token ]['title'] ) ) {
1355
+ $insert_data[ $token ]['title'] = 0;
1356
+ }
1357
+ $insert_data[ $token ]['title'] += $count;
1358
+ }
1359
+
1360
+ return $n;
1361
+ }
1362
+
1363
+ /**
1364
+ * Creates indexing queries for post content.
1365
+ *
1366
+ * @param array $insert_data The INSERT query data. Modified here.
1367
+ * @param object $post The post object.
1368
+ * @param int $min_word_length The minimum word length.
1369
+ * @param boolean $debug If true, print out debug notices.
1370
+ *
1371
+ * @return int The number of tokens added to the data.
1372
+ */
1373
+ function relevanssi_index_content( &$insert_data, $post, $min_word_length, $debug ) {
1374
+ $n = 0;
1375
+
1376
+ /**
1377
+ * If this filter returns false, post content is not indexed at all.
1378
+ *
1379
+ * @param boolean Return false to prevent post content from being indexed. Default true.
1380
+ */
1381
+ if ( ! apply_filters( 'relevanssi_index_content', true ) ) {
1382
+ return $n;
1383
+ }
1384
+
1385
+ if ( $debug ) {
1386
+ relevanssi_debug_echo( 'Indexing post content.' );
1387
+ }
1388
+
1389
+ remove_shortcode( 'noindex' );
1390
+ add_shortcode( 'noindex', 'relevanssi_noindex_shortcode_indexing' );
1391
+
1392
+ /**
1393
+ * Filters the post content before indexing.
1394
+ *
1395
+ * @param string $post->post_content The post content.
1396
+ * @param object $post The full post object.
1397
+ */
1398
+ $contents = apply_filters( 'relevanssi_post_content', $post->post_content, $post );
1399
+ if ( $debug ) {
1400
+ relevanssi_debug_echo( "\tPost content after relevanssi_post_content:\n$contents" );
1401
+ }
1402
+
1403
+ /**
1404
+ * Can be used to add extra content to the post before indexing.
1405
+ *
1406
+ * @author Alexander Gieg
1407
+ *
1408
+ * @param string The additional content.
1409
+ * @param object $post The post object.
1410
+ */
1411
+ $additional_content = trim( apply_filters( 'relevanssi_content_to_index', '', $post ) );
1412
+ if ( ! empty( $additional_content ) ) {
1413
+ $contents .= ' ' . $additional_content;
1414
+
1415
+ if ( $debug ) {
1416
+ relevanssi_debug_echo( "\tAdditional content from relevanssi_content_to_index:\n$additional_content" );
1417
+ }
1418
+ }
1419
+
1420
+ if ( 'on' === get_option( 'relevanssi_expand_shortcodes' ) ) {
1421
+ // TablePress support.
1422
+ $tablepress_controller = relevanssi_enable_tablepress_shortcodes();
1423
+
1424
+ relevanssi_disable_shortcodes();
1425
+
1426
+ $post_before_shortcode = $post;
1427
+ $contents = do_shortcode( $contents );
1428
+ $post = $post_before_shortcode; // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited
1429
+
1430
+ unset( $tablepress_controller );
1431
+ } else {
1432
+ $contents = strip_shortcodes( $contents );
1433
+ }
1434
+
1435
+ remove_shortcode( 'noindex' );
1436
+ add_shortcode( 'noindex', 'relevanssi_noindex_shortcode' );
1437
+
1438
+ $contents = relevanssi_strip_invisibles( $contents );
1439
+
1440
+ // Premium feature for better control over internal links.
1441
+ if ( function_exists( 'relevanssi_process_internal_links' ) ) {
1442
+ $contents = relevanssi_process_internal_links( $contents, $post->ID );
1443
+ }
1444
+
1445
+ $contents = preg_replace( '/<[a-zA-Z\/][^>]*>/', ' ', $contents );
1446
+ $contents = wp_strip_all_tags( $contents );
1447
+ $contents = wp_encode_emoji( $contents );
1448
+
1449
+ /**
1450
+ * Filters the post content in indexing before tokenization.
1451
+ *
1452
+ * @param string $contents The post content.
1453
+ * @param object $post The full post object.
1454
+ */
1455
+ $contents = apply_filters( 'relevanssi_post_content_before_tokenize', $contents, $post );
1456
+ /** This filter is documented in lib/indexing.php */
1457
+ $content_tokens = apply_filters(
1458
+ 'relevanssi_indexing_tokens',
1459
+ relevanssi_tokenize( $contents, 'body', $min_word_length ),
1460
+ 'content'
1461
+ );
1462
+ if ( $debug ) {
1463
+ relevanssi_debug_echo( "\tContent, tokenized:\n" . implode( ' ', array_keys( $content_tokens ) ) );
1464
+ }
1465
+
1466
+ foreach ( $content_tokens as $token => $count ) {
1467
+ $n++;
1468
+ if ( ! isset( $insert_data[ $token ]['content'] ) ) {
1469
+ $insert_data[ $token ]['content'] = 0;
1470
+ }
1471
+ $insert_data[ $token ]['content'] += $count;
1472
+ }
1473
+
1474
+ return $n;
1475
+ }
1476
+
1477
+ /**
1478
+ * Disables problematic shortcode before Relevanssi indexing to avoid problems.
1479
+ *
1480
+ * Uses the `relevanssi_disabled_shortcodes` filter hook to filter the
1481
+ * shortcodes. The disabled shortcodes are first removed with
1482
+ * remove_shortcode() and then given a reference to `__return_empty_string`.
1483
+ *
1484
+ * The option `relevanssi_disable_shortcodes` is also supported for legacy
1485
+ * reasons, but it's better to use the filter instead.
1486
+ */
1487
+ function relevanssi_disable_shortcodes() {
1488
+ $default_disables = array(
1489
+ 'contact-form', // Jetpack Contact Form causes an error message.
1490
+ 'starrater', // GD Star Rating rater shortcode causes problems.
1491
+ 'responsive-flipbook', // Responsive Flipbook causes problems.
1492
+ 'avatar_upload', // WP User Avatar is incompatible.
1493
+ 'product_categories', // A problematic WooCommerce shortcode.
1494
+ 'recent_products', // A problematic WooCommerce shortcode.
1495
+ 'php', // PHP Code for Posts.
1496
+ 'watupro', // Watu PRO doesn't co-operate.
1497
+ 'starbox', // Starbox shortcode breaks Relevanssi.
1498
+ 'cfdb-save-form-post', // Contact Form DB.
1499
+ 'cfdb-datatable',
1500
+ 'cfdb-table',
1501
+ 'cfdb-json',
1502
+ 'cfdb-value',
1503
+ 'cfdb-count',
1504
+ 'cfdb-html',
1505
+ 'woocommerce_cart', // WooCommerce.
1506
+ 'woocommerce_checkout',
1507
+ 'woocommerce_order_tracking',
1508
+ 'woocommerce_my_account',
1509
+ 'woocommerce_edit_account',
1510
+ 'woocommerce_change_password',
1511
+ 'woocommerce_view_order',
1512
+ 'woocommerce_logout',
1513
+ 'woocommerce_pay',
1514
+ 'woocommerce_thankyou',
1515
+ 'woocommerce_lost_password',
1516
+ 'woocommerce_edit_address',
1517
+ 'tc_process_payment',
1518
+ 'maxmegamenu', // Max Mega Menu.
1519
+ 'searchandfilter', // Search and Filter.
1520
+ 'downloads', // Easy Digital Downloads.
1521
+ 'download_history',
1522
+ 'purchase_history',
1523
+ 'download_checkout',
1524
+ 'purchase_link',
1525
+ 'download_cart',
1526
+ 'edd_profile_editor',
1527
+ 'edd_login',
1528
+ 'edd_register',
1529
+ 'swpm_protected', // Simple Membership Partially Protected content.
1530
+ 'gravityform', // Gravity Forms.
1531
+ 'sdm_latest_downloads', // SDM Simple Download Monitor.
1532
+ 'slimstat', // Slimstat Analytics.
1533
+ );
1534
+
1535
+ $disable_shortcodes = get_option( 'relevanssi_disable_shortcodes' );
1536
+ $shortcodes = explode( ',', $disable_shortcodes );
1537
+ /**
1538
+ * Filters the shortcodes Relevanssi disables while indexing posts.
1539
+ *
1540
+ * @param array An array of shortcodes disabled.
1541
+ *
1542
+ * @return array An array of shortcodes disabled.
1543
+ */
1544
+ $shortcodes = apply_filters(
1545
+ 'relevanssi_disabled_shortcodes',
1546
+ array_unique( array_merge( $shortcodes, $default_disables ) )
1547
+ );
1548
+
1549
+ foreach ( $shortcodes as $shortcode ) {
1550
+ if ( empty( $shortcode ) ) {
1551
+ continue;
1552
+ }
1553
+ remove_shortcode( trim( $shortcode ) );
1554
+ add_shortcode( trim( $shortcode ), '__return_empty_string' );
1555
+ }
1556
+
1557
+ }
1558
+
1559
+ /**
1560
+ * Converts INSERT query data array to query values.
1561
+ *
1562
+ * Takes the collected data and converts it to values that can be fed into
1563
+ * an INSERT query using $wpdb->prepare(). Provides filters to modify the
1564
+ * insert query values before and after the conversion.
1565
+ *
1566
+ * @global $wpdb The WordPress database interface.
1567
+ *
1568
+ * @param array $insert_data An array of term => data pairs, where data has
1569
+ * token counts for the term in different contexts.
1570
+ * @param object $post The indexed post object.
1571
+ *
1572
+ * @return array An array of values clauses for an INSERT query.
1573
+ */
1574
+ function relevanssi_convert_data_to_values( $insert_data, $post ) {
1575
+ global $wpdb;
1576
+
1577
+ /**
1578
+ * Sets the indexed post 'type' column in the index.
1579
+ *
1580
+ * Default value is 'post', but other common values include 'attachment',
1581
+ * 'user' and taxonomy name.
1582
+ *
1583
+ * @param string Type value.
1584
+ * @param object The post object for the current post.
1585
+ */
1586
+ $type = apply_filters( 'relevanssi_index_get_post_type', 'post', $post );
1587
+
1588
+ /**
1589
+ * Filters the indexing data before it is converted to INSERT queries.
1590
+ *
1591
+ * @param array $insert_data All the tokens and their counts.
1592
+ * @param object $post The post object.
1593
+ */
1594
+ $insert_data = apply_filters( 'relevanssi_indexing_data', $insert_data, $post );
1595
+
1596
+ $values = array();
1597
+ foreach ( $insert_data as $term => $data ) {
1598
+ $content = isset( $data['content'] ) ? $data['content'] : 0;
1599
+ $title = isset( $data['title'] ) ? $data['title'] : 0;
1600
+ $comment = isset( $data['comment'] ) ? $data['comment'] : 0;
1601
+ $tag = isset( $data['tag'] ) ? $data['tag'] : 0;
1602
+ $link = isset( $data['link'] ) ? $data['link'] : 0;
1603
+ $author = isset( $data['author'] ) ? $data['author'] : 0;
1604
+ $category = isset( $data['category'] ) ? $data['category'] : 0;
1605
+ $excerpt = isset( $data['excerpt'] ) ? $data['excerpt'] : 0;
1606
+ $taxonomy = isset( $data['taxonomy'] ) ? $data['taxonomy'] : 0;
1607
+ $customfield = isset( $data['customfield'] ) ? $data['customfield'] : 0;
1608
+ $mysqlcolumn = isset( $data['mysqlcolumn'] ) ? $data['mysqlcolumn'] : 0;
1609
+ $taxonomy_detail = isset( $data['taxonomy_detail'] ) ? $data['taxonomy_detail'] : '';
1610
+ $customfield_detail = isset( $data['customfield_detail'] ) ? $data['customfield_detail'] : '';
1611
+
1612
+ $term = trim( $term );
1613
+
1614
+ $value = $wpdb->prepare(
1615
+ '(%d, %s, REVERSE(%s), %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %s, %s, %s, %d)',
1616
+ $post->ID,
1617
+ $term,
1618
+ $term,
1619
+ $content,
1620
+ $title,
1621
+ $comment,
1622
+ $tag,
1623
+ $link,
1624
+ $author,
1625
+ $category,
1626
+ $excerpt,
1627
+ $taxonomy,
1628
+ $customfield,
1629
+ $type,
1630
+ $taxonomy_detail,
1631
+ $customfield_detail,
1632
+ $mysqlcolumn
1633
+ );
1634
+
1635
+ array_push( $values, $value );
1636
+ }
1637
+
1638
+ /**
1639
+ * Filters the INSERT query VALUES sections before they are inserted in the INSERT query.
1640
+ *
1641
+ * @param array $values Value sets.
1642
+ * @param object $post The post object.
1643
+ */
1644
+ return apply_filters( 'relevanssi_indexing_values', $values, $post );
1645
+ }
lib/init.php CHANGED
@@ -79,18 +79,16 @@ function relevanssi_init() {
79
  }
80
 
81
  if ( 'done' !== get_option( 'relevanssi_indexed' ) ) {
82
- /**
83
- * Prints out the "You do not have an index!" warning.
84
- */
85
- function relevanssi_warning() {
86
- $plugin = 'relevanssi';
87
- if ( RELEVANSSI_PREMIUM ) {
88
- $plugin = 'relevanssi-premium';
89
- }
90
- printf( "<div id='relevanssi-warning' class='update-nag'><p><strong>%s</strong></p></div>", esc_html__( 'You do not have an index! Remember to build the index (click the "Build the index" button), otherwise searching won\'t work.', 'relevanssi' ) );
91
- }
92
  if ( 'options-general.php' === $pagenow && $on_relevanssi_page ) {
93
- add_action( 'admin_notices', 'relevanssi_warning' );
 
 
 
 
 
 
 
 
94
  }
95
  }
96
 
@@ -193,6 +191,9 @@ function relevanssi_init() {
193
  if ( function_exists( 'pmpro_has_membership_access' ) ) {
194
  require_once 'compatibility/paidmembershippro.php';
195
  }
 
 
 
196
  }
197
 
198
  /**
79
  }
80
 
81
  if ( 'done' !== get_option( 'relevanssi_indexed' ) ) {
 
 
 
 
 
 
 
 
 
 
82
  if ( 'options-general.php' === $pagenow && $on_relevanssi_page ) {
83
+ add_action(
84
+ 'admin_notices',
85
+ function() {
86
+ printf(
87
+ "<div id='relevanssi-warning' class='update-nag'><p><strong>%s</strong></p></div>",
88
+ esc_html__( 'You do not have an index! Remember to build the index (click the "Build the index" button), otherwise searching won\'t work.', 'relevanssi' )
89
+ );
90
+ }
91
+ );
92
  }
93
  }
94
 
191
  if ( function_exists( 'pmpro_has_membership_access' ) ) {
192
  require_once 'compatibility/paidmembershippro.php';
193
  }
194
+
195
+ // Always required, the functions check if TablePress is active.
196
+ require_once 'compatibility/tablepress.php';
197
  }
198
 
199
  /**
lib/install.php CHANGED
@@ -100,7 +100,6 @@ function _relevanssi_install() {
100
  add_option( 'relevanssi_index_comments', 'none' );
101
  add_option( 'relevanssi_index_excerpt', 'off' );
102
  add_option( 'relevanssi_index_fields', '' );
103
- add_option( 'relevanssi_index_limit', '500' );
104
  add_option( 'relevanssi_index_post_types', array( 'post', 'page' ) );
105
  add_option( 'relevanssi_index_taxonomies_list', array() );
106
  add_option( 'relevanssi_indexed', '' );
100
  add_option( 'relevanssi_index_comments', 'none' );
101
  add_option( 'relevanssi_index_excerpt', 'off' );
102
  add_option( 'relevanssi_index_fields', '' );
 
103
  add_option( 'relevanssi_index_post_types', array( 'post', 'page' ) );
104
  add_option( 'relevanssi_index_taxonomies_list', array() );
105
  add_option( 'relevanssi_indexed', '' );
lib/interface.php CHANGED
@@ -425,9 +425,6 @@ function update_relevanssi_options() {
425
  if ( isset( $_REQUEST['relevanssi_omit_from_logs'] ) ) {
426
  update_option( 'relevanssi_omit_from_logs', $_REQUEST['relevanssi_omit_from_logs'] );
427
  }
428
- if ( isset( $_REQUEST['relevanssi_index_limit'] ) ) {
429
- update_option( 'relevanssi_index_limit', $_REQUEST['relevanssi_index_limit'] );
430
- }
431
  if ( isset( $_REQUEST['relevanssi_disable_or_fallback'] ) ) {
432
  update_option( 'relevanssi_disable_or_fallback', $_REQUEST['relevanssi_disable_or_fallback'] );
433
  }
@@ -1003,8 +1000,40 @@ function relevanssi_add_admin_scripts( $hook ) {
1003
  wp_localize_script( 'relevanssi_admin_js', 'nonce', $nonce );
1004
  }
1005
 
 
 
 
 
 
 
 
 
 
 
 
1006
  $indexing_limit = apply_filters( 'relevanssi_indexing_limit', 10 );
1007
- wp_localize_script( 'relevanssi_admin_js', 'relevanssi_params', array( 'indexing_limit' => $indexing_limit ) );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1008
  }
1009
 
1010
  /**
425
  if ( isset( $_REQUEST['relevanssi_omit_from_logs'] ) ) {
426
  update_option( 'relevanssi_omit_from_logs', $_REQUEST['relevanssi_omit_from_logs'] );
427
  }
 
 
 
428
  if ( isset( $_REQUEST['relevanssi_disable_or_fallback'] ) ) {
429
  update_option( 'relevanssi_disable_or_fallback', $_REQUEST['relevanssi_disable_or_fallback'] );
430
  }
1000
  wp_localize_script( 'relevanssi_admin_js', 'nonce', $nonce );
1001
  }
1002
 
1003
+ /**
1004
+ * Sets the indexing limit, ie. how many posts are indexed at once.
1005
+ *
1006
+ * Relevanssi starts by indexing this many posts at once. If the process
1007
+ * goes fast enough, Relevanssi will then increase the limit and if the
1008
+ * process is slow, the limit will be decreased. If necessary, you can
1009
+ * use the relevanssi_indexing_adjust filter hook to disable that
1010
+ * adjustment.
1011
+ *
1012
+ * @param int The indexing limit, default 10.
1013
+ */
1014
  $indexing_limit = apply_filters( 'relevanssi_indexing_limit', 10 );
1015
+
1016
+ /**
1017
+ * Sets the indexing adjustment.
1018
+ *
1019
+ * Relevanssi will adjust the number of posts indexed at once to speed
1020
+ * up the process if it goes fast and to slow down, if the posts are
1021
+ * slow to index. You can use this filter to stop that behaviour, making
1022
+ * Relevanssi index posts at constant pace. That's generally slower, but
1023
+ * more reliable.
1024
+ *
1025
+ * @param boolean Should the limit be adjusted, default true.
1026
+ */
1027
+ $indexing_adjust = apply_filters( 'relevanssi_indexing_adjust', true );
1028
+
1029
+ wp_localize_script(
1030
+ 'relevanssi_admin_js',
1031
+ 'relevanssi_params',
1032
+ array(
1033
+ 'indexing_limit' => $indexing_limit,
1034
+ 'indexing_adjust' => $indexing_adjust,
1035
+ )
1036
+ );
1037
  }
1038
 
1039
  /**
lib/search.php CHANGED
@@ -332,7 +332,7 @@ function relevanssi_search( $args ) {
332
  $added_post_ids = array_diff( array_keys( $include_these_posts ), $existing_ids );
333
  if ( count( $added_post_ids ) > 0 ) {
334
  $offset = 0;
335
- $slice_length = 1;
336
  $total_ids = count( $added_post_ids );
337
  do {
338
  $current_slice = array_slice( $added_post_ids, $offset, $slice_length );
332
  $added_post_ids = array_diff( array_keys( $include_these_posts ), $existing_ids );
333
  if ( count( $added_post_ids ) > 0 ) {
334
  $offset = 0;
335
+ $slice_length = 20;
336
  $total_ids = count( $added_post_ids );
337
  do {
338
  $current_slice = array_slice( $added_post_ids, $offset, $slice_length );
lib/uninstall.php CHANGED
@@ -29,17 +29,19 @@ function relevanssi_drop_database_tables() {
29
  $stopword_table = $wpdb->prefix . 'relevanssi_stopwords';
30
  $log_table = $wpdb->prefix . 'relevanssi_log';
31
 
32
- if ( $wpdb->get_var( "SHOW TABLES LIKE '$stopword_table'" ) === $stopword_table ) { // WPCS: unprepared SQL ok.
33
- $wpdb->query( "DROP TABLE $stopword_table" ); // WPCS: unprepared SQL ok.
 
34
  }
35
 
36
- if ( $wpdb->get_var( "SHOW TABLES LIKE '$relevanssi_table'" ) === $relevanssi_table ) { // WPCS: unprepared SQL ok.
37
- $wpdb->query( "DROP TABLE $relevanssi_table" ); // WPCS: unprepared SQL ok.
38
  }
39
 
40
- if ( $wpdb->get_var( "SHOW TABLES LIKE '$log_table'" ) === $log_table ) { // WPCS: unprepared SQL ok.
41
- $wpdb->query( "DROP TABLE $log_table" ); // WPCS: unprepared SQL ok.
42
  }
 
43
  }
44
 
45
  /**
@@ -53,10 +55,10 @@ function relevanssi_uninstall_free() {
53
  delete_option( 'relevanssi_admin_search' );
54
  delete_option( 'relevanssi_bg_col' );
55
  delete_option( 'relevanssi_cat' );
56
- delete_option( 'relevanssi_comment_boost' );
57
- delete_option( 'relevanssi_css' );
58
  delete_option( 'relevanssi_class' );
 
59
  delete_option( 'relevanssi_content_boost' );
 
60
  delete_option( 'relevanssi_db_version' );
61
  delete_option( 'relevanssi_default_orderby' );
62
  delete_option( 'relevanssi_disable_or_fallback' );
@@ -64,28 +66,26 @@ function relevanssi_uninstall_free() {
64
  delete_option( 'relevanssi_doc_count' );
65
  delete_option( 'relevanssi_exact_match_bonus' );
66
  delete_option( 'relevanssi_excat' );
67
- delete_option( 'relevanssi_extag' );
68
- delete_option( 'relevanssi_excerpt_length' );
69
- delete_option( 'relevanssi_excerpt_type' );
70
  delete_option( 'relevanssi_excerpt_allowable_tags' );
71
  delete_option( 'relevanssi_excerpt_custom_fields' );
 
 
72
  delete_option( 'relevanssi_excerpts' );
73
  delete_option( 'relevanssi_exclude_posts' );
74
  delete_option( 'relevanssi_expand_shortcodes' );
 
75
  delete_option( 'relevanssi_fuzzy' );
76
  delete_option( 'relevanssi_hide_branding' );
 
77
  delete_option( 'relevanssi_highlight_comments' );
78
  delete_option( 'relevanssi_highlight_docs' );
79
- delete_option( 'relevanssi_highlight' );
80
  delete_option( 'relevanssi_hilite_title' );
81
  delete_option( 'relevanssi_implicit_operator' );
82
  delete_option( 'relevanssi_index' );
83
  delete_option( 'relevanssi_index_author' );
84
  delete_option( 'relevanssi_index_comments' );
85
- delete_option( 'relevanssi_index_drafts' );
86
  delete_option( 'relevanssi_index_excerpt' );
87
  delete_option( 'relevanssi_index_fields' );
88
- delete_option( 'relevanssi_index_limit' );
89
  delete_option( 'relevanssi_index_post_types' );
90
  delete_option( 'relevanssi_index_taxonomies' );
91
  delete_option( 'relevanssi_index_taxonomies_list' );
@@ -100,14 +100,15 @@ function relevanssi_uninstall_free() {
100
  delete_option( 'relevanssi_post_type_weights' );
101
  delete_option( 'relevanssi_punctuation' );
102
  delete_option( 'relevanssi_respect_exclude' );
103
- delete_option( 'relevanssi_show_matches_text' );
104
  delete_option( 'relevanssi_show_matches' );
 
105
  delete_option( 'relevanssi_show_post_controls' );
106
  delete_option( 'relevanssi_synonyms' );
107
  delete_option( 'relevanssi_thousand_separator' );
108
  delete_option( 'relevanssi_throttle' );
109
  delete_option( 'relevanssi_throttle_limit' );
110
  delete_option( 'relevanssi_title_boost' );
 
111
  delete_option( 'relevanssi_txt_col' );
112
  delete_option( 'relevanssi_word_boundaries' );
113
  delete_option( 'relevanssi_wpml_only_current' );
@@ -118,6 +119,8 @@ function relevanssi_uninstall_free() {
118
  delete_option( 'relevanssi_enable_cache' );
119
  delete_option( 'relevanssi_hidesponsor' );
120
  delete_option( 'relevanssi_index_attachments' );
 
 
121
  delete_option( 'relevanssi_index_type' );
122
  delete_option( 'relevanssi_show_matches_txt' );
123
  delete_option( 'relevanssi_tag_boost' );
29
  $stopword_table = $wpdb->prefix . 'relevanssi_stopwords';
30
  $log_table = $wpdb->prefix . 'relevanssi_log';
31
 
32
+ // phpcs:disable WordPress.DB.PreparedSQL
33
+ if ( $wpdb->get_var( "SHOW TABLES LIKE '$stopword_table'" ) === $stopword_table ) {
34
+ $wpdb->query( "DROP TABLE $stopword_table" );
35
  }
36
 
37
+ if ( $wpdb->get_var( "SHOW TABLES LIKE '$relevanssi_table'" ) === $relevanssi_table ) {
38
+ $wpdb->query( "DROP TABLE $relevanssi_table" );
39
  }
40
 
41
+ if ( $wpdb->get_var( "SHOW TABLES LIKE '$log_table'" ) === $log_table ) {
42
+ $wpdb->query( "DROP TABLE $log_table" );
43
  }
44
+ // phpcs:enable WordPress.DB.PreparedSQL
45
  }
46
 
47
  /**
55
  delete_option( 'relevanssi_admin_search' );
56
  delete_option( 'relevanssi_bg_col' );
57
  delete_option( 'relevanssi_cat' );
 
 
58
  delete_option( 'relevanssi_class' );
59
+ delete_option( 'relevanssi_comment_boost' );
60
  delete_option( 'relevanssi_content_boost' );
61
+ delete_option( 'relevanssi_css' );
62
  delete_option( 'relevanssi_db_version' );
63
  delete_option( 'relevanssi_default_orderby' );
64
  delete_option( 'relevanssi_disable_or_fallback' );
66
  delete_option( 'relevanssi_doc_count' );
67
  delete_option( 'relevanssi_exact_match_bonus' );
68
  delete_option( 'relevanssi_excat' );
 
 
 
69
  delete_option( 'relevanssi_excerpt_allowable_tags' );
70
  delete_option( 'relevanssi_excerpt_custom_fields' );
71
+ delete_option( 'relevanssi_excerpt_length' );
72
+ delete_option( 'relevanssi_excerpt_type' );
73
  delete_option( 'relevanssi_excerpts' );
74
  delete_option( 'relevanssi_exclude_posts' );
75
  delete_option( 'relevanssi_expand_shortcodes' );
76
+ delete_option( 'relevanssi_extag' );
77
  delete_option( 'relevanssi_fuzzy' );
78
  delete_option( 'relevanssi_hide_branding' );
79
+ delete_option( 'relevanssi_highlight' );
80
  delete_option( 'relevanssi_highlight_comments' );
81
  delete_option( 'relevanssi_highlight_docs' );
 
82
  delete_option( 'relevanssi_hilite_title' );
83
  delete_option( 'relevanssi_implicit_operator' );
84
  delete_option( 'relevanssi_index' );
85
  delete_option( 'relevanssi_index_author' );
86
  delete_option( 'relevanssi_index_comments' );
 
87
  delete_option( 'relevanssi_index_excerpt' );
88
  delete_option( 'relevanssi_index_fields' );
 
89
  delete_option( 'relevanssi_index_post_types' );
90
  delete_option( 'relevanssi_index_taxonomies' );
91
  delete_option( 'relevanssi_index_taxonomies_list' );
100
  delete_option( 'relevanssi_post_type_weights' );
101
  delete_option( 'relevanssi_punctuation' );
102
  delete_option( 'relevanssi_respect_exclude' );
 
103
  delete_option( 'relevanssi_show_matches' );
104
+ delete_option( 'relevanssi_show_matches_text' );
105
  delete_option( 'relevanssi_show_post_controls' );
106
  delete_option( 'relevanssi_synonyms' );
107
  delete_option( 'relevanssi_thousand_separator' );
108
  delete_option( 'relevanssi_throttle' );
109
  delete_option( 'relevanssi_throttle_limit' );
110
  delete_option( 'relevanssi_title_boost' );
111
+ delete_option( 'relevanssi_trim_logs' );
112
  delete_option( 'relevanssi_txt_col' );
113
  delete_option( 'relevanssi_word_boundaries' );
114
  delete_option( 'relevanssi_wpml_only_current' );
119
  delete_option( 'relevanssi_enable_cache' );
120
  delete_option( 'relevanssi_hidesponsor' );
121
  delete_option( 'relevanssi_index_attachments' );
122
+ delete_option( 'relevanssi_index_drafts' );
123
+ delete_option( 'relevanssi_index_limit' );
124
  delete_option( 'relevanssi_index_type' );
125
  delete_option( 'relevanssi_show_matches_txt' );
126
  delete_option( 'relevanssi_tag_boost' );
readme.txt CHANGED
@@ -3,9 +3,9 @@ Contributors: msaari
3
  Donate link: https://www.relevanssi.com/buy-premium/
4
  Tags: search, relevance, better search
5
  Requires at least: 4.8.3
6
- Tested up to: 5.2.2
7
  Requires PHP: 5.6
8
- Stable tag: 4.3.2
9
  License: GPLv2 or later
10
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
11
 
@@ -129,6 +129,17 @@ Each document database is full of useless words. All the little words that appea
129
  * John Calahan for extensive 4.0 beta testing.
130
 
131
  == Changelog ==
 
 
 
 
 
 
 
 
 
 
 
132
  = 4.3.2 =
133
  * New feature: SEOPress support, posts marked "noindex" in SEOPress are no longer indexed by Relevanssi by default.
134
  * Changed behaviour: Membership plugin compatibility is removed from `relevanssi_default_post_ok` function and has been moved to individual compatibility functions for each supported membership plugin. This makes it much easier to for example disable the membership plugin features if required.
@@ -160,6 +171,9 @@ Each document database is full of useless words. All the little words that appea
160
  * Deprecated: `relevanssi_get_term_taxonomy()` function is deprecated and will be removed at some point in the future.
161
 
162
  == Upgrade notice ==
 
 
 
163
  = 4.3.2 =
164
  * Yoast SEO compatibility fix, minor updates.
165
 
3
  Donate link: https://www.relevanssi.com/buy-premium/
4
  Tags: search, relevance, better search
5
  Requires at least: 4.8.3
6
+ Tested up to: 5.2.3
7
  Requires PHP: 5.6
8
+ Stable tag: 4.3.3
9
  License: GPLv2 or later
10
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
11
 
129
  * John Calahan for extensive 4.0 beta testing.
130
 
131
  == Changelog ==
132
+ = 4.3.3 =
133
+ * New feature: New filter hook `relevanssi_indexing_adjust` can be used to stop Relevanssi from adjusting the number of posts indexed at once during the indexing.
134
+ * New feature: New filter hook `relevanssi_acf_field_value` filters ACF field values before they are indexed.
135
+ * New feature: New filter hook `relevanssi_disabled_shortcodes` filters the array containing shortcodes that are disabled when indexing.
136
+ * Removed feature: The `relevanssi_indexing_limit` option wasn't really used anymore, so it has been removed.
137
+ * Changed behaviour: Indexing exclusions from Yoast SEO and SEOPress are applied in a different way in the indexing, making for a smoother indexing process.
138
+ * Changed behaviour: WP Table Reloaded support has been removed; you really shouldn't be using WP Table Reloaded anymore.
139
+ * Minor fix: Relevanssi won't choke on ACF fields with array or object values anymore.
140
+ * Minor fix: Relevanssi uninstall process left couple of Relevanssi options in the database.
141
+ * Minor fix: WPML language filter didn't work when `fields` was set to `ids` or `id=>parent`.
142
+
143
  = 4.3.2 =
144
  * New feature: SEOPress support, posts marked "noindex" in SEOPress are no longer indexed by Relevanssi by default.
145
  * Changed behaviour: Membership plugin compatibility is removed from `relevanssi_default_post_ok` function and has been moved to individual compatibility functions for each supported membership plugin. This makes it much easier to for example disable the membership plugin features if required.
171
  * Deprecated: `relevanssi_get_term_taxonomy()` function is deprecated and will be removed at some point in the future.
172
 
173
  == Upgrade notice ==
174
+ = 4.3.3 =
175
+ * Bug fixes and overall improvements.
176
+
177
  = 4.3.2 =
178
  * Yoast SEO compatibility fix, minor updates.
179
 
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.3.2
17
  * Author: Mikko Saari
18
  * Author URI: http://www.mikkosaari.fi/
19
  * Text Domain: relevanssi
@@ -58,7 +58,7 @@ $relevanssi_variables['database_version'] = 5;
58
  $relevanssi_variables['file'] = __FILE__;
59
  $relevanssi_variables['plugin_dir'] = plugin_dir_path( __FILE__ );
60
  $relevanssi_variables['plugin_basename'] = plugin_basename( __FILE__ );
61
- $relevanssi_variables['plugin_version'] = '4.3.2';
62
 
63
  require_once 'lib/admin-ajax.php';
64
  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.3.3
17
  * Author: Mikko Saari
18
  * Author URI: http://www.mikkosaari.fi/
19
  * Text Domain: relevanssi
58
  $relevanssi_variables['file'] = __FILE__;
59
  $relevanssi_variables['plugin_dir'] = plugin_dir_path( __FILE__ );
60
  $relevanssi_variables['plugin_basename'] = plugin_basename( __FILE__ );
61
+ $relevanssi_variables['plugin_version'] = '4.3.3';
62
 
63
  require_once 'lib/admin-ajax.php';
64
  require_once 'lib/common.php';
uninstall.php CHANGED
@@ -13,7 +13,9 @@ if ( ! defined( 'WP_UNINSTALL_PLUGIN' ) ) {
13
  }
14
 
15
  global $wpdb;
16
- define( 'RELEVANSSI_PREMIUM', false );
 
 
17
  require_once 'lib/uninstall.php';
18
 
19
  if ( function_exists( 'is_multisite' ) && is_multisite() ) {
13
  }
14
 
15
  global $wpdb;
16
+ if ( ! defined( 'RELEVANSSI_PREMIUM' ) ) {
17
+ define( 'RELEVANSSI_PREMIUM', false );
18
+ }
19
  require_once 'lib/uninstall.php';
20
 
21
  if ( function_exists( 'is_multisite' ) && is_multisite() ) {