Relevanssi – A Better Search - Version 4.13.3

Version Description

  • New feature: You can now add a post type dropdown to search forms with the [searchform] shortcode with the parameter 'dropdown' set to 'post_type'.
  • New feature: Adds compatibility for Product GTIN (EAN, UPC, ISBN) for WooCommerce plugin.
  • New feature: New filter hook relevanssi_post_to_excerpt lets you filter the post object before an excerpt is created from it.
  • New feature: Relevanssi is now compatible with the Bricks page builder theme (requires Bricks 1.3.2).
  • Minor fix: The character is now counted as a quote.
  • Minor fix: Running indexing through WP CLI doesn't cause PHP notices anymore.
  • Minor fix: Sometimes the Did you mean would return really weird long suggestions from the search logs. That won't happen anymore.
  • Minor fix: Improves tax_query handling in fringe cases with multiple AND clauses joined together with OR.
  • Minor fix: Oxygen compatibility has been improved. Rich text fields and updating posts when they are saved in Oxygen now work better, and revisions are no longer indexed.
  • Minor fix: Searching without a search term works much better now, you get more posts in the results (default value is up to 500).
Download this release

Release Info

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

Code changes from version 4.13.2 to 4.13.3

lib/common.php CHANGED
@@ -387,6 +387,7 @@ function relevanssi_remove_punct( $a ) {
387
  '“' => $quote_replacement,
388
  '„' => $quote_replacement,
389
  '´' => $quote_replacement,
 
390
  '-' => $hyphen_replacement,
391
  '–' => $endash_replacement,
392
  '—' => $emdash_replacement,
@@ -1187,6 +1188,11 @@ function relevanssi_get_forbidden_post_types() {
1187
  'elementor_icons', // Elementor.
1188
  'elementor_library', // Elementor.
1189
  'elementor_snippet', // Elementor.
 
 
 
 
 
1190
  );
1191
  }
1192
 
@@ -1208,6 +1214,7 @@ function relevanssi_get_forbidden_taxonomies() {
1208
  'elementor_library_type', // Elementor.
1209
  'elementor_library_category', // Elementor.
1210
  'elementor_font_type', // Elementor.
 
1211
  );
1212
  }
1213
 
387
  '“' => $quote_replacement,
388
  '„' => $quote_replacement,
389
  '´' => $quote_replacement,
390
+ '″' => $quote_replacement,
391
  '-' => $hyphen_replacement,
392
  '–' => $endash_replacement,
393
  '—' => $emdash_replacement,
1188
  'elementor_icons', // Elementor.
1189
  'elementor_library', // Elementor.
1190
  'elementor_snippet', // Elementor.
1191
+ 'wffn_landing', // WooFunnel.
1192
+ 'wffn_ty', // WooFunnel.
1193
+ 'wffn_optin', // WooFunnel.
1194
+ 'wffn_oty', // WooFunnel.
1195
+ 'wp_template', // Block templates.
1196
  );
1197
  }
1198
 
1214
  'elementor_library_type', // Elementor.
1215
  'elementor_library_category', // Elementor.
1216
  'elementor_font_type', // Elementor.
1217
+ 'wp_theme', // WordPress themes.
1218
  );
1219
  }
1220
 
