Relevanssi – A Better Search - Version 4.10.2

Version Description

  • New feature: You can force Relevanssi to be active by setting the query variable relevanssi to true. Thanks to Jan Willem Oostendorp.
  • Changed behaviour: Relevanssi has been moved from the_posts filter to posts_pre_query. This change doesn't do much, but increases performance slightly as WordPress needs to do less useless work, as now the default query is no longer run. Thanks to Jan Willem Oostendorp.
  • Minor fix: Highlighting didn't work properly when highlighting something immediately following a HTML tag.
  • Minor fix: You can no longer set the value of minimum word length to less than 1 or higher than 9 from the settings page.
  • Minor fix: Importing options broke synonym and stopword settings.
  • Minor fix: Improves the Rank Math SEO compatibility to avoid errors in plugin activation.
  • Minor fix: WPML search results that included non-post results caused fatal errors and crashes. This fixes the crashing and makes non-post results work better in both WPML and Polylang.
Download this release

Release Info

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

Code changes from version 4.10.1 to 4.10.2

lib/admin_scripts.js CHANGED
@@ -148,6 +148,16 @@ jQuery(document).ready(function ($) {
148
  $("#relevanssi_searchblogs_all").click(function () {
149
  $("#relevanssi_searchblogs").attr("disabled", this.checked)
150
  })
 
 
 
 
 
 
 
 
 
 
151
  })
152
 
153
  var time = 0
148
  $("#relevanssi_searchblogs_all").click(function () {
149
  $("#relevanssi_searchblogs").attr("disabled", this.checked)
150
  })
151
+
152
+ var min_word_length = $("#relevanssi_min_word_length")
153
+ min_word_length.change(function(e) {
154
+ if ( min_word_length.val() < 1 ) {
155
+ min_word_length.val(1)
156
+ }
157
+ if ( min_word_length.val() > 9 ) {
158
+ min_word_length.val(9)
159
+ }
160
+ })
161
  })
162
 
163
  var time = 0
