Version Description
- Adds a missing file.
Download this release
Release Info
Developer | msaari |
Plugin | Relevanssi – A Better Search |
Version | 4.14.1 |
Comparing to | |
See all releases |
Code changes from version 4.13.3.1 to 4.14.1
- changelog.txt +21 -0
- lib/admin_scripts.js +6 -1
- lib/admin_styles.css +1 -1
- lib/common.php +66 -32
- lib/compatibility/acf.php +1 -1
- lib/compatibility/bricks.php +1 -1
- lib/compatibility/gutenberg.php +16 -3
- lib/compatibility/polylang.php +2 -2
- lib/compatibility/woocommerce.php +23 -0
- lib/compatibility/wp-members.php +6 -4
- lib/didyoumean.php +1 -1
- lib/excerpts-highlights.php +37 -15
- lib/indexing.php +10 -7
- lib/init.php +118 -102
- lib/install.php +1 -1
- lib/interface.php +69 -254
- lib/phrases.php +3 -3
- lib/search.php +25 -8
- lib/shortcodes.php +23 -1
- lib/sorting.php +21 -2
- lib/tabs/debugging-tab.php +45 -3
- lib/tabs/logging-tab.php +11 -3
- lib/tabs/search-page.php +20 -15
- lib/tabs/stopwords-tab.php +16 -0
- lib/tabs/synonyms-tab.php +25 -3
- lib/uninstall.php +5 -0
- lib/user-searches.php +370 -0
- lib/utils.php +103 -0
- readme.txt +25 -22
- relevanssi.php +3 -2
changelog.txt
CHANGED
@@ -1,3 +1,24 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
= 4.9.1 =
|
2 |
* Changed behaviour: The `relevanssi_excerpt_part` filter hook now gets the post ID as a second parameter. The documentation for the filter has been fixed to match actual use: this filter is applied to the excerpt part after the highlighting and the ellipsis have been added.
|
3 |
* Changed behaviour: The `relevanssi_index_custom_fields` filter hook is no longer used when determining which custom fields are used for phrase searching. If you have a use case where this change matters, please contact us.
|
1 |
+
= 4.10.2 =
|
2 |
+
* New feature: You can force Relevanssi to be active by setting the query variable `relevanssi` to `true`. Thanks to Jan Willem Oostendorp.
|
3 |
+
* 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.
|
4 |
+
* Minor fix: Highlighting didn't work properly when highlighting something immediately following a HTML tag.
|
5 |
+
* 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.
|
6 |
+
* Minor fix: Importing options broke synonym and stopword settings.
|
7 |
+
* Minor fix: Improves the Rank Math SEO compatibility to avoid errors in plugin activation.
|
8 |
+
* 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.
|
9 |
+
|
10 |
+
= 4.10.1 =
|
11 |
+
* 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.
|
12 |
+
|
13 |
+
= 4.10.0 =
|
14 |
+
* New feature: Relevanssi now supports multilingual synonyms and stopwords. Relevanssi now has a different set of synonyms and stopwords for each language. This feature is compatible with WPML and Polylang.
|
15 |
+
* New feature: SEO by Rank Math compatibility is added: posts marked as 'noindex' with Rank Math are not indexed by Relevanssi.
|
16 |
+
* Minor fix: With keyword matching set to 'whole words' and the 'expand highlights' disabled, words that ended with an 's' weren't highlighted correctly.
|
17 |
+
* Minor fix: The 'Post exclusion' setting didn't work correctly. It has been fixed.
|
18 |
+
* Minor fix: It's now impossible to set negative weights in searching settings. They did not work as expected anyway.
|
19 |
+
* Minor fix: Relevanssi had an unnecessary index on the `doc` column in the `wp_relevanssi` database table. It is now removed to save space. Thanks to Matthew Wang.
|
20 |
+
* Minor fix: Improved Oxygen Builder support makes sure `ct_builder_shortcodes` custom field is always indexed.
|
21 |
+
|
22 |
= 4.9.1 =
|
23 |
* Changed behaviour: The `relevanssi_excerpt_part` filter hook now gets the post ID as a second parameter. The documentation for the filter has been fixed to match actual use: this filter is applied to the excerpt part after the highlighting and the ellipsis have been added.
|
24 |
* Changed behaviour: The `relevanssi_index_custom_fields` filter hook is no longer used when determining which custom fields are used for phrase searching. If you have a use case where this change matters, please contact us.
|
lib/admin_scripts.js
CHANGED
@@ -8,7 +8,12 @@ jQuery(document).ready(function ($) {
|
|
8 |
|
9 |
$("#removeallstopwords").click(function () {
|
10 |
var c = confirm(relevanssi.confirm_stopwords)
|
11 |
-
return c
|
|
|
|
|
|
|
|
|
|
|
12 |
})
|
13 |
})
|
14 |
|
8 |
|
9 |
$("#removeallstopwords").click(function () {
|
10 |
var c = confirm(relevanssi.confirm_stopwords)
|
11 |
+
return c
|
12 |
+
})
|
13 |
+
|
14 |
+
$("#delete_query").click(function () {
|
15 |
+
var c = confirm(relevanssi.confirm_delete_query)
|
16 |
+
return c
|
17 |
})
|
18 |
})
|
19 |
|
lib/admin_styles.css
CHANGED
@@ -10,7 +10,7 @@ table.form-table table.widefat th {
|
|
10 |
width: 3em;
|
11 |
}
|
12 |
|
13 |
-
#relevanssi_trim_logs {
|
14 |
width: 4em;
|
15 |
}
|
16 |
|
10 |
width: 3em;
|
11 |
}
|
12 |
|
13 |
+
#relevanssi_trim_logs, #relevanssi_trim_click_logs {
|
14 |
width: 4em;
|
15 |
}
|
16 |
|
lib/common.php
CHANGED
@@ -551,19 +551,25 @@ function relevanssi_prevent_default_request( $request, $query ) {
|
|
551 |
* 'body', also removes the body stopwords. Default true.
|
552 |
* @param int $min_word_length The minimum word length to include.
|
553 |
* Default -1.
|
|
|
|
|
554 |
*
|
555 |
* @return int[] An array of tokens as the keys and their frequency as the
|
556 |
* value.
|
557 |
*/
|
558 |
-
function relevanssi_tokenize( $string, $remove_stops = true, int $min_word_length = -1 ) : array {
|
559 |
if ( ! $string || ( ! is_string( $string ) && ! is_array( $string ) ) ) {
|
560 |
return array();
|
561 |
}
|
562 |
-
|
563 |
-
$
|
564 |
-
$
|
565 |
-
|
566 |
-
$
|
|
|
|
|
|
|
|
|
567 |
}
|
568 |
|
569 |
$tokens = array();
|
@@ -637,9 +643,11 @@ function relevanssi_tokenize( $string, $remove_stops = true, int $min_word_lengt
|
|
637 |
* Filters the token through the Relevanssi Premium tokenizer to add
|
638 |
* some Premium features to the tokenizing (mostly stemming).
|
639 |
*
|
640 |
-
* @param string $token
|
|
|
|
|
641 |
*/
|
642 |
-
$token = apply_filters( 'relevanssi_premium_tokenizer', $token );
|
643 |
}
|
644 |
|
645 |
if ( $accept ) {
|
@@ -1034,6 +1042,10 @@ function relevanssi_permalink( $link, $link_post = null ) {
|
|
1034 |
$link = relevanssi_add_highlight( $link, $link_post );
|
1035 |
}
|
1036 |
|
|
|
|
|
|
|
|
|
1037 |
return $link;
|
1038 |
}
|
1039 |
|
@@ -1193,6 +1205,11 @@ function relevanssi_get_forbidden_post_types() {
|
|
1193 |
'wffn_optin', // WooFunnel.
|
1194 |
'wffn_oty', // WooFunnel.
|
1195 |
'wp_template', // Block templates.
|
|
|
|
|
|
|
|
|
|
|
1196 |
);
|
1197 |
}
|
1198 |
|
@@ -1203,18 +1220,20 @@ function relevanssi_get_forbidden_post_types() {
|
|
1203 |
*/
|
1204 |
function relevanssi_get_forbidden_taxonomies() {
|
1205 |
return array(
|
1206 |
-
'nav_menu',
|
1207 |
-
'link_category',
|
1208 |
-
'amp_validation_error',
|
1209 |
-
'product_visibility',
|
1210 |
-
'wpforms_log_type',
|
1211 |
-
'amp_template',
|
1212 |
-
'edd_commission_status',
|
1213 |
-
'edd_log_type',
|
1214 |
-
'elementor_library_type',
|
1215 |
-
'elementor_library_category',
|
1216 |
-
'elementor_font_type',
|
1217 |
-
'wp_theme',
|
|
|
|
|
1218 |
);
|
1219 |
}
|
1220 |
|
@@ -1415,10 +1434,11 @@ EOH;
|
|
1415 |
*
|
1416 |
* @param int $post_id The post ID.
|
1417 |
* @param boolean $display If false, add "display: none" style to the element.
|
|
|
1418 |
*
|
1419 |
* @return string The HTML code for the "How Relevanssi sees this post".
|
1420 |
*/
|
1421 |
-
function relevanssi_generate_how_relevanssi_sees( $post_id, $display = true ) {
|
1422 |
$style = '';
|
1423 |
if ( ! $display ) {
|
1424 |
$style = 'style="display: none"';
|
@@ -1426,12 +1446,12 @@ function relevanssi_generate_how_relevanssi_sees( $post_id, $display = true ) {
|
|
1426 |
|
1427 |
$element = '<div id="relevanssi_sees_container" ' . $style . '>';
|
1428 |
|
1429 |
-
$data = relevanssi_fetch_sees_data( $post_id );
|
1430 |
|
1431 |
if ( empty( $data['terms_list'] ) && empty( $data['reason'] ) ) {
|
1432 |
$element .= '<p>'
|
1433 |
// Translators: %d is the post ID.
|
1434 |
-
. sprintf( __( 'Nothing found for
|
1435 |
. '</p>';
|
1436 |
$element .= '</div>';
|
1437 |
return $element;
|
@@ -1442,11 +1462,11 @@ function relevanssi_generate_how_relevanssi_sees( $post_id, $display = true ) {
|
|
1442 |
$element .= '<p>' . esc_html( $data['reason'] ) . '</p>';
|
1443 |
}
|
1444 |
if ( ! empty( $data['title'] ) ) {
|
1445 |
-
$element .= '<h3>' . esc_html__( '
|
1446 |
$element .= '<p>' . esc_html( $data['title'] ) . '</p>';
|
1447 |
}
|
1448 |
if ( ! empty( $data['content'] ) ) {
|
1449 |
-
$element .= '<h3>' . esc_html__( '
|
1450 |
$element .= '<p>' . esc_html( $data['content'] ) . '</p>';
|
1451 |
}
|
1452 |
if ( ! empty( $data['comment'] ) ) {
|
@@ -1492,7 +1512,8 @@ function relevanssi_generate_how_relevanssi_sees( $post_id, $display = true ) {
|
|
1492 |
/**
|
1493 |
* Fetches the Relevanssi indexing data for a post.
|
1494 |
*
|
1495 |
-
* @param int
|
|
|
1496 |
*
|
1497 |
* @global array $relevanssi_variables The Relevanssi global variables array,
|
1498 |
* used for the database table name.
|
@@ -1501,16 +1522,29 @@ function relevanssi_generate_how_relevanssi_sees( $post_id, $display = true ) {
|
|
1501 |
* @return array The indexed terms for various parts of the post in an
|
1502 |
* associative array.
|
1503 |
*/
|
1504 |
-
function relevanssi_fetch_sees_data( $post_id ) {
|
1505 |
global $wpdb, $relevanssi_variables;
|
1506 |
|
1507 |
-
$
|
1508 |
-
$wpdb->prepare(
|
1509 |
'SELECT * FROM ' . $relevanssi_variables['relevanssi_table'] . ' WHERE doc = %d', // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared,WordPress.DB.PreparedSQL.NotPrepared
|
1510 |
$post_id
|
1511 |
-
)
|
1512 |
-
|
1513 |
-
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1514 |
|
1515 |
$terms['content'] = array();
|
1516 |
$terms['title'] = array();
|
551 |
* 'body', also removes the body stopwords. Default true.
|
552 |
* @param int $min_word_length The minimum word length to include.
|
553 |
* Default -1.
|
554 |
+
* @param string $context The context for tokenization, can be
|
555 |
+
* 'indexing' or 'search_query'.
|
556 |
*
|
557 |
* @return int[] An array of tokens as the keys and their frequency as the
|
558 |
* value.
|
559 |
*/
|
560 |
+
function relevanssi_tokenize( $string, $remove_stops = true, int $min_word_length = -1, $context = 'indexing' ) : array {
|
561 |
if ( ! $string || ( ! is_string( $string ) && ! is_array( $string ) ) ) {
|
562 |
return array();
|
563 |
}
|
564 |
+
|
565 |
+
$phrase_words = array();
|
566 |
+
if ( RELEVANSSI_PREMIUM && 'search_query' === $context ) {
|
567 |
+
$string_for_phrases = is_array( $string ) ? implode( ' ', $string ) : $string;
|
568 |
+
$phrases = relevanssi_extract_phrases( $string_for_phrases );
|
569 |
+
$phrase_words = array();
|
570 |
+
foreach ( $phrases as $phrase ) {
|
571 |
+
$phrase_words = array_merge( $phrase_words, explode( ' ', $phrase ) );
|
572 |
+
}
|
573 |
}
|
574 |
|
575 |
$tokens = array();
|
643 |
* Filters the token through the Relevanssi Premium tokenizer to add
|
644 |
* some Premium features to the tokenizing (mostly stemming).
|
645 |
*
|
646 |
+
* @param string $token Search query token.
|
647 |
+
* @param string $context The context for tokenization, can be
|
648 |
+
* 'indexing' or 'search_query'.
|
649 |
*/
|
650 |
+
$token = apply_filters( 'relevanssi_premium_tokenizer', $token, $context );
|
651 |
}
|
652 |
|
653 |
if ( $accept ) {
|
1042 |
$link = relevanssi_add_highlight( $link, $link_post );
|
1043 |
}
|
1044 |
|
1045 |
+
if ( function_exists( 'relevanssi_add_tracking' ) ) {
|
1046 |
+
$link = relevanssi_add_tracking( $link, $link_post );
|
1047 |
+
}
|
1048 |
+
|
1049 |
return $link;
|
1050 |
}
|
1051 |
|
1205 |
'wffn_optin', // WooFunnel.
|
1206 |
'wffn_oty', // WooFunnel.
|
1207 |
'wp_template', // Block templates.
|
1208 |
+
'memberpressrule', // Memberpress.
|
1209 |
+
'memberpresscoupon', // Memberpress.
|
1210 |
+
'fl-builder-template', // Beaver Builder.
|
1211 |
+
'itsec-dashboard', // iThemes Security.
|
1212 |
+
'itsec-dash-card', // iThemes Security.
|
1213 |
);
|
1214 |
}
|
1215 |
|
1220 |
*/
|
1221 |
function relevanssi_get_forbidden_taxonomies() {
|
1222 |
return array(
|
1223 |
+
'nav_menu', // Navigation menus.
|
1224 |
+
'link_category', // Link categories.
|
1225 |
+
'amp_validation_error', // AMP.
|
1226 |
+
'product_visibility', // WooCommerce.
|
1227 |
+
'wpforms_log_type', // WP Forms.
|
1228 |
+
'amp_template', // AMP.
|
1229 |
+
'edd_commission_status', // Easy Digital Downloads.
|
1230 |
+
'edd_log_type', // Easy Digital Downloads.
|
1231 |
+
'elementor_library_type', // Elementor.
|
1232 |
+
'elementor_library_category', // Elementor.
|
1233 |
+
'elementor_font_type', // Elementor.
|
1234 |
+
'wp_theme', // WordPress themes.
|
1235 |
+
'fl-builder-template-category', // Beaver Builder.
|
1236 |
+
'fl-builder-template-type', // Beaver Builder.
|
1237 |
);
|
1238 |
}
|
1239 |
|
1434 |
*
|
1435 |
* @param int $post_id The post ID.
|
1436 |
* @param boolean $display If false, add "display: none" style to the element.
|
1437 |
+
* @param string $type One of 'post', 'term' or 'user'. Default 'post'.
|
1438 |
*
|
1439 |
* @return string The HTML code for the "How Relevanssi sees this post".
|
1440 |
*/
|
1441 |
+
function relevanssi_generate_how_relevanssi_sees( $post_id, $display = true, $type = 'post' ) {
|
1442 |
$style = '';
|
1443 |
if ( ! $display ) {
|
1444 |
$style = 'style="display: none"';
|
1446 |
|
1447 |
$element = '<div id="relevanssi_sees_container" ' . $style . '>';
|
1448 |
|
1449 |
+
$data = relevanssi_fetch_sees_data( $post_id, $type );
|
1450 |
|
1451 |
if ( empty( $data['terms_list'] ) && empty( $data['reason'] ) ) {
|
1452 |
$element .= '<p>'
|
1453 |
// Translators: %d is the post ID.
|
1454 |
+
. sprintf( __( 'Nothing found for ID %d.', 'relevanssi' ), $post_id )
|
1455 |
. '</p>';
|
1456 |
$element .= '</div>';
|
1457 |
return $element;
|
1462 |
$element .= '<p>' . esc_html( $data['reason'] ) . '</p>';
|
1463 |
}
|
1464 |
if ( ! empty( $data['title'] ) ) {
|
1465 |
+
$element .= '<h3>' . esc_html__( 'The title', 'relevanssi' ) . '</h3>';
|
1466 |
$element .= '<p>' . esc_html( $data['title'] ) . '</p>';
|
1467 |
}
|
1468 |
if ( ! empty( $data['content'] ) ) {
|
1469 |
+
$element .= '<h3>' . esc_html__( 'The content', 'relevanssi' ) . '</h3>';
|
1470 |
$element .= '<p>' . esc_html( $data['content'] ) . '</p>';
|
1471 |
}
|
1472 |
if ( ! empty( $data['comment'] ) ) {
|
1512 |
/**
|
1513 |
* Fetches the Relevanssi indexing data for a post.
|
1514 |
*
|
1515 |
+
* @param int $post_id The post ID.
|
1516 |
+
* @param string $type One of 'post', 'term', or 'user'. Default 'post'.
|
1517 |
*
|
1518 |
* @global array $relevanssi_variables The Relevanssi global variables array,
|
1519 |
* used for the database table name.
|
1522 |
* @return array The indexed terms for various parts of the post in an
|
1523 |
* associative array.
|
1524 |
*/
|
1525 |
+
function relevanssi_fetch_sees_data( $post_id, $type = 'post' ) {
|
1526 |
global $wpdb, $relevanssi_variables;
|
1527 |
|
1528 |
+
if ( 'post' === $type ) {
|
1529 |
+
$query = $wpdb->prepare(
|
1530 |
'SELECT * FROM ' . $relevanssi_variables['relevanssi_table'] . ' WHERE doc = %d', // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared,WordPress.DB.PreparedSQL.NotPrepared
|
1531 |
$post_id
|
1532 |
+
);
|
1533 |
+
}
|
1534 |
+
if ( 'term' === $type ) {
|
1535 |
+
$query = $wpdb->prepare(
|
1536 |
+
'SELECT * FROM ' . $relevanssi_variables['relevanssi_table'] . ' WHERE type NOT IN ("post", "user") AND item = %d', // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared,WordPress.DB.PreparedSQL.NotPrepared
|
1537 |
+
$post_id
|
1538 |
+
);
|
1539 |
+
}
|
1540 |
+
if ( 'user' === $type ) {
|
1541 |
+
$query = $wpdb->prepare(
|
1542 |
+
'SELECT * FROM ' . $relevanssi_variables['relevanssi_table'] . ' WHERE type = "user" AND item = %d', // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared,WordPress.DB.PreparedSQL.NotPrepared
|
1543 |
+
$post_id
|
1544 |
+
);
|
1545 |
+
}
|
1546 |
+
|
1547 |
+
$terms_list = $wpdb->get_results( $query, OBJECT ); // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared,WordPress.DB.PreparedSQL.NotPrepared
|
1548 |
|
1549 |
$terms['content'] = array();
|
1550 |
$terms['title'] = array();
|
lib/compatibility/acf.php
CHANGED
@@ -93,7 +93,7 @@ function relevanssi_index_acf( &$insert_data, $post_id, $field_name, $field_valu
|
|
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'] ) ) {
|
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, 'indexing' ), 'custom_field' );
|
97 |
foreach ( $value_tokens as $token => $count ) {
|
98 |
$n++;
|
99 |
if ( ! isset( $insert_data[ $token ]['customfield'] ) ) {
|
lib/compatibility/bricks.php
CHANGED
@@ -13,7 +13,7 @@
|
|
13 |
add_filter( 'bricks/posts/query_vars', 'relevanssi_bricks_enable', 10 );
|
14 |
|
15 |
/**
|
16 |
-
*
|
17 |
*
|
18 |
* @param array $query_vars The query variables.
|
19 |
*
|
13 |
add_filter( 'bricks/posts/query_vars', 'relevanssi_bricks_enable', 10 );
|
14 |
|
15 |
/**
|
16 |
+
* Enables Relevanssi in the query when the 's' query var is set.
|
17 |
*
|
18 |
* @param array $query_vars The query variables.
|
19 |
*
|
lib/compatibility/gutenberg.php
CHANGED
@@ -37,7 +37,7 @@ function relevanssi_register_gutenberg_actions() {
|
|
37 |
);
|
38 |
}
|
39 |
|
40 |
-
add_filter( 'relevanssi_post_content', 'relevanssi_gutenberg_block_rendering', 10 );
|
41 |
|
42 |
/**
|
43 |
* Renders Gutenberg blocks.
|
@@ -49,11 +49,24 @@ add_filter( 'relevanssi_post_content', 'relevanssi_gutenberg_block_rendering', 1
|
|
49 |
*
|
50 |
* @see do_blocks()
|
51 |
*
|
52 |
-
* @param string $content
|
|
|
53 |
*
|
54 |
* @return string The post content with the rendered content added.
|
55 |
*/
|
56 |
-
function relevanssi_gutenberg_block_rendering( $content ) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
57 |
$blocks = parse_blocks( $content );
|
58 |
$output = '';
|
59 |
|
37 |
);
|
38 |
}
|
39 |
|
40 |
+
add_filter( 'relevanssi_post_content', 'relevanssi_gutenberg_block_rendering', 10, 2 );
|
41 |
|
42 |
/**
|
43 |
* Renders Gutenberg blocks.
|
49 |
*
|
50 |
* @see do_blocks()
|
51 |
*
|
52 |
+
* @param string $content The post content.
|
53 |
+
* @param object $post_object The post object.
|
54 |
*
|
55 |
* @return string The post content with the rendered content added.
|
56 |
*/
|
57 |
+
function relevanssi_gutenberg_block_rendering( $content, $post_object ) {
|
58 |
+
/**
|
59 |
+
* Filters whether the blocks are rendered or not.
|
60 |
+
*
|
61 |
+
* If this filter returns false, the blocks in this post are not rendered,
|
62 |
+
* and the post content is returned as such.
|
63 |
+
*
|
64 |
+
* @param boolean If true, render the blocks. Default true.
|
65 |
+
* @param object The post object.
|
66 |
+
*/
|
67 |
+
if ( ! apply_filters( 'relevanssi_render_blocks', true, $post_object ) ) {
|
68 |
+
return $content;
|
69 |
+
}
|
70 |
$blocks = parse_blocks( $content );
|
71 |
$output = '';
|
72 |
|
lib/compatibility/polylang.php
CHANGED
@@ -148,13 +148,13 @@ function relevanssi_polylang_term_filter( $hits ) {
|
|
148 |
$original_hit = $hit;
|
149 |
$hit = get_post( $hit );
|
150 |
}
|
151 |
-
if ( ! isset( $hit->post_content ) ) {
|
152 |
// The "fields" is set to "id=>parent".
|
153 |
$original_hit = $hit;
|
154 |
$hit = get_post( $hit->ID );
|
155 |
}
|
156 |
|
157 |
-
if ( -1 === $hit->ID && isset( $hit->term_id ) ) {
|
158 |
$term_id = intval( $hit->term_id );
|
159 |
$translations = pll_get_term_translations( $term_id );
|
160 |
if (
|
148 |
$original_hit = $hit;
|
149 |
$hit = get_post( $hit );
|
150 |
}
|
151 |
+
if ( ! isset( $hit->post_content ) && isset( $hit->ID ) ) {
|
152 |
// The "fields" is set to "id=>parent".
|
153 |
$original_hit = $hit;
|
154 |
$hit = get_post( $hit->ID );
|
155 |
}
|
156 |
|
157 |
+
if ( isset( $hit->ID ) && -1 === $hit->ID && isset( $hit->term_id ) ) {
|
158 |
$term_id = intval( $hit->term_id );
|
159 |
$translations = pll_get_term_translations( $term_id );
|
160 |
if (
|
lib/compatibility/woocommerce.php
CHANGED
@@ -11,6 +11,7 @@
|
|
11 |
*/
|
12 |
|
13 |
add_filter( 'relevanssi_indexing_restriction', 'relevanssi_woocommerce_restriction' );
|
|
|
14 |
|
15 |
/**
|
16 |
* This action solves the problems introduced by adjust_posts_count() in
|
@@ -129,3 +130,25 @@ function relevanssi_sku_boost( $match ) {
|
|
129 |
}
|
130 |
return $match;
|
131 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
11 |
*/
|
12 |
|
13 |
add_filter( 'relevanssi_indexing_restriction', 'relevanssi_woocommerce_restriction' );
|
14 |
+
add_filter( 'relevanssi_admin_search_blocked_post_types', 'relevanssi_woocommerce_admin_search_blocked_post_types' );
|
15 |
|
16 |
/**
|
17 |
* This action solves the problems introduced by adjust_posts_count() in
|
130 |
}
|
131 |
return $match;
|
132 |
}
|
133 |
+
|
134 |
+
/**
|
135 |
+
* Adds blocked WooCommerce post types to the list of blocked post types.
|
136 |
+
*
|
137 |
+
* Stops Relevanssi from taking over the admin search for the WooCommerce
|
138 |
+
* blocked post types using the relevanssi_admin_search_blocked_post_types
|
139 |
+
* filter hook.
|
140 |
+
*
|
141 |
+
* @param array $post_types The list of blocked post types.
|
142 |
+
* @return array
|
143 |
+
*/
|
144 |
+
function relevanssi_woocommerce_admin_search_blocked_post_types( array $post_types ) : array {
|
145 |
+
$woo_post_types = array(
|
146 |
+
'shop_coupon',
|
147 |
+
'shop_order',
|
148 |
+
'shop_order_refund',
|
149 |
+
'wc_order_status',
|
150 |
+
'wc_order_email',
|
151 |
+
'shop_webhook',
|
152 |
+
);
|
153 |
+
return array_merge( $post_types, $woo_post_types );
|
154 |
+
}
|
lib/compatibility/wp-members.php
CHANGED
@@ -19,12 +19,12 @@ add_filter( 'relevanssi_post_ok', 'relevanssi_wpmembers_compatibility', 10, 2 );
|
|
19 |
* the post is blocked by the _wpmem_block custom field, or if the post type is
|
20 |
* blocked in the $wpmem global.
|
21 |
*
|
22 |
-
* @param bool
|
23 |
-
* @param int
|
24 |
*
|
25 |
* @return bool
|
26 |
*/
|
27 |
-
function relevanssi_wpmembers_compatibility( bool $post_ok,
|
28 |
global $wpmem;
|
29 |
|
30 |
if ( is_user_logged_in() ) {
|
@@ -32,7 +32,9 @@ function relevanssi_wpmembers_compatibility( bool $post_ok, int $post_id ) : boo
|
|
32 |
}
|
33 |
|
34 |
$post_meta = get_post_meta( $post_id, '_wpmem_block', true );
|
35 |
-
$post_type = $wpmem->block[ relevanssi_get_post_type( $post_id ) ]
|
|
|
|
|
36 |
|
37 |
if ( '1' === $post_meta ) {
|
38 |
$post_ok = false;
|
19 |
* the post is blocked by the _wpmem_block custom field, or if the post type is
|
20 |
* blocked in the $wpmem global.
|
21 |
*
|
22 |
+
* @param bool $post_ok Whether the user is allowed to see the post.
|
23 |
+
* @param int|string $post_id The post ID.
|
24 |
*
|
25 |
* @return bool
|
26 |
*/
|
27 |
+
function relevanssi_wpmembers_compatibility( bool $post_ok, $post_id ) : bool {
|
28 |
global $wpmem;
|
29 |
|
30 |
if ( is_user_logged_in() ) {
|
32 |
}
|
33 |
|
34 |
$post_meta = get_post_meta( $post_id, '_wpmem_block', true );
|
35 |
+
$post_type = isset( $wpmem->block[ relevanssi_get_post_type( $post_id ) ] )
|
36 |
+
? $wpmem->block[ relevanssi_get_post_type( $post_id ) ]
|
37 |
+
: 0;
|
38 |
|
39 |
if ( '1' === $post_meta ) {
|
40 |
$post_ok = false;
|
lib/didyoumean.php
CHANGED
@@ -156,7 +156,7 @@ function relevanssi_simple_generate_suggestion( $query ) {
|
|
156 |
}
|
157 |
|
158 |
$query = htmlspecialchars_decode( $query, ENT_QUOTES );
|
159 |
-
$tokens = relevanssi_tokenize( $query );
|
160 |
$suggestions_made = false;
|
161 |
$suggestion = '';
|
162 |
|
156 |
}
|
157 |
|
158 |
$query = htmlspecialchars_decode( $query, ENT_QUOTES );
|
159 |
+
$tokens = relevanssi_tokenize( $query, true, -1, 'search_query' );
|
160 |
$suggestions_made = false;
|
161 |
$suggestion = '';
|
162 |
|
lib/excerpts-highlights.php
CHANGED
@@ -69,7 +69,7 @@ function relevanssi_do_excerpt( $t_post, $query, $excerpt_length = null, $excerp
|
|
69 |
$min_word_length = 1;
|
70 |
}
|
71 |
|
72 |
-
$terms = relevanssi_tokenize( $query, $remove_stopwords, $min_word_length );
|
73 |
|
74 |
if ( is_array( $query ) ) {
|
75 |
$untokenized_terms = array_filter( $query );
|
@@ -379,7 +379,7 @@ function relevanssi_create_excerpts( $content, $terms, $query, $excerpt_length =
|
|
379 |
$remove_stopwords = false;
|
380 |
$non_phrase_terms = array();
|
381 |
foreach ( $phrases as $phrase ) {
|
382 |
-
$phrase_terms = array_keys( relevanssi_tokenize( $phrase, $remove_stopwords ) );
|
383 |
foreach ( array_keys( $terms ) as $term ) { // array_keys(), because tokenized terms have the term as key.
|
384 |
if ( ! in_array( $term, $phrase_terms, true ) ) {
|
385 |
$non_phrase_terms[ $term ] = true;
|
@@ -567,7 +567,8 @@ function relevanssi_highlight_terms( $content, $query, $convert_entities = false
|
|
567 |
relevanssi_tokenize(
|
568 |
$query,
|
569 |
$remove_stopwords,
|
570 |
-
$min_word_length
|
|
|
571 |
)
|
572 |
);
|
573 |
|
@@ -603,7 +604,7 @@ function relevanssi_highlight_terms( $content, $query, $convert_entities = false
|
|
603 |
$remove_stopwords = false;
|
604 |
$non_phrase_terms = array();
|
605 |
foreach ( $phrases as $phrase ) {
|
606 |
-
$phrase_terms = array_keys( relevanssi_tokenize( $phrase, $remove_stopwords ) );
|
607 |
foreach ( $terms as $term ) {
|
608 |
if ( ! in_array( $term, $phrase_terms, true ) ) {
|
609 |
$non_phrase_terms[] = $term;
|
@@ -617,7 +618,9 @@ function relevanssi_highlight_terms( $content, $query, $convert_entities = false
|
|
617 |
|
618 |
$content = strtr( $content, array( "\xC2\xAD" => '' ) );
|
619 |
$content = html_entity_decode( $content, ENT_QUOTES, 'UTF-8' );
|
620 |
-
|
|
|
|
|
621 |
|
622 |
foreach ( $terms as $term ) {
|
623 |
$pr_term = preg_quote( $term, '/' );
|
@@ -693,7 +696,14 @@ function relevanssi_highlight_terms( $content, $query, $convert_entities = false
|
|
693 |
}
|
694 |
}
|
695 |
|
696 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
697 |
// Remove highlights from inside HTML entities.
|
698 |
foreach ( $matches as $match ) {
|
699 |
$new_match = str_replace( $start_emp_token, '', $match );
|
@@ -1493,16 +1503,28 @@ function relevanssi_add_excerpt( &$post, $query ) {
|
|
1493 |
if ( isset( $post->blog_id ) ) {
|
1494 |
switch_to_blog( $post->blog_id );
|
1495 |
}
|
1496 |
-
$excerpt_length = get_option( 'relevanssi_excerpt_length' );
|
1497 |
-
$excerpt_type = get_option( 'relevanssi_excerpt_type' );
|
1498 |
$post->original_excerpt = $post->post_excerpt;
|
1499 |
-
|
1500 |
-
|
1501 |
-
|
1502 |
-
|
1503 |
-
|
1504 |
-
|
1505 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1506 |
if ( isset( $post->blog_id ) ) {
|
1507 |
restore_current_blog();
|
1508 |
}
|
69 |
$min_word_length = 1;
|
70 |
}
|
71 |
|
72 |
+
$terms = relevanssi_tokenize( $query, $remove_stopwords, $min_word_length, 'search_query' );
|
73 |
|
74 |
if ( is_array( $query ) ) {
|
75 |
$untokenized_terms = array_filter( $query );
|
379 |
$remove_stopwords = false;
|
380 |
$non_phrase_terms = array();
|
381 |
foreach ( $phrases as $phrase ) {
|
382 |
+
$phrase_terms = array_keys( relevanssi_tokenize( $phrase, $remove_stopwords, -1, 'search_query' ) );
|
383 |
foreach ( array_keys( $terms ) as $term ) { // array_keys(), because tokenized terms have the term as key.
|
384 |
if ( ! in_array( $term, $phrase_terms, true ) ) {
|
385 |
$non_phrase_terms[ $term ] = true;
|
567 |
relevanssi_tokenize(
|
568 |
$query,
|
569 |
$remove_stopwords,
|
570 |
+
$min_word_length,
|
571 |
+
'search_query'
|
572 |
)
|
573 |
);
|
574 |
|
604 |
$remove_stopwords = false;
|
605 |
$non_phrase_terms = array();
|
606 |
foreach ( $phrases as $phrase ) {
|
607 |
+
$phrase_terms = array_keys( relevanssi_tokenize( $phrase, $remove_stopwords, -1, 'search_query' ) );
|
608 |
foreach ( $terms as $term ) {
|
609 |
if ( ! in_array( $term, $phrase_terms, true ) ) {
|
610 |
$non_phrase_terms[] = $term;
|
618 |
|
619 |
$content = strtr( $content, array( "\xC2\xAD" => '' ) );
|
620 |
$content = html_entity_decode( $content, ENT_QUOTES, 'UTF-8' );
|
621 |
+
if ( ! $convert_entities ) {
|
622 |
+
$content = str_replace( "\n", ' ', $content );
|
623 |
+
}
|
624 |
|
625 |
foreach ( $terms as $term ) {
|
626 |
$pr_term = preg_quote( $term, '/' );
|
696 |
}
|
697 |
}
|
698 |
|
699 |
+
$start_quoted = preg_quote( $start_emp_token, '/' );
|
700 |
+
$end_quoted = preg_quote( $end_emp_token, '/' );
|
701 |
+
if (
|
702 |
+
preg_match_all(
|
703 |
+
'/&' . $start_quoted . '([a-z0-9]+|#[0-9]{1,6}|#x[0-9a-fA-F]{1,6})' . $end_quoted . ';/U',
|
704 |
+
$content,
|
705 |
+
$matches
|
706 |
+
) > 0 ) {
|
707 |
// Remove highlights from inside HTML entities.
|
708 |
foreach ( $matches as $match ) {
|
709 |
$new_match = str_replace( $start_emp_token, '', $match );
|
1503 |
if ( isset( $post->blog_id ) ) {
|
1504 |
switch_to_blog( $post->blog_id );
|
1505 |
}
|
|
|
|
|
1506 |
$post->original_excerpt = $post->post_excerpt;
|
1507 |
+
/**
|
1508 |
+
* Filters whether an excerpt should be added to a post or not.
|
1509 |
+
*
|
1510 |
+
* If this filter hook returns false, Relevanssi does not create an excerpt
|
1511 |
+
* for the post. The original excerpt is still copied to
|
1512 |
+
* $post->original_excerpt.
|
1513 |
+
*
|
1514 |
+
* @param boolean If true, create an excerpt. Default true.
|
1515 |
+
* @param WP_Post $post The post object.
|
1516 |
+
* @param string $query The search quer.
|
1517 |
+
*/
|
1518 |
+
if ( apply_filters( 'relevanssi_excerpt_post', true, $post, $query ) ) {
|
1519 |
+
$excerpt_length = get_option( 'relevanssi_excerpt_length' );
|
1520 |
+
$excerpt_type = get_option( 'relevanssi_excerpt_type' );
|
1521 |
+
$post->post_excerpt = relevanssi_do_excerpt(
|
1522 |
+
$post,
|
1523 |
+
$query,
|
1524 |
+
$excerpt_length,
|
1525 |
+
$excerpt_type
|
1526 |
+
);
|
1527 |
+
}
|
1528 |
if ( isset( $post->blog_id ) ) {
|
1529 |
restore_current_blog();
|
1530 |
}
|
lib/indexing.php
CHANGED
@@ -654,7 +654,7 @@ function relevanssi_index_taxonomy_terms( &$insert_data, $post_id, $taxonomy, $d
|
|
654 |
/** This filter is documented in lib/indexing.php */
|
655 |
$term_tokens = apply_filters(
|
656 |
'relevanssi_indexing_tokens',
|
657 |
-
relevanssi_tokenize( $term_string, true, $min_word_length ),
|
658 |
'taxonomy-' . $taxonomy
|
659 |
);
|
660 |
|
@@ -1160,7 +1160,7 @@ function relevanssi_index_comments( &$insert_data, $post_id, $min_word_length, $
|
|
1160 |
*/
|
1161 |
$post_comments_tokens = apply_filters(
|
1162 |
'relevanssi_indexing_tokens',
|
1163 |
-
relevanssi_tokenize( $post_comments, true, $min_word_length ),
|
1164 |
'comments'
|
1165 |
);
|
1166 |
if ( count( $post_comments_tokens ) > 0 ) {
|
@@ -1199,7 +1199,7 @@ function relevanssi_index_author( &$insert_data, $post_author, $min_word_length,
|
|
1199 |
/** This filter is documented in lib/indexing.php */
|
1200 |
$name_tokens = apply_filters(
|
1201 |
'relevanssi_indexing_tokens',
|
1202 |
-
relevanssi_tokenize( $display_name, false, $min_word_length ),
|
1203 |
'author'
|
1204 |
);
|
1205 |
if ( $debug ) {
|
@@ -1294,7 +1294,7 @@ function relevanssi_index_custom_fields( &$insert_data, $post_id, $custom_fields
|
|
1294 |
/** This filter is documented in lib/indexing.php */
|
1295 |
$value_tokens = apply_filters(
|
1296 |
'relevanssi_indexing_tokens',
|
1297 |
-
relevanssi_tokenize( $value, $remove_stops, $min_word_length ),
|
1298 |
$context
|
1299 |
);
|
1300 |
|
@@ -1341,7 +1341,7 @@ function relevanssi_index_excerpt( &$insert_data, $excerpt, $min_word_length, $d
|
|
1341 |
/** This filter is documented in common/indexing.php */
|
1342 |
$excerpt_tokens = apply_filters(
|
1343 |
'relevanssi_indexing_tokens',
|
1344 |
-
relevanssi_tokenize( $excerpt, true, $min_word_length ),
|
1345 |
'excerpt'
|
1346 |
);
|
1347 |
foreach ( $excerpt_tokens as $token => $count ) {
|
@@ -1400,7 +1400,8 @@ function relevanssi_index_title( &$insert_data, $post, $min_word_length, $debug
|
|
1400 |
* @param boolean If true, remove stopwords. Default true.
|
1401 |
*/
|
1402 |
apply_filters( 'relevanssi_remove_stopwords_in_titles', true ),
|
1403 |
-
$min_word_length
|
|
|
1404 |
);
|
1405 |
/** This filter is documented in lib/indexing.php */
|
1406 |
$title_tokens = apply_filters( 'relevanssi_indexing_tokens', $title_tokens, 'title' );
|
@@ -1510,12 +1511,14 @@ function relevanssi_index_content( &$insert_data, $post_object, $min_word_length
|
|
1510 |
* @param object $post_object The full post object.
|
1511 |
*/
|
1512 |
$contents = apply_filters( 'relevanssi_post_content_before_tokenize', $contents, $post_object );
|
|
|
1513 |
/** This filter is documented in lib/indexing.php */
|
1514 |
$content_tokens = apply_filters(
|
1515 |
'relevanssi_indexing_tokens',
|
1516 |
-
relevanssi_tokenize( $contents, 'body', $min_word_length ),
|
1517 |
'content'
|
1518 |
);
|
|
|
1519 |
if ( $debug ) {
|
1520 |
relevanssi_debug_echo( "\tContent, tokenized:\n" . implode( ' ', array_keys( $content_tokens ) ) );
|
1521 |
}
|
654 |
/** This filter is documented in lib/indexing.php */
|
655 |
$term_tokens = apply_filters(
|
656 |
'relevanssi_indexing_tokens',
|
657 |
+
relevanssi_tokenize( $term_string, true, $min_word_length, 'indexing' ),
|
658 |
'taxonomy-' . $taxonomy
|
659 |
);
|
660 |
|
1160 |
*/
|
1161 |
$post_comments_tokens = apply_filters(
|
1162 |
'relevanssi_indexing_tokens',
|
1163 |
+
relevanssi_tokenize( $post_comments, true, $min_word_length, 'indexing' ),
|
1164 |
'comments'
|
1165 |
);
|
1166 |
if ( count( $post_comments_tokens ) > 0 ) {
|
1199 |
/** This filter is documented in lib/indexing.php */
|
1200 |
$name_tokens = apply_filters(
|
1201 |
'relevanssi_indexing_tokens',
|
1202 |
+
relevanssi_tokenize( $display_name, false, $min_word_length, 'indexing' ),
|
1203 |
'author'
|
1204 |
);
|
1205 |
if ( $debug ) {
|
1294 |
/** This filter is documented in lib/indexing.php */
|
1295 |
$value_tokens = apply_filters(
|
1296 |
'relevanssi_indexing_tokens',
|
1297 |
+
relevanssi_tokenize( $value, $remove_stops, $min_word_length, 'indexing' ),
|
1298 |
$context
|
1299 |
);
|
1300 |
|
1341 |
/** This filter is documented in common/indexing.php */
|
1342 |
$excerpt_tokens = apply_filters(
|
1343 |
'relevanssi_indexing_tokens',
|
1344 |
+
relevanssi_tokenize( $excerpt, true, $min_word_length, 'indexing' ),
|
1345 |
'excerpt'
|
1346 |
);
|
1347 |
foreach ( $excerpt_tokens as $token => $count ) {
|
1400 |
* @param boolean If true, remove stopwords. Default true.
|
1401 |
*/
|
1402 |
apply_filters( 'relevanssi_remove_stopwords_in_titles', true ),
|
1403 |
+
$min_word_length,
|
1404 |
+
'indexing'
|
1405 |
);
|
1406 |
/** This filter is documented in lib/indexing.php */
|
1407 |
$title_tokens = apply_filters( 'relevanssi_indexing_tokens', $title_tokens, 'title' );
|
1511 |
* @param object $post_object The full post object.
|
1512 |
*/
|
1513 |
$contents = apply_filters( 'relevanssi_post_content_before_tokenize', $contents, $post_object );
|
1514 |
+
|
1515 |
/** This filter is documented in lib/indexing.php */
|
1516 |
$content_tokens = apply_filters(
|
1517 |
'relevanssi_indexing_tokens',
|
1518 |
+
relevanssi_tokenize( $contents, 'body', $min_word_length, 'indexing' ),
|
1519 |
'content'
|
1520 |
);
|
1521 |
+
|
1522 |
if ( $debug ) {
|
1523 |
relevanssi_debug_echo( "\tContent, tokenized:\n" . implode( ' ', array_keys( $content_tokens ) ) );
|
1524 |
}
|
lib/init.php
CHANGED
@@ -179,6 +179,8 @@ function relevanssi_admin_init() {
|
|
179 |
|
180 |
add_action( 'admin_enqueue_scripts', 'relevanssi_add_admin_scripts' );
|
181 |
add_filter( 'plugin_action_links_' . $relevanssi_variables['plugin_basename'], 'relevanssi_action_links' );
|
|
|
|
|
182 |
}
|
183 |
|
184 |
/**
|
@@ -269,7 +271,11 @@ function relevanssi_query_vars( $qv ) {
|
|
269 |
function relevanssi_create_database_tables( $relevanssi_db_version ) {
|
270 |
global $wpdb;
|
271 |
|
272 |
-
|
|
|
|
|
|
|
|
|
273 |
|
274 |
$charset_collate_bin_column = '';
|
275 |
$charset_collate = '';
|
@@ -290,125 +296,135 @@ function relevanssi_create_database_tables( $relevanssi_db_version ) {
|
|
290 |
$relevanssi_table = $wpdb->prefix . 'relevanssi';
|
291 |
$relevanssi_stopword_table = $wpdb->prefix . 'relevanssi_stopwords';
|
292 |
$relevanssi_log_table = $wpdb->prefix . 'relevanssi_log';
|
293 |
-
$current_db_version = get_option( 'relevanssi_db_version' );
|
294 |
-
|
295 |
-
if ( $current_db_version !== $relevanssi_db_version ) {
|
296 |
-
$sql = 'CREATE TABLE ' . $relevanssi_table . " (doc bigint(20) NOT NULL DEFAULT '0',
|
297 |
-
term varchar(50) NOT NULL DEFAULT '0',
|
298 |
-
term_reverse varchar(50) NOT NULL DEFAULT '0',
|
299 |
-
content mediumint(9) NOT NULL DEFAULT '0',
|
300 |
-
title mediumint(9) NOT NULL DEFAULT '0',
|
301 |
-
comment mediumint(9) NOT NULL DEFAULT '0',
|
302 |
-
tag mediumint(9) NOT NULL DEFAULT '0',
|
303 |
-
link mediumint(9) NOT NULL DEFAULT '0',
|
304 |
-
author mediumint(9) NOT NULL DEFAULT '0',
|
305 |
-
category mediumint(9) NOT NULL DEFAULT '0',
|
306 |
-
excerpt mediumint(9) NOT NULL DEFAULT '0',
|
307 |
-
taxonomy mediumint(9) NOT NULL DEFAULT '0',
|
308 |
-
customfield mediumint(9) NOT NULL DEFAULT '0',
|
309 |
-
mysqlcolumn mediumint(9) NOT NULL DEFAULT '0',
|
310 |
-
taxonomy_detail longtext NOT NULL,
|
311 |
-
customfield_detail longtext NOT NULL DEFAULT '',
|
312 |
-
mysqlcolumn_detail longtext NOT NULL DEFAULT '',
|
313 |
-
type varchar(210) NOT NULL DEFAULT 'post',
|
314 |
-
item bigint(20) NOT NULL DEFAULT '0',
|
315 |
-
PRIMARY KEY doctermitem (doc, term, item)) $charset_collate";
|
316 |
-
|
317 |
-
dbDelta( $sql );
|
318 |
-
|
319 |
-
$sql = "SHOW INDEX FROM $relevanssi_table";
|
320 |
-
$indices = $wpdb->get_results( $sql ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.DirectDatabaseQuery
|
321 |
-
|
322 |
-
$terms_exists = false;
|
323 |
-
$relevanssi_term_reverse_idx_exists = false;
|
324 |
-
$docs_exists = false;
|
325 |
-
$typeitem_exists = false;
|
326 |
-
$doctermitem_exists = false;
|
327 |
-
foreach ( $indices as $index ) {
|
328 |
-
if ( 'terms' === $index->Key_name ) { // phpcs:ignore WordPress.NamingConventions.ValidVariableName
|
329 |
-
$terms_exists = true;
|
330 |
-
}
|
331 |
-
if ( 'relevanssi_term_reverse_idx' === $index->Key_name ) { // phpcs:ignore WordPress.NamingConventions.ValidVariableName
|
332 |
-
$relevanssi_term_reverse_idx_exists = true;
|
333 |
-
}
|
334 |
-
if ( 'docs' === $index->Key_name ) { // phpcs:ignore WordPress.NamingConventions.ValidVariableName
|
335 |
-
$docs_exists = true;
|
336 |
-
}
|
337 |
-
if ( 'typeitem' === $index->Key_name ) { // phpcs:ignore WordPress.NamingConventions.ValidVariableName
|
338 |
-
$typeitem_exists = true;
|
339 |
-
}
|
340 |
-
if ( 'doctermitem' === $index->Key_name ) { // phpcs:ignore WordPress.NamingConventions.ValidVariableName
|
341 |
-
$doctermitem_exists = true;
|
342 |
-
}
|
343 |
-
}
|
344 |
|
345 |
-
|
346 |
-
$sql = "CREATE INDEX terms ON $relevanssi_table (term(20))";
|
347 |
-
$wpdb->query( $sql ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.DirectDatabaseQuery
|
348 |
-
}
|
349 |
|
350 |
-
|
351 |
-
|
352 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
353 |
}
|
354 |
-
|
355 |
-
|
356 |
-
$sql = "CREATE INDEX typeitem ON $relevanssi_table (type(190), item)";
|
357 |
-
$wpdb->query( $sql ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.DirectDatabaseQuery
|
358 |
}
|
359 |
-
|
360 |
-
|
361 |
-
$sql = "DROP INDEX doctermitem ON $relevanssi_table";
|
362 |
-
$wpdb->query( $sql ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.DirectDatabaseQuery
|
363 |
}
|
364 |
-
|
365 |
-
|
366 |
-
$sql = "DROP INDEX docs ON $relevanssi_table";
|
367 |
-
$wpdb->query( $sql ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.DirectDatabaseQuery
|
368 |
}
|
|
|
|
|
|
|
|
|
369 |
|
370 |
-
|
371 |
-
|
|
|
|
|
372 |
|
373 |
-
|
|
|
|
|
|
|
374 |
|
375 |
-
|
376 |
-
|
377 |
-
|
378 |
-
|
379 |
-
user_id bigint(20) NOT NULL DEFAULT '0',
|
380 |
-
ip varchar(40) NOT NULL DEFAULT '',
|
381 |
-
PRIMARY KEY id (id)) $charset_collate;";
|
382 |
|
383 |
-
|
|
|
|
|
|
|
384 |
|
385 |
-
|
386 |
-
$
|
|
|
|
|
387 |
|
388 |
-
|
389 |
-
|
390 |
-
foreach ( $indices as $index ) {
|
391 |
-
if ( 'query' === $index->Key_name ) { // phpcs:ignore WordPress.NamingConventions.ValidVariableName
|
392 |
-
$query_exists = true;
|
393 |
-
}
|
394 |
-
if ( 'id' === $index->Key_name ) { // phpcs:ignore WordPress.NamingConventions.ValidVariableName
|
395 |
-
$id_exists = true;
|
396 |
-
}
|
397 |
-
}
|
398 |
|
399 |
-
|
400 |
-
$sql = "CREATE INDEX query ON $relevanssi_log_table (query(190))";
|
401 |
-
$wpdb->query( $sql ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.DirectDatabaseQuery.NoCaching
|
402 |
-
}
|
403 |
|
404 |
-
|
405 |
-
|
406 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
407 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
408 |
|
409 |
-
|
|
|
|
|
410 |
}
|
411 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
412 |
$stopwords = relevanssi_fetch_stopwords();
|
413 |
if ( empty( $stopwords ) ) {
|
414 |
relevanssi_populate_stopwords();
|
179 |
|
180 |
add_action( 'admin_enqueue_scripts', 'relevanssi_add_admin_scripts' );
|
181 |
add_filter( 'plugin_action_links_' . $relevanssi_variables['plugin_basename'], 'relevanssi_action_links' );
|
182 |
+
|
183 |
+
relevanssi_create_database_tables( $relevanssi_variables['database_version'] );
|
184 |
}
|
185 |
|
186 |
/**
|
271 |
function relevanssi_create_database_tables( $relevanssi_db_version ) {
|
272 |
global $wpdb;
|
273 |
|
274 |
+
$current_db_version = get_option( 'relevanssi_db_version' );
|
275 |
+
|
276 |
+
if ( $current_db_version === $relevanssi_db_version ) {
|
277 |
+
return;
|
278 |
+
}
|
279 |
|
280 |
$charset_collate_bin_column = '';
|
281 |
$charset_collate = '';
|
296 |
$relevanssi_table = $wpdb->prefix . 'relevanssi';
|
297 |
$relevanssi_stopword_table = $wpdb->prefix . 'relevanssi_stopwords';
|
298 |
$relevanssi_log_table = $wpdb->prefix . 'relevanssi_log';
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
299 |
|
300 |
+
require_once ABSPATH . 'wp-admin/includes/upgrade.php';
|
|
|
|
|
|
|
301 |
|
302 |
+
$sql = 'CREATE TABLE ' . $relevanssi_table . " (doc bigint(20) NOT NULL DEFAULT '0',
|
303 |
+
term varchar(50) NOT NULL DEFAULT '0',
|
304 |
+
term_reverse varchar(50) NOT NULL DEFAULT '0',
|
305 |
+
content mediumint(9) NOT NULL DEFAULT '0',
|
306 |
+
title mediumint(9) NOT NULL DEFAULT '0',
|
307 |
+
comment mediumint(9) NOT NULL DEFAULT '0',
|
308 |
+
tag mediumint(9) NOT NULL DEFAULT '0',
|
309 |
+
link mediumint(9) NOT NULL DEFAULT '0',
|
310 |
+
author mediumint(9) NOT NULL DEFAULT '0',
|
311 |
+
category mediumint(9) NOT NULL DEFAULT '0',
|
312 |
+
excerpt mediumint(9) NOT NULL DEFAULT '0',
|
313 |
+
taxonomy mediumint(9) NOT NULL DEFAULT '0',
|
314 |
+
customfield mediumint(9) NOT NULL DEFAULT '0',
|
315 |
+
mysqlcolumn mediumint(9) NOT NULL DEFAULT '0',
|
316 |
+
taxonomy_detail longtext NOT NULL,
|
317 |
+
customfield_detail longtext NOT NULL DEFAULT '',
|
318 |
+
mysqlcolumn_detail longtext NOT NULL DEFAULT '',
|
319 |
+
type varchar(210) NOT NULL DEFAULT 'post',
|
320 |
+
item bigint(20) NOT NULL DEFAULT '0',
|
321 |
+
PRIMARY KEY doctermitem (doc, term, item)) $charset_collate";
|
322 |
+
|
323 |
+
dbDelta( $sql );
|
324 |
+
|
325 |
+
$sql = "SHOW INDEX FROM $relevanssi_table";
|
326 |
+
$indices = $wpdb->get_results( $sql ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.DirectDatabaseQuery
|
327 |
+
|
328 |
+
$terms_exists = false;
|
329 |
+
$relevanssi_term_reverse_idx_exists = false;
|
330 |
+
$docs_exists = false;
|
331 |
+
$typeitem_exists = false;
|
332 |
+
$doctermitem_exists = false;
|
333 |
+
foreach ( $indices as $index ) {
|
334 |
+
if ( 'terms' === $index->Key_name ) { // phpcs:ignore WordPress.NamingConventions.ValidVariableName
|
335 |
+
$terms_exists = true;
|
336 |
}
|
337 |
+
if ( 'relevanssi_term_reverse_idx' === $index->Key_name ) { // phpcs:ignore WordPress.NamingConventions.ValidVariableName
|
338 |
+
$relevanssi_term_reverse_idx_exists = true;
|
|
|
|
|
339 |
}
|
340 |
+
if ( 'docs' === $index->Key_name ) { // phpcs:ignore WordPress.NamingConventions.ValidVariableName
|
341 |
+
$docs_exists = true;
|
|
|
|
|
342 |
}
|
343 |
+
if ( 'typeitem' === $index->Key_name ) { // phpcs:ignore WordPress.NamingConventions.ValidVariableName
|
344 |
+
$typeitem_exists = true;
|
|
|
|
|
345 |
}
|
346 |
+
if ( 'doctermitem' === $index->Key_name ) { // phpcs:ignore WordPress.NamingConventions.ValidVariableName
|
347 |
+
$doctermitem_exists = true;
|
348 |
+
}
|
349 |
+
}
|
350 |
|
351 |
+
if ( ! $terms_exists ) {
|
352 |
+
$sql = "CREATE INDEX terms ON $relevanssi_table (term(20))";
|
353 |
+
$wpdb->query( $sql ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.DirectDatabaseQuery
|
354 |
+
}
|
355 |
|
356 |
+
if ( ! $relevanssi_term_reverse_idx_exists ) {
|
357 |
+
$sql = "CREATE INDEX relevanssi_term_reverse_idx ON $relevanssi_table (term_reverse(10))";
|
358 |
+
$wpdb->query( $sql ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.DirectDatabaseQuery
|
359 |
+
}
|
360 |
|
361 |
+
if ( ! $typeitem_exists ) {
|
362 |
+
$sql = "CREATE INDEX typeitem ON $relevanssi_table (type(190), item)";
|
363 |
+
$wpdb->query( $sql ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.DirectDatabaseQuery
|
364 |
+
}
|
|
|
|
|
|
|
365 |
|
366 |
+
if ( $doctermitem_exists ) {
|
367 |
+
$sql = "DROP INDEX doctermitem ON $relevanssi_table";
|
368 |
+
$wpdb->query( $sql ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.DirectDatabaseQuery
|
369 |
+
}
|
370 |
|
371 |
+
if ( $docs_exists ) { // This index was removed in 4.9.2 / 2.11.2.
|
372 |
+
$sql = "DROP INDEX docs ON $relevanssi_table";
|
373 |
+
$wpdb->query( $sql ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.DirectDatabaseQuery
|
374 |
+
}
|
375 |
|
376 |
+
$sql = 'CREATE TABLE ' . $relevanssi_stopword_table . " (stopword varchar(50) $charset_collate_bin_column NOT NULL,
|
377 |
+
PRIMARY KEY stopword (stopword)) $charset_collate;";
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
378 |
|
379 |
+
dbDelta( $sql );
|
|
|
|
|
|
|
380 |
|
381 |
+
$sql = 'CREATE TABLE ' . $relevanssi_log_table . " (id bigint(9) NOT NULL AUTO_INCREMENT,
|
382 |
+
query varchar(200) NOT NULL,
|
383 |
+
hits mediumint(9) NOT NULL DEFAULT '0',
|
384 |
+
time timestamp DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
385 |
+
user_id bigint(20) NOT NULL DEFAULT '0',
|
386 |
+
ip varchar(40) NOT NULL DEFAULT '',
|
387 |
+
PRIMARY KEY id (id)) $charset_collate;";
|
388 |
+
|
389 |
+
dbDelta( $sql );
|
390 |
+
|
391 |
+
$sql = "SHOW INDEX FROM $relevanssi_log_table";
|
392 |
+
$indices = $wpdb->get_results( $sql ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.DirectDatabaseQuery.NoCaching
|
393 |
+
|
394 |
+
$query_exists = false;
|
395 |
+
$id_exists = false;
|
396 |
+
foreach ( $indices as $index ) {
|
397 |
+
if ( 'query' === $index->Key_name ) { // phpcs:ignore WordPress.NamingConventions.ValidVariableName
|
398 |
+
$query_exists = true;
|
399 |
+
}
|
400 |
+
if ( 'id' === $index->Key_name ) { // phpcs:ignore WordPress.NamingConventions.ValidVariableName
|
401 |
+
$id_exists = true;
|
402 |
}
|
403 |
+
}
|
404 |
+
|
405 |
+
if ( ! $query_exists ) {
|
406 |
+
$sql = "CREATE INDEX query ON $relevanssi_log_table (query(190))";
|
407 |
+
$wpdb->query( $sql ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.DirectDatabaseQuery.NoCaching
|
408 |
+
}
|
409 |
|
410 |
+
if ( $id_exists ) {
|
411 |
+
$sql = "DROP INDEX id ON $relevanssi_log_table";
|
412 |
+
$wpdb->query( $sql ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.DirectDatabaseQuery.NoCaching
|
413 |
}
|
414 |
|
415 |
+
/**
|
416 |
+
* Allows adding database tables.
|
417 |
+
*
|
418 |
+
* An action hook that runs in the create tables process if the database
|
419 |
+
* version in the options doesn't match the database version in the
|
420 |
+
* code.
|
421 |
+
*
|
422 |
+
* @param string $charset_collate The collation.
|
423 |
+
*/
|
424 |
+
do_action( 'relevanssi_create_tables', $charset_collate );
|
425 |
+
|
426 |
+
update_option( 'relevanssi_db_version', $relevanssi_db_version );
|
427 |
+
|
428 |
$stopwords = relevanssi_fetch_stopwords();
|
429 |
if ( empty( $stopwords ) ) {
|
430 |
relevanssi_populate_stopwords();
|
lib/install.php
CHANGED
@@ -91,7 +91,7 @@ function _relevanssi_install() {
|
|
91 |
add_option( 'relevanssi_expand_highlights', 'off' );
|
92 |
add_option( 'relevanssi_expand_shortcodes', 'on' );
|
93 |
add_option( 'relevanssi_extag', '0' );
|
94 |
-
add_option( 'relevanssi_fuzzy', '
|
95 |
add_option( 'relevanssi_highlight', 'strong' );
|
96 |
add_option( 'relevanssi_highlight_comments', 'off' );
|
97 |
add_option( 'relevanssi_highlight_docs', 'off' );
|
91 |
add_option( 'relevanssi_expand_highlights', 'off' );
|
92 |
add_option( 'relevanssi_expand_shortcodes', 'on' );
|
93 |
add_option( 'relevanssi_extag', '0' );
|
94 |
+
add_option( 'relevanssi_fuzzy', 'always' );
|
95 |
add_option( 'relevanssi_highlight', 'strong' );
|
96 |
add_option( 'relevanssi_highlight_comments', 'off' );
|
97 |
add_option( 'relevanssi_highlight_docs', 'off' );
|
lib/interface.php
CHANGED
@@ -99,45 +99,12 @@ function relevanssi_options() {
|
|
99 |
echo "<div style='clear:both'></div></div>";
|
100 |
}
|
101 |
|
102 |
-
/**
|
103 |
-
* Prints out the 'User searches' page.
|
104 |
-
*/
|
105 |
-
function relevanssi_search_stats() {
|
106 |
-
$relevanssi_hide_branding = get_option( 'relevanssi_hide_branding' );
|
107 |
-
|
108 |
-
if ( 'on' === $relevanssi_hide_branding ) {
|
109 |
-
$options_txt = __( 'User searches', 'relevanssi' );
|
110 |
-
} else {
|
111 |
-
$options_txt = __( 'Relevanssi User Searches', 'relevanssi' );
|
112 |
-
}
|
113 |
-
|
114 |
-
if ( isset( $_REQUEST['relevanssi_reset'] ) && current_user_can( 'manage_options' ) ) {
|
115 |
-
check_admin_referer( 'relevanssi_reset_logs', '_relresnonce' );
|
116 |
-
if ( isset( $_REQUEST['relevanssi_reset_code'] ) ) {
|
117 |
-
if ( 'reset' === $_REQUEST['relevanssi_reset_code'] ) {
|
118 |
-
$verbose = true;
|
119 |
-
relevanssi_truncate_logs( $verbose );
|
120 |
-
}
|
121 |
-
}
|
122 |
-
}
|
123 |
-
|
124 |
-
printf( "<div class='wrap'><h2>%s</h2>", esc_html( $options_txt ) );
|
125 |
-
|
126 |
-
if ( 'on' === get_option( 'relevanssi_log_queries' ) ) {
|
127 |
-
relevanssi_query_log();
|
128 |
-
} else {
|
129 |
-
printf( '<p>%s</p>', esc_html__( 'Enable query logging to see stats here.', 'relevanssi' ) );
|
130 |
-
}
|
131 |
-
}
|
132 |
-
|
133 |
/**
|
134 |
* Prints out the 'Admin search' page.
|
135 |
*/
|
136 |
function relevanssi_admin_search_page() {
|
137 |
global $relevanssi_variables;
|
138 |
|
139 |
-
$relevanssi_hide_branding = get_option( 'relevanssi_hide_branding' );
|
140 |
-
|
141 |
$options_txt = __( 'Admin Search', 'relevanssi' );
|
142 |
|
143 |
printf( "<div class='wrap'><h2>%s</h2>", esc_html( $options_txt ) );
|
@@ -172,232 +139,13 @@ function relevanssi_truncate_logs( $verbose = true ) {
|
|
172 |
return $result;
|
173 |
}
|
174 |
|
175 |
-
/**
|
176 |
-
* Shows the query log with the most common queries
|
177 |
-
*
|
178 |
-
* Uses relevanssi_total_queries() and relevanssi_date_queries() to fetch the data.
|
179 |
-
*/
|
180 |
-
function relevanssi_query_log() {
|
181 |
-
/**
|
182 |
-
* Adjusts the number of days to show the logs in User searches page.
|
183 |
-
*
|
184 |
-
* @param int Number of days, default 1.
|
185 |
-
*/
|
186 |
-
$days1 = apply_filters( 'relevanssi_1day', 1 );
|
187 |
-
|
188 |
-
/**
|
189 |
-
* Adjusts the number of days to show the logs in User searches page.
|
190 |
-
*
|
191 |
-
* @param int Number of days, default 7.
|
192 |
-
*/
|
193 |
-
$days7 = apply_filters( 'relevanssi_7days', 7 );
|
194 |
-
|
195 |
-
/**
|
196 |
-
* Adjusts the number of days to show the logs in User searches page.
|
197 |
-
*
|
198 |
-
* @param int Number of days, default 30.
|
199 |
-
*/
|
200 |
-
$days30 = apply_filters( 'relevanssi_30days', 30 );
|
201 |
-
|
202 |
-
printf( '<h3>%s</h3>', esc_html__( 'Total Searches', 'relevanssi' ) );
|
203 |
-
|
204 |
-
printf( "<div style='width: 50%%; overflow: auto'>%s</div>", relevanssi_total_queries( __( 'Totals', 'relevanssi' ) ) ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
205 |
-
|
206 |
-
echo '<div style="clear: both"></div>';
|
207 |
-
|
208 |
-
printf( '<h3>%s</h3>', esc_html__( 'Common Queries', 'relevanssi' ) );
|
209 |
-
|
210 |
-
/**
|
211 |
-
* Filters the number of rows to show.
|
212 |
-
*
|
213 |
-
* @param int Number of top results to show, default 20.
|
214 |
-
*/
|
215 |
-
$limit = apply_filters( 'relevanssi_user_searches_limit', 20 );
|
216 |
-
|
217 |
-
// Translators: %d is the number of queries to show.
|
218 |
-
printf( '<p>%s</p>', esc_html( sprintf( __( 'Here you can see the %d most common user search queries, how many times those queries were made and how many results were found for those queries.', 'relevanssi' ), $limit ) ) );
|
219 |
-
|
220 |
-
echo "<div style='width: 30%; float: left; margin-right: 2%; overflow: auto'>";
|
221 |
-
if ( 1 === $days1 ) {
|
222 |
-
relevanssi_date_queries( $days1, __( 'Today and yesterday', 'relevanssi' ) );
|
223 |
-
} else {
|
224 |
-
// Translators: number of days to show.
|
225 |
-
relevanssi_date_queries( $days1, sprintf( __( 'Last %d days', 'relevanssi' ), $days1 ) );
|
226 |
-
}
|
227 |
-
echo '</div>';
|
228 |
-
|
229 |
-
echo "<div style='width: 30%; float: left; margin-right: 2%; overflow: auto'>";
|
230 |
-
// Translators: number of days to show.
|
231 |
-
relevanssi_date_queries( $days7, sprintf( __( 'Last %d days', 'relevanssi' ), $days7 ) );
|
232 |
-
echo '</div>';
|
233 |
-
|
234 |
-
echo "<div style='width: 30%; float: left; margin-right: 2%; overflow: auto'>";
|
235 |
-
// Translators: number of days to show.
|
236 |
-
relevanssi_date_queries( $days30, sprintf( __( 'Last %d days', 'relevanssi' ), $days30 ) );
|
237 |
-
echo '</div>';
|
238 |
-
|
239 |
-
echo '<div style="clear: both"></div>';
|
240 |
-
|
241 |
-
printf( '<h3>%s</h3>', esc_html__( 'Unsuccessful Queries', 'relevanssi' ) );
|
242 |
-
|
243 |
-
echo "<div style='width: 30%; float: left; margin-right: 2%; overflow: auto'>";
|
244 |
-
relevanssi_date_queries( 1, __( 'Today and yesterday', 'relevanssi' ), 'bad' );
|
245 |
-
echo '</div>';
|
246 |
-
|
247 |
-
echo "<div style='width: 30%; float: left; margin-right: 2%; overflow: auto'>";
|
248 |
-
relevanssi_date_queries( 7, __( 'Last 7 days', 'relevanssi' ), 'bad' );
|
249 |
-
echo '</div>';
|
250 |
-
|
251 |
-
echo "<div style='width: 30%; float: left; margin-right: 2%; overflow: auto'>";
|
252 |
-
// Translators: number of days to show.
|
253 |
-
relevanssi_date_queries( $days30, sprintf( __( 'Last %d days', 'relevanssi' ), $days30 ), 'bad' );
|
254 |
-
echo '</div>';
|
255 |
-
|
256 |
-
if ( current_user_can( 'manage_options' ) ) {
|
257 |
-
|
258 |
-
echo '<div style="clear: both"></div>';
|
259 |
-
printf( '<h3>%s</h3>', esc_html__( 'Reset Logs', 'relevanssi' ) );
|
260 |
-
print( "<form method='post'>" );
|
261 |
-
wp_nonce_field( 'relevanssi_reset_logs', '_relresnonce', true, true );
|
262 |
-
printf(
|
263 |
-
'<p><label for="relevanssi_reset_code">%s</label>
|
264 |
-
<input type="text" id="relevanssi_reset_code" name="relevanssi_reset_code" />
|
265 |
-
<input type="submit" name="relevanssi_reset" value="%s" class="button" /></p></form>',
|
266 |
-
// Translators: do not translate "reset".
|
267 |
-
esc_html__(
|
268 |
-
'To reset the logs, type "reset" into the box here and click the Reset button',
|
269 |
-
'relevanssi'
|
270 |
-
),
|
271 |
-
esc_html__( 'Reset', 'relevanssi' )
|
272 |
-
);
|
273 |
-
}
|
274 |
-
|
275 |
-
echo '</div>';
|
276 |
-
}
|
277 |
-
|
278 |
-
/**
|
279 |
-
* Shows the total number of searches on 'User searches' page.
|
280 |
-
*
|
281 |
-
* @global object $wpdb The WP database interface.
|
282 |
-
* @global array $relevanssi_variables The global Relevanssi variables array.
|
283 |
-
*
|
284 |
-
* @param string $title The title that is printed out on top of the results.
|
285 |
-
*/
|
286 |
-
function relevanssi_total_queries( $title ) {
|
287 |
-
global $wpdb, $relevanssi_variables;
|
288 |
-
$log_table = $relevanssi_variables['log_table'];
|
289 |
-
|
290 |
-
$count = array();
|
291 |
-
$titles = array();
|
292 |
-
|
293 |
-
$titles[0] = __( 'Today and yesterday', 'relevanssi' );
|
294 |
-
$titles[1] = __( 'Last 7 days', 'relevanssi' );
|
295 |
-
$titles[2] = __( 'Last 30 days', 'relevanssi' );
|
296 |
-
$titles[3] = __( 'Forever', 'relevanssi' );
|
297 |
-
|
298 |
-
$count[0] = $wpdb->get_var( "SELECT COUNT(id) FROM $log_table WHERE TIMESTAMPDIFF(DAY, time, NOW()) <= 1;" ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared,WordPress.DB.PreparedSQL.InterpolatedNotPrepared
|
299 |
-
$count[1] = $wpdb->get_var( "SELECT COUNT(id) FROM $log_table WHERE TIMESTAMPDIFF(DAY, time, NOW()) <= 7;" ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared,WordPress.DB.PreparedSQL.InterpolatedNotPrepared
|
300 |
-
$count[2] = $wpdb->get_var( "SELECT COUNT(id) FROM $log_table WHERE TIMESTAMPDIFF(DAY, time, NOW()) <= 30;" ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared,WordPress.DB.PreparedSQL.InterpolatedNotPrepared
|
301 |
-
$count[3] = $wpdb->get_var( "SELECT COUNT(id) FROM $log_table;" ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared,WordPress.DB.PreparedSQL.InterpolatedNotPrepared
|
302 |
-
|
303 |
-
printf(
|
304 |
-
'<table class="widefat"><thead><tr><th colspan="2">%1$s</th></tr></thead><tbody><tr><th>%2$s</th><th style="text-align: center">%3$s</th></tr>',
|
305 |
-
esc_html( $title ),
|
306 |
-
esc_html__( 'When', 'relevanssi' ),
|
307 |
-
esc_html__( 'Searches', 'relevanssi' )
|
308 |
-
);
|
309 |
-
|
310 |
-
foreach ( $count as $key => $searches ) {
|
311 |
-
$when = $titles[ $key ];
|
312 |
-
printf( "<tr><td>%s</td><td style='text-align: center'>%d</td></tr>", esc_html( $when ), intval( $searches ) );
|
313 |
-
}
|
314 |
-
echo '</tbody></table>';
|
315 |
-
}
|
316 |
-
|
317 |
-
/**
|
318 |
-
* Shows the most common search queries on different time periods.
|
319 |
-
*
|
320 |
-
* @global object $wpdb The WP database interface.
|
321 |
-
* @global array $relevanssi_variables The global Relevanssi variables array.
|
322 |
-
*
|
323 |
-
* @param int $days The number of days to show.
|
324 |
-
* @param string $title The title that is printed out on top of the results.
|
325 |
-
* @param string $version If 'good', show the searches that found something; if
|
326 |
-
* 'bad', show the searches that didn't find anything. Default 'good'.
|
327 |
-
*/
|
328 |
-
function relevanssi_date_queries( $days, $title, $version = 'good' ) {
|
329 |
-
global $wpdb, $relevanssi_variables;
|
330 |
-
$log_table = $relevanssi_variables['log_table'];
|
331 |
-
|
332 |
-
/** Documented in lib/interface.php. */
|
333 |
-
$limit = apply_filters( 'relevanssi_user_searches_limit', 20 );
|
334 |
-
|
335 |
-
if ( 'good' === $version ) {
|
336 |
-
$queries = $wpdb->get_results(
|
337 |
-
$wpdb->prepare(
|
338 |
-
'SELECT COUNT(DISTINCT(id)) as cnt, query, hits ' .
|
339 |
-
"FROM $log_table " . // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared,WordPress.DB.PreparedSQL.InterpolatedNotPrepared
|
340 |
-
'WHERE TIMESTAMPDIFF(DAY, time, NOW()) <= %d
|
341 |
-
GROUP BY query
|
342 |
-
ORDER BY cnt DESC
|
343 |
-
LIMIT %d',
|
344 |
-
$days,
|
345 |
-
$limit
|
346 |
-
)
|
347 |
-
);
|
348 |
-
}
|
349 |
-
|
350 |
-
if ( 'bad' === $version ) {
|
351 |
-
$queries = $wpdb->get_results(
|
352 |
-
$wpdb->prepare(
|
353 |
-
'SELECT COUNT(DISTINCT(id)) as cnt, query, hits ' .
|
354 |
-
"FROM $log_table " . // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared,WordPress.DB.PreparedSQL.InterpolatedNotPrepared
|
355 |
-
'WHERE TIMESTAMPDIFF(DAY, time, NOW()) <= %d AND hits = 0
|
356 |
-
GROUP BY query
|
357 |
-
ORDER BY cnt DESC
|
358 |
-
LIMIT %d',
|
359 |
-
$days,
|
360 |
-
$limit
|
361 |
-
)
|
362 |
-
); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared,WordPress.DB.PreparedSQL.InterpolatedNotPrepared
|
363 |
-
}
|
364 |
-
|
365 |
-
if ( count( $queries ) > 0 ) {
|
366 |
-
printf(
|
367 |
-
"<table class='widefat'><thead><tr><th colspan='3'>%s</th></tr></thead><tbody><tr><th>%s</th><th style='text-align: center'>#</th><th style='text-align: center'>%s</th></tr>",
|
368 |
-
esc_html( $title ),
|
369 |
-
esc_html__( 'Query', 'relevanssi' ),
|
370 |
-
esc_html__( 'Hits', 'relevanssi' )
|
371 |
-
);
|
372 |
-
$url = get_bloginfo( 'url' );
|
373 |
-
foreach ( $queries as $query ) {
|
374 |
-
$search_parameter = rawurlencode( $query->query );
|
375 |
-
/**
|
376 |
-
* Filters the query URL for the user searches page.
|
377 |
-
*
|
378 |
-
* @param string Query URL.
|
379 |
-
*/
|
380 |
-
$query_url = apply_filters( 'relevanssi_user_searches_query_url', $url . '/?s=' . $search_parameter );
|
381 |
-
printf(
|
382 |
-
"<tr><td><a href='%s'>%s</a></td><td style='padding: 3px 5px; text-align: center'>%d</td><td style='padding: 3px 5px; text-align: center'>%d</td></tr>",
|
383 |
-
esc_attr( $query_url ),
|
384 |
-
esc_attr( $query->query ),
|
385 |
-
intval( $query->cnt ),
|
386 |
-
intval( $query->hits )
|
387 |
-
);
|
388 |
-
}
|
389 |
-
echo '</tbody></table>';
|
390 |
-
}
|
391 |
-
}
|
392 |
-
|
393 |
/**
|
394 |
* Prints out the Relevanssi options form.
|
395 |
*
|
396 |
-
* @global
|
397 |
-
* @global array $relevanssi_variables The global Relevanssi variables array.
|
398 |
*/
|
399 |
function relevanssi_options_form() {
|
400 |
-
global $relevanssi_variables
|
401 |
|
402 |
echo "<div class='postbox-container'>";
|
403 |
echo "<form method='post'>";
|
@@ -557,8 +305,10 @@ function relevanssi_add_admin_scripts( $hook ) {
|
|
557 |
$acceptable_hooks = array(
|
558 |
'toplevel_page_relevanssi-premium/relevanssi',
|
559 |
'settings_page_relevanssi-premium/relevanssi',
|
|
|
560 |
'toplevel_page_relevanssi/relevanssi',
|
561 |
'settings_page_relevanssi/relevanssi',
|
|
|
562 |
'dashboard_page_relevanssi_admin_search',
|
563 |
);
|
564 |
/**
|
@@ -586,9 +336,14 @@ function relevanssi_add_admin_scripts( $hook ) {
|
|
586 |
}
|
587 |
wp_enqueue_style( 'relevanssi_admin_css', $plugin_dir_url . 'lib/admin_styles.css', array(), $relevanssi_variables['plugin_version'] );
|
588 |
|
|
|
|
|
|
|
|
|
589 |
$localizations = array(
|
590 |
'confirm' => __( 'Click OK to copy Relevanssi options to all subsites', 'relevanssi' ),
|
591 |
'confirm_stopwords' => __( 'Are you sure you want to remove all stopwords?', 'relevanssi' ),
|
|
|
592 |
'truncating_index' => __( 'Wiping out the index...', 'relevanssi' ),
|
593 |
'done' => __( 'Done.', 'relevanssi' ),
|
594 |
'indexing_users' => __( 'Indexing users...', 'relevanssi' ),
|
@@ -702,3 +457,63 @@ function relevanssi_form_tag_weight() {
|
|
702 |
</tr>
|
703 |
<?php
|
704 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
99 |
echo "<div style='clear:both'></div></div>";
|
100 |
}
|
101 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
102 |
/**
|
103 |
* Prints out the 'Admin search' page.
|
104 |
*/
|
105 |
function relevanssi_admin_search_page() {
|
106 |
global $relevanssi_variables;
|
107 |
|
|
|
|
|
108 |
$options_txt = __( 'Admin Search', 'relevanssi' );
|
109 |
|
110 |
printf( "<div class='wrap'><h2>%s</h2>", esc_html( $options_txt ) );
|
139 |
return $result;
|
140 |
}
|
141 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
142 |
/**
|
143 |
* Prints out the Relevanssi options form.
|
144 |
*
|
145 |
+
* @global array $relevanssi_variables The global Relevanssi variables array.
|
|
|
146 |
*/
|
147 |
function relevanssi_options_form() {
|
148 |
+
global $relevanssi_variables;
|
149 |
|
150 |
echo "<div class='postbox-container'>";
|
151 |
echo "<form method='post'>";
|
305 |
$acceptable_hooks = array(
|
306 |
'toplevel_page_relevanssi-premium/relevanssi',
|
307 |
'settings_page_relevanssi-premium/relevanssi',
|
308 |
+
'dashboard_page_relevanssi-premium/relevanssi',
|
309 |
'toplevel_page_relevanssi/relevanssi',
|
310 |
'settings_page_relevanssi/relevanssi',
|
311 |
+
'dashboard_page_relevanssi/relevanssi',
|
312 |
'dashboard_page_relevanssi_admin_search',
|
313 |
);
|
314 |
/**
|
336 |
}
|
337 |
wp_enqueue_style( 'relevanssi_admin_css', $plugin_dir_url . 'lib/admin_styles.css', array(), $relevanssi_variables['plugin_version'] );
|
338 |
|
339 |
+
if ( 'dashboard_page_relevanssi' === substr( $hook, 0, strlen( 'dashboard_page_relevanssi' ) ) ) {
|
340 |
+
wp_enqueue_script( 'chartjs', 'https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.3.2/chart.min.js', array(), '3.3.2', false );
|
341 |
+
}
|
342 |
+
|
343 |
$localizations = array(
|
344 |
'confirm' => __( 'Click OK to copy Relevanssi options to all subsites', 'relevanssi' ),
|
345 |
'confirm_stopwords' => __( 'Are you sure you want to remove all stopwords?', 'relevanssi' ),
|
346 |
+
'confirm_delete_query' => __( 'Are you sure you want to delete the query?', 'relevanssi' ),
|
347 |
'truncating_index' => __( 'Wiping out the index...', 'relevanssi' ),
|
348 |
'done' => __( 'Done.', 'relevanssi' ),
|
349 |
'indexing_users' => __( 'Indexing users...', 'relevanssi' ),
|
457 |
</tr>
|
458 |
<?php
|
459 |
}
|
460 |
+
|
461 |
+
/**
|
462 |
+
* Creates a line chart.
|
463 |
+
*
|
464 |
+
* @param array $labels An array of labels for the line chart. These will be
|
465 |
+
* wrapped in apostrophes.
|
466 |
+
* @param array $datasets An array of (label, dataset) pairs.
|
467 |
+
*/
|
468 |
+
function relevanssi_create_line_chart( array $labels, array $datasets ) {
|
469 |
+
$labels = implode( ', ', array_map( 'relevanssi_add_apostrophes', $labels ) );
|
470 |
+
$datasets_array = array();
|
471 |
+
$bg_colors = array(
|
472 |
+
"'rgba(255, 99, 132, 0.2)'",
|
473 |
+
"'rgba(0, 175, 255, 0.2)'",
|
474 |
+
);
|
475 |
+
$border_colors = array(
|
476 |
+
"'rgba(255, 99, 132, 1)'",
|
477 |
+
"'rgba(0, 175, 255, 1)'",
|
478 |
+
);
|
479 |
+
foreach ( $datasets as $label => $values ) {
|
480 |
+
$values = implode( ', ', $values );
|
481 |
+
$bg_color = array_shift( $bg_colors );
|
482 |
+
$border_color = array_shift( $border_colors );
|
483 |
+
$datasets_array[] = <<< EOJSON
|
484 |
+
{
|
485 |
+
label: "$label",
|
486 |
+
data: [ $values ],
|
487 |
+
backgroundColor: [ $bg_color ],
|
488 |
+
borderColor: [ $border_color ],
|
489 |
+
borderWidth: 2,
|
490 |
+
fill: {
|
491 |
+
target: 'origin',
|
492 |
+
below: $border_color,
|
493 |
+
},
|
494 |
+
pointRadius: 1,
|
495 |
+
cubicInterpolationMode: 'monotone'
|
496 |
+
}
|
497 |
+
EOJSON;
|
498 |
+
}
|
499 |
+
?>
|
500 |
+
<canvas id="search_chart" height="100"></canvas>
|
501 |
+
<script>
|
502 |
+
var ctx = document.getElementById('search_chart').getContext('2d');
|
503 |
+
var myChart = new Chart(ctx, {
|
504 |
+
type: 'line',
|
505 |
+
data: {
|
506 |
+
labels: [<?php echo $labels; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>],
|
507 |
+
datasets: [<?php echo implode( ",\n", $datasets_array ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>],
|
508 |
+
},
|
509 |
+
options: {
|
510 |
+
scales: {
|
511 |
+
y: {
|
512 |
+
beginAtZero: true
|
513 |
+
}
|
514 |
+
}
|
515 |
+
}
|
516 |
+
});
|
517 |
+
</script>
|
518 |
+
<?php
|
519 |
+
}
|
lib/phrases.php
CHANGED
@@ -19,9 +19,9 @@
|
|
19 |
* @return array An array of phrases (strings).
|
20 |
*/
|
21 |
function relevanssi_extract_phrases( string $query ) {
|
22 |
-
// iOS uses “” as the default quotes, so Relevanssi needs to
|
23 |
-
//
|
24 |
-
$normalized_query = str_replace( array( '”', '“' ), '"', $query );
|
25 |
$pos = relevanssi_stripos( $normalized_query, '"' );
|
26 |
|
27 |
$phrases = array();
|
19 |
* @return array An array of phrases (strings).
|
20 |
*/
|
21 |
function relevanssi_extract_phrases( string $query ) {
|
22 |
+
// iOS uses “” or „“ as the default quotes, so Relevanssi needs to
|
23 |
+
// understand those as well.
|
24 |
+
$normalized_query = str_replace( array( '”', '“', '„' ), '"', $query );
|
25 |
$pos = relevanssi_stripos( $normalized_query, '"' );
|
26 |
|
27 |
$phrases = array();
|
lib/search.php
CHANGED
@@ -136,15 +136,15 @@ function relevanssi_search( $args ) {
|
|
136 |
*/
|
137 |
$remove_stopwords = apply_filters( 'relevanssi_remove_stopwords_in_titles', true );
|
138 |
|
139 |
-
$terms['terms'] = array_keys( relevanssi_tokenize( $q, $remove_stopwords, $min_length ) );
|
140 |
|
141 |
$terms['original_terms'] = $q_no_synonyms !== $q
|
142 |
-
? array_keys( relevanssi_tokenize( $q_no_synonyms, $remove_stopwords, $min_length ) )
|
143 |
: $terms['terms'];
|
144 |
|
145 |
if ( has_filter( 'relevanssi_stemmer' ) ) {
|
146 |
do_action( 'relevanssi_disable_stemmer' );
|
147 |
-
$terms['original_terms'] = array_keys( relevanssi_tokenize( $q_no_synonyms, $remove_stopwords, $min_length ) );
|
148 |
do_action( 'relevanssi_enable_stemmer' );
|
149 |
}
|
150 |
|
@@ -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
|
230 |
|
231 |
if ( count( $matches ) < 1 ) {
|
232 |
continue;
|
@@ -357,17 +357,17 @@ function relevanssi_search( $args ) {
|
|
357 |
|
358 |
if ( ! $remove_stopwords ) {
|
359 |
$strip_stops = true;
|
360 |
-
$terms['no_stops'] = array_keys( relevanssi_tokenize( implode( ' ', $terms['terms'] ), $strip_stops, $min_length ) );
|
361 |
|
362 |
if ( $q !== $q_no_synonyms ) {
|
363 |
-
$terms['original_terms_no_stops'] = array_keys( relevanssi_tokenize( implode( ' ', $terms['original_terms'] ), $strip_stops, $min_length ) );
|
364 |
} else {
|
365 |
$terms['original_terms_no_stops'] = $terms['no_stops'];
|
366 |
}
|
367 |
|
368 |
if ( has_filter( 'relevanssi_stemmer' ) ) {
|
369 |
do_action( 'relevanssi_disable_stemmer' );
|
370 |
-
$terms['original_terms_no_stops'] = array_keys( relevanssi_tokenize( implode( ' ', $terms['original_terms'] ), $strip_stops, $min_length ) );
|
371 |
do_action( 'relevanssi_enable_stemmer' );
|
372 |
} else {
|
373 |
$terms['original_terms_no_stops'] = $terms['no_stops'];
|
@@ -376,7 +376,7 @@ function relevanssi_search( $args ) {
|
|
376 |
$terms['no_stops'] = $terms['terms'];
|
377 |
$terms['original_terms_no_stops'] = $terms['original_terms'];
|
378 |
}
|
379 |
-
$total_terms = count( $terms['
|
380 |
|
381 |
if ( isset( $doc_weight ) ) {
|
382 |
/**
|
@@ -1087,6 +1087,23 @@ function relevanssi_compile_search_args( $query, $q ) {
|
|
1087 |
)
|
1088 |
);
|
1089 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1090 |
return $search_params;
|
1091 |
}
|
1092 |
|
136 |
*/
|
137 |
$remove_stopwords = apply_filters( 'relevanssi_remove_stopwords_in_titles', true );
|
138 |
|
139 |
+
$terms['terms'] = array_keys( relevanssi_tokenize( $q, $remove_stopwords, $min_length, 'search_query' ) );
|
140 |
|
141 |
$terms['original_terms'] = $q_no_synonyms !== $q
|
142 |
+
? array_keys( relevanssi_tokenize( $q_no_synonyms, $remove_stopwords, $min_length, 'search_query' ) )
|
143 |
: $terms['terms'];
|
144 |
|
145 |
if ( has_filter( 'relevanssi_stemmer' ) ) {
|
146 |
do_action( 'relevanssi_disable_stemmer' );
|
147 |
+
$terms['original_terms'] = array_keys( relevanssi_tokenize( $q_no_synonyms, $remove_stopwords, $min_length, 'search_query' ) );
|
148 |
do_action( 'relevanssi_enable_stemmer' );
|
149 |
}
|
150 |
|
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.InterpolatedNotPrepared,WordPress.DB.PreparedSQL.NotPrepared
|
230 |
|
231 |
if ( count( $matches ) < 1 ) {
|
232 |
continue;
|
357 |
|
358 |
if ( ! $remove_stopwords ) {
|
359 |
$strip_stops = true;
|
360 |
+
$terms['no_stops'] = array_keys( relevanssi_tokenize( implode( ' ', $terms['terms'] ), $strip_stops, $min_length, 'search_query' ) );
|
361 |
|
362 |
if ( $q !== $q_no_synonyms ) {
|
363 |
+
$terms['original_terms_no_stops'] = array_keys( relevanssi_tokenize( implode( ' ', $terms['original_terms'] ), $strip_stops, $min_length, 'search_query' ) );
|
364 |
} else {
|
365 |
$terms['original_terms_no_stops'] = $terms['no_stops'];
|
366 |
}
|
367 |
|
368 |
if ( has_filter( 'relevanssi_stemmer' ) ) {
|
369 |
do_action( 'relevanssi_disable_stemmer' );
|
370 |
+
$terms['original_terms_no_stops'] = array_keys( relevanssi_tokenize( implode( ' ', $terms['original_terms'] ), $strip_stops, $min_length, 'search_query' ) );
|
371 |
do_action( 'relevanssi_enable_stemmer' );
|
372 |
} else {
|
373 |
$terms['original_terms_no_stops'] = $terms['no_stops'];
|
376 |
$terms['no_stops'] = $terms['terms'];
|
377 |
$terms['original_terms_no_stops'] = $terms['original_terms'];
|
378 |
}
|
379 |
+
$total_terms = count( $terms['original_terms_no_stops'] );
|
380 |
|
381 |
if ( isset( $doc_weight ) ) {
|
382 |
/**
|
1087 |
)
|
1088 |
);
|
1089 |
|
1090 |
+
/**
|
1091 |
+
* Filters the Relevanssi search parameters after compiling.
|
1092 |
+
*
|
1093 |
+
* Relevanssi picks up the search parameters from the WP_Query query
|
1094 |
+
* variables and collects them in an array you can filter here.
|
1095 |
+
*
|
1096 |
+
* @param array $search_params The search parameters.
|
1097 |
+
* @param WP_Query $query The full WP_Query object.
|
1098 |
+
*
|
1099 |
+
* @return array The filtered parameters.
|
1100 |
+
*/
|
1101 |
+
$search_params = apply_filters(
|
1102 |
+
'relevanssi_search_params',
|
1103 |
+
$search_params,
|
1104 |
+
$query
|
1105 |
+
);
|
1106 |
+
|
1107 |
return $search_params;
|
1108 |
}
|
1109 |
|
lib/shortcodes.php
CHANGED
@@ -111,7 +111,29 @@ 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 |
$field = '<select name="post_type">';
|
116 |
$types = get_option( 'relevanssi_index_post_types' );
|
117 |
if ( ! is_array( $types ) ) {
|
111 |
if ( is_array( $atts ) ) {
|
112 |
$additional_fields = array();
|
113 |
foreach ( $atts as $key => $value ) {
|
114 |
+
if ( 'dropdown' === substr( $key, 0, 8 ) ) {
|
115 |
+
$key = 'dropdown';
|
116 |
+
}
|
117 |
+
if ( 'post_type_boxes' === $key ) {
|
118 |
+
$post_types = explode( ',', $value );
|
119 |
+
if ( is_array( $post_types ) ) {
|
120 |
+
$post_type_objects = get_post_types( array(), 'objects' );
|
121 |
+
$additional_fields[] = '<div class="post_types"><strong>Post types</strong>: ';
|
122 |
+
foreach ( $post_types as $post_type ) {
|
123 |
+
$checked = '';
|
124 |
+
if ( '*' === substr( $post_type, 0, 1 ) ) {
|
125 |
+
$post_type = substr( $post_type, 1 );
|
126 |
+
$checked = ' checked="checked" ';
|
127 |
+
}
|
128 |
+
if ( isset( $post_type_objects[ $post_type ] ) ) {
|
129 |
+
$additional_fields[] = '<span class="post_type post_type_' . $post_type . '">'
|
130 |
+
. '<input type="checkbox" name="post_types[]" value="' . $post_type . '"' . $checked . '/> '
|
131 |
+
. $post_type_objects[ $post_type ]->name . '</span>';
|
132 |
+
}
|
133 |
+
}
|
134 |
+
$additional_fields[] = '</div>';
|
135 |
+
}
|
136 |
+
} elseif ( 'dropdown' === $key && 'post_type' === $value ) {
|
137 |
$field = '<select name="post_type">';
|
138 |
$types = get_option( 'relevanssi_index_post_types' );
|
139 |
if ( ! is_array( $types ) ) {
|
lib/sorting.php
CHANGED
@@ -68,10 +68,27 @@ function relevanssi_get_next_key( &$orderby ) {
|
|
68 |
case 'relevance':
|
69 |
$key = 'relevance_score';
|
70 |
break;
|
|
|
|
|
|
|
71 |
}
|
72 |
|
73 |
-
$numeric_keys = array(
|
74 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
75 |
$filter_keys = array( 'post_type' );
|
76 |
|
77 |
$compare = 'string';
|
@@ -201,6 +218,8 @@ function relevanssi_get_compare_values( $key, $item_1, $item_2 ) {
|
|
201 |
*/
|
202 |
$key2 = apply_filters( 'relevanssi_missing_sort_key', $key2, $key );
|
203 |
}
|
|
|
|
|
204 |
} else {
|
205 |
global $relevanssi_meta_query;
|
206 |
if ( isset( $item_1->$key ) ) {
|
68 |
case 'relevance':
|
69 |
$key = 'relevance_score';
|
70 |
break;
|
71 |
+
case 'distance':
|
72 |
+
$key = 'proximity';
|
73 |
+
break;
|
74 |
}
|
75 |
|
76 |
+
$numeric_keys = array(
|
77 |
+
'meta_value_num',
|
78 |
+
'menu_order',
|
79 |
+
'ID',
|
80 |
+
'post_parent',
|
81 |
+
'post_author',
|
82 |
+
'comment_count',
|
83 |
+
'relevance_score',
|
84 |
+
'proximity',
|
85 |
+
);
|
86 |
+
$date_keys = array(
|
87 |
+
'post_date',
|
88 |
+
'post_date_gmt',
|
89 |
+
'post_modified',
|
90 |
+
'post_modified_gmt',
|
91 |
+
);
|
92 |
$filter_keys = array( 'post_type' );
|
93 |
|
94 |
$compare = 'string';
|
218 |
*/
|
219 |
$key2 = apply_filters( 'relevanssi_missing_sort_key', $key2, $key );
|
220 |
}
|
221 |
+
} elseif ( 'proximity' === $key && function_exists( 'relevanssi_get_proximity_values' ) ) {
|
222 |
+
list( $key1, $key2 ) = relevanssi_get_proximity_values( $item_1, $item_2 );
|
223 |
} else {
|
224 |
global $relevanssi_meta_query;
|
225 |
if ( isset( $item_1->$key ) ) {
|
lib/tabs/debugging-tab.php
CHANGED
@@ -16,11 +16,27 @@
|
|
16 |
function relevanssi_debugging_tab() {
|
17 |
$how_relevanssi_sees = '';
|
18 |
$current_post_id = 0;
|
|
|
19 |
if ( isset( $_REQUEST['post_id'] ) ) {
|
20 |
wp_verify_nonce( '_relevanssi_nonce', 'relevanssi_how_relevanssi_sees' );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
21 |
if ( intval( $_REQUEST['post_id'] ) > 0 ) {
|
22 |
$current_post_id = intval( $_REQUEST['post_id'] );
|
23 |
-
$how_relevanssi_sees = relevanssi_generate_how_relevanssi_sees(
|
|
|
|
|
|
|
|
|
24 |
}
|
25 |
}
|
26 |
wp_nonce_field( 'relevanssi_how_relevanssi_sees', '_relevanssi_nonce', true, true );
|
@@ -29,19 +45,45 @@ function relevanssi_debugging_tab() {
|
|
29 |
|
30 |
<p><?php esc_html_e( 'In order to figure out problems with indexing posts, you can test how Relevanssi sees the post by entering the post ID number in the field below.', 'relevanssi' ); ?></p>
|
31 |
<?php
|
|
|
|
|
|
|
|
|
|
|
32 |
if ( ! RELEVANSSI_PREMIUM ) {
|
33 |
// Translators: %1$s starts the link, %2$s closes it.
|
34 |
printf( '<p>' . esc_html__( 'In Relevanssi Premium, you can find this feature for each post on the post edit page. %1$sBuy Relevanssi Premium here%2$s.', 'relevanssi' ) . '</p>', '<a href="https://www.relevanssi.com/buy-premium/">', '</a>' );
|
35 |
}
|
36 |
?>
|
37 |
-
<p><label for="post_id"><?php esc_html_e( 'The
|
38 |
<input type="text" name="post_id" id="post_id"
|
39 |
<?php
|
40 |
if ( $current_post_id > 0 ) {
|
41 |
echo 'value="' . esc_attr( $current_post_id ) . '"';
|
42 |
}
|
43 |
?>
|
44 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
45 |
<p>
|
46 |
<input
|
47 |
type='submit' name='submit'
|
16 |
function relevanssi_debugging_tab() {
|
17 |
$how_relevanssi_sees = '';
|
18 |
$current_post_id = 0;
|
19 |
+
$selected = 'post';
|
20 |
if ( isset( $_REQUEST['post_id'] ) ) {
|
21 |
wp_verify_nonce( '_relevanssi_nonce', 'relevanssi_how_relevanssi_sees' );
|
22 |
+
$type = 'post';
|
23 |
+
if ( isset( $_REQUEST['type'] ) ) {
|
24 |
+
if ( 'term' === $_REQUEST['type'] ) {
|
25 |
+
$type = 'term';
|
26 |
+
$selected = 'term';
|
27 |
+
}
|
28 |
+
if ( 'user' === $_REQUEST['type'] ) {
|
29 |
+
$type = 'user';
|
30 |
+
$selected = 'user';
|
31 |
+
}
|
32 |
+
}
|
33 |
if ( intval( $_REQUEST['post_id'] ) > 0 ) {
|
34 |
$current_post_id = intval( $_REQUEST['post_id'] );
|
35 |
+
$how_relevanssi_sees = relevanssi_generate_how_relevanssi_sees(
|
36 |
+
intval( $current_post_id ),
|
37 |
+
true,
|
38 |
+
$type
|
39 |
+
);
|
40 |
}
|
41 |
}
|
42 |
wp_nonce_field( 'relevanssi_how_relevanssi_sees', '_relevanssi_nonce', true, true );
|
45 |
|
46 |
<p><?php esc_html_e( 'In order to figure out problems with indexing posts, you can test how Relevanssi sees the post by entering the post ID number in the field below.', 'relevanssi' ); ?></p>
|
47 |
<?php
|
48 |
+
if ( RELEVANSSI_PREMIUM ) {
|
49 |
+
?>
|
50 |
+
<p><?php esc_html_e( 'You can also check user profiles and taxonomy terms by choosing the type from the dropdown.', 'relevanssi' ); ?></p>
|
51 |
+
<?php
|
52 |
+
}
|
53 |
if ( ! RELEVANSSI_PREMIUM ) {
|
54 |
// Translators: %1$s starts the link, %2$s closes it.
|
55 |
printf( '<p>' . esc_html__( 'In Relevanssi Premium, you can find this feature for each post on the post edit page. %1$sBuy Relevanssi Premium here%2$s.', 'relevanssi' ) . '</p>', '<a href="https://www.relevanssi.com/buy-premium/">', '</a>' );
|
56 |
}
|
57 |
?>
|
58 |
+
<p><label for="post_id"><?php esc_html_e( 'The ID', 'relevanssi' ); ?></label>:
|
59 |
<input type="text" name="post_id" id="post_id"
|
60 |
<?php
|
61 |
if ( $current_post_id > 0 ) {
|
62 |
echo 'value="' . esc_attr( $current_post_id ) . '"';
|
63 |
}
|
64 |
?>
|
65 |
+
/>
|
66 |
+
<?php
|
67 |
+
if ( RELEVANSSI_PREMIUM ) {
|
68 |
+
?>
|
69 |
+
<select name="type">
|
70 |
+
<option value="post"
|
71 |
+
<?php if ( 'post' === $selected ) { ?>
|
72 |
+
selected="selected"
|
73 |
+
<?php } ?>><?php esc_html_e( 'Post', 'relevanssi' ); ?></option>
|
74 |
+
<option value="term"
|
75 |
+
<?php if ( 'term' === $selected ) { ?>
|
76 |
+
selected="selected"
|
77 |
+
<?php } ?>><?php esc_html_e( 'Taxonomy term', 'relevanssi' ); ?></option>
|
78 |
+
<option value="user"
|
79 |
+
<?php if ( 'user' === $selected ) { ?>
|
80 |
+
selected="selected"
|
81 |
+
<?php } ?>><?php esc_html_e( 'User', 'relevanssi' ); ?></option>
|
82 |
+
</select>
|
83 |
+
<?php
|
84 |
+
}
|
85 |
+
?>
|
86 |
+
</p>
|
87 |
<p>
|
88 |
<input
|
89 |
type='submit' name='submit'
|
lib/tabs/logging-tab.php
CHANGED
@@ -14,10 +14,9 @@
|
|
14 |
* Prints out the logging tab in Relevanssi settings.
|
15 |
*
|
16 |
* @global $wpdb The WordPress database interface.
|
17 |
-
* @global $relevanssi_variables The global Relevanssi variables array.
|
18 |
*/
|
19 |
function relevanssi_logging_tab() {
|
20 |
-
global $wpdb
|
21 |
|
22 |
$log_queries = get_option( 'relevanssi_log_queries' );
|
23 |
$log_queries = relevanssi_check( $log_queries );
|
@@ -96,7 +95,7 @@ function relevanssi_logging_tab() {
|
|
96 |
} else {
|
97 |
echo '<p class="description">';
|
98 |
// Translators: %d is the setting for no trim (probably 0).
|
99 |
-
printf( esc_html__( '
|
100 |
echo '</p>';
|
101 |
}
|
102 |
?>
|
@@ -115,4 +114,13 @@ function relevanssi_logging_tab() {
|
|
115 |
|
116 |
</table>
|
117 |
<?php
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
118 |
}
|
14 |
* Prints out the logging tab in Relevanssi settings.
|
15 |
*
|
16 |
* @global $wpdb The WordPress database interface.
|
|
|
17 |
*/
|
18 |
function relevanssi_logging_tab() {
|
19 |
+
global $wpdb;
|
20 |
|
21 |
$log_queries = get_option( 'relevanssi_log_queries' );
|
22 |
$log_queries = relevanssi_check( $log_queries );
|
95 |
} else {
|
96 |
echo '<p class="description">';
|
97 |
// Translators: %d is the setting for no trim (probably 0).
|
98 |
+
printf( esc_html__( 'Set to %d for no trimming.', 'relevanssi' ), 0 );
|
99 |
echo '</p>';
|
100 |
}
|
101 |
?>
|
114 |
|
115 |
</table>
|
116 |
<?php
|
117 |
+
|
118 |
+
if ( function_exists( 'relevanssi_click_tracking_interface' ) ) {
|
119 |
+
relevanssi_click_tracking_interface();
|
120 |
+
} else {
|
121 |
+
?>
|
122 |
+
<h3><?php esc_html_e( 'Click tracking', 'relevanssi' ); ?></h3>
|
123 |
+
<p><?php esc_html_e( 'Relevanssi Premium has a click tracking feature where you can track which posts are clicked from the search results. That way you can tell what is your most interesting content and how the search is actually used to access posts.', 'relevanssi' ); ?></p>
|
124 |
+
<?php
|
125 |
+
}
|
126 |
}
|
lib/tabs/search-page.php
CHANGED
@@ -35,21 +35,26 @@ function relevanssi_search_tab() {
|
|
35 |
<select name='post_types' id='post_types'>
|
36 |
<option value="any"><?php esc_html_e( 'Any', 'relevanssi' ); ?></option>
|
37 |
<?php
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
|
|
|
|
|
|
|
|
|
|
53 |
?>
|
54 |
</select>
|
55 |
</td>
|
35 |
<select name='post_types' id='post_types'>
|
36 |
<option value="any"><?php esc_html_e( 'Any', 'relevanssi' ); ?></option>
|
37 |
<?php
|
38 |
+
echo implode(
|
39 |
+
' ',
|
40 |
+
array_map( // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
41 |
+
function ( $post_type ) {
|
42 |
+
$pt = get_post_type_object( $post_type );
|
43 |
+
if ( $pt ) {
|
44 |
+
$post_type_value = esc_attr( $post_type );
|
45 |
+
$post_type_name = esc_html( $pt->labels->singular_name );
|
46 |
+
return "<option value='{$post_type_value}'>{$post_type_name}</option>";
|
47 |
+
}
|
48 |
+
return null;
|
49 |
+
},
|
50 |
+
get_option( 'relevanssi_index_post_types' )
|
51 |
+
)
|
52 |
+
);
|
53 |
+
if ( 'on' === get_option( 'relevanssi_index_users' ) ) {
|
54 |
+
?>
|
55 |
+
<option value='user'><?php esc_html_e( 'Users', 'relevanssi' ); ?></option>
|
56 |
+
<?php
|
57 |
+
}
|
58 |
?>
|
59 |
</select>
|
60 |
</td>
|
lib/tabs/stopwords-tab.php
CHANGED
@@ -14,6 +14,10 @@
|
|
14 |
* Prints out the stopwords tab in Relevanssi settings.
|
15 |
*/
|
16 |
function relevanssi_stopwords_tab() {
|
|
|
|
|
|
|
|
|
17 |
?>
|
18 |
<h3 id="stopwords"><?php esc_html_e( 'Stopwords', 'relevanssi' ); ?></h3>
|
19 |
<?php
|
@@ -131,3 +135,15 @@ function relevanssi_show_stopwords() {
|
|
131 |
|
132 |
<?php
|
133 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
14 |
* Prints out the stopwords tab in Relevanssi settings.
|
15 |
*/
|
16 |
function relevanssi_stopwords_tab() {
|
17 |
+
if ( class_exists( 'Polylang', false ) && ! relevanssi_get_current_language() ) {
|
18 |
+
relevanssi_polylang_all_languages_stopwords();
|
19 |
+
return;
|
20 |
+
}
|
21 |
?>
|
22 |
<h3 id="stopwords"><?php esc_html_e( 'Stopwords', 'relevanssi' ); ?></h3>
|
23 |
<?php
|
135 |
|
136 |
<?php
|
137 |
}
|
138 |
+
|
139 |
+
/**
|
140 |
+
* Displays an error message when Polylang is in all languages mode.
|
141 |
+
*/
|
142 |
+
function relevanssi_polylang_all_languages_stopwords() {
|
143 |
+
?>
|
144 |
+
<h3 id="stopwords"><?php esc_html_e( 'Stopwords', 'relevanssi' ); ?></h3>
|
145 |
+
|
146 |
+
<p class="description"><?php esc_html_e( 'You are using Polylang and are in "Show all languages" mode. Please select a language before adjusting the stopword settings.', 'relevanssi' ); ?></p>
|
147 |
+
<?php
|
148 |
+
}
|
149 |
+
|
lib/tabs/synonyms-tab.php
CHANGED
@@ -15,8 +15,12 @@
|
|
15 |
*/
|
16 |
function relevanssi_synonyms_tab() {
|
17 |
$current_language = relevanssi_get_current_language();
|
18 |
-
|
19 |
-
|
|
|
|
|
|
|
|
|
20 |
|
21 |
if ( isset( $synonyms ) ) {
|
22 |
$synonyms = str_replace( ';', "\n", $synonyms );
|
@@ -45,10 +49,28 @@ function relevanssi_synonyms_tab() {
|
|
45 |
<p class="description"><?php _e( "It's possible to use phrases for the value, but not for the key. <code>dog = \"great dane\"</code> works, but <code>\"great dane\" = dog</code> doesn't.", 'relevanssi' ); // phpcs:ignore WordPress.Security.EscapeOutput.UnsafePrintingFunction ?></p>
|
46 |
|
47 |
<?php if ( RELEVANSSI_PREMIUM ) : ?>
|
48 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
49 |
<?php endif; ?>
|
50 |
</td>
|
51 |
</tr>
|
52 |
</table>
|
53 |
<?php
|
54 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
15 |
*/
|
16 |
function relevanssi_synonyms_tab() {
|
17 |
$current_language = relevanssi_get_current_language();
|
18 |
+
if ( class_exists( 'Polylang', false ) && ! $current_language ) {
|
19 |
+
relevanssi_polylang_all_languages_synonyms();
|
20 |
+
return;
|
21 |
+
}
|
22 |
+
$synonyms_array = get_option( 'relevanssi_synonyms', array() );
|
23 |
+
$synonyms = isset( $synonyms_array[ $current_language ] ) ? $synonyms_array[ $current_language ] : '';
|
24 |
|
25 |
if ( isset( $synonyms ) ) {
|
26 |
$synonyms = str_replace( ';', "\n", $synonyms );
|
49 |
<p class="description"><?php _e( "It's possible to use phrases for the value, but not for the key. <code>dog = \"great dane\"</code> works, but <code>\"great dane\" = dog</code> doesn't.", 'relevanssi' ); // phpcs:ignore WordPress.Security.EscapeOutput.UnsafePrintingFunction ?></p>
|
50 |
|
51 |
<?php if ( RELEVANSSI_PREMIUM ) : ?>
|
52 |
+
</td>
|
53 |
+
</tr>
|
54 |
+
<tr>
|
55 |
+
<th scope="row">
|
56 |
+
<?php echo esc_html_e( 'Synonyms in AND searches', 'relevanssi' ); ?>
|
57 |
+
</th>
|
58 |
+
<td>
|
59 |
+
<p class="description"><?php esc_html_e( "If you want to use synonyms in AND searches, enable synonym indexing on the Indexing tab. Also, any changes to the synonyms won't take effect until you rebuild the index.", 'relevanssi' ); ?></p>
|
60 |
<?php endif; ?>
|
61 |
</td>
|
62 |
</tr>
|
63 |
</table>
|
64 |
<?php
|
65 |
}
|
66 |
+
|
67 |
+
/**
|
68 |
+
* Displays an error message when Polylang is in all languages mode.
|
69 |
+
*/
|
70 |
+
function relevanssi_polylang_all_languages_synonyms() {
|
71 |
+
?>
|
72 |
+
<h3 id="synonyms"><?php esc_html_e( 'Synonyms', 'relevanssi' ); ?></h3>
|
73 |
+
|
74 |
+
<p class="description"><?php esc_html_e( 'You are using Polylang and are in "Show all languages" mode. Please select a language before adjusting the synonym settings.', 'relevanssi' ); ?></p>
|
75 |
+
<?php
|
76 |
+
}
|
lib/uninstall.php
CHANGED
@@ -26,6 +26,7 @@ function relevanssi_drop_database_tables() {
|
|
26 |
$relevanssi_table = $wpdb->prefix . 'relevanssi';
|
27 |
$stopword_table = $wpdb->prefix . 'relevanssi_stopwords';
|
28 |
$log_table = $wpdb->prefix . 'relevanssi_log';
|
|
|
29 |
|
30 |
// phpcs:disable WordPress.DB.PreparedSQL
|
31 |
if ( $wpdb->get_var( "SHOW TABLES LIKE '$stopword_table'" ) === $stopword_table ) {
|
@@ -39,6 +40,10 @@ function relevanssi_drop_database_tables() {
|
|
39 |
if ( $wpdb->get_var( "SHOW TABLES LIKE '$log_table'" ) === $log_table ) {
|
40 |
$wpdb->query( "DROP TABLE $log_table" );
|
41 |
}
|
|
|
|
|
|
|
|
|
42 |
// phpcs:enable WordPress.DB.PreparedSQL
|
43 |
}
|
44 |
|
26 |
$relevanssi_table = $wpdb->prefix . 'relevanssi';
|
27 |
$stopword_table = $wpdb->prefix . 'relevanssi_stopwords';
|
28 |
$log_table = $wpdb->prefix . 'relevanssi_log';
|
29 |
+
$tracking_table = $wpdb->prefix . 'relevanssi_tracking';
|
30 |
|
31 |
// phpcs:disable WordPress.DB.PreparedSQL
|
32 |
if ( $wpdb->get_var( "SHOW TABLES LIKE '$stopword_table'" ) === $stopword_table ) {
|
40 |
if ( $wpdb->get_var( "SHOW TABLES LIKE '$log_table'" ) === $log_table ) {
|
41 |
$wpdb->query( "DROP TABLE $log_table" );
|
42 |
}
|
43 |
+
|
44 |
+
if ( $wpdb->get_var( "SHOW TABLES LIKE '$tracking_table'" ) === $tracking_table ) {
|
45 |
+
$wpdb->query( "DROP TABLE $tracking_table" );
|
46 |
+
}
|
47 |
// phpcs:enable WordPress.DB.PreparedSQL
|
48 |
}
|
49 |
|
lib/user-searches.php
ADDED
@@ -0,0 +1,370 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* /lib/user-searches.php
|
4 |
+
*
|
5 |
+
* @package Relevanssi
|
6 |
+
* @author Mikko Saari
|
7 |
+
* @license https://wordpress.org/about/gpl/ GNU General Public License
|
8 |
+
* @see https://www.relevanssi.com/
|
9 |
+
*/
|
10 |
+
|
11 |
+
/**
|
12 |
+
* Prints out the 'User searches' page.
|
13 |
+
*/
|
14 |
+
function relevanssi_search_stats() {
|
15 |
+
$relevanssi_hide_branding = get_option( 'relevanssi_hide_branding' );
|
16 |
+
|
17 |
+
if ( 'on' === $relevanssi_hide_branding ) {
|
18 |
+
$options_txt = __( 'User searches', 'relevanssi' );
|
19 |
+
} else {
|
20 |
+
$options_txt = __( 'Relevanssi User Searches', 'relevanssi' );
|
21 |
+
}
|
22 |
+
|
23 |
+
if ( isset( $_REQUEST['relevanssi_reset'] ) && current_user_can( 'manage_options' ) ) {
|
24 |
+
check_admin_referer( 'relevanssi_reset_logs', '_relresnonce' );
|
25 |
+
if ( isset( $_REQUEST['relevanssi_reset_code'] ) ) {
|
26 |
+
if ( 'reset' === $_REQUEST['relevanssi_reset_code'] ) {
|
27 |
+
$verbose = true;
|
28 |
+
relevanssi_truncate_logs( $verbose );
|
29 |
+
}
|
30 |
+
}
|
31 |
+
}
|
32 |
+
|
33 |
+
printf( "<div class='wrap'><h2>%s</h2>", esc_html( $options_txt ) );
|
34 |
+
|
35 |
+
$premium_screens_displayed =
|
36 |
+
function_exists( 'relevanssi_handle_insights_screens' )
|
37 |
+
? relevanssi_handle_insights_screens( $_REQUEST )
|
38 |
+
: false;
|
39 |
+
|
40 |
+
if ( ! $premium_screens_displayed ) {
|
41 |
+
if ( 'on' === get_option( 'relevanssi_log_queries' ) ) {
|
42 |
+
relevanssi_query_log();
|
43 |
+
} else {
|
44 |
+
printf( '<p>%s</p>', esc_html__( 'Enable query logging to see stats here.', 'relevanssi' ) );
|
45 |
+
}
|
46 |
+
}
|
47 |
+
}
|
48 |
+
|
49 |
+
/**
|
50 |
+
* Shows the query log with the most common queries
|
51 |
+
*
|
52 |
+
* Uses relevanssi_total_queries() and relevanssi_date_queries() to fetch the data.
|
53 |
+
*/
|
54 |
+
function relevanssi_query_log() {
|
55 |
+
global $wpdb, $relevanssi_variables;
|
56 |
+
$data = $wpdb->get_results(
|
57 |
+
'SELECT LEFT( `time`, 10 ) as `day`, count(*) as `count` ' .
|
58 |
+
"FROM {$relevanssi_variables['log_table']} " . // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared,WordPress.DB.PreparedSQL.NotPrepared
|
59 |
+
'GROUP BY LEFT( `time`, 10 )'
|
60 |
+
);
|
61 |
+
|
62 |
+
$labels = array();
|
63 |
+
$values = array();
|
64 |
+
$from = gmdate( 'Y-m-d' );
|
65 |
+
foreach ( $data as $point ) {
|
66 |
+
if ( $point->day < $from ) {
|
67 |
+
$from = $point->day;
|
68 |
+
}
|
69 |
+
}
|
70 |
+
|
71 |
+
wp_verify_nonce( '_relevanssi_nonce', 'relevanssi_user_searches' );
|
72 |
+
|
73 |
+
$from_and_to = relevanssi_from_and_to( $_REQUEST, $from );
|
74 |
+
$to = $from_and_to['to'];
|
75 |
+
$from = $from_and_to['from'];
|
76 |
+
|
77 |
+
foreach ( $data as $point ) {
|
78 |
+
if ( $point->day >= $from && $point->day <= $to ) {
|
79 |
+
$labels[] = gmdate( 'M j', strtotime( $point->day ) );
|
80 |
+
$values[] = $point->count;
|
81 |
+
}
|
82 |
+
}
|
83 |
+
|
84 |
+
?>
|
85 |
+
<form method="post" style="background: white; padding: 10px; margin-top: 20px;">
|
86 |
+
<?php
|
87 |
+
wp_nonce_field( 'relevanssi_user_searches', '_relevanssi_nonce', true, true );
|
88 |
+
?>
|
89 |
+
<div style="display: grid; grid-template-columns: 1fr 1fr; grid-gap: 20px">
|
90 |
+
<div>
|
91 |
+
<?php echo esc_html__( 'From:', 'relevanssi' ); ?> <input type="date" name="from" value="<?php echo esc_attr( $from ); ?>" />
|
92 |
+
<?php echo esc_html__( 'To:', 'relevanssi' ); ?> <input type="date" name="to" value="<?php echo esc_attr( $to ); ?>" />
|
93 |
+
<input type="submit" value="<?php echo esc_attr( __( 'Filter', 'relevanssi' ) ); ?>" /></p>
|
94 |
+
</div>
|
95 |
+
<div>
|
96 |
+
<input type="submit" value="<?php echo esc_attr( __( 'Year so far', 'relevanssi' ) ); ?>" name="this_year" style="margin-bottom: 10px" />
|
97 |
+
<input type="submit" value="<?php echo esc_attr( __( 'This month', 'relevanssi' ) ); ?>" name="this_month" />
|
98 |
+
<input type="submit" value="<?php echo esc_attr( __( 'Last month', 'relevanssi' ) ); ?>" name="last_month" />
|
99 |
+
<input type="submit" value="<?php echo esc_attr( __( '30 days', 'relevanssi' ) ); ?>" name="last_30" />
|
100 |
+
<input type="submit" value="<?php echo esc_attr( __( 'This week', 'relevanssi' ) ); ?>" name="this_week" />
|
101 |
+
<input type="submit" value="<?php echo esc_attr( __( 'Last week', 'relevanssi' ) ); ?>" name="last_week" />
|
102 |
+
<input type="submit" value="<?php echo esc_attr( __( '7 days', 'relevanssi' ) ); ?>" name="last_7" />
|
103 |
+
<input type="submit" value="<?php echo esc_attr( __( 'All history', 'relevanssi' ) ); ?>" name="everything" />
|
104 |
+
</div>
|
105 |
+
</div>
|
106 |
+
</form>
|
107 |
+
<?php
|
108 |
+
|
109 |
+
relevanssi_create_line_chart(
|
110 |
+
$labels,
|
111 |
+
array(
|
112 |
+
__( '# of Searches', 'relevanssi' ) => $values,
|
113 |
+
)
|
114 |
+
);
|
115 |
+
|
116 |
+
$total_queries = relevanssi_total_queries( $from, $to );
|
117 |
+
?>
|
118 |
+
<div style="background: white; padding: 10px; display: grid; grid-template-columns: 1fr 2fr 2fr; grid-gap: 20px; margin-top: 20px">
|
119 |
+
<div>
|
120 |
+
<div style="margin-bottom: 20px"><?php esc_html_e( 'Total searches', 'relevanssi' ); ?>
|
121 |
+
<span style="display: block; font-size: 42px; font-weight: bolder; line-height: 50px">
|
122 |
+
<?php echo intval( $total_queries ); ?>
|
123 |
+
</span>
|
124 |
+
</div>
|
125 |
+
<div style="margin-bottom: 20px"><?php esc_html_e( 'Searches that found nothing', 'relevanssi' ); ?>
|
126 |
+
<span style="display: block; font-size: 42px; font-weight: bolder; line-height: 50px">
|
127 |
+
<?php echo intval( relevanssi_nothing_found_queries( $from, $to ) ); ?>
|
128 |
+
</span>
|
129 |
+
</div>
|
130 |
+
<?php
|
131 |
+
if ( function_exists( 'relevanssi_user_searches_clicks' ) ) {
|
132 |
+
relevanssi_user_searches_clicks( $from, $to, $total_queries );
|
133 |
+
}
|
134 |
+
?>
|
135 |
+
</div>
|
136 |
+
<div>
|
137 |
+
<h3><?php esc_html_e( 'Successful searches', 'relevanssi' ); ?></h3>
|
138 |
+
<p><?php esc_html_e( '"Hits" is the average hits this search query has found.', 'relevanssi' ); ?></p>
|
139 |
+
<?php
|
140 |
+
if ( ! function_exists( 'relevanssi_get_query_clicks' ) ) {
|
141 |
+
?>
|
142 |
+
<p><?php esc_html_e( 'In order to see the clicks, you need Relevanssi Premium.', 'relevanssi' ); ?></p>
|
143 |
+
<?php
|
144 |
+
} elseif ( 'on' !== get_option( 'relevanssi_click_tracking' ) ) {
|
145 |
+
?>
|
146 |
+
<p><?php esc_html_e( 'In order to see the clicks, you need to enable click tracking. Click tracking is not currently enabled, and you\'re not collecting new clicks.', 'relevanssi' ); ?></p>
|
147 |
+
<?php
|
148 |
+
}
|
149 |
+
relevanssi_date_queries( $from, $to, 'good' );
|
150 |
+
?>
|
151 |
+
</div>
|
152 |
+
<div>
|
153 |
+
<h3><?php esc_html_e( 'Unsuccessful searches', 'relevanssi' ); ?></h3>
|
154 |
+
<p><?php esc_html_e( 'These queries have found no results.', 'relevanssi' ); ?></p>
|
155 |
+
<?php relevanssi_date_queries( $from, $to, 'bad' ); ?>
|
156 |
+
</div>
|
157 |
+
</div>
|
158 |
+
<?php
|
159 |
+
|
160 |
+
if ( current_user_can( 'manage_options' ) ) {
|
161 |
+
|
162 |
+
echo '<div style="clear: both"></div>';
|
163 |
+
printf( '<h3>%s</h3>', esc_html__( 'Reset Logs', 'relevanssi' ) );
|
164 |
+
print( "<form method='post'>" );
|
165 |
+
wp_nonce_field( 'relevanssi_reset_logs', '_relresnonce', true, true );
|
166 |
+
printf(
|
167 |
+
'<p><label for="relevanssi_reset_code">%s</label>
|
168 |
+
<input type="text" id="relevanssi_reset_code" name="relevanssi_reset_code" />
|
169 |
+
<input type="submit" name="relevanssi_reset" value="%s" class="button" /></p></form>',
|
170 |
+
// Translators: do not translate "reset".
|
171 |
+
esc_html__(
|
172 |
+
'To reset the logs, type "reset" into the box here and click the Reset button',
|
173 |
+
'relevanssi'
|
174 |
+
),
|
175 |
+
esc_html__( 'Reset', 'relevanssi' )
|
176 |
+
);
|
177 |
+
}
|
178 |
+
|
179 |
+
echo '</div>';
|
180 |
+
}
|
181 |
+
|
182 |
+
/**
|
183 |
+
* Shows the total number of searches on 'User searches' page.
|
184 |
+
*
|
185 |
+
* @global object $wpdb The WP database interface.
|
186 |
+
* @global array $relevanssi_variables The global Relevanssi variables array.
|
187 |
+
*
|
188 |
+
* @param string $from The start date.
|
189 |
+
* @param string $to The end date.
|
190 |
+
*
|
191 |
+
* @return int The number of searches.
|
192 |
+
*/
|
193 |
+
function relevanssi_total_queries( string $from, string $to ) {
|
194 |
+
global $wpdb, $relevanssi_variables;
|
195 |
+
$log_table = $relevanssi_variables['log_table'];
|
196 |
+
|
197 |
+
$count = $wpdb->get_var(
|
198 |
+
$wpdb->prepare(
|
199 |
+
"SELECT COUNT(id) FROM $log_table " // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared,WordPress.DB.PreparedSQL.InterpolatedNotPrepared
|
200 |
+
. 'WHERE time >= %s
|
201 |
+
AND time <= %s',
|
202 |
+
$from . ' 00:00:00',
|
203 |
+
$to . ' 23:59:59'
|
204 |
+
)
|
205 |
+
);
|
206 |
+
|
207 |
+
return $count;
|
208 |
+
}
|
209 |
+
|
210 |
+
/**
|
211 |
+
* Shows the total number of searches on 'User searches' page.
|
212 |
+
*
|
213 |
+
* @global object $wpdb The WP database interface.
|
214 |
+
* @global array $relevanssi_variables The global Relevanssi variables array.
|
215 |
+
*
|
216 |
+
* @param string $from The start date.
|
217 |
+
* @param string $to The end date.
|
218 |
+
*/
|
219 |
+
function relevanssi_nothing_found_queries( string $from, string $to ) {
|
220 |
+
global $wpdb, $relevanssi_variables;
|
221 |
+
$log_table = $relevanssi_variables['log_table'];
|
222 |
+
|
223 |
+
$count = $wpdb->get_var(
|
224 |
+
$wpdb->prepare(
|
225 |
+
"SELECT COUNT(id) FROM $log_table " // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared,WordPress.DB.PreparedSQL.InterpolatedNotPrepared
|
226 |
+
. 'WHERE time >= %s
|
227 |
+
AND time <= %s
|
228 |
+
AND hits = 0',
|
229 |
+
$from . ' 00:00:00',
|
230 |
+
$to . ' 23:59:59'
|
231 |
+
)
|
232 |
+
);
|
233 |
+
|
234 |
+
return $count;
|
235 |
+
}
|
236 |
+
|
237 |
+
/**
|
238 |
+
* Shows the most common search queries on different time periods.
|
239 |
+
*
|
240 |
+
* @global object $wpdb The WP database interface.
|
241 |
+
* @global array $relevanssi_variables The global Relevanssi variables array.
|
242 |
+
*
|
243 |
+
* @param string $from The beginning date.
|
244 |
+
* @param string $to The ending date.
|
245 |
+
* @param string $version If 'good', show the searches that found something; if
|
246 |
+
* 'bad', show the searches that didn't find anything. Default 'good'.
|
247 |
+
*/
|
248 |
+
function relevanssi_date_queries( string $from, string $to, string $version = 'good' ) {
|
249 |
+
global $wpdb, $relevanssi_variables;
|
250 |
+
$log_table = $relevanssi_variables['log_table'];
|
251 |
+
|
252 |
+
/** Documented in lib/interface.php. */
|
253 |
+
$limit = apply_filters( 'relevanssi_user_searches_limit', 100 );
|
254 |
+
|
255 |
+
if ( 'good' === $version ) {
|
256 |
+
$queries = $wpdb->get_results(
|
257 |
+
$wpdb->prepare(
|
258 |
+
'SELECT COUNT(DISTINCT(id)) as cnt, query, AVG(hits) AS hits ' .
|
259 |
+
"FROM $log_table " . // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared,WordPress.DB.PreparedSQL.InterpolatedNotPrepared
|
260 |
+
'WHERE time >= %s
|
261 |
+
AND time <= %s
|
262 |
+
AND hits > 0
|
263 |
+
GROUP BY query
|
264 |
+
ORDER BY cnt DESC
|
265 |
+
LIMIT %d',
|
266 |
+
$from . ' 00:00:00',
|
267 |
+
$to . ' 23:59:59',
|
268 |
+
$limit
|
269 |
+
)
|
270 |
+
);
|
271 |
+
}
|
272 |
+
|
273 |
+
if ( 'bad' === $version ) {
|
274 |
+
$queries = $wpdb->get_results(
|
275 |
+
$wpdb->prepare(
|
276 |
+
'SELECT COUNT(DISTINCT(id)) as cnt, query, hits ' .
|
277 |
+
"FROM $log_table " . // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared,WordPress.DB.PreparedSQL.InterpolatedNotPrepared
|
278 |
+
'WHERE time >= %s
|
279 |
+
AND time <= %s
|
280 |
+
AND hits = 0
|
281 |
+
GROUP BY query
|
282 |
+
ORDER BY cnt DESC
|
283 |
+
LIMIT %d',
|
284 |
+
$from . ' 00:00:00',
|
285 |
+
$to . ' 23:59:59',
|
286 |
+
$limit
|
287 |
+
)
|
288 |
+
);
|
289 |
+
}
|
290 |
+
|
291 |
+
if ( count( $queries ) > 0 ) {
|
292 |
+
if ( 'good' === $version ) {
|
293 |
+
printf(
|
294 |
+
"<table class='widefat' style='border: none'>
|
295 |
+
<thead>
|
296 |
+
<tr>
|
297 |
+
<th>%s</th>
|
298 |
+
<th style='text-align: center'>#</th>
|
299 |
+
<th style='text-align: center'>%s</th>
|
300 |
+
<th style='text-align: center'>%s</th>
|
301 |
+
</tr>
|
302 |
+
</thead>
|
303 |
+
<tbody>",
|
304 |
+
esc_html__( 'Query', 'relevanssi' ),
|
305 |
+
esc_html__( 'Hits', 'relevanssi' ),
|
306 |
+
esc_html__( 'Clicks', 'relevanssi' )
|
307 |
+
);
|
308 |
+
} else {
|
309 |
+
printf(
|
310 |
+
"<table class='widefat' style='border: none'>
|
311 |
+
<thead>
|
312 |
+
<tr>
|
313 |
+
<th>%s</th>
|
314 |
+
<th style='text-align: center'>#</th>
|
315 |
+
</tr>
|
316 |
+
</thead>
|
317 |
+
<tbody>",
|
318 |
+
esc_html__( 'Query', 'relevanssi' )
|
319 |
+
);
|
320 |
+
}
|
321 |
+
$url = get_bloginfo( 'url' );
|
322 |
+
foreach ( $queries as $query ) {
|
323 |
+
if ( 'good' === $version && function_exists( 'relevanssi_get_query_clicks' ) ) {
|
324 |
+
$clicks = intval( relevanssi_get_query_clicks( $query->query ) );
|
325 |
+
} else {
|
326 |
+
$clicks = '-';
|
327 |
+
}
|
328 |
+
$search_parameter = rawurlencode( $query->query );
|
329 |
+
/**
|
330 |
+
* Filters the query URL for the user searches page.
|
331 |
+
*
|
332 |
+
* @param string Query URL.
|
333 |
+
*/
|
334 |
+
$query_url = apply_filters( 'relevanssi_user_searches_query_url', $url . '/?s=' . $search_parameter );
|
335 |
+
|
336 |
+
if ( function_exists( 'relevanssi_insights_link' ) ) {
|
337 |
+
$query_link = relevanssi_insights_link( $query );
|
338 |
+
} else {
|
339 |
+
$query_link = $query->query;
|
340 |
+
}
|
341 |
+
|
342 |
+
if ( 'good' === $version ) {
|
343 |
+
printf(
|
344 |
+
"<tr>
|
345 |
+
<td>%s <a href='%s'><span class='dashicons dashicons-external'></span></a></td>
|
346 |
+
<td style='padding: 3px 5px; text-align: center'>%d</td>
|
347 |
+
<td style='padding: 3px 5px; text-align: center'>%d</td>
|
348 |
+
<td style='padding: 3px 5px; text-align: center'>%s</td>
|
349 |
+
</tr>",
|
350 |
+
$query_link, // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
351 |
+
esc_attr( $query_url ),
|
352 |
+
intval( $query->cnt ),
|
353 |
+
intval( $query->hits ),
|
354 |
+
$clicks // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
355 |
+
);
|
356 |
+
} else {
|
357 |
+
printf(
|
358 |
+
"<tr>
|
359 |
+
<td>%s <a href='%s'><span class='dashicons dashicons-external'></span></a></td>
|
360 |
+
<td style='padding: 3px 5px; text-align: center'>%d</td>
|
361 |
+
</tr>",
|
362 |
+
$query_link, // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
363 |
+
esc_attr( $query_url ),
|
364 |
+
intval( $query->cnt )
|
365 |
+
);
|
366 |
+
}
|
367 |
+
}
|
368 |
+
echo '</tbody></table>';
|
369 |
+
}
|
370 |
+
}
|
lib/utils.php
CHANGED
@@ -20,6 +20,17 @@ function get_relevanssi_taxonomy_walker() {
|
|
20 |
return new Relevanssi_Taxonomy_Walker();
|
21 |
}
|
22 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
23 |
/**
|
24 |
* Adds quotes around a string.
|
25 |
*
|
@@ -45,6 +56,25 @@ function relevanssi_array_walk_trim( string &$string ) {
|
|
45 |
$string = relevanssi_mb_trim( $string );
|
46 |
}
|
47 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
48 |
/**
|
49 |
* Returns 'checked' if the option is enabled.
|
50 |
*
|
@@ -175,6 +205,79 @@ function relevanssi_flatten_array( array $array ) {
|
|
175 |
return trim( $return_value );
|
176 |
}
|
177 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
178 |
/**
|
179 |
* Generates closing tags for an array of tags.
|
180 |
*
|
20 |
return new Relevanssi_Taxonomy_Walker();
|
21 |
}
|
22 |
|
23 |
+
/**
|
24 |
+
* Adds apostrophes around a string.
|
25 |
+
*
|
26 |
+
* @param string $string The string.
|
27 |
+
*
|
28 |
+
* @return string The string with apostrophes around it.
|
29 |
+
*/
|
30 |
+
function relevanssi_add_apostrophes( $string ) {
|
31 |
+
return "'" . $string . "'";
|
32 |
+
}
|
33 |
+
|
34 |
/**
|
35 |
* Adds quotes around a string.
|
36 |
*
|
56 |
$string = relevanssi_mb_trim( $string );
|
57 |
}
|
58 |
|
59 |
+
/**
|
60 |
+
* Converts sums in an array to averages, based on an array containing counts.
|
61 |
+
*
|
62 |
+
* Both arrays need to have (key, value) pairs with the same keys. The values
|
63 |
+
* in $array are then divided by the matching values in $counts, so when we have
|
64 |
+
* sums in $array and counts in $counts, we end up with averages.
|
65 |
+
*
|
66 |
+
* @param array $array The array with sums, passed as reference.
|
67 |
+
* @param array $counts The array with counts.
|
68 |
+
*/
|
69 |
+
function relevanssi_average_array( array &$array, array $counts ) {
|
70 |
+
array_walk(
|
71 |
+
$array,
|
72 |
+
function ( &$value, $key ) use ( $counts ) {
|
73 |
+
$value = $value / $counts[ $key ];
|
74 |
+
}
|
75 |
+
);
|
76 |
+
}
|
77 |
+
|
78 |
/**
|
79 |
* Returns 'checked' if the option is enabled.
|
80 |
*
|
205 |
return trim( $return_value );
|
206 |
}
|
207 |
|
208 |
+
/**
|
209 |
+
* Generates from and to date values from ranges.
|
210 |
+
*
|
211 |
+
* Possible values in the $request array: 'from' and 'to' for direct dates,
|
212 |
+
* 'this_year' for Jan 1st to today, 'this_month' for 1st of month to today,
|
213 |
+
* 'last_month' for 1st of previous month to last of previous month,
|
214 |
+
* 'this_week' for Monday of this week to today (or Sunday, if the
|
215 |
+
* relevanssi_week_starts_on_sunday returns `true`), 'last_week' for the
|
216 |
+
* previous week, 'last_30' for from 30 days ago to today, 'last_7' for from
|
217 |
+
* 7 days ago to today.
|
218 |
+
*
|
219 |
+
* @param array $request The request array where the settings are.
|
220 |
+
* @param string $from The default 'from' date in "Y-m-d" format.
|
221 |
+
* @return array The from date in 'from' and the to date in 'to' in "Y-m-d"
|
222 |
+
* format.
|
223 |
+
*/
|
224 |
+
function relevanssi_from_and_to( array $request, string $from ) : array {
|
225 |
+
$today = gmdate( 'Y-m-d' );
|
226 |
+
$week_start = 'monday';
|
227 |
+
$to = $today;
|
228 |
+
|
229 |
+
/**
|
230 |
+
* Controls whether the week starts on Sunday or Monday.
|
231 |
+
*
|
232 |
+
* @param boolean If `true`, week starts on Sunday. Default `false`, week
|
233 |
+
* starts on Monday.
|
234 |
+
*/
|
235 |
+
if ( apply_filters( 'relevanssi_week_starts_on_sunday', false ) ) {
|
236 |
+
$week_start = 'sunday';
|
237 |
+
}
|
238 |
+
if ( ! isset( $request['everything'] ) && isset( $request['from'] ) && $request['from'] > $from ) {
|
239 |
+
$from = $request['from'];
|
240 |
+
}
|
241 |
+
if ( ! isset( $request['everything'] ) && isset( $request['to'] ) && $request['to'] < $today ) {
|
242 |
+
$to = $request['to'];
|
243 |
+
}
|
244 |
+
if ( isset( $request['this_year'] ) ) {
|
245 |
+
$from = gmdate( 'Y-m-d', strtotime( 'first day of january this year' ) );
|
246 |
+
$to = gmdate( 'Y-m-d' );
|
247 |
+
}
|
248 |
+
if ( isset( $request['this_month'] ) ) {
|
249 |
+
$from = gmdate( 'Y-m-d', strtotime( 'first day of this month' ) );
|
250 |
+
$to = gmdate( 'Y-m-d' );
|
251 |
+
}
|
252 |
+
if ( isset( $request['last_month'] ) ) {
|
253 |
+
$from = gmdate( 'Y-m-d', strtotime( 'first day of previous month' ) );
|
254 |
+
$to = gmdate( 'Y-m-d', strtotime( 'last day of previous month' ) );
|
255 |
+
}
|
256 |
+
if ( isset( $request['this_week'] ) ) {
|
257 |
+
$from = gmdate( 'Y-m-d', strtotime( 'previous ' . $week_start ) );
|
258 |
+
$to = gmdate( 'Y-m-d' );
|
259 |
+
}
|
260 |
+
if ( isset( $request['last_week'] ) ) {
|
261 |
+
$start = 'sunday' === $week_start ? gmdate( 'w' ) + 7 : gmdate( 'w' ) + 6;
|
262 |
+
$end = 'sunday' === $week_start ? gmdate( 'w' ) + 1 : gmdate( 'w' );
|
263 |
+
$from = gmdate( 'Y-m-d', strtotime( '-' . $start . ' days' ) );
|
264 |
+
$to = gmdate( 'Y-m-d', strtotime( '-' . $end . ' days' ) );
|
265 |
+
}
|
266 |
+
if ( isset( $request['last_30'] ) ) {
|
267 |
+
$from = gmdate( 'Y-m-d', strtotime( '-30 days' ) );
|
268 |
+
$to = gmdate( 'Y-m-d' );
|
269 |
+
}
|
270 |
+
if ( isset( $request['last_7'] ) ) {
|
271 |
+
$from = gmdate( 'Y-m-d', strtotime( '-7 days' ) );
|
272 |
+
$to = gmdate( 'Y-m-d' );
|
273 |
+
}
|
274 |
+
|
275 |
+
return array(
|
276 |
+
'from' => $from,
|
277 |
+
'to' => $to,
|
278 |
+
);
|
279 |
+
}
|
280 |
+
|
281 |
/**
|
282 |
* Generates closing tags for an array of tags.
|
283 |
*
|
readme.txt
CHANGED
@@ -3,9 +3,9 @@ Contributors: msaari
|
|
3 |
Donate link: https://www.relevanssi.com/buy-premium/
|
4 |
Tags: search, relevance, better search, product search, woocommerce search
|
5 |
Requires at least: 4.9
|
6 |
-
Tested up to: 5.8
|
7 |
Requires PHP: 7.0
|
8 |
-
Stable tag: 4.
|
9 |
License: GPLv2 or later
|
10 |
License URI: http://www.gnu.org/licenses/gpl-2.0.html
|
11 |
|
@@ -131,6 +131,24 @@ 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.3.1 =
|
135 |
* Minor fix: The Bricks compatibility was broken. This version fixes it.
|
136 |
|
@@ -226,28 +244,13 @@ Each document database is full of useless words. All the little words that appea
|
|
226 |
* Minor fix: Old legacy scripts that caused Javascript warnings on admin pages have been removed.
|
227 |
* Minor fix: In some cases, having less than or greater than symbols in PDF content would block that PDF content from being indexed.
|
228 |
|
229 |
-
|
230 |
-
|
231 |
-
*
|
232 |
-
* Minor fix: Highlighting didn't work properly when highlighting something immediately following a HTML tag.
|
233 |
-
* 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.
|
234 |
-
* Minor fix: Importing options broke synonym and stopword settings.
|
235 |
-
* Minor fix: Improves the Rank Math SEO compatibility to avoid errors in plugin activation.
|
236 |
-
* 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.
|
237 |
-
|
238 |
-
= 4.10.1 =
|
239 |
-
* 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.
|
240 |
|
241 |
-
= 4.
|
242 |
-
*
|
243 |
-
* New feature: SEO by Rank Math compatibility is added: posts marked as 'noindex' with Rank Math are not indexed by Relevanssi.
|
244 |
-
* Minor fix: With keyword matching set to 'whole words' and the 'expand highlights' disabled, words that ended with an 's' weren't highlighted correctly.
|
245 |
-
* Minor fix: The 'Post exclusion' setting didn't work correctly. It has been fixed.
|
246 |
-
* Minor fix: It's now impossible to set negative weights in searching settings. They did not work as expected anyway.
|
247 |
-
* Minor fix: Relevanssi had an unnecessary index on the `doc` column in the `wp_relevanssi` database table. It is now removed to save space. Thanks to Matthew Wang.
|
248 |
-
* Minor fix: Improved Oxygen Builder support makes sure `ct_builder_shortcodes` custom field is always indexed.
|
249 |
|
250 |
-
== Upgrade notice ==
|
251 |
= 4.13.3.1 =
|
252 |
* Fixes the Bricks compatibility.
|
253 |
|
3 |
Donate link: https://www.relevanssi.com/buy-premium/
|
4 |
Tags: search, relevance, better search, product search, woocommerce search
|
5 |
Requires at least: 4.9
|
6 |
+
Tested up to: 5.8.1
|
7 |
Requires PHP: 7.0
|
8 |
+
Stable tag: 4.14.1
|
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.14.1 =
|
135 |
+
* Adds a missing file.
|
136 |
+
|
137 |
+
= 4.14.0 =
|
138 |
+
* New feature: New filter hook `relevanssi_render_blocks` controls whether Relevanssi renders blocks in a post or not. If you are having problems updating long posts with lots of blocks, having this filter hook return `false` for the post in question will likely help, as rendering the blocks in a long post can take huge amounts of memory.
|
139 |
+
* New feature: The user searches page has been improved a lot.
|
140 |
+
* New feature: The [searchform] shortcode has a new parameter, 'post_type_boxes', which creates a checkbox for each post type you list in the value. For example [searchform post_type_boxes='*post,page'] would create a search with a checkbox for 'post' and 'page' post types, with 'post' pre-checked.
|
141 |
+
* New feature: You can now have multiple dropdowns in one [searchform] shortcode. Anything that begins with 'dropdown' is considered a dropdown parameter, so you can do [searchform dropdown_1='category' dropdown_2='post_tag'] for example.
|
142 |
+
* New feature: New filter hook `relevanssi_search_params` lets you filter search parameters after they've been collected from the WP_Query.
|
143 |
+
* New feature: New filter hook `relevanssi_excerpt_post` lets you make Relevanssi skip creating excerpts for specific posts.
|
144 |
+
* Changed behaviour: Filter hooks `relevanssi_1day`, `relevanssi_7days` and `relevanssi_30days` are removed, as the user searches page is now different. The default value for `relevanssi_user_searches_limit` is now 100 instead of 20.
|
145 |
+
* Minor fix: In some languages, iOS uses „“ for quotes. Relevanssi now understands those for the phrase operator.
|
146 |
+
* Minor fix: Stops Relevanssi from blocking the admin search for WooCommerce coupons and other WooCommerce custom post types.
|
147 |
+
* Minor fix: Fixes problems with the WP-Members compatibility.
|
148 |
+
* Minor fix: New parameter for `relevanssi_tokenize()` introduces the context (indexing or search query). The `relevanssi_extract_phrases()` is only used on search queries.
|
149 |
+
* Minor fix: Relevanssi won't let you adjust synonyms and stopwords anymore if you use Polylang and are in 'Show all languages' mode.
|
150 |
+
* Minor fix: Highlighting is improved by a more precise HTML entity filter, thanks to Jacob Bearce.
|
151 |
+
|
152 |
= 4.13.3.1 =
|
153 |
* Minor fix: The Bricks compatibility was broken. This version fixes it.
|
154 |
|
244 |
* Minor fix: Old legacy scripts that caused Javascript warnings on admin pages have been removed.
|
245 |
* Minor fix: In some cases, having less than or greater than symbols in PDF content would block that PDF content from being indexed.
|
246 |
|
247 |
+
== Upgrade notice ==
|
248 |
+
= 4.14.1 =
|
249 |
+
* Adds a missing file.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
250 |
|
251 |
+
= 4.14.0 =
|
252 |
+
* User searches page update, bug fixes and improvements.
|
|
|
|
|
|
|
|
|
|
|
|
|
253 |
|
|
|
254 |
= 4.13.3.1 =
|
255 |
* Fixes the Bricks compatibility.
|
256 |
|
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.
|
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.
|
71 |
|
72 |
require_once 'lib/admin-ajax.php';
|
73 |
require_once 'lib/common.php';
|
@@ -87,4 +87,5 @@ require_once 'lib/search-query-restrictions.php';
|
|
87 |
require_once 'lib/shortcodes.php';
|
88 |
require_once 'lib/sorting.php';
|
89 |
require_once 'lib/stopwords.php';
|
|
|
90 |
require_once 'lib/utils.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.14.1
|
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.14.1';
|
71 |
|
72 |
require_once 'lib/admin-ajax.php';
|
73 |
require_once 'lib/common.php';
|
87 |
require_once 'lib/shortcodes.php';
|
88 |
require_once 'lib/sorting.php';
|
89 |
require_once 'lib/stopwords.php';
|
90 |
+
require_once 'lib/user-searches.php';
|
91 |
require_once 'lib/utils.php';
|