lib/compatibility/bricks.php ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * /lib/compatibility/bricks.php
4
+ *
5
+ * Bricks theme 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
+ add_filter(
14
+ 'bricks/posts/query_vars',
15
+ function( $query_vars ) {
16
+ $query_vars['relevanssi'] = true;
17
+ return $query_vars;
18
+ }
19
+ );
lib/compatibility/oxygen.php CHANGED
@@ -14,6 +14,8 @@ add_filter( 'relevanssi_custom_field_value', 'relevanssi_oxygen_compatibility',
14
  add_filter( 'relevanssi_index_custom_fields', 'relevanssi_add_oxygen' );
15
  add_filter( 'option_relevanssi_index_fields', 'relevanssi_oxygen_fix_none_setting' );
16
  add_filter( 'relevanssi_oxygen_section_content', 'relevanssi_oxygen_code_block' );
 
 
17
 
18
  /**
19
  * Cleans up the Oxygen Builder custom field for Relevanssi consumption.
@@ -33,6 +35,12 @@ add_filter( 'relevanssi_oxygen_section_content', 'relevanssi_oxygen_code_block'
33
  * @return array|null An array of custom field values, null if no value exists.
34
  */
35
  function relevanssi_oxygen_compatibility( $value, $field, $post_id ) {
 
 
 
 
 
 
36
  if ( 'ct_builder_shortcodes' === $field ) {
37
  if ( empty( $value ) ) {
38
  return null;
@@ -122,6 +130,7 @@ function relevanssi_add_oxygen( $fields ) {
122
  if ( ! in_array( 'ct_builder_shortcodes', $fields, true ) ) {
123
  $fields[] = 'ct_builder_shortcodes';
124
  }
 
125
  return $fields;
126
  }
127
 
@@ -164,3 +173,15 @@ function relevanssi_oxygen_code_block( $content ) {
164
  }
165
  return $content;
166
  }
 
 
 
 
 
 
 
 
 
 
 
 
14
  add_filter( 'relevanssi_index_custom_fields', 'relevanssi_add_oxygen' );
15
  add_filter( 'option_relevanssi_index_fields', 'relevanssi_oxygen_fix_none_setting' );
16
  add_filter( 'relevanssi_oxygen_section_content', 'relevanssi_oxygen_code_block' );
17
+ add_filter( 'relevanssi_oxygen_section_content', 'relevanssi_oxygen_rich_text' );
18
+ add_action( 'save_post', 'relevanssi_insert_edit', 99, 1 );
19
 
20
  /**
21
  * Cleans up the Oxygen Builder custom field for Relevanssi consumption.
35
  * @return array|null An array of custom field values, null if no value exists.
36
  */
37
  function relevanssi_oxygen_compatibility( $value, $field, $post_id ) {
38
+ if ( 'ct_builder_shortcodes_revisions_dates' === $field ) {
39
+ return '';
40
+ }
41
+ if ( 'ct_builder_shortcodes_revisions' === $field ) {
42
+ return '';
43
+ }
44
  if ( 'ct_builder_shortcodes' === $field ) {
45
  if ( empty( $value ) ) {
46
  return null;
130
  if ( ! in_array( 'ct_builder_shortcodes', $fields, true ) ) {
131
  $fields[] = 'ct_builder_shortcodes';
132
  }
133
+
134
  return $fields;
135
  }
136
 
173
  }
174
  return $content;
175
  }
176
+
177
+ /**
178
+ * Removes the Oxygen rich text shortcode.
179
+ *
180
+ * @param string $content The content of the Oxygen section.
181
+ *
182
+ * @return string The content with the oxy_rich_text shortcodes removed.
183
+ */
184
+ function relevanssi_oxygen_rich_text( $content ) {
185
+ $content = preg_replace( '/\[\/?oxy_rich_text.*?\]/im', '', $content );
186
+ return $content;
187
+ }
lib/compatibility/polylang.php CHANGED
@@ -39,7 +39,7 @@ function relevanssi_polylang_filter( $query ) {
39
  }
40
 
41
  foreach ( $query->tax_query->queries as $tax_query ) {
42
- if ( 'language' !== $tax_query['taxonomy'] ) {
43
  // Not a language tax query.
44
  $ok_queries[] = $tax_query;
45
  }
39
  }
40
 
41
  foreach ( $query->tax_query->queries as $tax_query ) {
42
+ if ( isset( $tax_query['taxonomy'] ) && 'language' !== $tax_query['taxonomy'] ) {
43
  // Not a language tax query.
44
  $ok_queries[] = $tax_query;
45
  }
lib/compatibility/product-gtin-ean-upc-isbn-for-woocommerce.php ADDED
@@ -0,0 +1,64 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * /lib/compatibility/product-gtin-ean-upc-isbn-for-woocommerce.php.php
4
+ *
5
+ * Adds Product GTIN (EAN, UPC, ISBN) for WooCommerce support for Relevanssi.
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
+ add_action( 'pre_option_wpm_pgw_search_by_code', 'relevanssi_disable_gtin_code' );
14
+ add_filter( 'relevanssi_index_custom_fields', 'relevanssi_add_wpm_gtin_code' );
15
+ add_filter( 'option_relevanssi_index_fields', 'relevanssi_wpm_pgw_fix_none_setting' );
16
+
17
+ /**
18
+ * Disables the 'wpm_pgw_search_by_code' option.
19
+ *
20
+ * If this option is enabled, it will break Relevanssi search when there's a
21
+ * match for the code.
22
+ *
23
+ * @param string $value Not used.
24
+ *
25
+ * @return string 'no'.
26
+ */
27
+ function relevanssi_disable_gtin_code( $value ) {
28
+ return 'no';
29
+ }
30
+
31
+ /**
32
+ * Adds the `_wpm_gtin_code` to the list of indexed custom fields.
33
+ *
34
+ * @param array|boolean $fields An array of custom fields to index, or false.
35
+ *
36
+ * @return array An array of custom fields, including `_wpm_gtin_code`.
37
+ */
38
+ function relevanssi_add_wpm_gtin_code( $fields ) {
39
+ if ( ! is_array( $fields ) ) {
40
+ $fields = array();
41
+ }
42
+ if ( ! in_array( '_wpm_gtin_code', $fields, true ) ) {
43
+ $fields[] = '_wpm_gtin_code';
44
+ }
45
+ return $fields;
46
+ }
47
+
48
+ /**
49
+ * Makes sure the GTIN code is included in the index, even when the custom field
50
+ * setting is set to 'none'.
51
+ *
52
+ * @param string $value The custom field indexing setting value. The parameter
53
+ * is ignored, Relevanssi disables this filter and then checks the option to
54
+ * see what the value is.
55
+ *
56
+ * @return string If value is undefined, it's set to '_wpm_gtin_code'.
57
+ */
58
+ function relevanssi_wpm_pgw_fix_none_setting( $value ) {
59
+ if ( ! $value ) {
60
+ $value = '_wpm_gtin_code';
61
+ }
62
+
63
+ return $value;
64
+ }
lib/compatibility/woocommerce.php CHANGED
@@ -18,6 +18,8 @@ add_filter( 'relevanssi_indexing_restriction', 'relevanssi_woocommerce_restricti
18
  */
19
  add_action( 'woocommerce_before_shop_loop', 'relevanssi_wc_reset_loop' );
20
 
 
 
21
  /**
22
  * Resets the WC post loop in search queries.
23
  *
@@ -103,3 +105,27 @@ function relevanssi_woocommerce_indexing_filter() {
103
  }
104
  return $restriction;
105
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
18
  */
19
  add_action( 'woocommerce_before_shop_loop', 'relevanssi_wc_reset_loop' );
20
 
21
+ RELEVANSSI_PREMIUM && add_filter( 'relevanssi_match', 'relevanssi_sku_boost' );
22
+
23
  /**
24
  * Resets the WC post loop in search queries.
25
  *
105
  }
106
  return $restriction;
107
  }
108
+
109
+ /**
110
+ * SKU weight boost.
111
+ *
112
+ * Increases the weight for matches in the _sku custom field. The amount of
113
+ * boost can be adjusted with the `relevanssi_sku_boost` filter hook. The
114
+ * default is 2.
115
+ *
116
+ * @param object $match The match object.
117
+ *
118
+ * @return object The match object.
119
+ */
120
+ function relevanssi_sku_boost( $match ) {
121
+ $custom_field_detail = json_decode( $match->customfield_detail );
122
+ if ( null !== $custom_field_detail && isset( $custom_field_detail->_sku ) ) {
123
+ /**
124
+ * Filters the SKU boost value.
125
+ *
126
+ * @param float The boost multiplier, default 2.
127
+ */
128
+ $match->weight *= apply_filters( 'relevanssi_sku_boost', 2 );
129
+ }
130
+ return $match;
131
+ }
lib/didyoumean.php CHANGED
@@ -172,8 +172,10 @@ function relevanssi_simple_generate_suggestion( $query ) {
172
  $closest = '';
173
  break;
174
  } else {
175
- if ( relevanssi_strlen( $token ) < 255 ) {
176
- // The levenshtein() function has a max length of 255 characters.
 
 
177
  $lev = levenshtein( $token, $row->query );
178
  if ( $lev < 3 && ( $lev < $distance || $distance < 0 ) ) {
179
  if ( $row->a > 0 ) {
172
  $closest = '';
173
  break;
174
  } else {
175
+ if ( strlen( $token ) < 255 && strlen( $row->query ) < 255 ) {
176
+ // The levenshtein() function has a max length of 255
177
+ // characters. The function uses strlen(), so we must use
178
+ // too, instead of relevanssi_strlen().
179
  $lev = levenshtein( $token, $row->query );
180
  if ( $lev < 3 && ( $lev < $distance || $distance < 0 ) ) {
181
  if ( $row->a > 0 ) {
lib/excerpts-highlights.php CHANGED
@@ -39,7 +39,12 @@ function relevanssi_do_excerpt( $t_post, $query, $excerpt_length = null, $excerp
39
  if ( null !== $post ) {
40
  $old_global_post = $post;
41
  }
42
- $post = $t_post; // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited
 
 
 
 
 
43
 
44
  $remove_stopwords = 'body';
45
 
39
  if ( null !== $post ) {
40
  $old_global_post = $post;
41
  }
42
+ /**
43
+ * Allows filtering the indexed post before building an excerpt from it.
44
+ *
45
+ * @param object $post The post object.
46
+ */
47
+ $post = apply_filters( 'relevanssi_post_to_excerpt', $t_post ); // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited
48
 
49
  $remove_stopwords = 'body';
50
 
lib/indexing.php CHANGED
@@ -344,13 +344,13 @@ function relevanssi_build_index( $extend_offset = false, $verbose = null, $post_
344
  // $n calculates the number of posts indexed.
345
  $n++;
346
  }
347
- if ( defined( 'WP_CLI' ) && WP_CLI && $progress ) {
348
  // @codeCoverageIgnoreStart
349
  $progress->tick();
350
  // @codeCoverageIgnoreEnd
351
  }
352
  }
353
- if ( defined( 'WP_CLI' ) && WP_CLI && $progress ) {
354
  // @codeCoverageIgnoreStart
355
  $progress->finish();
356
  // @codeCoverageIgnoreEnd
344
  // $n calculates the number of posts indexed.
345
  $n++;
346
  }
347
+ if ( defined( 'WP_CLI' ) && WP_CLI && isset( $progress ) ) {
348
  // @codeCoverageIgnoreStart
349
  $progress->tick();
350
  // @codeCoverageIgnoreEnd
351
  }
352
  }
353
+ if ( defined( 'WP_CLI' ) && WP_CLI && isset( $progress ) ) {
354
  // @codeCoverageIgnoreStart
355
  $progress->finish();
356
  // @codeCoverageIgnoreEnd
lib/init.php CHANGED
@@ -476,11 +476,13 @@ function relevanssi_load_compatibility_code() {
476
  class_exists( 'WooCommerce', false ) && require_once 'compatibility/woocommerce.php';
477
  defined( 'AIOSEO_DIR' ) && require_once 'compatibility/aioseo.php';
478
  defined( 'AVADA_VERSION' ) && require_once 'compatibility/avada.php';
 
479
  defined( 'CT_VERSION' ) && require_once 'compatibility/oxygen.php';
480
  defined( 'ELEMENTOR_VERSION' ) && require_once 'compatibility/elementor.php';
481
  defined( 'GROUPS_CORE_VERSION' ) && require_once 'compatibility/groups.php';
482
  defined( 'NINJA_TABLES_VERSION' ) && require_once 'compatibility/ninjatables.php';
483
  defined( 'PRLI_PLUGIN_NAME' ) && require_once 'compatibility/pretty-links.php';
 
484
  defined( 'SIMPLE_WP_MEMBERSHIP_VER' ) && require_once 'compatibility/simplemembership.php';
485
  defined( 'THE_SEO_FRAMEWORK_VERSION' ) && require_once 'compatibility/seoframework.php';
486
  defined( 'WPFD_VERSION' ) && require_once 'compatibility/wp-file-download.php';
476
  class_exists( 'WooCommerce', false ) && require_once 'compatibility/woocommerce.php';
477
  defined( 'AIOSEO_DIR' ) && require_once 'compatibility/aioseo.php';
478
  defined( 'AVADA_VERSION' ) && require_once 'compatibility/avada.php';
479
+ defined( 'BRICKS_VERSION' ) && require_once 'compatibility/bricks.php';
480
  defined( 'CT_VERSION' ) && require_once 'compatibility/oxygen.php';
481
  defined( 'ELEMENTOR_VERSION' ) && require_once 'compatibility/elementor.php';
482
  defined( 'GROUPS_CORE_VERSION' ) && require_once 'compatibility/groups.php';
483
  defined( 'NINJA_TABLES_VERSION' ) && require_once 'compatibility/ninjatables.php';
484
  defined( 'PRLI_PLUGIN_NAME' ) && require_once 'compatibility/pretty-links.php';
485
+ defined( 'WPM_PRODUCT_GTIN_WC_VERSION' ) && require_once 'compatibility/product-gtin-ean-upc-isbn-for-woocommerce.php';
486
  defined( 'SIMPLE_WP_MEMBERSHIP_VER' ) && require_once 'compatibility/simplemembership.php';
487
  defined( 'THE_SEO_FRAMEWORK_VERSION' ) && require_once 'compatibility/seoframework.php';
488
  defined( 'WPFD_VERSION' ) && require_once 'compatibility/wp-file-download.php';
lib/search-tax-query.php CHANGED
@@ -274,17 +274,36 @@ array $and_term_tax_ids, array $exist_queries ) : string {
274
  // Clean: all variables are Relevanssi-generated.
275
  }
276
  if ( count( $and_term_tax_ids ) > 0 ) {
277
- $and_term_tax_ids = implode( ',', $and_term_tax_ids );
278
- $n = count( explode( ',', $and_term_tax_ids ) );
279
- $query_restriction_parts[] .= " relevanssi.doc IN (
280
- SELECT ID FROM $wpdb->posts WHERE 1=1
281
- AND (
282
- SELECT COUNT(1)
283
- FROM $wpdb->term_relationships AS tr
284
- WHERE tr.term_taxonomy_id IN ($and_term_tax_ids)
285
- AND tr.object_id = $wpdb->posts.ID ) = $n
286
- )";
287
- // Clean: all variables are Relevanssi-generated.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
288
  }
289
 
290
  if ( $exist_queries ) {
274
  // Clean: all variables are Relevanssi-generated.
275
  }
276
  if ( count( $and_term_tax_ids ) > 0 ) {
277
+ $single_term_ids = array();
278
+ foreach ( $and_term_tax_ids as $term_ids ) {
279
+ $n = count( explode( ',', $term_ids ) );
280
+ if ( 1 === $n ) {
281
+ $single_term_ids[] = $term_ids;
282
+ continue;
283
+ }
284
+ $query_restriction_parts[] .= " relevanssi.doc IN (
285
+ SELECT ID FROM $wpdb->posts WHERE 1=1
286
+ AND (
287
+ SELECT COUNT(1)
288
+ FROM $wpdb->term_relationships AS tr
289
+ WHERE tr.term_taxonomy_id IN ($term_ids)
290
+ AND tr.object_id = $wpdb->posts.ID ) = $n
291
+ )";
292
+ // Clean: all variables are Relevanssi-generated.
293
+ }
294
+ if ( count( $single_term_ids ) > 0 ) {
295
+ $n = count( $single_term_ids );
296
+ $term_ids = implode( ',', $single_term_ids );
297
+ $query_restriction_parts[] .= " relevanssi.doc IN (
298
+ SELECT ID FROM $wpdb->posts WHERE 1=1
299
+ AND (
300
+ SELECT COUNT(1)
301
+ FROM $wpdb->term_relationships AS tr
302
+ WHERE tr.term_taxonomy_id IN ($term_ids)
303
+ AND tr.object_id = $wpdb->posts.ID ) = $n
304
+ )";
305
+ // Clean: all variables are Relevanssi-generated.
306
+ }
307
  }
308
 
309
  if ( $exist_queries ) {
lib/search.php CHANGED
@@ -226,7 +226,7 @@ function relevanssi_search( $args ) {
226
  );
227
 
228
  $query = relevanssi_generate_search_query( $term, $search_again, $no_terms, $query_join, $this_query_restrictions );
229
- $matches = $wpdb->get_results( $query ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared,WordPress.DB.PreparedSQL.InterpolatedNotPrepared
230
 
231
  if ( count( $matches ) < 1 ) {
232
  continue;
@@ -713,10 +713,13 @@ function relevanssi_limit_filter( $query ) {
713
  if ( $limit < 0 ) {
714
  $limit = 500;
715
  }
716
- return $query . " ORDER BY tf DESC LIMIT $limit";
717
- } else {
718
- return $query;
 
 
719
  }
 
720
  }
721
 
722
  /**
@@ -1610,23 +1613,34 @@ bool $no_terms, string $query_join = '', string $query_restrictions = '' ) : str
1610
  global $relevanssi_variables;
1611
  $relevanssi_table = $relevanssi_variables['relevanssi_table'];
1612
 
1613
- $term_cond = relevanssi_generate_term_where( $term, $search_again, $no_terms, get_option( 'relevanssi_fuzzy' ) );
 
 
 
 
 
 
 
 
 
1614
 
1615
- $content_boost = floatval( get_option( 'relevanssi_content_boost', 1 ) );
1616
- $title_boost = floatval( get_option( 'relevanssi_title_boost' ) );
1617
- $link_boost = floatval( get_option( 'relevanssi_link_boost' ) );
1618
- $comment_boost = floatval( get_option( 'relevanssi_comment_boost' ) );
1619
 
1620
- $tag = ! empty( $post_type_weights['post_tag'] ) ? $post_type_weights['post_tag'] : $relevanssi_variables['post_type_weight_defaults']['post_tag'];
1621
- $cat = ! empty( $post_type_weights['category'] ) ? $post_type_weights['category'] : $relevanssi_variables['post_type_weight_defaults']['category'];
 
 
 
 
 
 
 
 
 
1622
 
1623
- // Clean: $term is escaped, as are $query_restrictions.
1624
- $query = "SELECT DISTINCT(relevanssi.doc), relevanssi.*, relevanssi.title * $title_boost +
1625
- relevanssi.content * $content_boost + relevanssi.comment * $comment_boost +
1626
- relevanssi.tag * $tag + relevanssi.link * $link_boost +
1627
- relevanssi.author + relevanssi.category * $cat + relevanssi.excerpt +
1628
- relevanssi.taxonomy + relevanssi.customfield + relevanssi.mysqlcolumn AS tf
1629
- FROM $relevanssi_table AS relevanssi $query_join WHERE $term_cond $query_restrictions";
1630
  /**
1631
  * Filters the Relevanssi search query.
1632
  *
226
  );
227
 
228
  $query = relevanssi_generate_search_query( $term, $search_again, $no_terms, $query_join, $this_query_restrictions );
229
+ $matches = $wpdb->get_results( $query ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared.
230
 
231
  if ( count( $matches ) < 1 ) {
232
  continue;
713
  if ( $limit < 0 ) {
714
  $limit = 500;
715
  }
716
+ if ( $termless_search ) {
717
+ $query = $query . " GROUP BY doc, item, type ORDER BY doc ASC LIMIT $limit";
718
+ } else {
719
+ $query = $query . " ORDER BY tf DESC LIMIT $limit";
720
+ }
721
  }
722
+ return $query;
723
  }
724
 
725
  /**
1613
  global $relevanssi_variables;
1614
  $relevanssi_table = $relevanssi_variables['relevanssi_table'];
1615
 
1616
+ if ( $no_terms ) {
1617
+ $query = "SELECT DISTINCT(relevanssi.doc), 1 AS term, 1 AS term_reverse,
1618
+ 1 AS content, 1 AS title, 1 AS comment, 1 AS tag, 1 AS link, 1 AS
1619
+ author, 1 AS category, 1 AS excerpt, 1 AS taxonomy, 1 AS customfield,
1620
+ 1 AS mysqlcolumn, 1 AS taxonomy_detail, 1 AS customfield_detail, 1 AS
1621
+ mysqlcolumn_detail, type, item, 1 AS tf
1622
+ FROM $relevanssi_table AS relevanssi $query_join
1623
+ WHERE relevanssi.term = relevanssi.term $query_restrictions";
1624
+ } else {
1625
+ $term_cond = relevanssi_generate_term_where( $term, $search_again, $no_terms, get_option( 'relevanssi_fuzzy' ) );
1626
 
1627
+ $content_boost = floatval( get_option( 'relevanssi_content_boost', 1 ) );
1628
+ $title_boost = floatval( get_option( 'relevanssi_title_boost' ) );
1629
+ $link_boost = floatval( get_option( 'relevanssi_link_boost' ) );
1630
+ $comment_boost = floatval( get_option( 'relevanssi_comment_boost' ) );
1631
 
1632
+ $tag = ! empty( $post_type_weights['post_tag'] ) ? $post_type_weights['post_tag'] : $relevanssi_variables['post_type_weight_defaults']['post_tag'];
1633
+ $cat = ! empty( $post_type_weights['category'] ) ? $post_type_weights['category'] : $relevanssi_variables['post_type_weight_defaults']['category'];
1634
+
1635
+ // Clean: $term is escaped, as are $query_restrictions.
1636
+ $query = "SELECT DISTINCT(relevanssi.doc), relevanssi.*, relevanssi.title * $title_boost +
1637
+ relevanssi.content * $content_boost + relevanssi.comment * $comment_boost +
1638
+ relevanssi.tag * $tag + relevanssi.link * $link_boost +
1639
+ relevanssi.author + relevanssi.category * $cat + relevanssi.excerpt +
1640
+ relevanssi.taxonomy + relevanssi.customfield + relevanssi.mysqlcolumn AS tf
1641
+ FROM $relevanssi_table AS relevanssi $query_join WHERE $term_cond $query_restrictions";
1642
+ }
1643
 
 
 
 
 
 
 
 
1644
  /**
1645
  * Filters the Relevanssi search query.
1646
  *
lib/shortcodes.php CHANGED
@@ -111,7 +111,22 @@ function relevanssi_search_form( $atts ) {
111
  if ( is_array( $atts ) ) {
112
  $additional_fields = array();
113
  foreach ( $atts as $key => $value ) {
114
- if ( 'dropdown' === $key ) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
115
  $name = $value;
116
  if ( 'category' === $value ) {
117
  $name = 'cat';
111
  if ( is_array( $atts ) ) {
112
  $additional_fields = array();
113
  foreach ( $atts as $key => $value ) {
114
+ if ( 'dropdown' === $key && 'post_type' === $value ) {
115
+ $field = '<select name="post_type">';
116
+ $types = get_option( 'relevanssi_index_post_types' );
117
+ if ( ! is_array( $types ) ) {
118
+ $types = array();
119
+ }
120
+ foreach ( $types as $type ) {
121
+ if ( post_type_exists( $type ) ) {
122
+ $object = get_post_type_object( $type );
123
+ $field .= '<option value="' . $type . '">' . $object->labels->singular_name . '</option>';
124
+ }
125
+ }
126
+ $field .= '</select>';
127
+ $additional_fields[] = $field;
128
+
129
+ } elseif ( 'dropdown' === $key && 'post_type' !== $value ) {
130
  $name = $value;
131
  if ( 'category' === $value ) {
132
  $name = 'cat';
lib/utils.php CHANGED
@@ -887,14 +887,16 @@ function relevanssi_strip_all_tags( $content ) : string {
887
  if ( ! is_string( $content ) ) {
888
  $content = '';
889
  }
890
- return preg_replace( '/<[!a-zA-Z\/][^>]*>/', ' ', $content );
 
 
891
  }
892
 
893
  /**
894
  * Strips invisible elements from text.
895
  *
896
  * Strips <style>, <script>, <object>, <embed>, <applet>, <noscript>, <noembed>,
897
- * <iframe>, and <del> tags and their contents from the text.
898
  *
899
  * @param string $text The source text.
900
  *
@@ -915,6 +917,7 @@ function relevanssi_strip_invisibles( $text ) {
915
  '@<noembed[^>]*?.*?</noembed>@siu',
916
  '@<iframe[^>]*?.*?</iframe>@siu',
917
  '@<del[^>]*?.*?</del>@siu',
 
918
  ),
919
  ' ',
920
  $text
887
  if ( ! is_string( $content ) ) {
888
  $content = '';
889
  }
890
+ $content = preg_replace( '/<!--.*?-->/ms', '', $content );
891
+ $content = preg_replace( '/<[!a-zA-Z\/][^>].*?>/ms', ' ', $content );
892
+ return $content;
893
  }
894
 
895
  /**
896
  * Strips invisible elements from text.
897
  *
898
  * Strips <style>, <script>, <object>, <embed>, <applet>, <noscript>, <noembed>,
899
+ * <iframe> and <del> tags and their contents and comments from the text.
900
  *
901
  * @param string $text The source text.
902
  *
917
  '@<noembed[^>]*?.*?</noembed>@siu',
918
  '@<iframe[^>]*?.*?</iframe>@siu',
919
  '@<del[^>]*?.*?</del>@siu',
920
+ '@<!--.*?-->@siu',
921
  ),
922
  ' ',
923
  $text
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.7.2
7
  Requires PHP: 7.0
8
- Stable tag: 4.13.2
9
  License: GPLv2 or later
10
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
11
 
@@ -131,6 +131,18 @@ Each document database is full of useless words. All the little words that appea
131
  * John Calahan for extensive 4.0 beta testing.
132
 
133
  == Changelog ==
 
 
 
 
 
 
 
 
 
 
 
 
134
  = 4.13.2 =
135
  * New feature: Adds support for Avada Live Search.
136
  * New feature: Adds support for Fibo Search.
@@ -233,6 +245,9 @@ Each document database is full of useless words. All the little words that appea
233
  * Minor fix: Improved Oxygen Builder support makes sure `ct_builder_shortcodes` custom field is always indexed.
234
 
235
  == Upgrade notice ==
 
 
 
236
  = 4.13.2 =
237
  * Small bug and compatibility fixes.
238
 
5
  Requires at least: 4.9
6
  Tested up to: 5.7.2
7
  Requires PHP: 7.0
8
+ Stable tag: 4.13.3
9
  License: GPLv2 or later
10
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
11
 
131
  * John Calahan for extensive 4.0 beta testing.
132
 
133
  == Changelog ==
134
+ = 4.13.3 =
135
+ * New feature: You can now add a post type dropdown to search forms with the [searchform] shortcode with the parameter 'dropdown' set to 'post_type'.
136
+ * New feature: Adds compatibility for Product GTIN (EAN, UPC, ISBN) for WooCommerce plugin.
137
+ * New feature: New filter hook `relevanssi_post_to_excerpt` lets you filter the post object before an excerpt is created from it.
138
+ * New feature: Relevanssi is now compatible with the Bricks page builder theme (requires Bricks 1.3.2).
139
+ * Minor fix: The ″ character is now counted as a quote.
140
+ * Minor fix: Running indexing through WP CLI doesn't cause PHP notices anymore.
141
+ * Minor fix: Sometimes the Did you mean would return really weird long suggestions from the search logs. That won't happen anymore.
142
+ * Minor fix: Improves tax_query handling in fringe cases with multiple AND clauses joined together with OR.
143
+ * Minor fix: Oxygen compatibility has been improved. Rich text fields and updating posts when they are saved in Oxygen now work better, and revisions are no longer indexed.
144
+ * Minor fix: Searching without a search term works much better now, you get more posts in the results (default value is up to 500).
145
+
146
  = 4.13.2 =
147
  * New feature: Adds support for Avada Live Search.
148
  * New feature: Adds support for Fibo Search.
245
  * Minor fix: Improved Oxygen Builder support makes sure `ct_builder_shortcodes` custom field is always indexed.
246
 
247
  == Upgrade notice ==
248
+ = 4.13.3 =
249
+ * Bug fixes and small improvements.
250
+
251
  = 4.13.2 =
252
  * Small bug and compatibility fixes.
253
 
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.13.2
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.13.2';
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.13.3
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.13.3';
71
 
72
  require_once 'lib/admin-ajax.php';
73
  require_once 'lib/common.php';