lib/common.php CHANGED
@@ -1558,6 +1558,11 @@ function relevanssi_generate_list_of_custom_fields( $post_id, $custom_fields = n
1558
  */
1559
  function relevanssi_update_synonyms_setting() {
1560
  $synonyms = get_option( 'relevanssi_synonyms' );
 
 
 
 
 
1561
 
1562
  $current_language = relevanssi_get_current_language();
1563
 
1558
  */
1559
  function relevanssi_update_synonyms_setting() {
1560
  $synonyms = get_option( 'relevanssi_synonyms' );
1561
+ if ( is_object( $synonyms ) ) {
1562
+ $array_synonyms = (array) $synonyms;
1563
+ update_option( 'relevanssi_synonyms', $array_synonyms );
1564
+ return;
1565
+ }
1566
 
1567
  $current_language = relevanssi_get_current_language();
1568
 
lib/compatibility/rankmath.php CHANGED
@@ -25,7 +25,7 @@ add_filter( 'relevanssi_indexing_restriction', 'relevanssi_rankmath_exclude' );
25
  */
26
  function relevanssi_rankmath_noindex( $do_not_index, $post_id ) {
27
  $noindex = get_post_meta( $post_id, 'rank_math_robots', true );
28
- if ( in_array( 'noindex', $noindex, true ) ) {
29
  $do_not_index = 'RankMath';
30
  }
31
  return $do_not_index;
25
  */
26
  function relevanssi_rankmath_noindex( $do_not_index, $post_id ) {
27
  $noindex = get_post_meta( $post_id, 'rank_math_robots', true );
28
+ if ( is_array( $noindex ) && in_array( 'noindex', $noindex, true ) ) {
29
  $do_not_index = 'RankMath';
30
  }
31
  return $do_not_index;
lib/compatibility/wpml.php CHANGED
@@ -29,21 +29,15 @@ function relevanssi_wpml_filter( $data ) {
29
  $filter_enabled = get_option( 'relevanssi_wpml_only_current' );
30
  if ( 'on' === $filter_enabled ) {
31
  $wpml_post_type_setting = apply_filters( 'wpml_setting', false, 'custom_posts_sync_option' );
 
32
 
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 ) ) {
49
  // This is a multisite search.
@@ -61,7 +55,6 @@ function relevanssi_wpml_filter( $data ) {
61
  // Check if WPML is used.
62
  if ( function_exists( 'icl_object_id' ) && ! function_exists( 'pll_is_translated_post_type' ) ) {
63
  if ( $sitepress->is_translated_post_type( $hit->post_type ) ) {
64
-
65
  $fallback_to_default = false;
66
  if ( isset( $wpml_post_type_setting[ $hit->post_type ] ) && '2' === $wpml_post_type_setting[ $hit->post_type ] ) {
67
  $fallback_to_default = true;
@@ -72,6 +65,20 @@ function relevanssi_wpml_filter( $data ) {
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;
29
  $filter_enabled = get_option( 'relevanssi_wpml_only_current' );
30
  if ( 'on' === $filter_enabled ) {
31
  $wpml_post_type_setting = apply_filters( 'wpml_setting', false, 'custom_posts_sync_option' );
32
+ $wpml_taxonomy_setting = apply_filters( 'wpml_setting', false, 'taxonomies_sync_option' );
33
 
34
  $current_blog_language = get_bloginfo( 'language' );
35
  $filtered_hits = array();
36
  foreach ( $data[0] as $hit ) {
37
  $original_hit = $hit;
38
+
39
+ $object_array = relevanssi_get_an_object( $hit );
40
+ $hit = $object_array['object'];
 
 
 
 
 
 
 
41
 
42
  if ( isset( $hit->blog_id ) ) {
43
  // This is a multisite search.
55
  // Check if WPML is used.
56
  if ( function_exists( 'icl_object_id' ) && ! function_exists( 'pll_is_translated_post_type' ) ) {
57
  if ( $sitepress->is_translated_post_type( $hit->post_type ) ) {
 
58
  $fallback_to_default = false;
59
  if ( isset( $wpml_post_type_setting[ $hit->post_type ] ) && '2' === $wpml_post_type_setting[ $hit->post_type ] ) {
60
  $fallback_to_default = true;
65
  // The post exists in the current language, and can be included.
66
  $filtered_hits[] = $original_hit;
67
  }
68
+ } elseif ( isset( $hit->term_id ) ) {
69
+ $fallback_to_default = false;
70
+ if ( isset( $wpml_taxonomy_setting[ $hit->post_type ] ) && '2' === $wpml_taxonomy_setting[ $hit->post_type ] ) {
71
+ $fallback_to_default = true;
72
+ }
73
+ if ( ! isset( $hit->post_type ) ) {
74
+ // This is a term object, not a Relevanssi-generated post object.
75
+ $hit->post_type = $hit->taxonomy;
76
+ }
77
+ $id = apply_filters( 'wpml_object_id', $hit->term_id, $hit->post_type, $fallback_to_default );
78
+ if ( intval( $hit->term_id ) === intval( $id ) ) {
79
+ // The post exists in the current language, and can be included.
80
+ $filtered_hits[] = $original_hit;
81
+ }
82
  } else {
83
  // This is not a translated post type, so include all posts.
84
  $filtered_hits[] = $original_hit;
lib/excerpts-highlights.php CHANGED
@@ -640,10 +640,10 @@ function relevanssi_highlight_terms( $content, $query, $convert_entities = false
640
  );
641
 
642
  /**
643
- * The method here leaves extra spaces inside the highlighting. That
644
- * is cleaned away here.
645
  */
646
- $replace_regex = '/(.)(' . preg_quote( $start_emp_token, '/' ) . ')(\s)/iu';
647
  $content = preg_replace( $replace_regex, '\1\3\2', $content );
648
 
649
  $replace_regex = '/^(' . preg_quote( $start_emp_token, '/' ) . ')\s/iu';
640
  );
641
 
642
  /**
643
+ * The method here leaves extra spaces or HTML tag closing brackets
644
+ * inside the highlighting. That is cleaned away here.
645
  */
646
+ $replace_regex = '/(.)(' . preg_quote( $start_emp_token, '/' ) . ')(>|\s)/iu';
647
  $content = preg_replace( $replace_regex, '\1\3\2', $content );
648
 
649
  $replace_regex = '/^(' . preg_quote( $start_emp_token, '/' ) . ')\s/iu';
lib/init.php CHANGED
@@ -17,7 +17,7 @@ add_action( 'admin_init', 'relevanssi_admin_init' );
17
  add_action( 'admin_menu', 'relevanssi_menu' );
18
 
19
  // Taking over the search.
20
- add_filter( 'the_posts', 'relevanssi_query', 99, 2 );
21
  add_filter( 'posts_request', 'relevanssi_prevent_default_request', 10, 2 );
22
  add_filter( 'relevanssi_search_ok', 'relevanssi_block_on_admin_searches', 10, 2 );
23
  add_filter( 'relevanssi_admin_search_ok', 'relevanssi_block_on_admin_searches', 10, 2 );
17
  add_action( 'admin_menu', 'relevanssi_menu' );
18
 
19
  // Taking over the search.
20
+ add_filter( 'posts_pre_query', 'relevanssi_query', 99, 2 );
21
  add_filter( 'posts_request', 'relevanssi_prevent_default_request', 10, 2 );
22
  add_filter( 'relevanssi_search_ok', 'relevanssi_block_on_admin_searches', 10, 2 );
23
  add_filter( 'relevanssi_admin_search_ok', 'relevanssi_block_on_admin_searches', 10, 2 );
lib/search.php CHANGED
@@ -60,6 +60,10 @@ function relevanssi_query( $posts, $query = false ) {
60
  }
61
  }
62
 
 
 
 
 
63
  /**
64
  * Filters whether Relevanssi search can be run or not.
65
  *
60
  }
61
  }
62
 
63
+ if ( $query->get( 'relevanssi' ) ) {
64
+ $search_ok = true; // Manual override, always search.
65
+ }
66
+
67
  /**
68
  * Filters whether Relevanssi search can be run or not.
69
  *
lib/stopwords.php CHANGED
@@ -407,6 +407,11 @@ function relevanssi_remove_stopwords_from_array( $terms ) {
407
  */
408
  function relevanssi_update_stopwords_setting() {
409
  $stopwords = get_option( 'relevanssi_stopwords' );
 
 
 
 
 
410
 
411
  $current_language = relevanssi_get_current_language();
412
 
407
  */
408
  function relevanssi_update_stopwords_setting() {
409
  $stopwords = get_option( 'relevanssi_stopwords' );
410
+ if ( is_object( $stopwords ) ) {
411
+ $array_stopwords = (array) $stopwords;
412
+ update_option( 'relevanssi_stopwords', $array_stopwords );
413
+ return;
414
+ }
415
 
416
  $current_language = relevanssi_get_current_language();
417
 
lib/utils.php CHANGED
@@ -137,6 +137,36 @@ function relevanssi_generate_closing_tags( $tags ) {
137
  return $closing_tags;
138
  }
139
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
140
  /**
141
  * Returns the locale or language code.
142
  *
@@ -157,13 +187,17 @@ function relevanssi_generate_closing_tags( $tags ) {
157
  function relevanssi_get_current_language( $locale = true ) {
158
  $current_language = get_locale();
159
  if ( ! $locale ) {
160
- $current_language = substr( $locale, 0, 2 );
161
  }
162
  if ( function_exists( 'pll_current_language' ) ) {
163
  global $post;
164
 
165
  if ( isset( $post ) ) {
166
- $current_language = pll_get_post_language( $post->ID, $locale ? 'locale' : 'slug' );
 
 
 
 
167
  } else {
168
  $current_language = pll_current_language( $locale ? 'locale' : 'slug' );
169
  }
@@ -172,7 +206,24 @@ function relevanssi_get_current_language( $locale = true ) {
172
  global $post;
173
 
174
  if ( isset( $post ) ) {
175
- $language_details = apply_filters( 'wpml_post_language_details', null, $post->ID );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
176
  $current_language = $language_details[ $locale ? 'locale' : 'language_code' ];
177
  } else {
178
  if ( $locale ) {
@@ -240,6 +291,35 @@ function relevanssi_get_post( $post_id, $blog_id = -1 ) {
240
  return $post;
241
  }
242
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
243
  /**
244
  * Returns the term taxonomy ID for a term based on term ID.
245
  *
@@ -476,6 +556,35 @@ function relevanssi_remove_quotes_from_array_keys( $array ) {
476
  return array_flip( $array );
477
  }
478
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
479
  /**
480
  * Returns "off".
481
  *
@@ -487,6 +596,25 @@ function relevanssi_return_off() {
487
  return 'off';
488
  }
489
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
490
  /**
491
  * Sanitizes hex color strings.
492
  *
137
  return $closing_tags;
138
  }
139
 
140
+ /**
141
+ * Returns a post object based on ID, **type**id notation or an object.
142
+ *
143
+ * @param int|string|WP_Post The source identified to parse, either a post ID
144
+ * integer, a **type**id string or a post object.
145
+ *
146
+ * @return array An array containing the actual object in 'object' and the
147
+ * format of the original value in 'format'. The value can be 'object', 'id'
148
+ * or 'id=>parent'.
149
+ */
150
+ function relevanssi_get_an_object( $source ) {
151
+ $object = $source;
152
+ $format = 'object';
153
+
154
+ if ( ! is_object( $source ) ) {
155
+ // Convert from post ID to post.
156
+ $object = relevanssi_get_post_object( $source );
157
+ $format = 'id';
158
+ } elseif ( ! isset( $source->post_content ) ) {
159
+ // Convert from id=>parent to post.
160
+ $object = relevanssi_get_post_object( $source->ID );
161
+ $format = 'id=>parent';
162
+ }
163
+
164
+ return array(
165
+ 'object' => $object,
166
+ 'format' => $format,
167
+ );
168
+ }
169
+
170
  /**
171
  * Returns the locale or language code.
172
  *
187
  function relevanssi_get_current_language( $locale = true ) {
188
  $current_language = get_locale();
189
  if ( ! $locale ) {
190
+ $current_language = substr( $current_language, 0, 2 );
191
  }
192
  if ( function_exists( 'pll_current_language' ) ) {
193
  global $post;
194
 
195
  if ( isset( $post ) ) {
196
+ if ( isset( $post->term_id ) ) {
197
+ $current_language = pll_get_term_language( $post->term_id, $locale ? 'locale' : 'slug' );
198
+ } elseif ( ! isset( $post->user_id ) ) {
199
+ $current_language = pll_get_post_language( $post->ID, $locale ? 'locale' : 'slug' );
200
+ }
201
  } else {
202
  $current_language = pll_current_language( $locale ? 'locale' : 'slug' );
203
  }
206
  global $post;
207
 
208
  if ( isset( $post ) ) {
209
+ $language_details = array(
210
+ 'locale' => '',
211
+ 'language_code' => '',
212
+ );
213
+ if ( isset( $post->term_id ) ) {
214
+ // Terms don't have a locale, just a language code.
215
+ $element = array(
216
+ 'element_id' => relevanssi_get_term_tax_id( $post->term_id, $post->post_type ),
217
+ 'element_type' => $post->post_type,
218
+ );
219
+ $language_code = apply_filters( 'wpml_element_language_code', null, $element );
220
+
221
+ $language_details['language_code'] = $language_code;
222
+ } elseif ( ! isset( $post->user_id ) ) {
223
+ // Users don't have language details.
224
+ $language_details = apply_filters( 'wpml_post_language_details', null, $post->ID );
225
+ }
226
+
227
  $current_language = $language_details[ $locale ? 'locale' : 'language_code' ];
228
  } else {
229
  if ( $locale ) {
291
  return $post;
292
  }
293
 
294
+ /**
295
+ * Returns an object based on ID.
296
+ *
297
+ * @param int|string $post_id An ID, either an integer post ID or a
298
+ * **type**id string for terms and users.
299
+ *
300
+ * @return WP_Post|WP_Term|WP_User An object, type of which depends on the
301
+ * target object.
302
+ */
303
+ function relevanssi_get_post_object( $post_id ) {
304
+ $object = null;
305
+ if ( '*' === substr( $post_id, 0, 1 ) ) {
306
+ // Convert from **type**id to a user or a term object.
307
+ $parts = explode( '**', $post_id );
308
+ $type = $parts[1] ?? null;
309
+ $id = $parts[2] ?? null;
310
+ if ( $type && $id ) {
311
+ if ( 'user' === $type ) {
312
+ $object = get_user_by( 'id', $id );
313
+ } else {
314
+ $object = get_term( $id, $type );
315
+ }
316
+ }
317
+ } else {
318
+ $object = relevanssi_get_post( $post_id );
319
+ }
320
+ return $object;
321
+ }
322
+
323
  /**
324
  * Returns the term taxonomy ID for a term based on term ID.
325
  *
556
  return array_flip( $array );
557
  }
558
 
559
+ /**
560
+ * Returns an ID=>parent object from a post (or a term, or a user).
561
+ *
562
+ * @param WP_Post|WP_Term|WP_User $post_object The source object.
563
+ *
564
+ * @return object An object with the attributes ID and post_parent set. For
565
+ * terms and users, ID is the term or user ID and post_parent is 0. For bad
566
+ * inputs, returns 0 and 0.
567
+ */
568
+ function relevanssi_return_id_parent( $post_object ) {
569
+ $id_parent_object = new stdClass();
570
+
571
+ if ( isset( $post_object->ID ) ) {
572
+ $id_parent_object->ID = $post_object->ID;
573
+ $id_parent_object->post_parent = $post_object->post_parent;
574
+ } elseif ( isset( $post_object->term_id ) ) {
575
+ $id_parent_object->ID = $post_object->term_id;
576
+ $id_parent_object->post_parent = 0;
577
+ } elseif ( isset( $post_object->user_id ) ) {
578
+ $id_parent_object->ID = $post_object->user_id;
579
+ $id_parent_object->post_parent = 0;
580
+ } else {
581
+ $id_parent_object->ID = 0;
582
+ $id_parent_object->post_parent = 0;
583
+ }
584
+
585
+ return $id_parent_object;
586
+ }
587
+
588
  /**
589
  * Returns "off".
590
  *
596
  return 'off';
597
  }
598
 
599
+ /**
600
+ * Gets a post object, returns ID, ID=>parent or the post object.
601
+ *
602
+ * @param WP_Post $post The post object.
603
+ * @param string $return_value The value to return, possible values are 'id'
604
+ * for returning the ID and 'id=>parent' for returning the ID=>parent object,
605
+ * otherwise the post object is returned.
606
+ *
607
+ * @return int|object|WP_Post The post object in the desired format.
608
+ */
609
+ function relevanssi_return_value( $post, $return_value ) {
610
+ if ( 'id' === $return_value ) {
611
+ return $post->ID;
612
+ } elseif ( 'id=>parent' === $return_value ) {
613
+ return relevanssi_return_id_parent( $post );
614
+ }
615
+ return $post;
616
+ }
617
+
618
  /**
619
  * Sanitizes hex color strings.
620
  *
readme.txt CHANGED
@@ -5,7 +5,7 @@ Tags: search, relevance, better search, product search, woocommerce search
5
  Requires at least: 4.9
6
  Tested up to: 5.6.1
7
  Requires PHP: 7.0
8
- Stable tag: 4.10.1
9
  License: GPLv2 or later
10
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
11
 
@@ -133,6 +133,15 @@ Each document database is full of useless words. All the little words that appea
133
  * John Calahan for extensive 4.0 beta testing.
134
 
135
  == Changelog ==
 
 
 
 
 
 
 
 
 
136
  = 4.10.1 =
137
  * Major fix: The multilingual stopwords and synonyms were used based on the global language. Now when indexing posts, the post language is used instead of the global language.
138
 
@@ -202,6 +211,9 @@ Each document database is full of useless words. All the little words that appea
202
  * Minor fix: Relevanssi only updates doc count on `relevanssi_insert_edit()` when the post is indexed.
203
 
204
  == Upgrade notice ==
 
 
 
205
  = 4.10.1 =
206
  * Corrects the multilingual stopwords and synonyms.
207
 
5
  Requires at least: 4.9
6
  Tested up to: 5.6.1
7
  Requires PHP: 7.0
8
+ Stable tag: 4.10.2
9
  License: GPLv2 or later
10
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
11
 
133
  * John Calahan for extensive 4.0 beta testing.
134
 
135
  == Changelog ==
136
+ = 4.10.2 =
137
+ * New feature: You can force Relevanssi to be active by setting the query variable `relevanssi` to `true`. Thanks to Jan Willem Oostendorp.
138
+ * Changed behaviour: Relevanssi has been moved from `the_posts` filter to `posts_pre_query`. This change doesn't do much, but increases performance slightly as WordPress needs to do less useless work, as now the default query is no longer run. Thanks to Jan Willem Oostendorp.
139
+ * Minor fix: Highlighting didn't work properly when highlighting something immediately following a HTML tag.
140
+ * Minor fix: You can no longer set the value of minimum word length to less than 1 or higher than 9 from the settings page.
141
+ * Minor fix: Importing options broke synonym and stopword settings.
142
+ * Minor fix: Improves the Rank Math SEO compatibility to avoid errors in plugin activation.
143
+ * Minor fix: WPML search results that included non-post results caused fatal errors and crashes. This fixes the crashing and makes non-post results work better in both WPML and Polylang.
144
+
145
  = 4.10.1 =
146
  * Major fix: The multilingual stopwords and synonyms were used based on the global language. Now when indexing posts, the post language is used instead of the global language.
147
 
211
  * Minor fix: Relevanssi only updates doc count on `relevanssi_insert_edit()` when the post is indexed.
212
 
213
  == Upgrade notice ==
214
+ = 4.10.2 =
215
+ * Switch from `the_posts` to `posts_pre_query`, bug fixes.
216
+
217
  = 4.10.1 =
218
  * Corrects the multilingual stopwords and synonyms.
219
 
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.10.1
17
  * Author: Mikko Saari
18
  * Author URI: http://www.mikkosaari.fi/
19
  * Text Domain: relevanssi
@@ -67,7 +67,7 @@ $relevanssi_variables['database_version'] = 6;
67
  $relevanssi_variables['file'] = __FILE__;
68
  $relevanssi_variables['plugin_dir'] = plugin_dir_path( __FILE__ );
69
  $relevanssi_variables['plugin_basename'] = plugin_basename( __FILE__ );
70
- $relevanssi_variables['plugin_version'] = '4.10.1';
71
 
72
  require_once 'lib/admin-ajax.php';
73
  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.10.2
17
  * Author: Mikko Saari
18
  * Author URI: http://www.mikkosaari.fi/
19
  * Text Domain: relevanssi
67
  $relevanssi_variables['file'] = __FILE__;
68
  $relevanssi_variables['plugin_dir'] = plugin_dir_path( __FILE__ );
69
  $relevanssi_variables['plugin_basename'] = plugin_basename( __FILE__ );
70
+ $relevanssi_variables['plugin_version'] = '4.10.2';
71
 
72
  require_once 'lib/admin-ajax.php';
73
  require_once 'lib/common.php';