Version Description
- New feature: The search form shortcode has a new parameter
dropdown
which can be used to add a category dropdown, like this:[searchform dropdown="category"]
. - New feature: Relevanssi can now use the contents of the PDF files indexed with WP File Download.
- New filter:
relevanssi_indexing_tokens
can be used to filter the tokens (individual words) before they are indexed. - Removed filter:
relevanssi_default_meta_query_relation
did not have any effect anymore. - Changed behaviour: The default taxonomy relation was set to AND in 4.1.4, but wasn't properly applied before. Now it is really switched.
- Changed behaviour: New post types have been added to list of forbidden post types Relevanssi won't show as indexing options (ACF, TablePress and WooCommerce).
- Major fix: Tax query processing has been completely refactored, eliminating all sorts of bugs, especially with various edge cases.
- Major fix: Gutenberg block indexing only worked with the Gutenberg plugin enabled. It now works with WP 5.0 built-in Gutenberg as well. If you use Gutenberg blocks, reindex to get all the block content in the index.
- Major fix: Excerpt-building and highlighting did not respect the "Keyword matching" setting. They do now, and the excerpts should be better now.
- Major fix: AND searches needed queries that could get too long for the database to handle. This has been fixed and optimized.
- Major fix: Taxonomy term subquery relations didn't work; now they are applied.
- Minor fix: iOS uses curly quotes by default, and that didn't work as a phrase operator. Now phrase operator works with curly quotes and straight quotes.
- Minor fix: The Did you mean broke with search terms longer than 255 characters.
- Minor fix: Phrases with numbers and one word like "team 17" didn't work, because numbers weren't counted as words.
Download this release
Release Info
Developer | msaari |
Plugin | Relevanssi – A Better Search |
Version | 4.2.0 |
Comparing to | |
See all releases |
Code changes from version 4.1.4 to 4.2.0
- lib/admin-ajax.php +22 -16
- lib/admin_scripts.js +399 -300
- lib/admin_scripts_free.js +45 -45
- lib/common.php +68 -31
- lib/compatibility/gutenberg.php +2 -3
- lib/compatibility/wp-file-download.php +44 -0
- lib/contextual-help.php +2 -0
- lib/excerpts-highlights.php +18 -8
- lib/indexing.php +20 -7
- lib/init.php +5 -1
- lib/interface.php +19 -0
- lib/search-query-restrictions.php +515 -0
- lib/search-tax-query.php +360 -0
- lib/search.php +96 -754
- lib/shortcodes.php +25 -4
- lib/sorting.php +3 -3
- lib/stopwords.php +0 -3
- lib/tabs/searching-tab.php +4 -0
- lib/tabs/stopwords-tab.php +11 -5
- readme.txt +21 -2
- relevanssi.php +10 -8
- relevanssi.po +215 -153
lib/admin-ajax.php
CHANGED
@@ -174,7 +174,7 @@ function relevanssi_admin_search() {
|
|
174 |
if ( isset( $query->query_vars['offset'] ) ) {
|
175 |
$offset = $query->query_vars['offset'];
|
176 |
}
|
177 |
-
$results .= relevanssi_admin_search_format_posts( $query->posts, $query->found_posts, $offset );
|
178 |
|
179 |
echo wp_json_encode( $results );
|
180 |
wp_die();
|
@@ -186,23 +186,24 @@ function relevanssi_admin_search() {
|
|
186 |
* Results are presented as an ordered list of posts. The format is very basic, and
|
187 |
* can be modified with the 'relevanssi_admin_search_element' filter hook.
|
188 |
*
|
189 |
-
* @param array
|
190 |
-
* @param int
|
191 |
-
* @param int
|
|
|
192 |
*
|
193 |
* @return string The formatted posts.
|
194 |
*
|
195 |
* @since 2.2.0
|
196 |
*/
|
197 |
-
function relevanssi_admin_search_format_posts( $posts, $total, $offset ) {
|
198 |
$result = '<h3>' . __( 'Results', 'relevanssi' ) . '</h3>';
|
199 |
// Translators: %1$d is the total number of posts found, %2$d is the current search result count, %3$d is the offset.
|
200 |
$result .= '<p>' . sprintf( __( 'Found a total of %1$d posts, showing %2$d posts from offset %3$s.', 'relevanssi' ), $total, count( $posts ), '<span id="offset">' . $offset . '</span>' ) . '</p>';
|
201 |
if ( $offset > 0 ) {
|
202 |
-
$result .= '<button type="button" id="prev_page">Previous page
|
203 |
}
|
204 |
if ( count( $posts ) + $offset < $total ) {
|
205 |
-
$result .= '<button type="button" id="next_page">Next page
|
206 |
}
|
207 |
$result .= '<ol>';
|
208 |
|
@@ -215,25 +216,31 @@ function relevanssi_admin_search_format_posts( $posts, $total, $offset ) {
|
|
215 |
$blog_name = get_bloginfo( 'name' ) . ': ';
|
216 |
}
|
217 |
$permalink = get_permalink( $post->ID );
|
218 |
-
$
|
219 |
$post_type = $post->post_type;
|
220 |
if ( isset( $post->relevanssi_link ) ) {
|
221 |
$permalink = $post->relevanssi_link;
|
222 |
}
|
223 |
if ( 'user' === $post->post_type ) {
|
224 |
-
$
|
225 |
}
|
226 |
-
if ( empty( $
|
227 |
if ( isset( $post->term_id ) ) {
|
228 |
-
$
|
229 |
}
|
230 |
}
|
231 |
-
$
|
232 |
-
|
233 |
-
|
|
|
|
|
|
|
|
|
|
|
234 |
}
|
|
|
235 |
$post_element = <<<EOH
|
236 |
-
<li>$blog_name <strong>$post->post_title</strong> (
|
237 |
$post->post_excerpt<br />
|
238 |
$score_label $post->relevance_score $pinned</li>
|
239 |
EOH;
|
@@ -309,7 +316,6 @@ function relevanssi_admin_search_debugging_info( $query ) {
|
|
309 |
'relevanssi_orderby',
|
310 |
'relevanssi_order',
|
311 |
'relevanssi_default_tax_query_relation',
|
312 |
-
'relevanssi_default_meta_query_relation',
|
313 |
'relevanssi_hits_filter',
|
314 |
);
|
315 |
|
174 |
if ( isset( $query->query_vars['offset'] ) ) {
|
175 |
$offset = $query->query_vars['offset'];
|
176 |
}
|
177 |
+
$results .= relevanssi_admin_search_format_posts( $query->posts, $query->found_posts, $offset, $args['s'] );
|
178 |
|
179 |
echo wp_json_encode( $results );
|
180 |
wp_die();
|
186 |
* Results are presented as an ordered list of posts. The format is very basic, and
|
187 |
* can be modified with the 'relevanssi_admin_search_element' filter hook.
|
188 |
*
|
189 |
+
* @param array $posts The posts array.
|
190 |
+
* @param int $total The number of posts found in total.
|
191 |
+
* @param int $offset Offset value.
|
192 |
+
* @param string $query The search query.
|
193 |
*
|
194 |
* @return string The formatted posts.
|
195 |
*
|
196 |
* @since 2.2.0
|
197 |
*/
|
198 |
+
function relevanssi_admin_search_format_posts( $posts, $total, $offset, $query ) {
|
199 |
$result = '<h3>' . __( 'Results', 'relevanssi' ) . '</h3>';
|
200 |
// Translators: %1$d is the total number of posts found, %2$d is the current search result count, %3$d is the offset.
|
201 |
$result .= '<p>' . sprintf( __( 'Found a total of %1$d posts, showing %2$d posts from offset %3$s.', 'relevanssi' ), $total, count( $posts ), '<span id="offset">' . $offset . '</span>' ) . '</p>';
|
202 |
if ( $offset > 0 ) {
|
203 |
+
$result .= sprintf( '<button type="button" id="prev_page">%s</button>', __( 'Previous page', 'relevanssi' ) );
|
204 |
}
|
205 |
if ( count( $posts ) + $offset < $total ) {
|
206 |
+
$result .= sprintf( '<button type="button" id="next_page">%s</button>', __( 'Next page', 'relevanssi' ) );
|
207 |
}
|
208 |
$result .= '<ol>';
|
209 |
|
216 |
$blog_name = get_bloginfo( 'name' ) . ': ';
|
217 |
}
|
218 |
$permalink = get_permalink( $post->ID );
|
219 |
+
$edit_url = get_edit_post_link( $post->ID );
|
220 |
$post_type = $post->post_type;
|
221 |
if ( isset( $post->relevanssi_link ) ) {
|
222 |
$permalink = $post->relevanssi_link;
|
223 |
}
|
224 |
if ( 'user' === $post->post_type ) {
|
225 |
+
$edit_url = get_edit_user_link( $post->ID );
|
226 |
}
|
227 |
+
if ( empty( $edit_url ) ) {
|
228 |
if ( isset( $post->term_id ) ) {
|
229 |
+
$edit_url = get_edit_term_link( $post->term_id, $post->post_type );
|
230 |
}
|
231 |
}
|
232 |
+
$view_link = sprintf( '<a href="%1$s">%2$s %3$s</a>', $permalink, __( 'View', 'relevanssi' ), $post_type );
|
233 |
+
$edit_link = sprintf( '<a href="%1$s">%2$s %3$s</a>', $edit_url, __( 'Edit', 'relevanssi' ), $post_type );
|
234 |
+
$pinning_buttons = '';
|
235 |
+
$pinned = '';
|
236 |
+
|
237 |
+
if ( function_exists( 'relevanssi_admin_search_pinning' ) ) {
|
238 |
+
// Relevanssi Premium adds pinning features to the admin search.
|
239 |
+
list( $pinning_buttons, $pinned ) = relevanssi_admin_search_pinning( $post, $query );
|
240 |
}
|
241 |
+
|
242 |
$post_element = <<<EOH
|
243 |
+
<li>$blog_name <strong>$post->post_title</strong> ($view_link) ($edit_link) $pinning_buttons <br />
|
244 |
$post->post_excerpt<br />
|
245 |
$score_label $post->relevance_score $pinned</li>
|
246 |
EOH;
|
316 |
'relevanssi_orderby',
|
317 |
'relevanssi_order',
|
318 |
'relevanssi_default_tax_query_relation',
|
|
|
319 |
'relevanssi_hits_filter',
|
320 |
);
|
321 |
|
lib/admin_scripts.js
CHANGED
@@ -1,403 +1,502 @@
|
|
1 |
/* Confirmation for copying options between blogs */
|
2 |
|
3 |
jQuery(document).ready(function($) {
|
4 |
-
|
5 |
-
|
6 |
-
|
7 |
-
|
8 |
-
|
9 |
-
|
10 |
-
|
11 |
-
|
12 |
-
|
13 |
-
})
|
14 |
-
|
15 |
-
jQuery(document).ready(function($){
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
-
txtcol_control.addClass(
|
25 |
-
bgcol_control.addClass(
|
26 |
-
class_control.addClass(
|
27 |
-
css_control.addClass(
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
var post_type_archives = $("#posttypearchives")
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
|
81 |
$("#indexing_tab :input").change(function(e) {
|
82 |
-
$("#build_index").attr("disabled", "disabled")
|
83 |
-
var relevanssi_note = $("#relevanssi-note")
|
84 |
-
relevanssi_note.show()
|
85 |
-
relevanssi_note.html(relevanssi.options_changed)
|
86 |
-
})
|
87 |
|
88 |
$("#relevanssi_default_orderby").change(function(e) {
|
89 |
if (this.value == "post_date") {
|
90 |
-
$("#relevanssi_throttle").prop("checked", false)
|
91 |
}
|
92 |
-
$("#throttle_disabled").toggleClass(
|
93 |
-
$("#throttle_enabled").toggleClass(
|
94 |
-
})
|
95 |
|
96 |
$("#relevanssi_show_pdf_errors").click(function(e) {
|
97 |
-
var error_box = $("#relevanssi_pdf_errors")
|
98 |
-
error_box.toggle()
|
99 |
var data = {
|
100 |
-
|
101 |
-
}
|
102 |
jQuery.post(ajaxurl, data, function(response) {
|
103 |
-
error_box.val(JSON.parse(response))
|
104 |
-
})
|
105 |
-
})
|
106 |
|
107 |
$("#relevanssi_excerpts").click(function() {
|
108 |
-
$("#relevanssi_breakdown").toggleClass(
|
109 |
-
$("#relevanssi_highlighting").toggleClass(
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
$("#
|
114 |
-
|
115 |
-
|
116 |
-
|
117 |
-
$("#
|
118 |
-
|
119 |
-
|
120 |
-
|
121 |
-
$("#
|
122 |
-
$("#
|
123 |
-
$("#
|
124 |
-
$("#
|
125 |
-
$("#
|
126 |
-
$("#
|
127 |
-
$("#
|
128 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
129 |
|
130 |
$("#relevanssi_searchblogs_all").click(function() {
|
131 |
-
$("#relevanssi_searchblogs").attr(
|
132 |
-
})
|
133 |
-
})
|
134 |
|
135 |
-
var time = 0
|
136 |
-
var intervalID = 0
|
137 |
|
138 |
function relevanssiUpdateClock() {
|
139 |
-
time
|
140 |
-
var time_formatted = rlv_format_time(Math.round(time))
|
141 |
-
document.getElementById("relevanssi_elapsed").innerHTML = time_formatted
|
142 |
}
|
143 |
|
144 |
jQuery(document).ready(function($) {
|
145 |
$("#continue_indexing").click(function() {
|
146 |
-
|
147 |
-
$("#results").show()
|
148 |
-
$("#relevanssi-timer").show()
|
149 |
-
$("#stateoftheindex").html(relevanssi.reload_state)
|
150 |
-
$("#indexing_button_instructions").hide()
|
151 |
-
var results = document.getElementById("results")
|
152 |
-
results.value = ""
|
153 |
|
154 |
-
intervalID = window.setInterval(relevanssiUpdateClock, 1000)
|
155 |
|
156 |
var data = {
|
157 |
-
|
158 |
-
}
|
159 |
-
console.log("Counting posts.")
|
160 |
-
results.value += relevanssi.counting_posts + " "
|
161 |
jQuery.post(ajaxurl, data, function(response) {
|
162 |
-
count_response = JSON.parse(response)
|
163 |
-
console.log("Counted " + count_response + " posts.")
|
164 |
-
results.value += count_response + " " + relevanssi.posts_found + "\n"
|
165 |
|
166 |
if (count_response > 0) {
|
167 |
var args = {
|
168 |
-
|
169 |
-
|
170 |
-
|
171 |
-
|
172 |
-
|
173 |
-
|
174 |
-
|
175 |
-
}
|
176 |
-
process_indexing_step(args)
|
177 |
-
}
|
178 |
-
|
179 |
-
clearInterval(intervalID);
|
180 |
}
|
181 |
-
})
|
182 |
-
})
|
183 |
-
})
|
184 |
|
185 |
function process_indexing_step(args) {
|
186 |
// console.log(args.completed + " / " + args.total);
|
187 |
-
var t0 = performance.now()
|
188 |
jQuery.ajax({
|
189 |
-
type:
|
190 |
url: ajaxurl,
|
191 |
data: {
|
192 |
-
action:
|
193 |
completed: args.completed,
|
194 |
total: args.total,
|
195 |
offset: args.offset,
|
196 |
limit: args.limit,
|
197 |
extend: args.extend,
|
198 |
-
security: args.security
|
199 |
},
|
200 |
-
dataType:
|
201 |
success: function(response) {
|
202 |
-
console.log(response)
|
203 |
if (response.completed == "done") {
|
204 |
//console.log("response " + parseInt(response.total_posts));
|
205 |
-
var results_textarea = document.getElementById("results")
|
206 |
-
results_textarea.value += response.feedback
|
207 |
-
|
208 |
-
document.getElementById("relevanssi_estimated").innerHTML =
|
209 |
-
|
210 |
-
|
211 |
-
|
212 |
-
results_textarea.
|
213 |
-
|
214 |
-
|
215 |
-
|
216 |
-
|
217 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
218 |
|
219 |
-
clearInterval(intervalID);
|
220 |
-
}
|
221 |
-
else {
|
222 |
-
var t1 = performance.now();
|
223 |
-
var time_seconds = (t1 - t0) / 1000;
|
224 |
-
time_seconds = Math.round(time_seconds * 100) / 100;
|
225 |
-
args.total_seconds += time_seconds;
|
226 |
-
|
227 |
-
var estimated_time = rlv_format_approximate_time(Math.round(args.total_seconds / response.percentage * 100 - args.total_seconds));
|
228 |
-
|
229 |
-
document.getElementById("relevanssi_estimated").innerHTML = estimated_time;
|
230 |
-
|
231 |
/*console.log("total time: " + total_seconds);
|
232 |
console.log("estimated time: " + Math.round(total_seconds / response.percentage * 100));
|
233 |
console.log("estimated remaining: " + Math.round((total_seconds / response.percentage * 100) - total_seconds));
|
234 |
console.log("estimated formatted: " + estimated_time);
|
235 |
*/
|
236 |
if (time_seconds < 2) {
|
237 |
-
args.limit = args.limit * 2
|
238 |
// current limit can be indexed in less than two seconds; double the limit
|
239 |
-
}
|
240 |
-
|
241 |
-
args.limit += 5;
|
242 |
// current limit can be indexed in less than five seconds; up the limit
|
243 |
-
}
|
244 |
-
|
245 |
-
args.limit
|
246 |
-
if (args.limit < 1) args.limit = 1;
|
247 |
// current limit takes more than twenty seconds; halve the limit
|
248 |
-
}
|
249 |
-
|
250 |
-
args.limit
|
251 |
-
if (args.limit < 1) args.limit = 1;
|
252 |
// current limit takes more than ten seconds; reduce the limit
|
253 |
}
|
254 |
|
255 |
-
var results_textarea = document.getElementById("results")
|
256 |
-
results_textarea.value += response.feedback
|
257 |
-
results_textarea.scrollTop = results_textarea.scrollHeight
|
258 |
-
var percentage_rounded = Math.round(response.percentage)
|
259 |
-
|
260 |
-
jQuery(
|
261 |
-
|
262 |
-
|
263 |
-
|
264 |
-
|
|
|
|
|
|
|
|
|
265 |
//console.log("Next step.");
|
266 |
var new_args = {
|
267 |
-
|
268 |
-
|
269 |
-
|
270 |
-
|
271 |
-
|
272 |
-
|
273 |
-
|
274 |
-
}
|
275 |
-
|
276 |
-
process_indexing_step(new_args)
|
277 |
}
|
278 |
}
|
279 |
-
})
|
280 |
}
|
281 |
|
282 |
function rlv_format_time(total_seconds) {
|
283 |
-
var hours = Math.floor(total_seconds / 3600)
|
284 |
-
var minutes = Math.floor((total_seconds -
|
285 |
-
var seconds = total_seconds -
|
286 |
|
287 |
-
if (minutes < 10) minutes = "0" + minutes
|
288 |
-
if (seconds < 10) seconds = "0" + seconds
|
289 |
|
290 |
-
return hours + ":" + minutes + ":" + seconds
|
291 |
}
|
292 |
|
293 |
function rlv_format_approximate_time(total_seconds) {
|
294 |
-
var hours = Math.floor(total_seconds / 3600)
|
295 |
-
var minutes = Math.floor(total_seconds / 60)
|
296 |
-
var seconds = total_seconds -
|
297 |
-
|
298 |
var time = ""
|
299 |
if (minutes > 99) {
|
300 |
-
hour_word = relevanssi.hours
|
301 |
-
if (hours == 1) hour_word = relevanssi.hour
|
302 |
-
time = relevanssi.about + " " + hours + " " + hour_word
|
303 |
}
|
304 |
-
if (minutes > 79 && minutes < 100) time = relevanssi.ninety_min
|
305 |
-
if (minutes > 49 && minutes < 80) time = relevanssi.sixty_min
|
306 |
if (minutes < 50) {
|
307 |
-
if (seconds > 30) minutes += 1
|
308 |
-
minute_word = relevanssi.minutes
|
309 |
-
if (minutes == 1) minute_word = relevanssi.minute
|
310 |
-
time = relevanssi.about + " " + minutes + " " + minute_word
|
311 |
-
}
|
312 |
-
if (minutes < 1) time = relevanssi.underminute
|
313 |
-
|
314 |
-
return time
|
315 |
}
|
316 |
|
317 |
jQuery(document).ready(function($) {
|
318 |
-
$(
|
319 |
-
var results = document.getElementById("results")
|
320 |
-
results.innerHTML =
|
321 |
-
e.preventDefault()
|
322 |
jQuery.ajax({
|
323 |
-
type:
|
324 |
url: ajaxurl,
|
325 |
data: {
|
326 |
-
action:
|
327 |
-
args: document.getElementById(
|
328 |
-
posts_per_page: document.getElementById(
|
329 |
-
s: document.getElementById(
|
330 |
-
security
|
331 |
},
|
332 |
-
dataType:
|
333 |
success: function(response) {
|
334 |
-
results.innerHTML = response
|
335 |
}
|
336 |
-
})
|
337 |
-
})
|
338 |
|
339 |
// Show the filters on the "Admin search" page.
|
340 |
-
$(document).on(
|
341 |
-
$(
|
342 |
-
$(
|
343 |
-
$(
|
344 |
-
})
|
345 |
|
346 |
// Hide the filters on the "Admin search" page.
|
347 |
-
$(document).on(
|
348 |
-
$(
|
349 |
-
$(
|
350 |
-
$(
|
351 |
-
})
|
352 |
-
|
353 |
-
$(document).on(
|
354 |
-
var results = document.getElementById("results")
|
355 |
-
e.preventDefault()
|
356 |
-
var offset = parseInt(document.getElementById(
|
357 |
-
var posts = parseInt(document.getElementById(
|
358 |
-
offset = offset + posts
|
359 |
-
results.innerHTML =
|
360 |
jQuery.ajax({
|
361 |
-
type:
|
362 |
url: ajaxurl,
|
363 |
data: {
|
364 |
-
action:
|
365 |
-
args: document.getElementById(
|
366 |
-
posts_per_page: document.getElementById(
|
367 |
-
s: document.getElementById(
|
368 |
offset: offset,
|
369 |
-
security
|
370 |
},
|
371 |
-
dataType:
|
372 |
success: function(response) {
|
373 |
-
results.innerHTML = response
|
374 |
}
|
375 |
-
})
|
376 |
-
})
|
377 |
-
|
378 |
-
$(document).on(
|
379 |
-
var results = document.getElementById("results")
|
380 |
-
e.preventDefault()
|
381 |
-
var offset = parseInt(document.getElementById(
|
382 |
-
var posts = parseInt(document.getElementById(
|
383 |
-
offset = offset - posts
|
384 |
-
if (
|
385 |
-
results.innerHTML =
|
386 |
jQuery.ajax({
|
387 |
-
type:
|
388 |
url: ajaxurl,
|
389 |
data: {
|
390 |
-
action:
|
391 |
-
args: document.getElementById(
|
392 |
-
posts_per_page: document.getElementById(
|
393 |
-
s: document.getElementById(
|
394 |
offset: offset,
|
395 |
-
security
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
396 |
},
|
397 |
-
dataType:
|
398 |
success: function(response) {
|
399 |
-
results
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
400 |
}
|
401 |
-
})
|
402 |
-
})
|
403 |
-
})
|
1 |
/* Confirmation for copying options between blogs */
|
2 |
|
3 |
jQuery(document).ready(function($) {
|
4 |
+
$("#copy_config").submit(function() {
|
5 |
+
var c = confirm(relevanssi.confirm)
|
6 |
+
return c //you can just return c because it will be true or false
|
7 |
+
})
|
8 |
+
|
9 |
+
$("#removeallstopwords").click(function() {
|
10 |
+
var c = confirm(relevanssi.confirm_stopwords)
|
11 |
+
return c //you can just return c because it will be true or false
|
12 |
+
})
|
13 |
+
})
|
14 |
+
|
15 |
+
jQuery(document).ready(function($) {
|
16 |
+
$(".color-field").wpColorPicker()
|
17 |
+
|
18 |
+
var txtcol_control = $("#tr_relevanssi_txt_col")
|
19 |
+
var bgcol_control = $("#tr_relevanssi_bg_col")
|
20 |
+
var class_control = $("#tr_relevanssi_class")
|
21 |
+
var css_control = $("#tr_relevanssi_css")
|
22 |
+
|
23 |
+
$("#relevanssi_highlight").change(function() {
|
24 |
+
txtcol_control.addClass("screen-reader-text")
|
25 |
+
bgcol_control.addClass("screen-reader-text")
|
26 |
+
class_control.addClass("screen-reader-text")
|
27 |
+
css_control.addClass("screen-reader-text")
|
28 |
+
|
29 |
+
if (this.value == "col") txtcol_control.toggleClass("screen-reader-text")
|
30 |
+
if (this.value == "bgcol") bgcol_control.toggleClass("screen-reader-text")
|
31 |
+
if (this.value == "class") class_control.toggleClass("screen-reader-text")
|
32 |
+
if (this.value == "css") css_control.toggleClass("screen-reader-text")
|
33 |
+
})
|
34 |
+
|
35 |
+
$("#relevanssi_hilite_title").click(function() {
|
36 |
+
$("#title_description").toggleClass("screen-reader-text", !this.checked)
|
37 |
+
})
|
38 |
+
|
39 |
+
var or_fallback = $("#orfallback")
|
40 |
+
$("#relevanssi_implicit_operator").change(function() {
|
41 |
+
or_fallback.toggleClass("screen-reader-text")
|
42 |
+
})
|
43 |
+
|
44 |
+
var index_subscribers = $("#index_subscribers")
|
45 |
+
var user_extra_fields = $("#user_extra_fields")
|
46 |
+
$("#relevanssi_index_users").click(function() {
|
47 |
+
$("#user_profile_notice").toggleClass("screen-reader-text", !this.checked)
|
48 |
+
index_subscribers.toggleClass("screen-reader-text", !this.checked)
|
49 |
+
user_extra_fields.toggleClass("screen-reader-text", !this.checked)
|
50 |
+
})
|
51 |
+
|
52 |
+
var taxonomies = $("#taxonomies")
|
53 |
+
$("#relevanssi_index_taxonomies").click(function() {
|
54 |
+
taxonomies.toggleClass("screen-reader-text", !this.checked)
|
55 |
+
})
|
56 |
+
|
57 |
+
var post_type_archives = $("#posttypearchives")
|
58 |
+
$("#relevanssi_index_post_type_archives").click(function() {
|
59 |
+
post_type_archives.toggleClass("screen-reader-text", !this.checked)
|
60 |
+
})
|
61 |
+
|
62 |
+
var fields_content = $("#index_field_input")
|
63 |
+
var fields_select = $("#relevanssi_index_fields_select")
|
64 |
+
fields_select.change(function() {
|
65 |
+
if (this.value == "some") fields_content.show()
|
66 |
+
if (this.value != "some") fields_content.hide()
|
67 |
+
})
|
68 |
+
|
69 |
+
$("#show_advanced_indexing").click(function(e) {
|
70 |
+
$("#advanced_indexing").toggleClass("screen-reader-text")
|
71 |
+
$("#hide_advanced_indexing").show()
|
72 |
+
$("#show_advanced_indexing").hide()
|
73 |
+
})
|
74 |
+
|
75 |
+
$("#hide_advanced_indexing").click(function(e) {
|
76 |
+
$("#advanced_indexing").toggleClass("screen-reader-text")
|
77 |
+
$("#show_advanced_indexing").show()
|
78 |
+
$("#hide_advanced_indexing").hide()
|
79 |
+
})
|
80 |
|
81 |
$("#indexing_tab :input").change(function(e) {
|
82 |
+
$("#build_index").attr("disabled", "disabled")
|
83 |
+
var relevanssi_note = $("#relevanssi-note")
|
84 |
+
relevanssi_note.show()
|
85 |
+
relevanssi_note.html(relevanssi.options_changed)
|
86 |
+
})
|
87 |
|
88 |
$("#relevanssi_default_orderby").change(function(e) {
|
89 |
if (this.value == "post_date") {
|
90 |
+
$("#relevanssi_throttle").prop("checked", false)
|
91 |
}
|
92 |
+
$("#throttle_disabled").toggleClass("screen-reader-text")
|
93 |
+
$("#throttle_enabled").toggleClass("screen-reader-text")
|
94 |
+
})
|
95 |
|
96 |
$("#relevanssi_show_pdf_errors").click(function(e) {
|
97 |
+
var error_box = $("#relevanssi_pdf_errors")
|
98 |
+
error_box.toggle()
|
99 |
var data = {
|
100 |
+
action: "relevanssi_get_pdf_errors"
|
101 |
+
}
|
102 |
jQuery.post(ajaxurl, data, function(response) {
|
103 |
+
error_box.val(JSON.parse(response))
|
104 |
+
})
|
105 |
+
})
|
106 |
|
107 |
$("#relevanssi_excerpts").click(function() {
|
108 |
+
$("#relevanssi_breakdown").toggleClass("relevanssi_disabled", !this.checked)
|
109 |
+
$("#relevanssi_highlighting").toggleClass(
|
110 |
+
"relevanssi_disabled",
|
111 |
+
!this.checked
|
112 |
+
)
|
113 |
+
$("#tr_excerpt_custom_fields").toggleClass(
|
114 |
+
"relevanssi_disabled",
|
115 |
+
!this.checked
|
116 |
+
)
|
117 |
+
$("#tr_excerpt_allowable_tags").toggleClass(
|
118 |
+
"relevanssi_disabled",
|
119 |
+
!this.checked
|
120 |
+
)
|
121 |
+
$("#tr_excerpt_length").toggleClass("relevanssi_disabled", !this.checked)
|
122 |
+
$("#relevanssi_excerpt_length").attr("disabled", !this.checked)
|
123 |
+
$("#relevanssi_excerpt_type").attr("disabled", !this.checked)
|
124 |
+
$("#relevanssi_excerpt_allowable_tags").attr("disabled", !this.checked)
|
125 |
+
$("#relevanssi_excerpt_custom_fields").attr("disabled", !this.checked)
|
126 |
+
$("#relevanssi_highlight").attr("disabled", !this.checked)
|
127 |
+
$("#relevanssi_txt_col").attr("disabled", !this.checked)
|
128 |
+
$("#relevanssi_bg_col").attr("disabled", !this.checked)
|
129 |
+
$("#relevanssi_css").attr("disabled", !this.checked)
|
130 |
+
$("#relevanssi_class").attr("disabled", !this.checked)
|
131 |
+
$("#relevanssi_hilite_title").attr("disabled", !this.checked)
|
132 |
+
$("#relevanssi_highlight_docs").attr("disabled", !this.checked)
|
133 |
+
$("#relevanssi_highlight_comments").attr("disabled", !this.checked)
|
134 |
+
$("#relevanssi_word_boundaries").attr("disabled", !this.checked)
|
135 |
+
$("#relevanssi_show_matches").attr("disabled", !this.checked)
|
136 |
+
$("#relevanssi_show_matches_text").attr("disabled", !this.checked)
|
137 |
+
})
|
138 |
|
139 |
$("#relevanssi_searchblogs_all").click(function() {
|
140 |
+
$("#relevanssi_searchblogs").attr("disabled", this.checked)
|
141 |
+
})
|
142 |
+
})
|
143 |
|
144 |
+
var time = 0
|
145 |
+
var intervalID = 0
|
146 |
|
147 |
function relevanssiUpdateClock() {
|
148 |
+
time++
|
149 |
+
var time_formatted = rlv_format_time(Math.round(time))
|
150 |
+
document.getElementById("relevanssi_elapsed").innerHTML = time_formatted
|
151 |
}
|
152 |
|
153 |
jQuery(document).ready(function($) {
|
154 |
$("#continue_indexing").click(function() {
|
155 |
+
$("#relevanssi-progress").show()
|
156 |
+
$("#results").show()
|
157 |
+
$("#relevanssi-timer").show()
|
158 |
+
$("#stateoftheindex").html(relevanssi.reload_state)
|
159 |
+
$("#indexing_button_instructions").hide()
|
160 |
+
var results = document.getElementById("results")
|
161 |
+
results.value = ""
|
162 |
|
163 |
+
intervalID = window.setInterval(relevanssiUpdateClock, 1000)
|
164 |
|
165 |
var data = {
|
166 |
+
action: "relevanssi_count_missing_posts"
|
167 |
+
}
|
168 |
+
console.log("Counting posts.")
|
169 |
+
results.value += relevanssi.counting_posts + " "
|
170 |
jQuery.post(ajaxurl, data, function(response) {
|
171 |
+
count_response = JSON.parse(response)
|
172 |
+
console.log("Counted " + count_response + " posts.")
|
173 |
+
results.value += count_response + " " + relevanssi.posts_found + "\n"
|
174 |
|
175 |
if (count_response > 0) {
|
176 |
var args = {
|
177 |
+
completed: 0,
|
178 |
+
total: count_response,
|
179 |
+
offset: 0,
|
180 |
+
total_seconds: 0,
|
181 |
+
limit: 10,
|
182 |
+
extend: true,
|
183 |
+
security: nonce.indexing_nonce
|
184 |
+
}
|
185 |
+
process_indexing_step(args)
|
186 |
+
} else {
|
187 |
+
clearInterval(intervalID)
|
|
|
188 |
}
|
189 |
+
})
|
190 |
+
})
|
191 |
+
})
|
192 |
|
193 |
function process_indexing_step(args) {
|
194 |
// console.log(args.completed + " / " + args.total);
|
195 |
+
var t0 = performance.now()
|
196 |
jQuery.ajax({
|
197 |
+
type: "POST",
|
198 |
url: ajaxurl,
|
199 |
data: {
|
200 |
+
action: "relevanssi_index_posts",
|
201 |
completed: args.completed,
|
202 |
total: args.total,
|
203 |
offset: args.offset,
|
204 |
limit: args.limit,
|
205 |
extend: args.extend,
|
206 |
+
security: args.security
|
207 |
},
|
208 |
+
dataType: "json",
|
209 |
success: function(response) {
|
210 |
+
console.log(response)
|
211 |
if (response.completed == "done") {
|
212 |
//console.log("response " + parseInt(response.total_posts));
|
213 |
+
var results_textarea = document.getElementById("results")
|
214 |
+
results_textarea.value += response.feedback
|
215 |
+
|
216 |
+
document.getElementById("relevanssi_estimated").innerHTML =
|
217 |
+
relevanssi.notimeremaining
|
218 |
+
|
219 |
+
var hidden_posts = args.total - parseInt(response.total_posts)
|
220 |
+
results_textarea.value +=
|
221 |
+
relevanssi.indexing_complete +
|
222 |
+
" " +
|
223 |
+
hidden_posts +
|
224 |
+
" " +
|
225 |
+
relevanssi.excluded_posts
|
226 |
+
results_textarea.scrollTop = results_textarea.scrollHeight
|
227 |
+
jQuery(".rpi-progress div").animate(
|
228 |
+
{
|
229 |
+
width: response.percentage + "%"
|
230 |
+
},
|
231 |
+
50,
|
232 |
+
function() {
|
233 |
+
// Animation complete.
|
234 |
+
}
|
235 |
+
)
|
236 |
+
|
237 |
+
clearInterval(intervalID)
|
238 |
+
} else {
|
239 |
+
var t1 = performance.now()
|
240 |
+
var time_seconds = (t1 - t0) / 1000
|
241 |
+
time_seconds = Math.round(time_seconds * 100) / 100
|
242 |
+
args.total_seconds += time_seconds
|
243 |
+
|
244 |
+
var estimated_time = rlv_format_approximate_time(
|
245 |
+
Math.round(
|
246 |
+
(args.total_seconds / response.percentage) * 100 -
|
247 |
+
args.total_seconds
|
248 |
+
)
|
249 |
+
)
|
250 |
+
|
251 |
+
document.getElementById(
|
252 |
+
"relevanssi_estimated"
|
253 |
+
).innerHTML = estimated_time
|
254 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
255 |
/*console.log("total time: " + total_seconds);
|
256 |
console.log("estimated time: " + Math.round(total_seconds / response.percentage * 100));
|
257 |
console.log("estimated remaining: " + Math.round((total_seconds / response.percentage * 100) - total_seconds));
|
258 |
console.log("estimated formatted: " + estimated_time);
|
259 |
*/
|
260 |
if (time_seconds < 2) {
|
261 |
+
args.limit = args.limit * 2
|
262 |
// current limit can be indexed in less than two seconds; double the limit
|
263 |
+
} else if (time_seconds < 5) {
|
264 |
+
args.limit += 5
|
|
|
265 |
// current limit can be indexed in less than five seconds; up the limit
|
266 |
+
} else if (time_seconds > 20) {
|
267 |
+
args.limit = Math.round(args.limit / 2)
|
268 |
+
if (args.limit < 1) args.limit = 1
|
|
|
269 |
// current limit takes more than twenty seconds; halve the limit
|
270 |
+
} else if (time_seconds > 10) {
|
271 |
+
args.limit -= 5
|
272 |
+
if (args.limit < 1) args.limit = 1
|
|
|
273 |
// current limit takes more than ten seconds; reduce the limit
|
274 |
}
|
275 |
|
276 |
+
var results_textarea = document.getElementById("results")
|
277 |
+
results_textarea.value += response.feedback
|
278 |
+
results_textarea.scrollTop = results_textarea.scrollHeight
|
279 |
+
var percentage_rounded = Math.round(response.percentage)
|
280 |
+
|
281 |
+
jQuery(".rpi-progress div").animate(
|
282 |
+
{
|
283 |
+
width: percentage_rounded + "%"
|
284 |
+
},
|
285 |
+
50,
|
286 |
+
function() {
|
287 |
+
// Animation complete.
|
288 |
+
}
|
289 |
+
)
|
290 |
//console.log("Next step.");
|
291 |
var new_args = {
|
292 |
+
completed: parseInt(response.completed),
|
293 |
+
total: args.total,
|
294 |
+
offset: response.offset,
|
295 |
+
total_seconds: args.total_seconds,
|
296 |
+
limit: args.limit,
|
297 |
+
extend: args.extend,
|
298 |
+
security: args.security
|
299 |
+
}
|
300 |
+
|
301 |
+
process_indexing_step(new_args)
|
302 |
}
|
303 |
}
|
304 |
+
})
|
305 |
}
|
306 |
|
307 |
function rlv_format_time(total_seconds) {
|
308 |
+
var hours = Math.floor(total_seconds / 3600)
|
309 |
+
var minutes = Math.floor((total_seconds - hours * 3600) / 60)
|
310 |
+
var seconds = total_seconds - hours * 3600 - minutes * 60
|
311 |
|
312 |
+
if (minutes < 10) minutes = "0" + minutes
|
313 |
+
if (seconds < 10) seconds = "0" + seconds
|
314 |
|
315 |
+
return hours + ":" + minutes + ":" + seconds
|
316 |
}
|
317 |
|
318 |
function rlv_format_approximate_time(total_seconds) {
|
319 |
+
var hours = Math.floor(total_seconds / 3600)
|
320 |
+
var minutes = Math.floor(total_seconds / 60)
|
321 |
+
var seconds = total_seconds - hours * 3600 - minutes * 60
|
322 |
+
|
323 |
var time = ""
|
324 |
if (minutes > 99) {
|
325 |
+
hour_word = relevanssi.hours
|
326 |
+
if (hours == 1) hour_word = relevanssi.hour
|
327 |
+
time = relevanssi.about + " " + hours + " " + hour_word
|
328 |
}
|
329 |
+
if (minutes > 79 && minutes < 100) time = relevanssi.ninety_min
|
330 |
+
if (minutes > 49 && minutes < 80) time = relevanssi.sixty_min
|
331 |
if (minutes < 50) {
|
332 |
+
if (seconds > 30) minutes += 1
|
333 |
+
minute_word = relevanssi.minutes
|
334 |
+
if (minutes == 1) minute_word = relevanssi.minute
|
335 |
+
time = relevanssi.about + " " + minutes + " " + minute_word
|
336 |
+
}
|
337 |
+
if (minutes < 1) time = relevanssi.underminute
|
338 |
+
|
339 |
+
return time
|
340 |
}
|
341 |
|
342 |
jQuery(document).ready(function($) {
|
343 |
+
$("#search").click(function(e) {
|
344 |
+
var results = document.getElementById("results")
|
345 |
+
results.innerHTML = "Searching..."
|
346 |
+
e.preventDefault()
|
347 |
jQuery.ajax({
|
348 |
+
type: "POST",
|
349 |
url: ajaxurl,
|
350 |
data: {
|
351 |
+
action: "relevanssi_admin_search",
|
352 |
+
args: document.getElementById("args").value,
|
353 |
+
posts_per_page: document.getElementById("posts_per_page").value,
|
354 |
+
s: document.getElementById("s").value,
|
355 |
+
security: nonce.searching_nonce
|
356 |
},
|
357 |
+
dataType: "json",
|
358 |
success: function(response) {
|
359 |
+
results.innerHTML = response
|
360 |
}
|
361 |
+
})
|
362 |
+
})
|
363 |
|
364 |
// Show the filters on the "Admin search" page.
|
365 |
+
$(document).on("click", "#show_filters", function(e) {
|
366 |
+
$("#relevanssi_filter_list").toggle()
|
367 |
+
$("#show_filters").toggle()
|
368 |
+
$("#hide_filters").toggle()
|
369 |
+
})
|
370 |
|
371 |
// Hide the filters on the "Admin search" page.
|
372 |
+
$(document).on("click", "#hide_filters", function(e) {
|
373 |
+
$("#relevanssi_filter_list").toggle()
|
374 |
+
$("#show_filters").toggle()
|
375 |
+
$("#hide_filters").toggle()
|
376 |
+
})
|
377 |
+
|
378 |
+
$(document).on("click", "#next_page", function(e) {
|
379 |
+
var results = document.getElementById("results")
|
380 |
+
e.preventDefault()
|
381 |
+
var offset = parseInt(document.getElementById("offset").innerHTML)
|
382 |
+
var posts = parseInt(document.getElementById("posts_per_page").value)
|
383 |
+
offset = offset + posts
|
384 |
+
results.innerHTML = "Searching..."
|
385 |
jQuery.ajax({
|
386 |
+
type: "POST",
|
387 |
url: ajaxurl,
|
388 |
data: {
|
389 |
+
action: "relevanssi_admin_search",
|
390 |
+
args: document.getElementById("args").value,
|
391 |
+
posts_per_page: document.getElementById("posts_per_page").value,
|
392 |
+
s: document.getElementById("s").value,
|
393 |
offset: offset,
|
394 |
+
security: nonce.searching_nonce
|
395 |
},
|
396 |
+
dataType: "json",
|
397 |
success: function(response) {
|
398 |
+
results.innerHTML = response
|
399 |
}
|
400 |
+
})
|
401 |
+
})
|
402 |
+
|
403 |
+
$(document).on("click", "#prev_page", function(e) {
|
404 |
+
var results = document.getElementById("results")
|
405 |
+
e.preventDefault()
|
406 |
+
var offset = parseInt(document.getElementById("offset").innerHTML)
|
407 |
+
var posts = parseInt(document.getElementById("posts_per_page").value)
|
408 |
+
offset = offset - posts
|
409 |
+
if (offset < 0) offset = 0
|
410 |
+
results.innerHTML = "Searching..."
|
411 |
jQuery.ajax({
|
412 |
+
type: "POST",
|
413 |
url: ajaxurl,
|
414 |
data: {
|
415 |
+
action: "relevanssi_admin_search",
|
416 |
+
args: document.getElementById("args").value,
|
417 |
+
posts_per_page: document.getElementById("posts_per_page").value,
|
418 |
+
s: document.getElementById("s").value,
|
419 |
offset: offset,
|
420 |
+
security: nonce.searching_nonce
|
421 |
+
},
|
422 |
+
dataType: "json",
|
423 |
+
success: function(response) {
|
424 |
+
results.innerHTML = response
|
425 |
+
}
|
426 |
+
})
|
427 |
+
})
|
428 |
+
|
429 |
+
$(document).on("click", ".pin", function(e) {
|
430 |
+
e.preventDefault()
|
431 |
+
var keyword = e.target.dataset.keyword
|
432 |
+
var post_id = e.target.dataset.postid
|
433 |
+
jQuery.ajax({
|
434 |
+
type: "POST",
|
435 |
+
url: ajaxurl,
|
436 |
+
data: {
|
437 |
+
action: "relevanssi_pin_post",
|
438 |
+
keyword,
|
439 |
+
post_id,
|
440 |
+
security: nonce.searching_nonce
|
441 |
+
},
|
442 |
+
dataType: "json",
|
443 |
+
success: function(response) {
|
444 |
+
var results = document.getElementById("results")
|
445 |
+
results.innerHTML = "Searching..."
|
446 |
+
e.preventDefault()
|
447 |
+
jQuery.ajax({
|
448 |
+
type: "POST",
|
449 |
+
url: ajaxurl,
|
450 |
+
data: {
|
451 |
+
action: "relevanssi_admin_search",
|
452 |
+
args: document.getElementById("args").value,
|
453 |
+
posts_per_page: document.getElementById("posts_per_page").value,
|
454 |
+
s: document.getElementById("s").value,
|
455 |
+
security: nonce.searching_nonce
|
456 |
+
},
|
457 |
+
dataType: "json",
|
458 |
+
success: function(response) {
|
459 |
+
results.innerHTML = response
|
460 |
+
}
|
461 |
+
})
|
462 |
+
}
|
463 |
+
})
|
464 |
+
})
|
465 |
+
|
466 |
+
$(document).on("click", ".unpin", function(e) {
|
467 |
+
e.preventDefault()
|
468 |
+
var keyword = e.target.dataset.keyword
|
469 |
+
var post_id = e.target.dataset.postid
|
470 |
+
jQuery.ajax({
|
471 |
+
type: "POST",
|
472 |
+
url: ajaxurl,
|
473 |
+
data: {
|
474 |
+
action: "relevanssi_unpin_post",
|
475 |
+
keyword,
|
476 |
+
post_id,
|
477 |
+
security: nonce.searching_nonce
|
478 |
},
|
479 |
+
dataType: "json",
|
480 |
success: function(response) {
|
481 |
+
var results = document.getElementById("results")
|
482 |
+
results.innerHTML = "Searching..."
|
483 |
+
e.preventDefault()
|
484 |
+
jQuery.ajax({
|
485 |
+
type: "POST",
|
486 |
+
url: ajaxurl,
|
487 |
+
data: {
|
488 |
+
action: "relevanssi_admin_search",
|
489 |
+
args: document.getElementById("args").value,
|
490 |
+
posts_per_page: document.getElementById("posts_per_page").value,
|
491 |
+
s: document.getElementById("s").value,
|
492 |
+
security: nonce.searching_nonce
|
493 |
+
},
|
494 |
+
dataType: "json",
|
495 |
+
success: function(response) {
|
496 |
+
results.innerHTML = response
|
497 |
+
}
|
498 |
+
})
|
499 |
}
|
500 |
+
})
|
501 |
+
})
|
502 |
+
})
|
lib/admin_scripts_free.js
CHANGED
@@ -1,51 +1,51 @@
|
|
1 |
jQuery(document).ready(function($) {
|
2 |
-
|
3 |
-
|
4 |
-
|
5 |
-
$("#relevanssi-timer").show()
|
6 |
-
$("#relevanssi-indexing-instructions").show()
|
7 |
-
|
8 |
-
|
9 |
-
|
10 |
-
|
11 |
|
12 |
-
|
13 |
-
|
14 |
-
|
15 |
|
16 |
-
|
17 |
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
})
|
1 |
jQuery(document).ready(function($) {
|
2 |
+
$("#build_index").click(function() {
|
3 |
+
$("#relevanssi-progress").show()
|
4 |
+
$("#results").show()
|
5 |
+
$("#relevanssi-timer").show()
|
6 |
+
$("#relevanssi-indexing-instructions").show()
|
7 |
+
$("#stateoftheindex").html(relevanssi.reload_state)
|
8 |
+
$("#indexing_button_instructions").hide()
|
9 |
+
var results = document.getElementById("results")
|
10 |
+
results.value = ""
|
11 |
|
12 |
+
var data = {
|
13 |
+
action: "relevanssi_truncate_index"
|
14 |
+
}
|
15 |
|
16 |
+
intervalID = window.setInterval(relevanssiUpdateClock, 1000)
|
17 |
|
18 |
+
console.log("Truncating index.")
|
19 |
+
results.value += relevanssi.truncating_index + " "
|
20 |
+
jQuery.post(ajaxurl, data, function(response) {
|
21 |
+
truncate_response = JSON.parse(response)
|
22 |
+
console.log("Truncate index: " + truncate_response)
|
23 |
+
if (truncate_response == true) {
|
24 |
+
results.value += relevanssi.done + "\n"
|
25 |
+
}
|
26 |
|
27 |
+
var data = {
|
28 |
+
action: "relevanssi_count_posts"
|
29 |
+
}
|
30 |
+
console.log("Counting posts.")
|
31 |
+
results.value += relevanssi.counting_posts + " "
|
32 |
+
jQuery.post(ajaxurl, data, function(response) {
|
33 |
+
count_response = JSON.parse(response)
|
34 |
+
console.log("Counted " + count_response + " posts.")
|
35 |
+
var post_total = parseInt(count_response)
|
36 |
+
results.value += count_response + " " + relevanssi.posts_found + "\n"
|
37 |
|
38 |
+
var args = {
|
39 |
+
completed: 0,
|
40 |
+
total: post_total,
|
41 |
+
offset: 0,
|
42 |
+
total_seconds: 0,
|
43 |
+
limit: 10,
|
44 |
+
extend: false,
|
45 |
+
security: nonce.indexing_nonce
|
46 |
+
}
|
47 |
+
process_indexing_step(args)
|
48 |
+
})
|
49 |
+
})
|
50 |
+
})
|
51 |
+
})
|
lib/common.php
CHANGED
@@ -167,9 +167,16 @@ function relevanssi_default_post_ok( $post_ok, $post_id ) {
|
|
167 |
// Current user has the required capabilities and can see the page.
|
168 |
$post_ok = true;
|
169 |
}
|
170 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
171 |
if ( function_exists( 'members_content_permissions_enabled' ) && function_exists( 'members_can_current_user_view_post' ) ) {
|
172 |
-
// Members. Only use
|
173 |
if ( members_content_permissions_enabled() ) {
|
174 |
$post_ok = members_can_current_user_view_post( $post_id );
|
175 |
}
|
@@ -201,6 +208,13 @@ function relevanssi_default_post_ok( $post_ok, $post_id ) {
|
|
201 |
// Restrict Content Pro.
|
202 |
$post_ok = rcp_user_can_access( get_current_user_id(), $post_id );
|
203 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
204 |
/**
|
205 |
* Filters statuses allowed in admin searches.
|
206 |
*
|
@@ -293,23 +307,26 @@ function relevanssi_extract_phrases( $query ) {
|
|
293 |
$substr_function = 'mb_substr';
|
294 |
}
|
295 |
|
296 |
-
|
|
|
|
|
|
|
297 |
|
298 |
$phrases = array();
|
299 |
while ( false !== $pos ) {
|
300 |
$start = $pos;
|
301 |
-
$end = call_user_func( $strpos_function, $
|
302 |
|
303 |
if ( false === $end ) {
|
304 |
// Just one " in the query.
|
305 |
$pos = $end;
|
306 |
continue;
|
307 |
}
|
308 |
-
$phrase = call_user_func( $substr_function, $
|
309 |
$phrase = trim( $phrase );
|
310 |
|
311 |
// Do not count single-word phrases as phrases.
|
312 |
-
if ( ! empty( $phrase ) &&
|
313 |
$phrases[] = $phrase;
|
314 |
}
|
315 |
$pos = $end;
|
@@ -705,9 +722,13 @@ function relevanssi_prevent_default_request( $request, $query ) {
|
|
705 |
* source material. If the parameter is an array of string, each string is
|
706 |
* tokenized separately and the resulting tokens are combined into one array.
|
707 |
*
|
708 |
-
* @param string|array
|
709 |
-
*
|
710 |
-
* @param
|
|
|
|
|
|
|
|
|
711 |
*/
|
712 |
function relevanssi_tokenize( $string, $remove_stops = true, $min_word_length = -1 ) {
|
713 |
$tokens = array();
|
@@ -731,6 +752,9 @@ function relevanssi_tokenize( $string, $remove_stops = true, $min_word_length =
|
|
731 |
if ( $remove_stops ) {
|
732 |
$stopword_list = relevanssi_fetch_stopwords();
|
733 |
}
|
|
|
|
|
|
|
734 |
|
735 |
if ( function_exists( 'relevanssi_apply_thousands_separator' ) ) {
|
736 |
// A Premium feature.
|
@@ -854,16 +878,21 @@ function relevanssi_get_post_status( $post_id ) {
|
|
854 |
*/
|
855 |
function relevanssi_get_post_type( $post_id ) {
|
856 |
global $relevanssi_post_array;
|
857 |
-
|
858 |
if ( isset( $relevanssi_post_array[ $post_id ] ) ) {
|
859 |
return $relevanssi_post_array[ $post_id ]->post_type;
|
860 |
} else {
|
861 |
// No hit from the cache; let's add this post to the cache.
|
862 |
-
$post =
|
863 |
-
|
864 |
-
|
865 |
-
|
866 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
867 |
}
|
868 |
}
|
869 |
|
@@ -1026,6 +1055,7 @@ function relevanssi_stripos( $haystack, $needle, $offset = 0 ) {
|
|
1026 |
* @return string The HTML code, with tags closed.
|
1027 |
*/
|
1028 |
function relevanssi_close_tags( $html ) {
|
|
|
1029 |
preg_match_all( '#<(?!meta|img|br|hr|input\b)\b([a-z]+)(?: .*)?(?<![/|/ ])>#iU', $html, $result );
|
1030 |
$opened_tags = $result[1];
|
1031 |
preg_match_all( '#</([a-z]+)>#iU', $html, $result );
|
@@ -1330,7 +1360,7 @@ function relevanssi_didyoumean( $query, $pre, $post, $n = 5, $echo = true ) {
|
|
1330 |
* @return string The suggestion HTML code, null if nothing found.
|
1331 |
*/
|
1332 |
function relevanssi_simple_didyoumean( $query, $pre, $post, $n = 5 ) {
|
1333 |
-
global $
|
1334 |
|
1335 |
$total_results = $wp_query->found_posts;
|
1336 |
|
@@ -1425,13 +1455,16 @@ function relevanssi_simple_generate_suggestion( $query ) {
|
|
1425 |
$closest = '';
|
1426 |
break;
|
1427 |
} else {
|
1428 |
-
|
1429 |
-
|
1430 |
-
|
1431 |
-
|
1432 |
-
|
1433 |
-
|
1434 |
-
|
|
|
|
|
|
|
1435 |
}
|
1436 |
}
|
1437 |
}
|
@@ -1555,11 +1588,6 @@ function relevanssi_sanitize_hex_color( $color ) {
|
|
1555 |
function relevanssi_common_words( $limit = 25, $wp_cli = false ) {
|
1556 |
global $wpdb, $relevanssi_variables;
|
1557 |
|
1558 |
-
$plugin = 'relevanssi';
|
1559 |
-
if ( RELEVANSSI_PREMIUM ) {
|
1560 |
-
$plugin = 'relevanssi-premium';
|
1561 |
-
}
|
1562 |
-
|
1563 |
if ( ! is_numeric( $limit ) ) {
|
1564 |
$limit = 25;
|
1565 |
}
|
@@ -1578,11 +1606,14 @@ function relevanssi_common_words( $limit = 25, $wp_cli = false ) {
|
|
1578 |
<td>
|
1579 |
<ul>
|
1580 |
<?php
|
1581 |
-
$src = plugins_url( 'delete.png', $relevanssi_variables['file'] );
|
1582 |
-
|
1583 |
foreach ( $words as $word ) {
|
1584 |
$stop = __( 'Add to stopwords', 'relevanssi' );
|
1585 |
-
printf( '<li
|
|
|
|
|
|
|
|
|
|
|
1586 |
}
|
1587 |
?>
|
1588 |
</ul>
|
@@ -1605,6 +1636,7 @@ function relevanssi_get_forbidden_post_types() {
|
|
1605 |
return array(
|
1606 |
'nav_menu_item', // Navigation menu items.
|
1607 |
'revision', // Never index revisions.
|
|
|
1608 |
'acf-field', // Advanced Custom Fields.
|
1609 |
'acf-field-group', // Advanced Custom Fields.
|
1610 |
'oembed_cache', // Mysterious caches.
|
@@ -1617,6 +1649,10 @@ function relevanssi_get_forbidden_post_types() {
|
|
1617 |
'amp_validated_url', // AMP.
|
1618 |
'jp_pay_order', // Jetpack.
|
1619 |
'jp_pay_product', // Jetpack.
|
|
|
|
|
|
|
|
|
1620 |
);
|
1621 |
}
|
1622 |
|
@@ -1630,5 +1666,6 @@ function relevanssi_get_forbidden_taxonomies() {
|
|
1630 |
'nav_menu', // Navigation menus.
|
1631 |
'link_category', // Link categories.
|
1632 |
'amp_validation_error', // AMP.
|
|
|
1633 |
);
|
1634 |
}
|
167 |
// Current user has the required capabilities and can see the page.
|
168 |
$post_ok = true;
|
169 |
}
|
170 |
+
$current_user = wp_get_current_user();
|
171 |
+
if ( ! $post_ok && $current_user->ID > 0 ) {
|
172 |
+
$post = relevanssi_get_post( $post_id );
|
173 |
+
if ( $current_user->ID === (int) $post->post_author ) {
|
174 |
+
// Allow authors to see their own private posts.
|
175 |
+
$post_ok = true;
|
176 |
+
}
|
177 |
+
}
|
178 |
if ( function_exists( 'members_content_permissions_enabled' ) && function_exists( 'members_can_current_user_view_post' ) ) {
|
179 |
+
// Members. Only use if 'content permissions' feature is enabled.
|
180 |
if ( members_content_permissions_enabled() ) {
|
181 |
$post_ok = members_can_current_user_view_post( $post_id );
|
182 |
}
|
208 |
// Restrict Content Pro.
|
209 |
$post_ok = rcp_user_can_access( get_current_user_id(), $post_id );
|
210 |
}
|
211 |
+
// User Access Manager.
|
212 |
+
global $userAccessManager; // phpcs:ignore WordPress.NamingConventions.ValidVariableName
|
213 |
+
if ( isset( $userAccessManager ) ) { // phpcs:ignore WordPress.NamingConventions.ValidVariableName
|
214 |
+
$type = relevanssi_get_post_type( $post_id );
|
215 |
+
$post_ok = $userAccessManager->getAccessHandler()->checkObjectAccess( $type, $post_id ); // phpcs:ignore WordPress.NamingConventions.ValidVariableName
|
216 |
+
}
|
217 |
+
|
218 |
/**
|
219 |
* Filters statuses allowed in admin searches.
|
220 |
*
|
307 |
$substr_function = 'mb_substr';
|
308 |
}
|
309 |
|
310 |
+
// iOS uses “” as the default quotes, so Relevanssi needs to understand that as
|
311 |
+
// well.
|
312 |
+
$normalized_query = str_replace( array( '”', '“' ), '"', $query );
|
313 |
+
$pos = call_user_func( $strpos_function, $normalized_query, '"' );
|
314 |
|
315 |
$phrases = array();
|
316 |
while ( false !== $pos ) {
|
317 |
$start = $pos;
|
318 |
+
$end = call_user_func( $strpos_function, $normalized_query, '"', $start + 1 );
|
319 |
|
320 |
if ( false === $end ) {
|
321 |
// Just one " in the query.
|
322 |
$pos = $end;
|
323 |
continue;
|
324 |
}
|
325 |
+
$phrase = call_user_func( $substr_function, $normalized_query, $start + 1, $end - $start - 1 );
|
326 |
$phrase = trim( $phrase );
|
327 |
|
328 |
// Do not count single-word phrases as phrases.
|
329 |
+
if ( ! empty( $phrase ) && count( explode( ' ', $phrase ) ) > 1 ) {
|
330 |
$phrases[] = $phrase;
|
331 |
}
|
332 |
$pos = $end;
|
722 |
* source material. If the parameter is an array of string, each string is
|
723 |
* tokenized separately and the resulting tokens are combined into one array.
|
724 |
*
|
725 |
+
* @param string|array $string The string, or an array of strings, to
|
726 |
+
* tokenize.
|
727 |
+
* @param boolean|string $remove_stops If true, stopwords are removed. If 'body',
|
728 |
+
* also removes the body stopwords. Default
|
729 |
+
* true.
|
730 |
+
* @param int $min_word_length The minimum word length to include.
|
731 |
+
* Default -1.
|
732 |
*/
|
733 |
function relevanssi_tokenize( $string, $remove_stops = true, $min_word_length = -1 ) {
|
734 |
$tokens = array();
|
752 |
if ( $remove_stops ) {
|
753 |
$stopword_list = relevanssi_fetch_stopwords();
|
754 |
}
|
755 |
+
if ( 'body' === $remove_stops && function_exists( 'relevanssi_fetch_body_stopwords' ) ) {
|
756 |
+
$stopword_list = array_merge( $stopword_list, relevanssi_fetch_body_stopwords() );
|
757 |
+
}
|
758 |
|
759 |
if ( function_exists( 'relevanssi_apply_thousands_separator' ) ) {
|
760 |
// A Premium feature.
|
878 |
*/
|
879 |
function relevanssi_get_post_type( $post_id ) {
|
880 |
global $relevanssi_post_array;
|
|
|
881 |
if ( isset( $relevanssi_post_array[ $post_id ] ) ) {
|
882 |
return $relevanssi_post_array[ $post_id ]->post_type;
|
883 |
} else {
|
884 |
// No hit from the cache; let's add this post to the cache.
|
885 |
+
$post = relevanssi_get_post( $post_id );
|
886 |
+
|
887 |
+
if ( is_wp_error( $post ) ) {
|
888 |
+
$post->add_data( 'not_found', "relevanssi_get_post_type() didn't get a post, relevanssi_get_post() returned null." );
|
889 |
+
return $post;
|
890 |
+
} elseif ( $post ) {
|
891 |
+
$relevanssi_post_array[ $post_id ] = $post;
|
892 |
+
return $post->post_type;
|
893 |
+
} else {
|
894 |
+
return new WP_Error( 'not_found', 'Something went wrong.' );
|
895 |
+
}
|
896 |
}
|
897 |
}
|
898 |
|
1055 |
* @return string The HTML code, with tags closed.
|
1056 |
*/
|
1057 |
function relevanssi_close_tags( $html ) {
|
1058 |
+
$result = array();
|
1059 |
preg_match_all( '#<(?!meta|img|br|hr|input\b)\b([a-z]+)(?: .*)?(?<![/|/ ])>#iU', $html, $result );
|
1060 |
$opened_tags = $result[1];
|
1061 |
preg_match_all( '#</([a-z]+)>#iU', $html, $result );
|
1360 |
* @return string The suggestion HTML code, null if nothing found.
|
1361 |
*/
|
1362 |
function relevanssi_simple_didyoumean( $query, $pre, $post, $n = 5 ) {
|
1363 |
+
global $wp_query;
|
1364 |
|
1365 |
$total_results = $wp_query->found_posts;
|
1366 |
|
1455 |
$closest = '';
|
1456 |
break;
|
1457 |
} else {
|
1458 |
+
if ( relevanssi_strlen( $token ) < 255 ) {
|
1459 |
+
// The levenshtein() function has a max length of 255 characters.
|
1460 |
+
$lev = levenshtein( $token, $row->query );
|
1461 |
+
if ( $lev < 3 && ( $lev < $distance || $distance < 0 ) ) {
|
1462 |
+
if ( $row->a > 0 ) {
|
1463 |
+
$distance = $lev;
|
1464 |
+
$closest = $row->query;
|
1465 |
+
if ( $lev < 2 ) {
|
1466 |
+
break; // get the first with distance of 1 and go.
|
1467 |
+
}
|
1468 |
}
|
1469 |
}
|
1470 |
}
|
1588 |
function relevanssi_common_words( $limit = 25, $wp_cli = false ) {
|
1589 |
global $wpdb, $relevanssi_variables;
|
1590 |
|
|
|
|
|
|
|
|
|
|
|
1591 |
if ( ! is_numeric( $limit ) ) {
|
1592 |
$limit = 25;
|
1593 |
}
|
1606 |
<td>
|
1607 |
<ul>
|
1608 |
<?php
|
|
|
|
|
1609 |
foreach ( $words as $word ) {
|
1610 |
$stop = __( 'Add to stopwords', 'relevanssi' );
|
1611 |
+
printf( '<li>%1$s (%2$d) <button name="term" value="%1$s" />%3$s</button>', esc_attr( $word->term ), esc_html( $word->cnt ), esc_html( $stop ) );
|
1612 |
+
if ( RELEVANSSI_PREMIUM ) {
|
1613 |
+
$body = __( 'Add to content stopwords', 'relevanssi' );
|
1614 |
+
printf( ' <button name="body_term" value="%1$s" />%3$s</button>', esc_attr( $word->term ), esc_html( $word->cnt ), esc_html( $body ) );
|
1615 |
+
}
|
1616 |
+
echo '</li>';
|
1617 |
}
|
1618 |
?>
|
1619 |
</ul>
|
1636 |
return array(
|
1637 |
'nav_menu_item', // Navigation menu items.
|
1638 |
'revision', // Never index revisions.
|
1639 |
+
'acf', // Advanced Custom Fields.
|
1640 |
'acf-field', // Advanced Custom Fields.
|
1641 |
'acf-field-group', // Advanced Custom Fields.
|
1642 |
'oembed_cache', // Mysterious caches.
|
1649 |
'amp_validated_url', // AMP.
|
1650 |
'jp_pay_order', // Jetpack.
|
1651 |
'jp_pay_product', // Jetpack.
|
1652 |
+
'tablepress_table', // TablePress.
|
1653 |
+
'shop_order', // WooCommerce.
|
1654 |
+
'shop_order_refund', // WooCommerce.
|
1655 |
+
'shop_webhook', // WooCommerce.
|
1656 |
);
|
1657 |
}
|
1658 |
|
1666 |
'nav_menu', // Navigation menus.
|
1667 |
'link_category', // Link categories.
|
1668 |
'amp_validation_error', // AMP.
|
1669 |
+
'product_visibility', // WooCommerce.
|
1670 |
);
|
1671 |
}
|
lib/compatibility/gutenberg.php
CHANGED
@@ -16,7 +16,7 @@ if ( RELEVANSSI_PREMIUM ) {
|
|
16 |
add_action( 'save_post', 'relevanssi_remove_duplicate_postmeta', 100 );
|
17 |
}
|
18 |
|
19 |
-
add_filter( 'relevanssi_post_content', 'relevanssi_gutenberg_block_rendering', 10
|
20 |
|
21 |
/**
|
22 |
* Renders Gutenberg reusable blocks.
|
@@ -25,10 +25,9 @@ add_filter( 'relevanssi_post_content', 'relevanssi_gutenberg_block_rendering', 1
|
|
25 |
* picks up the comments and renders the blocks.
|
26 |
*
|
27 |
* @param string $content The post content.
|
28 |
-
* @param object $post The post object.
|
29 |
*
|
30 |
* @return string The post content with the rendered content added.
|
31 |
*/
|
32 |
-
function relevanssi_gutenberg_block_rendering( $content
|
33 |
return do_blocks( $content );
|
34 |
}
|
16 |
add_action( 'save_post', 'relevanssi_remove_duplicate_postmeta', 100 );
|
17 |
}
|
18 |
|
19 |
+
add_filter( 'relevanssi_post_content', 'relevanssi_gutenberg_block_rendering', 10 );
|
20 |
|
21 |
/**
|
22 |
* Renders Gutenberg reusable blocks.
|
25 |
* picks up the comments and renders the blocks.
|
26 |
*
|
27 |
* @param string $content The post content.
|
|
|
28 |
*
|
29 |
* @return string The post content with the rendered content added.
|
30 |
*/
|
31 |
+
function relevanssi_gutenberg_block_rendering( $content ) {
|
32 |
return do_blocks( $content );
|
33 |
}
|
lib/compatibility/wp-file-download.php
ADDED
@@ -0,0 +1,44 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* /lib/compatibility/wp-file-download.php
|
4 |
+
*
|
5 |
+
* WP File Download compatibility features. Compatibility with WPFD checked for
|
6 |
+
* version 4.5.4.
|
7 |
+
*
|
8 |
+
* @package Relevanssi
|
9 |
+
* @author Mikko Saari
|
10 |
+
* @license https://wordpress.org/about/gpl/ GNU General Public License
|
11 |
+
* @see https://www.relevanssi.com/
|
12 |
+
*/
|
13 |
+
|
14 |
+
add_filter( 'relevanssi_content_to_index', 'relevanssi_wpfd_content', 10, 2 );
|
15 |
+
|
16 |
+
/**
|
17 |
+
* Adds the WPFD indexed content to wpfd_file posts.
|
18 |
+
*
|
19 |
+
* Fetches the words from wpfd_words. wpfd_index.tid is the post ID, wpfd_index.id is
|
20 |
+
* then used to get the wpfd_docs.id, that is used to get the wpfd_vectors.did which
|
21 |
+
* can then be used to fetch the correct words from wpfd_words. This function is
|
22 |
+
* hooked onto relevanssi_content_to_index filter hook.
|
23 |
+
*
|
24 |
+
* @param string $content The post content as a string.
|
25 |
+
* @param object $post The post object.
|
26 |
+
*
|
27 |
+
* @return string The post content with the words added to the end.
|
28 |
+
*/
|
29 |
+
function relevanssi_wpfd_content( $content, $post ) {
|
30 |
+
$wpfd_search_config = get_option( '_wpfd_global_search_config', null );
|
31 |
+
if ( 'wpfd_file' === $post->post_type ) {
|
32 |
+
if ( $wpfd_search_config && isset( $wpfd_search_config['plain_text_search'] ) && $wpfd_search_config['plain_text_search'] ) {
|
33 |
+
global $wpdb;
|
34 |
+
$words = $wpdb->get_col("SELECT word
|
35 |
+
FROM {$wpdb->prefix}wpfd_words, {$wpdb->prefix}wpfd_docs, {$wpdb->prefix}wpfd_index, {$wpdb->prefix}wpfd_vectors
|
36 |
+
WHERE {$wpdb->prefix}wpfd_index.tid = {$post->ID}
|
37 |
+
AND {$wpdb->prefix}wpfd_docs.index_id = {$wpdb->prefix}wpfd_index.id
|
38 |
+
AND {$wpdb->prefix}wpfd_docs.id = {$wpdb->prefix}wpfd_vectors.did
|
39 |
+
AND {$wpdb->prefix}wpfd_vectors.wid = {$wpdb->prefix}wpfd_words.id"); // WPCS: unprepared SQL ok, no user-generated inputs.
|
40 |
+
$content .= implode( ' ', $words );
|
41 |
+
}
|
42 |
+
}
|
43 |
+
return $content;
|
44 |
+
}
|
lib/contextual-help.php
CHANGED
@@ -130,6 +130,8 @@ function rlv_index_filter( $block, $post_id ) {
|
|
130 |
'<li>' . sprintf( __( 'If you need a search form on some page on your site, you can use the %s shortcode to print out a basic search form.', 'relevanssi' ), '<code>[searchform]</code>' ) . '</li>' .
|
131 |
// Translators: %1$s is '[searchform post_types="page"]', %2$s is '[searchform cats="10,14,17"]'.
|
132 |
'<li>' . sprintf( __( 'If you need to add query variables to the search form, the shortcode takes parameters, which are then printed out as hidden input fields. To get a search form with a post type restriction, you can use %1$s. To restrict the search to categories 10, 14 and 17, you can use %2$s and so on.', 'relevanssi' ), '<code>[searchform post_types="page"]</code>', '<code>[searchform cats="10,14,17"]</code>' ) . '</li>' .
|
|
|
|
|
133 |
'</ul>',
|
134 |
));
|
135 |
$screen->add_help_tab( array(
|
130 |
'<li>' . sprintf( __( 'If you need a search form on some page on your site, you can use the %s shortcode to print out a basic search form.', 'relevanssi' ), '<code>[searchform]</code>' ) . '</li>' .
|
131 |
// Translators: %1$s is '[searchform post_types="page"]', %2$s is '[searchform cats="10,14,17"]'.
|
132 |
'<li>' . sprintf( __( 'If you need to add query variables to the search form, the shortcode takes parameters, which are then printed out as hidden input fields. To get a search form with a post type restriction, you can use %1$s. To restrict the search to categories 10, 14 and 17, you can use %2$s and so on.', 'relevanssi' ), '<code>[searchform post_types="page"]</code>', '<code>[searchform cats="10,14,17"]</code>' ) . '</li>' .
|
133 |
+
// Translators: %1$s is 'dropdown', %2$s is '[searchform dropdown="category"]'.
|
134 |
+
'<li>' . sprintf( __( 'You can use the %1$s parameter to add a taxonomy dropdown to the search form. Just use the name of the taxonomy, like %2$s. This works best with hierarchical taxonomies like categories with relatively few options available.', 'relevanssi' ), '<code>dropdown</code>', '<code>[searchform dropdown="category"]</code>' ) . '</li>' .
|
135 |
'</ul>',
|
136 |
));
|
137 |
$screen->add_help_tab( array(
|
lib/excerpts-highlights.php
CHANGED
@@ -293,7 +293,6 @@ function relevanssi_create_excerpt( $content, $terms, $query ) {
|
|
293 |
$excerpt_slice = array_slice( $words, $offset, $excerpt_length );
|
294 |
$excerpt_slice = ' ' . implode( ' ', $excerpt_slice );
|
295 |
|
296 |
-
$term_hits = 0;
|
297 |
$count_matches = relevanssi_count_matches( array_keys( $terms ), $excerpt_slice );
|
298 |
if ( $count_matches > 0 && $count_matches > $best_excerpt_term_hits ) {
|
299 |
$best_excerpt_term_hits = $count_matches;
|
@@ -488,9 +487,9 @@ function relevanssi_highlight_terms( $content, $query, $in_docs = false ) {
|
|
488 |
|
489 |
usort( $terms, 'relevanssi_strlen_sort' );
|
490 |
|
491 |
-
$
|
492 |
if ( 'on' === get_option( 'relevanssi_word_boundaries', 'on' ) ) {
|
493 |
-
$
|
494 |
}
|
495 |
|
496 |
foreach ( $terms as $term ) {
|
@@ -500,7 +499,7 @@ function relevanssi_highlight_terms( $content, $query, $in_docs = false ) {
|
|
500 |
$undecoded_content = $content;
|
501 |
$content = html_entity_decode( $content, ENT_QUOTES, 'UTF-8' );
|
502 |
|
503 |
-
if ( $
|
504 |
$regex = "/(\b$pr_term\b)/iu";
|
505 |
if ( 'never' !== get_option( 'relevanssi_fuzzy' ) ) {
|
506 |
$regex = "/(\b$pr_term|$pr_term\b)/iu";
|
@@ -516,9 +515,6 @@ function relevanssi_highlight_terms( $content, $query, $in_docs = false ) {
|
|
516 |
}
|
517 |
}
|
518 |
|
519 |
-
$preg_start = preg_quote( $start_emp_token );
|
520 |
-
$preg_end = preg_quote( $end_emp_token );
|
521 |
-
|
522 |
if ( preg_match_all( '/<.*>/U', $content, $matches ) > 0 ) {
|
523 |
// Remove highlights from inside HTML tags.
|
524 |
foreach ( $matches as $match ) {
|
@@ -821,10 +817,24 @@ function relevanssi_count_matches( $words, $complete_text ) {
|
|
821 |
$lowercase_text = relevanssi_strtolower( $complete_text, 'UTF-8' );
|
822 |
$text = '';
|
823 |
|
|
|
|
|
|
|
|
|
|
|
824 |
$count_words = count( $words );
|
825 |
for ( $t = 0; $t < $count_words; $t++ ) {
|
826 |
$word_slice = relevanssi_strtolower( relevanssi_add_accent_variations( $words[ $t ] ), 'UTF-8' );
|
827 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
828 |
if ( count( $lines ) > 1 ) {
|
829 |
$count_lines = count( $lines );
|
830 |
for ( $tt = 0; $tt < $count_lines; $tt++ ) {
|
293 |
$excerpt_slice = array_slice( $words, $offset, $excerpt_length );
|
294 |
$excerpt_slice = ' ' . implode( ' ', $excerpt_slice );
|
295 |
|
|
|
296 |
$count_matches = relevanssi_count_matches( array_keys( $terms ), $excerpt_slice );
|
297 |
if ( $count_matches > 0 && $count_matches > $best_excerpt_term_hits ) {
|
298 |
$best_excerpt_term_hits = $count_matches;
|
487 |
|
488 |
usort( $terms, 'relevanssi_strlen_sort' );
|
489 |
|
490 |
+
$word_boundaries_available = true;
|
491 |
if ( 'on' === get_option( 'relevanssi_word_boundaries', 'on' ) ) {
|
492 |
+
$word_boundaries_available = false;
|
493 |
}
|
494 |
|
495 |
foreach ( $terms as $term ) {
|
499 |
$undecoded_content = $content;
|
500 |
$content = html_entity_decode( $content, ENT_QUOTES, 'UTF-8' );
|
501 |
|
502 |
+
if ( $word_boundaries_available ) {
|
503 |
$regex = "/(\b$pr_term\b)/iu";
|
504 |
if ( 'never' !== get_option( 'relevanssi_fuzzy' ) ) {
|
505 |
$regex = "/(\b$pr_term|$pr_term\b)/iu";
|
515 |
}
|
516 |
}
|
517 |
|
|
|
|
|
|
|
518 |
if ( preg_match_all( '/<.*>/U', $content, $matches ) > 0 ) {
|
519 |
// Remove highlights from inside HTML tags.
|
520 |
foreach ( $matches as $match ) {
|
817 |
$lowercase_text = relevanssi_strtolower( $complete_text, 'UTF-8' );
|
818 |
$text = '';
|
819 |
|
820 |
+
$word_boundaries_available = true;
|
821 |
+
if ( 'on' === get_option( 'relevanssi_word_boundaries', 'on' ) ) {
|
822 |
+
$word_boundaries_available = false;
|
823 |
+
}
|
824 |
+
|
825 |
$count_words = count( $words );
|
826 |
for ( $t = 0; $t < $count_words; $t++ ) {
|
827 |
$word_slice = relevanssi_strtolower( relevanssi_add_accent_variations( $words[ $t ] ), 'UTF-8' );
|
828 |
+
if ( $word_boundaries_available ) {
|
829 |
+
if ( 'never' !== get_option( 'relevanssi_fuzzy' ) ) {
|
830 |
+
$regex = "/\b$word_slice|$word_slice\b/";
|
831 |
+
} else {
|
832 |
+
$regex = "/\b$word_slice\b/";
|
833 |
+
}
|
834 |
+
} else {
|
835 |
+
$regex = "/$word_slice/";
|
836 |
+
}
|
837 |
+
$lines = preg_split( $regex, $lowercase_text );
|
838 |
if ( count( $lines ) > 1 ) {
|
839 |
$count_lines = count( $lines );
|
840 |
for ( $tt = 0; $tt < $count_lines; $tt++ ) {
|
lib/indexing.php
CHANGED
@@ -567,7 +567,15 @@ function relevanssi_index_doc( $index_post, $remove_first = false, $custom_field
|
|
567 |
if ( $debug ) {
|
568 |
relevanssi_debug_echo( "Comment content: $post_comments" );
|
569 |
}
|
570 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
571 |
if ( count( $post_comments_tokens ) > 0 ) {
|
572 |
foreach ( $post_comments_tokens as $token => $count ) {
|
573 |
$n++;
|
@@ -590,7 +598,8 @@ function relevanssi_index_doc( $index_post, $remove_first = false, $custom_field
|
|
590 |
if ( 'on' === get_option( 'relevanssi_index_author' ) ) {
|
591 |
$author_id = $post->post_author;
|
592 |
$display_name = get_the_author_meta( 'display_name', $author_id );
|
593 |
-
|
|
|
594 |
if ( $debug ) {
|
595 |
relevanssi_debug_echo( 'Indexing post author as: ' . implode( ' ', array_keys( $name_tokens ) ) );
|
596 |
}
|
@@ -671,8 +680,8 @@ function relevanssi_index_doc( $index_post, $remove_first = false, $custom_field
|
|
671 |
if ( $debug ) {
|
672 |
relevanssi_debug_echo( "\tKey: " . $field . ' – value: ' . $value );
|
673 |
}
|
674 |
-
|
675 |
-
$value_tokens = relevanssi_tokenize( $value, true, $min_word_length );
|
676 |
foreach ( $value_tokens as $token => $count ) {
|
677 |
if ( ! isset( $insert_data[ $token ]['customfield'] ) ) {
|
678 |
$insert_data[ $token ]['customfield'] = 0;
|
@@ -694,7 +703,8 @@ function relevanssi_index_doc( $index_post, $remove_first = false, $custom_field
|
|
694 |
if ( $debug ) {
|
695 |
relevanssi_debug_echo( "Indexing post excerpt: $post->post_excerpt" );
|
696 |
}
|
697 |
-
|
|
|
698 |
foreach ( $excerpt_tokens as $token => $count ) {
|
699 |
if ( ! isset( $insert_data[ $token ]['excerpt'] ) ) {
|
700 |
$insert_data[ $token ]['excerpt'] = 0;
|
@@ -745,6 +755,8 @@ function relevanssi_index_doc( $index_post, $remove_first = false, $custom_field
|
|
745 |
* @param boolean If true, remove stopwords. Default true.
|
746 |
*/
|
747 |
$title_tokens = relevanssi_tokenize( $filtered_title, apply_filters( 'relevanssi_remove_stopwords_in_titles', true ), $min_word_length );
|
|
|
|
|
748 |
|
749 |
if ( $debug ) {
|
750 |
relevanssi_debug_echo( "\tTitle, tokenized: " . implode( ' ', array_keys( $title_tokens ) ) );
|
@@ -914,8 +926,9 @@ function relevanssi_index_doc( $index_post, $remove_first = false, $custom_field
|
|
914 |
* @param string $contents The post content.
|
915 |
* @param object $post The full post object.
|
916 |
*/
|
917 |
-
$contents
|
918 |
-
|
|
|
919 |
if ( $debug ) {
|
920 |
relevanssi_debug_echo( "\tContent, tokenized:\n" . implode( ' ', array_keys( $content_tokens ) ) );
|
921 |
}
|
567 |
if ( $debug ) {
|
568 |
relevanssi_debug_echo( "Comment content: $post_comments" );
|
569 |
}
|
570 |
+
/**
|
571 |
+
* Filters the indexing tokens before they are added to the $insert_data.
|
572 |
+
*
|
573 |
+
* @param array An array of token-frequency pairs.
|
574 |
+
* @param string The context of the tokens (eg. 'content', 'title').
|
575 |
+
*
|
576 |
+
* @return array The filtered tokens.
|
577 |
+
*/
|
578 |
+
$post_comments_tokens = apply_filters( 'relevanssi_indexing_tokens', relevanssi_tokenize( $post_comments, true, $min_word_length ), 'comments' );
|
579 |
if ( count( $post_comments_tokens ) > 0 ) {
|
580 |
foreach ( $post_comments_tokens as $token => $count ) {
|
581 |
$n++;
|
598 |
if ( 'on' === get_option( 'relevanssi_index_author' ) ) {
|
599 |
$author_id = $post->post_author;
|
600 |
$display_name = get_the_author_meta( 'display_name', $author_id );
|
601 |
+
/** This filter is documented in common/indexing.php */
|
602 |
+
$name_tokens = apply_filters( 'relevanssi_indexing_tokens', relevanssi_tokenize( $display_name, false, $min_word_length ), 'author' );
|
603 |
if ( $debug ) {
|
604 |
relevanssi_debug_echo( 'Indexing post author as: ' . implode( ' ', array_keys( $name_tokens ) ) );
|
605 |
}
|
680 |
if ( $debug ) {
|
681 |
relevanssi_debug_echo( "\tKey: " . $field . ' – value: ' . $value );
|
682 |
}
|
683 |
+
/** This filter is documented in common/indexing.php */
|
684 |
+
$value_tokens = apply_filters( 'relevanssi_indexing_tokens', relevanssi_tokenize( $value, true, $min_word_length ), 'custom_field' );
|
685 |
foreach ( $value_tokens as $token => $count ) {
|
686 |
if ( ! isset( $insert_data[ $token ]['customfield'] ) ) {
|
687 |
$insert_data[ $token ]['customfield'] = 0;
|
703 |
if ( $debug ) {
|
704 |
relevanssi_debug_echo( "Indexing post excerpt: $post->post_excerpt" );
|
705 |
}
|
706 |
+
/** This filter is documented in common/indexing.php */
|
707 |
+
$excerpt_tokens = apply_filters( 'relevanssi_indexing_tokens', relevanssi_tokenize( $post->post_excerpt, true, $min_word_length ), 'excerpt' );
|
708 |
foreach ( $excerpt_tokens as $token => $count ) {
|
709 |
if ( ! isset( $insert_data[ $token ]['excerpt'] ) ) {
|
710 |
$insert_data[ $token ]['excerpt'] = 0;
|
755 |
* @param boolean If true, remove stopwords. Default true.
|
756 |
*/
|
757 |
$title_tokens = relevanssi_tokenize( $filtered_title, apply_filters( 'relevanssi_remove_stopwords_in_titles', true ), $min_word_length );
|
758 |
+
/** This filter is documented in common/indexing.php */
|
759 |
+
$title_tokens = apply_filters( 'relevanssi_indexing_tokens', $title_tokens, 'title' );
|
760 |
|
761 |
if ( $debug ) {
|
762 |
relevanssi_debug_echo( "\tTitle, tokenized: " . implode( ' ', array_keys( $title_tokens ) ) );
|
926 |
* @param string $contents The post content.
|
927 |
* @param object $post The full post object.
|
928 |
*/
|
929 |
+
$contents = apply_filters( 'relevanssi_post_content_before_tokenize', $contents, $post );
|
930 |
+
/** This filter is documented in common/indexing.php */
|
931 |
+
$content_tokens = apply_filters( 'relevanssi_indexing_tokens', relevanssi_tokenize( $contents, 'body', $min_word_length ), 'content' );
|
932 |
if ( $debug ) {
|
933 |
relevanssi_debug_echo( "\tContent, tokenized:\n" . implode( ' ', array_keys( $content_tokens ) ) );
|
934 |
}
|
lib/init.php
CHANGED
@@ -140,9 +140,13 @@ function relevanssi_init() {
|
|
140 |
require_once 'compatibility/wp-search-suggest.php';
|
141 |
}
|
142 |
|
143 |
-
if (
|
144 |
require_once 'compatibility/gutenberg.php';
|
145 |
}
|
|
|
|
|
|
|
|
|
146 |
}
|
147 |
|
148 |
/**
|
140 |
require_once 'compatibility/wp-search-suggest.php';
|
141 |
}
|
142 |
|
143 |
+
if ( function_exists( 'do_blocks' ) ) {
|
144 |
require_once 'compatibility/gutenberg.php';
|
145 |
}
|
146 |
+
|
147 |
+
if ( defined( 'WPFD_VERSION' ) ) {
|
148 |
+
require_once 'compatibility/wp-file-download.php';
|
149 |
+
}
|
150 |
}
|
151 |
|
152 |
/**
|
lib/interface.php
CHANGED
@@ -45,6 +45,10 @@ function relevanssi_options() {
|
|
45 |
check_admin_referer( plugin_basename( $relevanssi_variables['file'] ), 'relevanssi_options' );
|
46 |
relevanssi_add_stopword( $_REQUEST['term'] );
|
47 |
}
|
|
|
|
|
|
|
|
|
48 |
}
|
49 |
}
|
50 |
|
@@ -62,6 +66,21 @@ function relevanssi_options() {
|
|
62 |
check_admin_referer( plugin_basename( $relevanssi_variables['file'] ), 'relevanssi_options' );
|
63 |
relevanssi_remove_all_stopwords();
|
64 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
65 |
}
|
66 |
|
67 |
relevanssi_options_form();
|
45 |
check_admin_referer( plugin_basename( $relevanssi_variables['file'] ), 'relevanssi_options' );
|
46 |
relevanssi_add_stopword( $_REQUEST['term'] );
|
47 |
}
|
48 |
+
if ( isset( $_REQUEST['body_term'] ) ) {
|
49 |
+
check_admin_referer( plugin_basename( $relevanssi_variables['file'] ), 'relevanssi_options' );
|
50 |
+
relevanssi_add_body_stopword( $_REQUEST['body_term'] );
|
51 |
+
}
|
52 |
}
|
53 |
}
|
54 |
|
66 |
check_admin_referer( plugin_basename( $relevanssi_variables['file'] ), 'relevanssi_options' );
|
67 |
relevanssi_remove_all_stopwords();
|
68 |
}
|
69 |
+
|
70 |
+
if ( isset( $_REQUEST['addbodystopword'] ) ) {
|
71 |
+
check_admin_referer( plugin_basename( $relevanssi_variables['file'] ), 'relevanssi_options' );
|
72 |
+
relevanssi_add_body_stopword( $_REQUEST['addbodystopword'] );
|
73 |
+
}
|
74 |
+
|
75 |
+
if ( isset( $_REQUEST['removebodystopword'] ) ) {
|
76 |
+
check_admin_referer( plugin_basename( $relevanssi_variables['file'] ), 'relevanssi_options' );
|
77 |
+
relevanssi_remove_body_stopword( $_REQUEST['removebodystopword'] );
|
78 |
+
}
|
79 |
+
|
80 |
+
if ( isset( $_REQUEST['removeallbodystopwords'] ) ) {
|
81 |
+
check_admin_referer( plugin_basename( $relevanssi_variables['file'] ), 'relevanssi_options' );
|
82 |
+
relevanssi_remove_all_body_stopwords();
|
83 |
+
}
|
84 |
}
|
85 |
|
86 |
relevanssi_options_form();
|
lib/search-query-restrictions.php
ADDED
@@ -0,0 +1,515 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* /lib/search-query-restrictions.php
|
4 |
+
*
|
5 |
+
* Responsible for converting query parameters to MySQL query restrictions.
|
6 |
+
*
|
7 |
+
* @package Relevanssi
|
8 |
+
* @author Mikko Saari
|
9 |
+
* @license https://wordpress.org/about/gpl/ GNU General Public License
|
10 |
+
* @see https://www.relevanssi.com/
|
11 |
+
*/
|
12 |
+
|
13 |
+
/**
|
14 |
+
* Processes the arguments to create the query restrictions.
|
15 |
+
*
|
16 |
+
* All individual parts are tested.
|
17 |
+
*
|
18 |
+
* @param array $args The query arguments.
|
19 |
+
*
|
20 |
+
* @return array An array containing `query_restriction` and `query_join`.
|
21 |
+
*/
|
22 |
+
function relevanssi_process_query_args( $args ) {
|
23 |
+
$query_restrictions = '';
|
24 |
+
$query_join = '';
|
25 |
+
$query = '';
|
26 |
+
|
27 |
+
if ( function_exists( 'wp_encode_emoji' ) ) {
|
28 |
+
$query = wp_encode_emoji( $args['q'] );
|
29 |
+
}
|
30 |
+
|
31 |
+
if ( $args['sentence'] ) {
|
32 |
+
$query = str_replace( array( '"', '“', '”' ), '', $query );
|
33 |
+
$query = '"' . $query . '"';
|
34 |
+
}
|
35 |
+
|
36 |
+
if ( is_array( $args['tax_query'] ) ) {
|
37 |
+
$query_restrictions .= relevanssi_process_tax_query( $args['tax_query_relation'], $args['tax_query'] );
|
38 |
+
}
|
39 |
+
|
40 |
+
if ( is_array( $args['post_query'] ) ) {
|
41 |
+
$query_restrictions .= relevanssi_process_post_query( $args['post_query'] );
|
42 |
+
}
|
43 |
+
|
44 |
+
if ( is_array( $args['parent_query'] ) ) {
|
45 |
+
$query_restrictions .= relevanssi_process_parent_query( $args['parent_query'] );
|
46 |
+
}
|
47 |
+
|
48 |
+
if ( is_array( $args['meta_query'] ) ) {
|
49 |
+
$processed_meta = relevanssi_process_meta_query( $args['meta_query'] );
|
50 |
+
$query_restrictions .= $processed_meta['where'];
|
51 |
+
$query_join .= $processed_meta['join'];
|
52 |
+
}
|
53 |
+
|
54 |
+
if ( $args['date_query'] instanceof WP_Date_Query ) {
|
55 |
+
$query_restrictions .= relevanssi_process_date_query( $args['date_query'] );
|
56 |
+
}
|
57 |
+
|
58 |
+
if ( $args['expost'] ) {
|
59 |
+
$query_restrictions .= relevanssi_process_expost( $args['expost'] );
|
60 |
+
}
|
61 |
+
|
62 |
+
if ( $args['author'] ) {
|
63 |
+
$query_restrictions .= relevanssi_process_author( $args['author'] );
|
64 |
+
}
|
65 |
+
|
66 |
+
if ( $args['by_date'] ) {
|
67 |
+
$query_restrictions .= relevanssi_process_by_date( $args['by_date'] );
|
68 |
+
}
|
69 |
+
|
70 |
+
$phrases = relevanssi_recognize_phrases( $query );
|
71 |
+
if ( $phrases ) {
|
72 |
+
$query_restrictions .= " $phrases";
|
73 |
+
// Clean: $phrases is escaped earlier.
|
74 |
+
}
|
75 |
+
|
76 |
+
if ( $args['post_type'] || $args['include_attachments'] ) {
|
77 |
+
$query_restrictions .= relevanssi_process_post_type( $args['post_type'],
|
78 |
+
$args['admin_search'], $args['include_attachments'] );
|
79 |
+
}
|
80 |
+
|
81 |
+
if ( $args['post_status'] ) {
|
82 |
+
$query_restrictions .= relevanssi_process_post_status( $args['post_status'] );
|
83 |
+
}
|
84 |
+
|
85 |
+
return array(
|
86 |
+
'query_restrictions' => $query_restrictions,
|
87 |
+
'query_join' => $query_join,
|
88 |
+
'query_query' => $query,
|
89 |
+
);
|
90 |
+
}
|
91 |
+
|
92 |
+
/**
|
93 |
+
* Processes the 'in' and 'not in' parameters to MySQL query restrictions.
|
94 |
+
*
|
95 |
+
* Checks that the parameters are integers and formulates a MySQL query restriction
|
96 |
+
* from them. If the same posts are both included and excluded, exclusion will take
|
97 |
+
* precedence.
|
98 |
+
*
|
99 |
+
* Tested.
|
100 |
+
*
|
101 |
+
* @param array $post_query An array where included posts are in $post_query['in']
|
102 |
+
* and excluded posts are in $post_query['not in'].
|
103 |
+
*
|
104 |
+
* @return string MySQL query restrictions matching the array.
|
105 |
+
*/
|
106 |
+
function relevanssi_process_post_query( $post_query ) {
|
107 |
+
$query_restrictions = '';
|
108 |
+
$valid_exclude_values = array();
|
109 |
+
if ( ! empty( $post_query['not in'] ) ) {
|
110 |
+
foreach ( $post_query['not in'] as $post_not_in_id ) {
|
111 |
+
if ( is_numeric( $post_not_in_id ) ) {
|
112 |
+
$valid_exclude_values[] = $post_not_in_id;
|
113 |
+
}
|
114 |
+
}
|
115 |
+
$posts = implode( ',', $valid_exclude_values );
|
116 |
+
if ( ! empty( $posts ) ) {
|
117 |
+
$query_restrictions .= " AND relevanssi.doc NOT IN ($posts)";
|
118 |
+
// Clean: $posts is checked to be integers.
|
119 |
+
}
|
120 |
+
}
|
121 |
+
if ( ! empty( $post_query['in'] ) ) {
|
122 |
+
$valid_values = array();
|
123 |
+
foreach ( $post_query['in'] as $post_in_id ) {
|
124 |
+
if ( is_numeric( $post_in_id ) ) {
|
125 |
+
$valid_values[] = $post_in_id;
|
126 |
+
}
|
127 |
+
}
|
128 |
+
// If same values appear in both arrays, exclusion will override inclusion.
|
129 |
+
$valid_values = array_diff( $valid_values, $valid_exclude_values );
|
130 |
+
$posts = implode( ',', $valid_values );
|
131 |
+
if ( ! empty( $posts ) ) {
|
132 |
+
$query_restrictions .= " AND relevanssi.doc IN ($posts)";
|
133 |
+
// Clean: $posts is checked to be integers.
|
134 |
+
}
|
135 |
+
}
|
136 |
+
return $query_restrictions;
|
137 |
+
}
|
138 |
+
|
139 |
+
/**
|
140 |
+
* Processes the 'parent in' and 'parent not in' parameters to MySQL query
|
141 |
+
* restrictions.
|
142 |
+
*
|
143 |
+
* Checks that the parameters are integers and formulates a MySQL query restriction
|
144 |
+
* from them. If the same posts are both included and excluded, exclusion will take
|
145 |
+
* precedence.
|
146 |
+
*
|
147 |
+
* Tested.
|
148 |
+
*
|
149 |
+
* @param array $parent_query An array where included posts are in
|
150 |
+
* $post_query['parent in'] and excluded posts are in $post_query['parent not in'].
|
151 |
+
*
|
152 |
+
* @return string MySQL query restrictions matching the array.
|
153 |
+
*/
|
154 |
+
function relevanssi_process_parent_query( $parent_query ) {
|
155 |
+
global $wpdb;
|
156 |
+
|
157 |
+
$query_restrictions = '';
|
158 |
+
$valid_exclude_values = array();
|
159 |
+
if ( isset( $parent_query['parent not in'] ) ) {
|
160 |
+
foreach ( $parent_query['parent not in'] as $post_not_in_id ) {
|
161 |
+
if ( is_int( $post_not_in_id ) ) {
|
162 |
+
$valid_exclude_values[] = $post_not_in_id;
|
163 |
+
}
|
164 |
+
}
|
165 |
+
$posts = implode( ',', $valid_exclude_values );
|
166 |
+
if ( isset( $posts ) ) {
|
167 |
+
$query_restrictions .= " AND relevanssi.doc NOT IN (SELECT ID FROM $wpdb->posts WHERE post_parent IN ($posts))";
|
168 |
+
// Clean: $posts is checked to be integers.
|
169 |
+
}
|
170 |
+
}
|
171 |
+
if ( isset( $parent_query['parent in'] ) ) {
|
172 |
+
$valid_values = array();
|
173 |
+
foreach ( $parent_query['parent in'] as $post_in_id ) {
|
174 |
+
if ( is_int( $post_in_id ) ) {
|
175 |
+
$valid_values[] = $post_in_id;
|
176 |
+
}
|
177 |
+
}
|
178 |
+
$valid_values = array_diff( $valid_values, $valid_exclude_values );
|
179 |
+
$posts = implode( ',', $valid_values );
|
180 |
+
if ( strlen( $posts ) > 0 ) {
|
181 |
+
$query_restrictions .= " AND relevanssi.doc IN (SELECT ID FROM $wpdb->posts WHERE post_parent IN ($posts))";
|
182 |
+
// Clean: $posts is checked to be integers.
|
183 |
+
}
|
184 |
+
}
|
185 |
+
|
186 |
+
return $query_restrictions;
|
187 |
+
}
|
188 |
+
|
189 |
+
/**
|
190 |
+
* Processes the meta query parameter to MySQL query restrictions.
|
191 |
+
*
|
192 |
+
* Uses the WP_Meta_Query object to parse the query variables to create the MySQL
|
193 |
+
* JOIN and WHERE clauses.
|
194 |
+
*
|
195 |
+
* Tested.
|
196 |
+
*
|
197 |
+
* @see WP_Meta_Query
|
198 |
+
*
|
199 |
+
* @param array $meta_query A meta query array.
|
200 |
+
*
|
201 |
+
* @return array Index 'where' is the WHERE, index 'join' is the JOIN.
|
202 |
+
*/
|
203 |
+
function relevanssi_process_meta_query( $meta_query ) {
|
204 |
+
$mq_vars = array( 'meta_query' => $meta_query );
|
205 |
+
|
206 |
+
$mq = new WP_Meta_Query();
|
207 |
+
$mq->parse_query_vars( $mq_vars );
|
208 |
+
$meta_sql = $mq->get_sql( 'post', 'relevanssi', 'doc' );
|
209 |
+
$meta_join = '';
|
210 |
+
$meta_where = '';
|
211 |
+
if ( $meta_sql ) {
|
212 |
+
$meta_join = $meta_sql['join'];
|
213 |
+
$meta_where = $meta_sql['where'];
|
214 |
+
}
|
215 |
+
|
216 |
+
return array(
|
217 |
+
'where' => $meta_where,
|
218 |
+
'join' => $meta_join,
|
219 |
+
);
|
220 |
+
}
|
221 |
+
|
222 |
+
/**
|
223 |
+
* Processes the date query parameter to MySQL query restrictions.
|
224 |
+
*
|
225 |
+
* Uses the WP_Date_Query object to parse the query variables to create the MySQL
|
226 |
+
* WHERE clause.
|
227 |
+
*
|
228 |
+
* Tested.
|
229 |
+
*
|
230 |
+
* @see WP_Date_Query
|
231 |
+
*
|
232 |
+
* @global object $wpdb The WP database interface.
|
233 |
+
*
|
234 |
+
* @param WP_Date_Query $date_query A date query object.
|
235 |
+
*
|
236 |
+
* @return string The MySQL query restriction.
|
237 |
+
*/
|
238 |
+
function relevanssi_process_date_query( $date_query ) {
|
239 |
+
global $wpdb;
|
240 |
+
|
241 |
+
$query_restrictions = '';
|
242 |
+
if ( method_exists( $date_query, 'get_sql' ) ) {
|
243 |
+
$sql = $date_query->get_sql(); // AND ( the query itself ).
|
244 |
+
$query_restrictions = " AND relevanssi.doc IN ( SELECT DISTINCT(ID) FROM $wpdb->posts WHERE 1 $sql )";
|
245 |
+
// Clean: $sql generated by $date_query->get_sql() query.
|
246 |
+
}
|
247 |
+
return $query_restrictions;
|
248 |
+
}
|
249 |
+
|
250 |
+
/**
|
251 |
+
* Processes the post exclusion parameter to MySQL query restrictions.
|
252 |
+
*
|
253 |
+
* Takes a comma-separated list of post ID numbers and creates a MySQL query
|
254 |
+
* restriction from them.
|
255 |
+
*
|
256 |
+
* @param string $expost The post IDs to exclude, comma-separated.
|
257 |
+
*
|
258 |
+
* @return string The MySQL query restriction.
|
259 |
+
*/
|
260 |
+
function relevanssi_process_expost( $expost ) {
|
261 |
+
$posts_to_exclude = '';
|
262 |
+
$excluded_post_ids_unchecked = explode( ',', $expost );
|
263 |
+
$excluded_post_ids = array();
|
264 |
+
foreach ( $excluded_post_ids_unchecked as $excluded_post_id ) {
|
265 |
+
$excluded_post_ids[] = intval( trim( $excluded_post_id, ' -' ) );
|
266 |
+
}
|
267 |
+
$excluded_post_ids_string = implode( ',', $excluded_post_ids );
|
268 |
+
$posts_to_exclude .= " AND relevanssi.doc NOT IN ($excluded_post_ids_string)";
|
269 |
+
// Clean: escaped.
|
270 |
+
return $posts_to_exclude;
|
271 |
+
}
|
272 |
+
|
273 |
+
/**
|
274 |
+
* Processes the author parameter to MySQL query restrictions.
|
275 |
+
*
|
276 |
+
* Takes an array of author ID numbers and creates the MySQL query restriction code
|
277 |
+
* from them. Negative values are counted as exclusion and positive values as
|
278 |
+
* inclusion.
|
279 |
+
*
|
280 |
+
* Tested.
|
281 |
+
*
|
282 |
+
* @global object $wpdb The WP database interface.
|
283 |
+
*
|
284 |
+
* @param array $author An array of authors. Positive values are inclusion,
|
285 |
+
* negative values are exclusion.
|
286 |
+
*
|
287 |
+
* @return string The MySQL query restriction.
|
288 |
+
*/
|
289 |
+
function relevanssi_process_author( $author ) {
|
290 |
+
global $wpdb;
|
291 |
+
|
292 |
+
$query_restrictions = '';
|
293 |
+
|
294 |
+
$author_in = array();
|
295 |
+
$author_not_in = array();
|
296 |
+
foreach ( $author as $id ) {
|
297 |
+
if ( ! is_numeric( $id ) ) {
|
298 |
+
continue;
|
299 |
+
}
|
300 |
+
if ( $id > 0 ) {
|
301 |
+
$author_in[] = $id;
|
302 |
+
} else {
|
303 |
+
$author_not_in[] = abs( $id );
|
304 |
+
}
|
305 |
+
}
|
306 |
+
if ( count( $author_in ) > 0 ) {
|
307 |
+
$authors = implode( ',', $author_in );
|
308 |
+
$query_restrictions .= " AND relevanssi.doc IN (SELECT DISTINCT(posts.ID) FROM $wpdb->posts AS posts
|
309 |
+
WHERE posts.post_author IN ($authors))";
|
310 |
+
// Clean: $authors is always just numbers.
|
311 |
+
}
|
312 |
+
if ( count( $author_not_in ) > 0 ) {
|
313 |
+
$authors = implode( ',', $author_not_in );
|
314 |
+
$query_restrictions .= " AND relevanssi.doc NOT IN (SELECT DISTINCT(posts.ID) FROM $wpdb->posts AS posts
|
315 |
+
WHERE posts.post_author IN ($authors))";
|
316 |
+
// Clean: $authors is always just numbers.
|
317 |
+
}
|
318 |
+
|
319 |
+
return $query_restrictions;
|
320 |
+
}
|
321 |
+
|
322 |
+
/**
|
323 |
+
* Processes the by_date parameter to MySQL query restrictions.
|
324 |
+
*
|
325 |
+
* The by_date parameter is a simple data parameter in the format '24h', that is a
|
326 |
+
* number followed by an unit (h, d, m, y, or w).
|
327 |
+
*
|
328 |
+
* Tested.
|
329 |
+
*
|
330 |
+
* @global object $wpdb The WP database interface.
|
331 |
+
*
|
332 |
+
* @param string $n The date parameter.
|
333 |
+
*
|
334 |
+
* @return string The MySQL query restriction.
|
335 |
+
*/
|
336 |
+
function relevanssi_process_by_date( $n ) {
|
337 |
+
global $wpdb;
|
338 |
+
$query_restrictions = '';
|
339 |
+
|
340 |
+
$u = substr( $n, -1, 1 );
|
341 |
+
switch ( $u ) {
|
342 |
+
case 'h':
|
343 |
+
$unit = 'HOUR';
|
344 |
+
break;
|
345 |
+
case 'd':
|
346 |
+
$unit = 'DAY';
|
347 |
+
break;
|
348 |
+
case 'm':
|
349 |
+
$unit = 'MONTH';
|
350 |
+
break;
|
351 |
+
case 'y':
|
352 |
+
$unit = 'YEAR';
|
353 |
+
break;
|
354 |
+
case 'w':
|
355 |
+
$unit = 'WEEK';
|
356 |
+
break;
|
357 |
+
default:
|
358 |
+
$unit = 'DAY';
|
359 |
+
}
|
360 |
+
|
361 |
+
$n = preg_replace( '/[hdmyw]/', '', $n );
|
362 |
+
|
363 |
+
if ( is_numeric( $n ) ) {
|
364 |
+
$query_restrictions .= " AND relevanssi.doc IN (SELECT DISTINCT(posts.ID) FROM $wpdb->posts AS posts
|
365 |
+
WHERE posts.post_date > DATE_SUB(NOW(), INTERVAL $n $unit))";
|
366 |
+
// Clean: $n is always numeric, $unit is Relevanssi-generated.
|
367 |
+
}
|
368 |
+
|
369 |
+
return $query_restrictions;
|
370 |
+
}
|
371 |
+
|
372 |
+
/**
|
373 |
+
* Extracts the post types from a comma-separated list or an array.
|
374 |
+
*
|
375 |
+
* Handles the non-post post types as well (user, taxonomies, etc.) and escapes the
|
376 |
+
* post types for SQL injections.
|
377 |
+
*
|
378 |
+
* Tested.
|
379 |
+
*
|
380 |
+
* @param string|array $post_type An array or a comma-separated list of
|
381 |
+
* post types.
|
382 |
+
* @param boolean $admin_search True if this is an admin search.
|
383 |
+
* @param boolean $include_attachments True if attachments are allowed in the
|
384 |
+
* search.
|
385 |
+
*
|
386 |
+
* @global object $wpdb The WP database interface.
|
387 |
+
*
|
388 |
+
* @return array Array containing the 'post_type' and 'non_post_post_type' (which
|
389 |
+
* defaults to null).
|
390 |
+
*/
|
391 |
+
function relevanssi_process_post_type( $post_type, $admin_search, $include_attachments ) {
|
392 |
+
global $wpdb;
|
393 |
+
|
394 |
+
// If $post_type is not set, see if there are post types to exclude from the search.
|
395 |
+
// If $post_type is set, there's no need to exclude, as we only include.
|
396 |
+
$negative_post_type = null;
|
397 |
+
if ( ! $post_type && ! $admin_search ) {
|
398 |
+
$negative_post_type = relevanssi_get_negative_post_type( $include_attachments );
|
399 |
+
}
|
400 |
+
|
401 |
+
$non_post_post_type = null;
|
402 |
+
$non_post_post_types_array = array();
|
403 |
+
if ( function_exists( 'relevanssi_get_non_post_post_types' ) ) {
|
404 |
+
// Relevanssi Premium includes post types which are not actually posts.
|
405 |
+
$non_post_post_types_array = relevanssi_get_non_post_post_types();
|
406 |
+
}
|
407 |
+
|
408 |
+
if ( $post_type ) {
|
409 |
+
if ( ! is_array( $post_type ) ) {
|
410 |
+
$post_types = explode( ',', $post_type );
|
411 |
+
} else {
|
412 |
+
$post_types = $post_type;
|
413 |
+
}
|
414 |
+
|
415 |
+
// This array will contain all regular post types involved in the search parameters.
|
416 |
+
$post_post_types = array_diff( $post_types, $non_post_post_types_array );
|
417 |
+
|
418 |
+
// This array has the non-post post types involved.
|
419 |
+
$non_post_post_types = array_intersect( $post_types, $non_post_post_types_array );
|
420 |
+
|
421 |
+
// Escape both for SQL queries, just in case.
|
422 |
+
$non_post_post_types = esc_sql( $non_post_post_types );
|
423 |
+
$post_types = esc_sql( $post_post_types );
|
424 |
+
|
425 |
+
// Implode to a parameter string, or set to null if empty.
|
426 |
+
$non_post_post_type = null;
|
427 |
+
if ( count( $non_post_post_types ) > 0 ) {
|
428 |
+
$non_post_post_type = "'" . implode( "', '", $non_post_post_types ) . "'";
|
429 |
+
}
|
430 |
+
$post_type = null;
|
431 |
+
if ( count( $post_types ) > 0 ) {
|
432 |
+
$post_type = "'" . implode( "', '", $post_types ) . "'";
|
433 |
+
}
|
434 |
+
}
|
435 |
+
|
436 |
+
$query_restrictions = '';
|
437 |
+
|
438 |
+
if ( $post_type ) {
|
439 |
+
$restriction = " AND (
|
440 |
+
relevanssi.doc IN (
|
441 |
+
SELECT DISTINCT(posts.ID) FROM $wpdb->posts AS posts
|
442 |
+
WHERE posts.post_type IN ($post_type)
|
443 |
+
) *np*
|
444 |
+
)"; // Clean: $post_type is escaped.
|
445 |
+
|
446 |
+
// There are post types involved that are taxonomies or users, so can't
|
447 |
+
// match to wp_posts. Add a relevanssi.type restriction.
|
448 |
+
if ( $non_post_post_type ) {
|
449 |
+
$restriction = str_replace( '*np*', "OR (relevanssi.type IN ($non_post_post_type))", $restriction );
|
450 |
+
// Clean: $non_post_post_types is escaped.
|
451 |
+
} else {
|
452 |
+
// No non-post post types, so remove the placeholder.
|
453 |
+
$restriction = str_replace( '*np*', '', $restriction );
|
454 |
+
}
|
455 |
+
$query_restrictions .= $restriction;
|
456 |
+
} else {
|
457 |
+
// No regular post types.
|
458 |
+
if ( $non_post_post_type ) {
|
459 |
+
// But there is a non-post post type restriction.
|
460 |
+
$query_restrictions .= " AND (relevanssi.type IN ($non_post_post_type))";
|
461 |
+
// Clean: $non_post_post_types is escaped.
|
462 |
+
}
|
463 |
+
}
|
464 |
+
|
465 |
+
if ( $negative_post_type ) {
|
466 |
+
$query_restrictions .= " AND ((relevanssi.doc IN (SELECT DISTINCT(posts.ID) FROM $wpdb->posts AS posts
|
467 |
+
WHERE posts.post_type NOT IN ($negative_post_type))) OR (doc = -1))";
|
468 |
+
// Clean: $negative_post_type is escaped.
|
469 |
+
}
|
470 |
+
|
471 |
+
return $query_restrictions;
|
472 |
+
}
|
473 |
+
|
474 |
+
/**
|
475 |
+
* Processes the post status parameter.
|
476 |
+
*
|
477 |
+
* Takes the post status parameter and creates a MySQL query restriction from it.
|
478 |
+
* Checks if this is in admin context: if the query isn't, there's a catch added to
|
479 |
+
* capture user profiles and taxonomy terms.
|
480 |
+
*
|
481 |
+
* @param string $post_status A post status string.
|
482 |
+
*
|
483 |
+
* @global WP_Query $wp_query The WP Query object.
|
484 |
+
* @global object $wpdb The WP database interface.
|
485 |
+
*
|
486 |
+
* @return string The MySQL query restriction.
|
487 |
+
*/
|
488 |
+
function relevanssi_process_post_status( $post_status ) {
|
489 |
+
global $wp_query, $wpdb;
|
490 |
+
$query_restrictions = '';
|
491 |
+
|
492 |
+
if ( ! is_array( $post_status ) ) {
|
493 |
+
$post_statuses = esc_sql( explode( ',', $post_status ) );
|
494 |
+
} else {
|
495 |
+
$post_statuses = esc_sql( $post_status );
|
496 |
+
}
|
497 |
+
|
498 |
+
$escaped_post_status = '';
|
499 |
+
if ( count( $post_statuses ) > 0 ) {
|
500 |
+
$escaped_post_status = "'" . implode( "', '", $post_statuses ) . "'";
|
501 |
+
}
|
502 |
+
|
503 |
+
if ( $escaped_post_status ) {
|
504 |
+
if ( $wp_query->is_admin ) {
|
505 |
+
$query_restrictions .= " AND ((relevanssi.doc IN (SELECT DISTINCT(posts.ID) FROM $wpdb->posts AS posts
|
506 |
+
WHERE posts.post_status IN ($escaped_post_status))))";
|
507 |
+
} else {
|
508 |
+
// The -1 is there to get user profiles and category pages.
|
509 |
+
$query_restrictions .= " AND ((relevanssi.doc IN (SELECT DISTINCT(posts.ID) FROM $wpdb->posts AS posts
|
510 |
+
WHERE posts.post_status IN ($escaped_post_status))) OR (doc = -1))";
|
511 |
+
}
|
512 |
+
}
|
513 |
+
|
514 |
+
return $query_restrictions;
|
515 |
+
}
|
lib/search-tax-query.php
ADDED
@@ -0,0 +1,360 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* /lib/search-tax-query.php
|
4 |
+
*
|
5 |
+
* Responsible for converting tax_query parameters to MySQL query restrictions.
|
6 |
+
*
|
7 |
+
* @package Relevanssi
|
8 |
+
* @author Mikko Saari
|
9 |
+
* @license https://wordpress.org/about/gpl/ GNU General Public License
|
10 |
+
* @see https://www.relevanssi.com/
|
11 |
+
*/
|
12 |
+
|
13 |
+
/**
|
14 |
+
* Processes the tax query to formulate a query restriction to the MySQL query.
|
15 |
+
*
|
16 |
+
* Tested.
|
17 |
+
*
|
18 |
+
* @uses relevanssi_process_tax_query_row()
|
19 |
+
*
|
20 |
+
* @global object $wpdb The WP database interface.
|
21 |
+
*
|
22 |
+
* @param string $tax_query_relation The base tax query relation. Default 'and'.
|
23 |
+
* @param array $tax_query The tax query array.
|
24 |
+
*
|
25 |
+
* @return string The query restrictions for the MySQL query.
|
26 |
+
*/
|
27 |
+
function relevanssi_process_tax_query( $tax_query_relation, $tax_query ) {
|
28 |
+
global $wpdb;
|
29 |
+
|
30 |
+
$query_restrictions = '';
|
31 |
+
|
32 |
+
if ( ! isset( $tax_query_relation ) ) {
|
33 |
+
$tax_query_relation = 'and';
|
34 |
+
}
|
35 |
+
$tax_query_relation = relevanssi_strtolower( $tax_query_relation );
|
36 |
+
$term_tax_ids = array();
|
37 |
+
$not_term_tax_ids = array();
|
38 |
+
$and_term_tax_ids = array();
|
39 |
+
|
40 |
+
$is_sub_row = false;
|
41 |
+
foreach ( $tax_query as $row ) {
|
42 |
+
if ( isset( $row['terms'] ) || ( isset( $row['operator'] ) && ( 'not exists' === strtolower( $row['operator'] ) || 'exists' === strtolower( $row['operator'] ) ) ) ) {
|
43 |
+
list( $query_restrictions, $term_tax_ids, $not_term_tax_ids, $and_term_tax_ids ) =
|
44 |
+
relevanssi_process_tax_query_row( $row, $is_sub_row, $tax_query_relation, $query_restrictions, $tax_query_relation, $term_tax_ids, $not_term_tax_ids, $and_term_tax_ids );
|
45 |
+
} else {
|
46 |
+
$row_tax_query_relation = $tax_query_relation;
|
47 |
+
if ( isset( $row['relation'] ) ) {
|
48 |
+
$row_tax_query_relation = relevanssi_strtolower( $row['relation'] );
|
49 |
+
}
|
50 |
+
if ( is_array( $row ) ) {
|
51 |
+
foreach ( $row as $subrow ) {
|
52 |
+
$is_sub_row = true;
|
53 |
+
if ( isset( $subrow['terms'] ) ) {
|
54 |
+
list( $query_restrictions, $term_tax_ids, $not_term_tax_ids, $and_term_tax_ids ) =
|
55 |
+
relevanssi_process_tax_query_row( $subrow, $is_sub_row, $tax_query_relation, $query_restrictions, $row_tax_query_relation, $term_tax_ids, $not_term_tax_ids, $and_term_tax_ids );
|
56 |
+
}
|
57 |
+
}
|
58 |
+
if ( 'or' === $row_tax_query_relation ) {
|
59 |
+
$query_restrictions .= relevanssi_process_term_tax_ids(
|
60 |
+
$term_tax_ids,
|
61 |
+
$not_term_tax_ids,
|
62 |
+
$and_term_tax_ids
|
63 |
+
);
|
64 |
+
}
|
65 |
+
}
|
66 |
+
}
|
67 |
+
}
|
68 |
+
|
69 |
+
if ( 'or' === $tax_query_relation ) {
|
70 |
+
$query_restrictions .= relevanssi_process_term_tax_ids(
|
71 |
+
$term_tax_ids,
|
72 |
+
$not_term_tax_ids,
|
73 |
+
$and_term_tax_ids
|
74 |
+
);
|
75 |
+
}
|
76 |
+
|
77 |
+
return $query_restrictions;
|
78 |
+
}
|
79 |
+
|
80 |
+
/**
|
81 |
+
* Processes one tax_query row.
|
82 |
+
*
|
83 |
+
* Tested.
|
84 |
+
*
|
85 |
+
* @global object $wpdb The WordPress database interface.
|
86 |
+
*
|
87 |
+
* @param array $row The tax_query row array.
|
88 |
+
* @param boolean $is_sub_row True if this is a subrow.
|
89 |
+
* @param string $global_relation The global tax_query relation (AND or OR).
|
90 |
+
* @param string $query_restrictions The MySQL query restriction.
|
91 |
+
* @param string $tax_query_relation The tax_query relation.
|
92 |
+
* @param array $term_tax_ids Array of term taxonomy IDs.
|
93 |
+
* @param array $not_term_tax_ids Array of excluded term taxonomy IDs.
|
94 |
+
* @param array $and_term_tax_ids Array of AND term taxonomy IDs.
|
95 |
+
*
|
96 |
+
* @return array Returns an array where the first item is the updated
|
97 |
+
* $query_restrictions, then $term_tax_ids, $not_term_tax_ids, and $and_term_tax_ids.
|
98 |
+
*/
|
99 |
+
function relevanssi_process_tax_query_row( $row, $is_sub_row, $global_relation, $query_restrictions, $tax_query_relation, $term_tax_ids, $not_term_tax_ids, $and_term_tax_ids ) {
|
100 |
+
global $wpdb;
|
101 |
+
|
102 |
+
$local_term_tax_ids = array();
|
103 |
+
$local_not_term_tax_ids = array();
|
104 |
+
$local_and_term_tax_ids = array();
|
105 |
+
$term_tax_id = array();
|
106 |
+
|
107 |
+
$exists_query = false;
|
108 |
+
if ( isset( $row['operator'] ) && ( 'exists' === strtolower( $row['operator'] ) || 'not exists' === strtolower( $row['operator'] ) ) ) {
|
109 |
+
$exists_query = true;
|
110 |
+
}
|
111 |
+
|
112 |
+
if ( $exists_query ) {
|
113 |
+
$row['field'] = 'exists';
|
114 |
+
}
|
115 |
+
if ( ! isset( $row['field'] ) ) {
|
116 |
+
$row['field'] = 'term_id'; // In case 'field' is not set, go with the WP default of 'term_id'.
|
117 |
+
}
|
118 |
+
$row['field'] = strtolower( $row['field'] ); // In some cases, you can get 'ID' instead of 'id'.
|
119 |
+
|
120 |
+
if ( in_array( $row['field'], array( 'slug', 'name', 'id', 'term_id' ), true ) ) {
|
121 |
+
$term_tax_id = relevanssi_term_tax_id_from_row( $row );
|
122 |
+
}
|
123 |
+
|
124 |
+
if ( 'term_taxonomy_id' === $row['field'] ) {
|
125 |
+
if ( ! is_array( $row['terms'] ) ) {
|
126 |
+
$row['terms'] = array( $row['terms'] );
|
127 |
+
}
|
128 |
+
$term_tax_id = array_filter( $row['terms'], 'is_numeric' );
|
129 |
+
}
|
130 |
+
|
131 |
+
if ( ! $exists_query && ( ! isset( $row['include_children'] ) || true === $row['include_children'] ) ) {
|
132 |
+
foreach ( $term_tax_id as $t_id ) {
|
133 |
+
$t_term = get_term_by( 'term_taxonomy_id', $t_id, $row['taxonomy'] );
|
134 |
+
$t_id = $t_term->term_id;
|
135 |
+
$kids = get_term_children( $t_id, $row['taxonomy'] );
|
136 |
+
foreach ( $kids as $kid ) {
|
137 |
+
$kid_term_tax_id = relevanssi_get_term_tax_id( $kid, $row['taxonomy'] );
|
138 |
+
if ( $kid_term_tax_id ) {
|
139 |
+
// In some weird cases, this may be null. See: https://wordpress.org/support/topic/childrens-of-chosen-product_cat-not-showing-up/.
|
140 |
+
$term_tax_id[] = $kid_term_tax_id;
|
141 |
+
}
|
142 |
+
}
|
143 |
+
}
|
144 |
+
}
|
145 |
+
|
146 |
+
$term_tax_id = array_unique( $term_tax_id );
|
147 |
+
if ( ! empty( $term_tax_id ) ) {
|
148 |
+
$n = count( $term_tax_id );
|
149 |
+
$term_tax_id = implode( ',', $term_tax_id );
|
150 |
+
|
151 |
+
$tq_operator = 'IN'; // Assuming the default operator "IN", unless something else is provided.
|
152 |
+
if ( isset( $row['operator'] ) ) {
|
153 |
+
$tq_operator = strtoupper( $row['operator'] );
|
154 |
+
}
|
155 |
+
if ( ! in_array( $tq_operator, array( 'IN', 'NOT IN', 'AND' ), true ) ) {
|
156 |
+
$tq_operator = 'IN';
|
157 |
+
}
|
158 |
+
if ( 'and' === $tax_query_relation ) {
|
159 |
+
if ( 'AND' === $tq_operator ) {
|
160 |
+
$query_restrictions .= " AND relevanssi.doc IN (
|
161 |
+
SELECT ID FROM $wpdb->posts WHERE 1=1
|
162 |
+
AND (
|
163 |
+
SELECT COUNT(1)
|
164 |
+
FROM $wpdb->term_relationships AS tr
|
165 |
+
WHERE tr.term_taxonomy_id IN ($term_tax_id)
|
166 |
+
AND tr.object_id = $wpdb->posts.ID ) = $n
|
167 |
+
)";
|
168 |
+
// Clean: $term_tax_id and $n are Relevanssi-generated.
|
169 |
+
} else {
|
170 |
+
$query_restrictions .= " AND relevanssi.doc $tq_operator (
|
171 |
+
SELECT DISTINCT(tr.object_id)
|
172 |
+
FROM $wpdb->term_relationships AS tr
|
173 |
+
WHERE tr.term_taxonomy_id IN ($term_tax_id))";
|
174 |
+
// Clean: all variables are Relevanssi-generated.
|
175 |
+
}
|
176 |
+
} else {
|
177 |
+
if ( 'IN' === $tq_operator ) {
|
178 |
+
$local_term_tax_ids[] = $term_tax_id;
|
179 |
+
}
|
180 |
+
if ( 'NOT IN' === $tq_operator ) {
|
181 |
+
$local_not_term_tax_ids[] = $term_tax_id;
|
182 |
+
}
|
183 |
+
if ( 'AND' === $tq_operator ) {
|
184 |
+
$local_and_term_tax_ids[] = $term_tax_id;
|
185 |
+
}
|
186 |
+
}
|
187 |
+
} else {
|
188 |
+
global $wp_query;
|
189 |
+
$wp_query->is_category = false;
|
190 |
+
}
|
191 |
+
|
192 |
+
$copy_term_tax_ids = false;
|
193 |
+
if ( ! $is_sub_row ) {
|
194 |
+
$copy_term_tax_ids = true;
|
195 |
+
}
|
196 |
+
if ( $is_sub_row && ( 'or' === $global_relation || 'or' === $tax_query_relation ) ) {
|
197 |
+
$copy_term_tax_ids = true;
|
198 |
+
}
|
199 |
+
|
200 |
+
if ( $copy_term_tax_ids ) {
|
201 |
+
$term_tax_ids = array_merge( $term_tax_ids, $local_term_tax_ids );
|
202 |
+
$not_term_tax_ids = array_merge( $not_term_tax_ids, $local_not_term_tax_ids );
|
203 |
+
$and_term_tax_ids = array_merge( $and_term_tax_ids, $local_and_term_tax_ids );
|
204 |
+
}
|
205 |
+
|
206 |
+
if ( $exists_query ) {
|
207 |
+
$taxonomy = $row['taxonomy'];
|
208 |
+
$operator = 'IN';
|
209 |
+
if ( 'not exists' === strtolower( $row['operator'] ) ) {
|
210 |
+
$operator = 'NOT IN';
|
211 |
+
}
|
212 |
+
$query_restrictions .= " AND relevanssi.doc $operator (
|
213 |
+
SELECT DISTINCT(tr.object_id)
|
214 |
+
FROM $wpdb->term_relationships AS tr, $wpdb->term_taxonomy AS tt
|
215 |
+
WHERE tr.term_taxonomy_id = tt.term_taxonomy_id
|
216 |
+
AND tt.taxonomy = '$taxonomy'
|
217 |
+
)";
|
218 |
+
}
|
219 |
+
|
220 |
+
return array( $query_restrictions, $term_tax_ids, $not_term_tax_ids, $and_term_tax_ids );
|
221 |
+
}
|
222 |
+
|
223 |
+
/**
|
224 |
+
* Generates query restrictions from the term taxonomy ids.
|
225 |
+
*
|
226 |
+
* Combines different term tax ID arrays into a set of query restrictions that can be
|
227 |
+
* used in an OR query.
|
228 |
+
*
|
229 |
+
* @global object $wpdb The WP database interface.
|
230 |
+
*
|
231 |
+
* @param array $term_tax_ids The regular terms.
|
232 |
+
* @param array $not_term_tax_ids The NOT terms.
|
233 |
+
* @param array $and_term_tax_ids The AND terms.
|
234 |
+
*
|
235 |
+
* @return string The MySQL query restrictions.
|
236 |
+
*/
|
237 |
+
function relevanssi_process_term_tax_ids( $term_tax_ids, $not_term_tax_ids, $and_term_tax_ids ) {
|
238 |
+
global $wpdb;
|
239 |
+
|
240 |
+
$query_restriction_parts = array();
|
241 |
+
$query_restrictions = '';
|
242 |
+
|
243 |
+
$term_tax_ids = array_unique( $term_tax_ids );
|
244 |
+
if ( count( $term_tax_ids ) > 0 ) {
|
245 |
+
$term_tax_ids = implode( ',', $term_tax_ids );
|
246 |
+
$query_restriction_parts[] = " relevanssi.doc IN (
|
247 |
+
SELECT DISTINCT(tr.object_id)
|
248 |
+
FROM $wpdb->term_relationships AS tr
|
249 |
+
WHERE tr.term_taxonomy_id IN ($term_tax_ids)
|
250 |
+
)";
|
251 |
+
// Clean: all variables are Relevanssi-generated.
|
252 |
+
}
|
253 |
+
if ( count( $not_term_tax_ids ) > 0 ) {
|
254 |
+
$not_term_tax_ids = implode( ',', $not_term_tax_ids );
|
255 |
+
$query_restriction_parts[] .= " relevanssi.doc NOT IN (
|
256 |
+
SELECT DISTINCT(tr.object_id)
|
257 |
+
FROM $wpdb->term_relationships AS tr
|
258 |
+
WHERE tr.term_taxonomy_id IN ($not_term_tax_ids)
|
259 |
+
)";
|
260 |
+
// Clean: all variables are Relevanssi-generated.
|
261 |
+
}
|
262 |
+
if ( count( $and_term_tax_ids ) > 0 ) {
|
263 |
+
$and_term_tax_ids = implode( ',', $and_term_tax_ids );
|
264 |
+
$n = count( explode( ',', $and_term_tax_ids ) );
|
265 |
+
$query_restriction_parts[] .= " relevanssi.doc IN (
|
266 |
+
SELECT ID FROM $wpdb->posts WHERE 1=1
|
267 |
+
AND (
|
268 |
+
SELECT COUNT(1)
|
269 |
+
FROM $wpdb->term_relationships AS tr
|
270 |
+
WHERE tr.term_taxonomy_id IN ($and_term_tax_ids)
|
271 |
+
AND tr.object_id = $wpdb->posts.ID ) = $n
|
272 |
+
)";
|
273 |
+
// Clean: all variables are Relevanssi-generated.
|
274 |
+
}
|
275 |
+
$query_restrictions .= ' AND ';
|
276 |
+
if ( count( $query_restriction_parts ) > 1 ) {
|
277 |
+
$query_restrictions .= '(';
|
278 |
+
}
|
279 |
+
$query_restrictions .= implode( ' OR', $query_restriction_parts );
|
280 |
+
if ( count( $query_restriction_parts ) > 1 ) {
|
281 |
+
$query_restrictions .= ')';
|
282 |
+
}
|
283 |
+
|
284 |
+
return $query_restrictions;
|
285 |
+
}
|
286 |
+
|
287 |
+
/**
|
288 |
+
* Gets and sanitizes the taxonomy name and slug parameters.
|
289 |
+
*
|
290 |
+
* Checks parameters: if they're numeric, pass them for term_id filtering, otherwise
|
291 |
+
* sanitize and create a comma-separated list.
|
292 |
+
*
|
293 |
+
* @param string $terms_parameter The 'terms' field from the tax_query row.
|
294 |
+
* @param string $taxonomy The taxonomy name.
|
295 |
+
*
|
296 |
+
* @return array An array containing numeric terms and the list of sanitized term
|
297 |
+
* names.
|
298 |
+
*/
|
299 |
+
function relevanssi_get_term_in( $terms_parameter, $taxonomy ) {
|
300 |
+
$numeric_terms = array();
|
301 |
+
$names = array();
|
302 |
+
|
303 |
+
if ( ! is_array( $terms_parameter ) ) {
|
304 |
+
$terms_parameter = array( $terms_parameter );
|
305 |
+
}
|
306 |
+
foreach ( $terms_parameter as $name ) {
|
307 |
+
$term = get_term_by( 'name', $name, $taxonomy );
|
308 |
+
if ( ! $term && is_numeric( $name ) ) {
|
309 |
+
$numeric_terms[] = $name;
|
310 |
+
} else {
|
311 |
+
if ( isset( $term->term_id ) ) {
|
312 |
+
$name = sanitize_title( $name );
|
313 |
+
$names[] = "'$name'";
|
314 |
+
}
|
315 |
+
}
|
316 |
+
}
|
317 |
+
|
318 |
+
return array(
|
319 |
+
'numeric_terms' => implode( ',', $numeric_terms ),
|
320 |
+
'term_in' => implode( ',', $names ),
|
321 |
+
);
|
322 |
+
}
|
323 |
+
|
324 |
+
/**
|
325 |
+
* Gets the term_tax_id from a row with 'field' set to 'slug' or 'name'.
|
326 |
+
*
|
327 |
+
* If the slugs or names are all numeric values, will switch the 'field' parameter
|
328 |
+
* to 'term_id'.
|
329 |
+
*
|
330 |
+
* @param array $row The taxonomy query row.
|
331 |
+
*
|
332 |
+
* @return array An array of term taxonomy IDs.
|
333 |
+
*/
|
334 |
+
function relevanssi_term_tax_id_from_row( $row ) {
|
335 |
+
global $wpdb;
|
336 |
+
|
337 |
+
$term_in_results = relevanssi_get_term_in( $row['terms'], $row['taxonomy'] );
|
338 |
+
$numeric_terms = $term_in_results['numeric_terms'];
|
339 |
+
$term_in = $term_in_results['term_in'];
|
340 |
+
$term_tax_id = array();
|
341 |
+
|
342 |
+
$type = $row['field'];
|
343 |
+
if ( ! empty( $numeric_terms ) ) {
|
344 |
+
$type = 'term_id';
|
345 |
+
$term_in = $numeric_terms;
|
346 |
+
}
|
347 |
+
|
348 |
+
if ( ! empty( $term_in ) ) {
|
349 |
+
$row_taxonomy = sanitize_text_field( $row['taxonomy'] );
|
350 |
+
|
351 |
+
$tt_q = "SELECT tt.term_taxonomy_id
|
352 |
+
FROM $wpdb->term_taxonomy AS tt
|
353 |
+
LEFT JOIN $wpdb->terms AS t ON (tt.term_id=t.term_id)
|
354 |
+
WHERE tt.taxonomy = '$row_taxonomy' AND t.$type IN ($term_in)";
|
355 |
+
// Clean: $row_taxonomy is sanitized, each term in $term_in is sanitized.
|
356 |
+
$term_tax_id = $wpdb->get_col( $tt_q ); // WPCS: unprepared SQL ok.
|
357 |
+
}
|
358 |
+
|
359 |
+
return $term_tax_id;
|
360 |
+
}
|
lib/search.php
CHANGED
@@ -116,264 +116,20 @@ function relevanssi_search( $args ) {
|
|
116 |
*
|
117 |
* @param array The search parameters.
|
118 |
*/
|
119 |
-
$filtered_args
|
120 |
-
$
|
121 |
-
$
|
122 |
-
$
|
123 |
-
$
|
124 |
-
$
|
125 |
-
$meta_query
|
126 |
-
$date_query = $filtered_args['date_query'];
|
127 |
-
$expost = $filtered_args['expost'];
|
128 |
-
$post_type = $filtered_args['post_type'];
|
129 |
-
$post_status = $filtered_args['post_status'];
|
130 |
-
$operator = $filtered_args['operator'];
|
131 |
-
$search_blogs = $filtered_args['search_blogs'];
|
132 |
-
$author = $filtered_args['author'];
|
133 |
-
$orderby = $filtered_args['orderby'];
|
134 |
-
$order = $filtered_args['order'];
|
135 |
-
$fields = $filtered_args['fields'];
|
136 |
-
$sentence = $filtered_args['sentence'];
|
137 |
-
$by_date = $filtered_args['by_date'];
|
138 |
-
$admin_search = $filtered_args['admin_search'];
|
139 |
-
$include_attachments = $filtered_args['include_attachments'];
|
140 |
-
$meta_query = $filtered_args['meta_query'];
|
141 |
-
|
142 |
-
$hits = array();
|
143 |
-
$query_restrictions = '';
|
144 |
-
|
145 |
-
if ( ! isset( $tax_query_relation ) ) {
|
146 |
-
$tax_query_relation = 'and';
|
147 |
-
}
|
148 |
-
$tax_query_relation = relevanssi_strtolower( $tax_query_relation );
|
149 |
-
$term_tax_id = array();
|
150 |
-
$term_tax_ids = array();
|
151 |
-
$not_term_tax_ids = array();
|
152 |
-
$and_term_tax_ids = array();
|
153 |
-
|
154 |
-
if ( is_array( $tax_query ) ) {
|
155 |
-
$is_sub_row = false;
|
156 |
-
foreach ( $tax_query as $row ) {
|
157 |
-
if ( isset( $row['terms'] ) || ( isset( $row['operator'] ) && ( 'not exists' === strtolower( $row['operator'] ) || 'exists' === strtolower( $row['operator'] ) ) ) ) {
|
158 |
-
list( $query_restrictions, $term_tax_ids, $not_term_tax_ids, $and_term_tax_ids ) =
|
159 |
-
relevanssi_process_tax_query_row( $row, $is_sub_row, $tax_query_relation, $query_restrictions, $tax_query_relation, $term_tax_ids, $not_term_tax_ids, $and_term_tax_ids );
|
160 |
-
} else {
|
161 |
-
$row_tax_query_relation = $tax_query_relation;
|
162 |
-
if ( isset( $row['relation'] ) ) {
|
163 |
-
$row_tax_query_relation = relevanssi_strtolower( $row['relation'] );
|
164 |
-
}
|
165 |
-
foreach ( $row as $subrow ) {
|
166 |
-
$is_sub_row = true;
|
167 |
-
if ( isset( $subrow['terms'] ) ) {
|
168 |
-
list( $query_restrictions, $term_tax_ids, $not_term_tax_ids, $and_term_tax_ids ) =
|
169 |
-
relevanssi_process_tax_query_row( $subrow, $is_sub_row, $tax_query_relation, $query_restrictions, $tax_query_relation, $term_tax_ids, $not_term_tax_ids, $and_term_tax_ids );
|
170 |
-
}
|
171 |
-
}
|
172 |
-
}
|
173 |
-
}
|
174 |
-
|
175 |
-
if ( 'or' === $tax_query_relation ) {
|
176 |
-
$term_tax_ids = array_unique( $term_tax_ids );
|
177 |
-
if ( count( $term_tax_ids ) > 0 ) {
|
178 |
-
$term_tax_ids = implode( ',', $term_tax_ids );
|
179 |
-
$query_restrictions .= " AND relevanssi.doc IN (SELECT DISTINCT(tr.object_id) FROM $wpdb->term_relationships AS tr WHERE tr.term_taxonomy_id IN ($term_tax_ids))";
|
180 |
-
// Clean: all variables are Relevanssi-generated.
|
181 |
-
}
|
182 |
-
if ( count( $not_term_tax_ids ) > 0 ) {
|
183 |
-
$not_term_tax_ids = implode( ',', $not_term_tax_ids );
|
184 |
-
$query_restrictions .= " AND relevanssi.doc NOT IN (SELECT DISTINCT(tr.object_id) FROM $wpdb->term_relationships AS tr WHERE tr.term_taxonomy_id IN ($not_term_tax_ids))";
|
185 |
-
// Clean: all variables are Relevanssi-generated.
|
186 |
-
}
|
187 |
-
if ( count( $and_term_tax_ids ) > 0 ) {
|
188 |
-
$and_term_tax_ids = implode( ',', $and_term_tax_ids );
|
189 |
-
$n = count( explode( ',', $and_term_tax_ids ) );
|
190 |
-
$query_restrictions .= " AND relevanssi.doc IN (
|
191 |
-
SELECT ID FROM $wpdb->posts WHERE 1=1
|
192 |
-
AND (
|
193 |
-
SELECT COUNT(1)
|
194 |
-
FROM $wpdb->term_relationships AS tr
|
195 |
-
WHERE tr.term_taxonomy_id IN ($and_term_tax_ids)
|
196 |
-
AND tr.object_id = $wpdb->posts.ID ) = $n
|
197 |
-
)";
|
198 |
-
// Clean: all variables are Relevanssi-generated.
|
199 |
-
}
|
200 |
-
}
|
201 |
-
}
|
202 |
-
|
203 |
-
if ( is_array( $post_query ) ) {
|
204 |
-
if ( ! empty( $post_query['in'] ) ) {
|
205 |
-
$valid_values = array();
|
206 |
-
foreach ( $post_query['in'] as $post_in_id ) {
|
207 |
-
if ( is_numeric( $post_in_id ) ) {
|
208 |
-
$valid_values[] = $post_in_id;
|
209 |
-
}
|
210 |
-
}
|
211 |
-
$posts = implode( ',', $valid_values );
|
212 |
-
if ( ! empty( $posts ) ) {
|
213 |
-
$query_restrictions .= " AND relevanssi.doc IN ($posts)";
|
214 |
-
// Clean: $posts is checked to be integers.
|
215 |
-
}
|
216 |
-
}
|
217 |
-
if ( ! empty( $post_query['not in'] ) ) {
|
218 |
-
$valid_values = array();
|
219 |
-
foreach ( $post_query['not in'] as $post_not_in_id ) {
|
220 |
-
if ( is_numeric( $post_not_in_id ) ) {
|
221 |
-
$valid_values[] = $post_not_in_id;
|
222 |
-
}
|
223 |
-
}
|
224 |
-
$posts = implode( ',', $valid_values );
|
225 |
-
if ( ! empty( $posts ) ) {
|
226 |
-
$query_restrictions .= " AND relevanssi.doc NOT IN ($posts)";
|
227 |
-
// Clean: $posts is checked to be integers.
|
228 |
-
}
|
229 |
-
}
|
230 |
-
}
|
231 |
-
|
232 |
-
if ( is_array( $parent_query ) ) {
|
233 |
-
if ( isset( $parent_query['parent in'] ) ) {
|
234 |
-
$valid_values = array();
|
235 |
-
foreach ( $parent_query['parent in'] as $post_in_id ) {
|
236 |
-
if ( is_int( $post_in_id ) ) {
|
237 |
-
$valid_values[] = $post_in_id;
|
238 |
-
}
|
239 |
-
}
|
240 |
-
$posts = implode( ',', $valid_values );
|
241 |
-
if ( strlen( $posts ) > 0 ) {
|
242 |
-
$query_restrictions .= " AND relevanssi.doc IN (SELECT ID FROM $wpdb->posts WHERE post_parent IN ($posts))";
|
243 |
-
// Clean: $posts is checked to be integers.
|
244 |
-
}
|
245 |
-
}
|
246 |
-
if ( isset( $parent_query['parent not in'] ) ) {
|
247 |
-
$valid_values = array();
|
248 |
-
foreach ( $parent_query['parent not in'] as $post_not_in_id ) {
|
249 |
-
if ( is_int( $post_not_in_id ) ) {
|
250 |
-
$valid_values[] = $post_not_in_id;
|
251 |
-
}
|
252 |
-
}
|
253 |
-
$posts = implode( ',', $valid_values );
|
254 |
-
if ( isset( $posts ) ) {
|
255 |
-
$query_restrictions .= " AND relevanssi.doc NOT IN (SELECT ID FROM $wpdb->posts WHERE post_parent IN ($posts))";
|
256 |
-
// Clean: $posts is checked to be integers.
|
257 |
-
}
|
258 |
-
}
|
259 |
-
}
|
260 |
-
|
261 |
-
if ( is_array( $meta_query ) ) {
|
262 |
-
$meta_query_restrictions = '';
|
263 |
-
|
264 |
-
$mq_vars = array( 'meta_query' => $meta_query );
|
265 |
-
|
266 |
-
$mq = new WP_Meta_Query();
|
267 |
-
$mq->parse_query_vars( $mq_vars );
|
268 |
-
$meta_sql = $mq->get_sql( 'post', 'relevanssi', 'doc' );
|
269 |
-
$meta_join = '';
|
270 |
-
$meta_where = '';
|
271 |
-
if ( $meta_sql ) {
|
272 |
-
$meta_join = $meta_sql['join'];
|
273 |
-
$meta_where = $meta_sql['where'];
|
274 |
-
}
|
275 |
-
|
276 |
-
$query_restrictions .= $meta_where;
|
277 |
-
}
|
278 |
-
|
279 |
-
if ( ! empty( $date_query ) ) {
|
280 |
-
if ( is_object( $date_query ) && method_exists( $date_query, 'get_sql' ) ) {
|
281 |
-
$sql = $date_query->get_sql(); // AND ( the query itself ).
|
282 |
-
$query_restrictions .= " AND relevanssi.doc IN ( SELECT DISTINCT(ID) FROM $wpdb->posts WHERE 1 $sql )";
|
283 |
-
// Clean: $sql generated by $date_query->get_sql() query.
|
284 |
-
}
|
285 |
-
}
|
286 |
-
|
287 |
-
// If $post_type is not set, see if there are post types to exclude from the search.
|
288 |
-
// If $post_type is set, there's no need to exclude, as we only include.
|
289 |
-
$negative_post_type = null;
|
290 |
-
if ( ! $post_type && ! $admin_search ) {
|
291 |
-
$negative_post_type = relevanssi_get_negative_post_type( $include_attachments );
|
292 |
-
}
|
293 |
-
|
294 |
-
$non_post_post_type = null;
|
295 |
-
$non_post_post_types_array = array();
|
296 |
-
if ( function_exists( 'relevanssi_get_non_post_post_types' ) ) {
|
297 |
-
// Relevanssi Premium includes post types which are not actually posts.
|
298 |
-
$non_post_post_types_array = relevanssi_get_non_post_post_types();
|
299 |
-
}
|
300 |
-
|
301 |
-
if ( $post_type ) {
|
302 |
-
if ( ! is_array( $post_type ) ) {
|
303 |
-
$post_types = explode( ',', $post_type );
|
304 |
-
} else {
|
305 |
-
$post_types = $post_type;
|
306 |
-
}
|
307 |
-
|
308 |
-
// This array will contain all regular post types involved in the search parameters.
|
309 |
-
$post_post_types = array_diff( $post_types, $non_post_post_types_array );
|
310 |
-
|
311 |
-
// This array has the non-post post types involved.
|
312 |
-
$non_post_post_types = array_intersect( $post_types, $non_post_post_types_array );
|
313 |
-
|
314 |
-
// Escape both for SQL queries, just in case.
|
315 |
-
$non_post_post_types = esc_sql( $non_post_post_types );
|
316 |
-
$post_types = esc_sql( $post_post_types );
|
317 |
-
|
318 |
-
// Implode to a parameter string, or set to null if empty.
|
319 |
-
$non_post_post_type = null;
|
320 |
-
if ( count( $non_post_post_types ) > 0 ) {
|
321 |
-
$non_post_post_type = "'" . implode( "', '", $non_post_post_types ) . "'";
|
322 |
-
}
|
323 |
-
$post_type = null;
|
324 |
-
if ( count( $post_types ) > 0 ) {
|
325 |
-
$post_type = "'" . implode( "', '", $post_types ) . "'";
|
326 |
-
}
|
327 |
-
}
|
328 |
-
|
329 |
-
if ( $post_status ) {
|
330 |
-
if ( ! is_array( $post_status ) ) {
|
331 |
-
$post_statuses = esc_sql( explode( ',', $post_status ) );
|
332 |
-
} else {
|
333 |
-
$post_statuses = esc_sql( $post_status );
|
334 |
-
}
|
335 |
-
|
336 |
-
$post_status = null;
|
337 |
-
if ( count( $post_statuses ) > 0 ) {
|
338 |
-
$post_status = "'" . implode( "', '", $post_statuses ) . "'";
|
339 |
-
}
|
340 |
-
}
|
341 |
|
342 |
-
$
|
343 |
-
if ( ! empty( $expost ) ) {
|
344 |
-
$excluded_post_ids = explode( ',', $expost );
|
345 |
-
foreach ( $excluded_post_ids as $excluded_post_id ) {
|
346 |
-
$excluded_post_id = intval( trim( $excluded_post_id, ' -' ) );
|
347 |
-
$posts_to_exclude .= " AND relevanssi.doc != $excluded_post_id";
|
348 |
-
// Clean: escaped.
|
349 |
-
}
|
350 |
-
$query_restrictions .= $posts_to_exclude;
|
351 |
-
}
|
352 |
-
|
353 |
-
if ( function_exists( 'wp_encode_emoji' ) ) {
|
354 |
-
$q = wp_encode_emoji( $q );
|
355 |
-
}
|
356 |
-
|
357 |
-
if ( $sentence ) {
|
358 |
-
$q = str_replace( '"', '', $q );
|
359 |
-
$q = '"' . $q . '"';
|
360 |
-
}
|
361 |
-
|
362 |
-
$phrases = relevanssi_recognize_phrases( $q );
|
363 |
-
|
364 |
-
if ( function_exists( 'relevanssi_recognize_negatives' ) ) {
|
365 |
-
// Relevanssi Premium supports negative minus operator.
|
366 |
-
$negative_terms = relevanssi_recognize_negatives( $q );
|
367 |
-
} else {
|
368 |
-
$negative_terms = false;
|
369 |
-
}
|
370 |
|
371 |
-
|
372 |
-
|
373 |
-
|
374 |
-
|
375 |
-
$positive_terms = false;
|
376 |
-
}
|
377 |
|
378 |
/**
|
379 |
* Filters whether stopwords are removed from titles.
|
@@ -383,17 +139,38 @@ function relevanssi_search( $args ) {
|
|
383 |
$remove_stopwords = apply_filters( 'relevanssi_remove_stopwords_in_titles', true );
|
384 |
|
385 |
$terms = relevanssi_tokenize( $q, $remove_stopwords );
|
386 |
-
|
387 |
if ( count( $terms ) < 1 ) {
|
388 |
// Tokenizer killed all the search terms.
|
389 |
return $hits;
|
390 |
}
|
391 |
$terms = array_keys( $terms ); // Don't care about tf in query.
|
392 |
|
393 |
-
if (
|
394 |
-
$
|
|
|
|
|
395 |
}
|
396 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
397 |
// Go get the count from the options, but run the full query if it's not available.
|
398 |
$doc_count = get_option( 'relevanssi_doc_count' );
|
399 |
if ( ! $doc_count || $doc_count < 1 ) {
|
@@ -414,146 +191,6 @@ function relevanssi_search( $args ) {
|
|
414 |
|
415 |
$fuzzy = get_option( 'relevanssi_fuzzy' );
|
416 |
|
417 |
-
if ( function_exists( 'relevanssi_negatives_positives' ) ) {
|
418 |
-
$query_restrictions .= relevanssi_negatives_positives( $negative_terms, $positive_terms, $relevanssi_table );
|
419 |
-
// Clean: escaped in the function.
|
420 |
-
}
|
421 |
-
|
422 |
-
if ( ! empty( $author ) ) {
|
423 |
-
$author_in = array();
|
424 |
-
$author_not_in = array();
|
425 |
-
foreach ( $author as $id ) {
|
426 |
-
if ( ! is_numeric( $id ) ) {
|
427 |
-
continue;
|
428 |
-
}
|
429 |
-
if ( $id > 0 ) {
|
430 |
-
$author_in[] = $id;
|
431 |
-
} else {
|
432 |
-
$author_not_in[] = abs( $id );
|
433 |
-
}
|
434 |
-
}
|
435 |
-
if ( count( $author_in ) > 0 ) {
|
436 |
-
$authors = implode( ',', $author_in );
|
437 |
-
$query_restrictions .= " AND relevanssi.doc IN (SELECT DISTINCT(posts.ID) FROM $wpdb->posts AS posts
|
438 |
-
WHERE posts.post_author IN ($authors))";
|
439 |
-
// Clean: $authors is always just numbers.
|
440 |
-
}
|
441 |
-
if ( count( $author_not_in ) > 0 ) {
|
442 |
-
$authors = implode( ',', $author_not_in );
|
443 |
-
$query_restrictions .= " AND relevanssi.doc NOT IN (SELECT DISTINCT(posts.ID) FROM $wpdb->posts AS posts
|
444 |
-
WHERE posts.post_author IN ($authors))";
|
445 |
-
// Clean: $authors is always just numbers.
|
446 |
-
}
|
447 |
-
}
|
448 |
-
|
449 |
-
if ( $post_type ) {
|
450 |
-
// A post type is set: add a restriction.
|
451 |
-
$restriction = " AND (
|
452 |
-
relevanssi.doc IN (
|
453 |
-
SELECT DISTINCT(posts.ID) FROM $wpdb->posts AS posts
|
454 |
-
WHERE posts.post_type IN ($post_type)
|
455 |
-
) *np*
|
456 |
-
)"; // Clean: $post_type is escaped.
|
457 |
-
|
458 |
-
// There are post types involved that are taxonomies or users, so can't
|
459 |
-
// match to wp_posts. Add a relevanssi.type restriction.
|
460 |
-
if ( $non_post_post_type ) {
|
461 |
-
$restriction = str_replace( '*np*', "OR (relevanssi.type IN ($non_post_post_type))", $restriction );
|
462 |
-
// Clean: $non_post_post_types is escaped.
|
463 |
-
} else {
|
464 |
-
// No non-post post types, so remove the placeholder.
|
465 |
-
$restriction = str_replace( '*np*', '', $restriction );
|
466 |
-
}
|
467 |
-
$query_restrictions .= $restriction;
|
468 |
-
} else {
|
469 |
-
// No regular post types.
|
470 |
-
if ( $non_post_post_type ) {
|
471 |
-
// But there is a non-post post type restriction.
|
472 |
-
$query_restrictions .= " AND (relevanssi.type IN ($non_post_post_type))";
|
473 |
-
// Clean: $non_post_post_types is escaped.
|
474 |
-
}
|
475 |
-
}
|
476 |
-
|
477 |
-
if ( $negative_post_type ) {
|
478 |
-
$query_restrictions .= " AND ((relevanssi.doc IN (SELECT DISTINCT(posts.ID) FROM $wpdb->posts AS posts
|
479 |
-
WHERE posts.post_type NOT IN ($negative_post_type))) OR (doc = -1))";
|
480 |
-
// Clean: $negative_post_type is escaped.
|
481 |
-
}
|
482 |
-
|
483 |
-
if ( $post_status ) {
|
484 |
-
global $wp_query;
|
485 |
-
if ( $wp_query->is_admin ) {
|
486 |
-
$query_restrictions .= " AND ((relevanssi.doc IN (SELECT DISTINCT(posts.ID) FROM $wpdb->posts AS posts
|
487 |
-
WHERE posts.post_status IN ($post_status))))";
|
488 |
-
} else {
|
489 |
-
// The -1 is there to get user profiles and category pages.
|
490 |
-
$query_restrictions .= " AND ((relevanssi.doc IN (SELECT DISTINCT(posts.ID) FROM $wpdb->posts AS posts
|
491 |
-
WHERE posts.post_status IN ($post_status))) OR (doc = -1))";
|
492 |
-
}
|
493 |
-
// Clean: $post_status is escaped.
|
494 |
-
}
|
495 |
-
|
496 |
-
if ( $phrases ) {
|
497 |
-
$query_restrictions .= " $phrases";
|
498 |
-
// Clean: $phrases is escaped earlier.
|
499 |
-
}
|
500 |
-
|
501 |
-
if ( isset( $by_date ) ) {
|
502 |
-
$n = $by_date;
|
503 |
-
|
504 |
-
$u = substr( $n, -1, 1 );
|
505 |
-
switch ( $u ) {
|
506 |
-
case 'h':
|
507 |
-
$unit = 'HOUR';
|
508 |
-
break;
|
509 |
-
case 'd':
|
510 |
-
$unit = 'DAY';
|
511 |
-
break;
|
512 |
-
case 'm':
|
513 |
-
$unit = 'MONTH';
|
514 |
-
break;
|
515 |
-
case 'y':
|
516 |
-
$unit = 'YEAR';
|
517 |
-
break;
|
518 |
-
case 'w':
|
519 |
-
$unit = 'WEEK';
|
520 |
-
break;
|
521 |
-
default:
|
522 |
-
$unit = 'DAY';
|
523 |
-
}
|
524 |
-
|
525 |
-
$n = preg_replace( '/[hdmyw]/', '', $n );
|
526 |
-
|
527 |
-
if ( is_numeric( $n ) ) {
|
528 |
-
$query_restrictions .= " AND relevanssi.doc IN (SELECT DISTINCT(posts.ID) FROM $wpdb->posts AS posts
|
529 |
-
WHERE posts.post_date > DATE_SUB(NOW(), INTERVAL $n $unit))";
|
530 |
-
// Clean: $n is always numeric, $unit is Relevanssi-generated.
|
531 |
-
}
|
532 |
-
}
|
533 |
-
|
534 |
-
/**
|
535 |
-
* Filters the query restrictions for the Relevanssi query.
|
536 |
-
*
|
537 |
-
* Equivalent to the 'posts_where' filter.
|
538 |
-
*
|
539 |
-
* @author Charles St-Pierre
|
540 |
-
*
|
541 |
-
* @param string The MySQL code that restricts the query.
|
542 |
-
*/
|
543 |
-
$query_restrictions = apply_filters( 'relevanssi_where', $query_restrictions );
|
544 |
-
$query_join = '';
|
545 |
-
if ( ! empty( $meta_join ) ) {
|
546 |
-
$query_join = $meta_join;
|
547 |
-
}
|
548 |
-
/**
|
549 |
-
* Filters the meta query JOIN for the Relevanssi search query.
|
550 |
-
*
|
551 |
-
* Somewhat equivalent to the 'posts_join' filter.
|
552 |
-
*
|
553 |
-
* @param string The JOINed query.
|
554 |
-
*/
|
555 |
-
$query_join = apply_filters( 'relevanssi_join', $query_join );
|
556 |
-
|
557 |
$no_matches = true;
|
558 |
if ( 'always' === $fuzzy ) {
|
559 |
/**
|
@@ -580,7 +217,9 @@ function relevanssi_search( $args ) {
|
|
580 |
$recency_bonus = false;
|
581 |
$recency_cutoff_date = false;
|
582 |
if ( function_exists( 'relevanssi_get_recency_bonus' ) ) {
|
583 |
-
|
|
|
|
|
584 |
}
|
585 |
|
586 |
$exact_match_bonus = false;
|
@@ -698,27 +337,37 @@ function relevanssi_search( $args ) {
|
|
698 |
} else {
|
699 |
$no_matches = false;
|
700 |
if ( count( $include_these_posts ) > 0 ) {
|
701 |
-
$
|
702 |
-
$existing_ids = array();
|
703 |
foreach ( $matches as $match ) {
|
704 |
$existing_ids[] = $match->doc;
|
705 |
}
|
706 |
-
$existing_ids
|
707 |
-
$
|
708 |
-
$
|
709 |
-
|
710 |
-
|
711 |
-
|
712 |
-
|
713 |
-
|
714 |
-
|
715 |
-
|
716 |
-
|
717 |
-
|
718 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
719 |
}
|
720 |
if ( count( $include_these_items ) > 0 ) {
|
721 |
-
$items_to_add = implode( ',', array_keys( $include_these_items ) );
|
722 |
$existing_items = array();
|
723 |
foreach ( $matches as $match ) {
|
724 |
if ( 0 !== intval( $match->item ) ) {
|
@@ -726,21 +375,21 @@ function relevanssi_search( $args ) {
|
|
726 |
}
|
727 |
}
|
728 |
$existing_items = array_keys( array_flip( $existing_items ) );
|
729 |
-
$
|
730 |
-
|
731 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
732 |
}
|
733 |
-
$query = "SELECT relevanssi.*, relevanssi.title * $title_boost +
|
734 |
-
relevanssi.content * $content_boost + relevanssi.comment * $comment_boost +
|
735 |
-
relevanssi.tag * $tag + relevanssi.link * $link_boost +
|
736 |
-
relevanssi.author + relevanssi.category * $cat + relevanssi.excerpt +
|
737 |
-
relevanssi.taxonomy + relevanssi.customfield + relevanssi.mysqlcolumn AS tf
|
738 |
-
FROM $relevanssi_table AS relevanssi WHERE relevanssi.item IN ($items_to_add)
|
739 |
-
$existing_items AND $term_cond";
|
740 |
-
|
741 |
-
// Clean: no unescaped user inputs.
|
742 |
-
$matches_to_add = $wpdb->get_results( $query ); // WPCS: unprepared SQL ok.
|
743 |
-
$matches = array_merge( $matches, $matches_to_add );
|
744 |
}
|
745 |
}
|
746 |
|
@@ -754,6 +403,7 @@ function relevanssi_search( $args ) {
|
|
754 |
if ( $idf < 1 ) {
|
755 |
$idf = 1;
|
756 |
}
|
|
|
757 |
foreach ( $matches as $match ) {
|
758 |
if ( 'user' === $match->type ) {
|
759 |
$match->doc = 'u_' . $match->item;
|
@@ -1290,9 +940,9 @@ function relevanssi_do_query( &$query ) {
|
|
1290 |
/**
|
1291 |
* Filters the default tax_query relation.
|
1292 |
*
|
1293 |
-
* @param string The default relation, default '
|
1294 |
*/
|
1295 |
-
$tax_query_relation = apply_filters( 'relevanssi_default_tax_query_relation', '
|
1296 |
if ( isset( $query->tax_query ) && empty( $query->tax_query->queries ) ) {
|
1297 |
// Tax query is empty, let's get rid of it.
|
1298 |
$query->tax_query = null;
|
@@ -1517,13 +1167,7 @@ function relevanssi_do_query( &$query ) {
|
|
1517 |
$parent_query = array( 'parent not in' => $query->query_vars['post_parent__not_in'] );
|
1518 |
}
|
1519 |
|
1520 |
-
|
1521 |
-
* Filters the default meta_query relation.
|
1522 |
-
*
|
1523 |
-
* @param string The meta_query relation, default 'AND'.
|
1524 |
-
*/
|
1525 |
-
$meta_query_relation = apply_filters( 'relevanssi_default_meta_query_relation', 'AND' );
|
1526 |
-
$meta_query = array();
|
1527 |
if ( ! empty( $query->query_vars['meta_query'] ) ) {
|
1528 |
$meta_query = $query->query_vars['meta_query'];
|
1529 |
}
|
@@ -1584,6 +1228,10 @@ function relevanssi_do_query( &$query ) {
|
|
1584 |
} else {
|
1585 |
$date_query = new WP_Date_Query( $query->date_query );
|
1586 |
}
|
|
|
|
|
|
|
|
|
1587 |
}
|
1588 |
|
1589 |
$search_blogs = false;
|
@@ -1842,6 +1490,8 @@ function relevanssi_do_query( &$query ) {
|
|
1842 |
/**
|
1843 |
* Limits the search queries to restrict the number of posts handled.
|
1844 |
*
|
|
|
|
|
1845 |
* @param string $query The MySQL query.
|
1846 |
*
|
1847 |
* @return string The query with the LIMIT parameter added, if necessary.
|
@@ -1866,6 +1516,8 @@ function relevanssi_limit_filter( $query ) {
|
|
1866 |
*
|
1867 |
* Figures out the post types that are not included in the search.
|
1868 |
*
|
|
|
|
|
1869 |
* @param string $include_attachments Whether to include attachments or not.
|
1870 |
*
|
1871 |
* @return string SQL escaped list of excluded post types.
|
@@ -1874,7 +1526,7 @@ function relevanssi_get_negative_post_type( $include_attachments ) {
|
|
1874 |
$negative_post_type = null;
|
1875 |
$negative_post_type_list = array();
|
1876 |
|
1877 |
-
if ( isset( $include_attachments ) && in_array( $include_attachments, array( '0', 'off', 'false' ), true ) ) {
|
1878 |
$negative_post_type_list[] = 'attachment';
|
1879 |
}
|
1880 |
|
@@ -1903,325 +1555,13 @@ function relevanssi_get_negative_post_type( $include_attachments ) {
|
|
1903 |
return $negative_post_type;
|
1904 |
}
|
1905 |
|
1906 |
-
/**
|
1907 |
-
* Processes one tax_query row.
|
1908 |
-
*
|
1909 |
-
* @global object $wpdb The WordPress database interface.
|
1910 |
-
*
|
1911 |
-
* @param array $row The tax_query row array.
|
1912 |
-
* @param boolean $is_sub_row True if this is a subrow.
|
1913 |
-
* @param string $global_relation The global tax_query relation (AND or OR).
|
1914 |
-
* @param string $query_restrictions The MySQL query restriction.
|
1915 |
-
* @param string $tax_query_relation The tax_query relation.
|
1916 |
-
* @param array $term_tax_ids Array of term taxonomy IDs.
|
1917 |
-
* @param array $not_term_tax_ids Array of excluded term taxonomy IDs.
|
1918 |
-
* @param array $and_term_tax_ids Array of AND term taxonomy IDs.
|
1919 |
-
*
|
1920 |
-
* @return array Returns an array where the first item is the updated
|
1921 |
-
* $query_restrictions, then $term_tax_ids, $not_term_tax_ids, and $and_term_tax_ids.
|
1922 |
-
*/
|
1923 |
-
function relevanssi_process_tax_query_row( $row, $is_sub_row, $global_relation, $query_restrictions, $tax_query_relation, $term_tax_ids, $not_term_tax_ids, $and_term_tax_ids ) {
|
1924 |
-
global $wpdb;
|
1925 |
-
|
1926 |
-
$local_term_tax_ids = array();
|
1927 |
-
$local_not_term_tax_ids = array();
|
1928 |
-
$local_and_term_tax_ids = array();
|
1929 |
-
$term_tax_id = array();
|
1930 |
-
|
1931 |
-
$exists_query = false;
|
1932 |
-
if ( isset( $row['operator'] ) && ( 'exists' === strtolower( $row['operator'] ) || 'not exists' === strtolower( $row['operator'] ) ) ) {
|
1933 |
-
$exists_query = true;
|
1934 |
-
}
|
1935 |
-
|
1936 |
-
$using_term_tax_id = false;
|
1937 |
-
if ( $exists_query ) {
|
1938 |
-
$row['field'] = 'exists';
|
1939 |
-
}
|
1940 |
-
if ( ! isset( $row['field'] ) ) {
|
1941 |
-
$row['field'] = 'term_id'; // In case 'field' is not set, go with the WP default of 'term_id'.
|
1942 |
-
}
|
1943 |
-
$row['field'] = strtolower( $row['field'] ); // In some cases, you can get 'ID' instead of 'id'.
|
1944 |
-
if ( 'slug' === $row['field'] ) {
|
1945 |
-
$slug = $row['terms'];
|
1946 |
-
$numeric_slugs = array();
|
1947 |
-
$slug_in = null;
|
1948 |
-
if ( is_array( $slug ) ) {
|
1949 |
-
$slugs = array();
|
1950 |
-
$term_id = array();
|
1951 |
-
foreach ( $slug as $t_slug ) {
|
1952 |
-
$term = get_term_by( 'slug', $t_slug, $row['taxonomy'] );
|
1953 |
-
if ( ! $term && is_numeric( $t_slug ) ) {
|
1954 |
-
$numeric_slugs[] = "'$t_slug'";
|
1955 |
-
} else {
|
1956 |
-
if ( isset( $term->term_id ) ) {
|
1957 |
-
$t_slug = sanitize_title( $t_slug );
|
1958 |
-
$term_id[] = $term->term_id;
|
1959 |
-
$slugs[] = "'$t_slug'";
|
1960 |
-
}
|
1961 |
-
}
|
1962 |
-
}
|
1963 |
-
if ( ! empty( $slugs ) ) {
|
1964 |
-
$slug_in = implode( ',', $slugs );
|
1965 |
-
}
|
1966 |
-
} else {
|
1967 |
-
$term = get_term_by( 'slug', $slug, $row['taxonomy'], OBJECT );
|
1968 |
-
if ( ! $term && is_numeric( $slug ) ) {
|
1969 |
-
$numeric_slugs[] = $slug;
|
1970 |
-
} else {
|
1971 |
-
if ( isset( $term->term_id ) ) {
|
1972 |
-
$slug = sanitize_title( $slug );
|
1973 |
-
$term_id = $term->term_id;
|
1974 |
-
$slug_in = "'$slug'";
|
1975 |
-
}
|
1976 |
-
}
|
1977 |
-
}
|
1978 |
-
if ( ! empty( $slug_in ) ) {
|
1979 |
-
$row_taxonomy = sanitize_text_field( $row['taxonomy'] );
|
1980 |
-
|
1981 |
-
$tt_q = "SELECT tt.term_taxonomy_id
|
1982 |
-
FROM $wpdb->term_taxonomy AS tt
|
1983 |
-
LEFT JOIN $wpdb->terms AS t ON (tt.term_id=t.term_id)
|
1984 |
-
WHERE tt.taxonomy = '$row_taxonomy' AND t.slug IN ($slug_in)";
|
1985 |
-
// Clean: $row_taxonomy is sanitized, each slug in $slug_in is sanitized.
|
1986 |
-
$term_tax_id = $wpdb->get_col( $tt_q ); // WPCS: unprepared SQL ok.
|
1987 |
-
}
|
1988 |
-
if ( ! empty( $numeric_slugs ) ) {
|
1989 |
-
$row['field'] = 'term_id';
|
1990 |
-
}
|
1991 |
-
}
|
1992 |
-
if ( 'name' === $row['field'] ) {
|
1993 |
-
$name = $row['terms'];
|
1994 |
-
$numeric_names = array();
|
1995 |
-
$name_in = null;
|
1996 |
-
if ( is_array( $name ) ) {
|
1997 |
-
$names = array();
|
1998 |
-
$term_id = array();
|
1999 |
-
foreach ( $name as $t_name ) {
|
2000 |
-
$term = get_term_by( 'name', $t_name, $row['taxonomy'] );
|
2001 |
-
if ( ! $term && is_numeric( $t_name ) ) {
|
2002 |
-
$numeric_names[] = "'$t_name'";
|
2003 |
-
} else {
|
2004 |
-
if ( isset( $term->term_id ) ) {
|
2005 |
-
$t_name = sanitize_title( $t_name );
|
2006 |
-
$term_id[] = $term->term_id;
|
2007 |
-
$names[] = "'$t_name'";
|
2008 |
-
}
|
2009 |
-
}
|
2010 |
-
}
|
2011 |
-
if ( ! empty( $names ) ) {
|
2012 |
-
$name_in = implode( ',', $names );
|
2013 |
-
}
|
2014 |
-
} else {
|
2015 |
-
$term = get_term_by( 'name', $name, $row['taxonomy'] );
|
2016 |
-
if ( ! $term && is_numeric( $name ) ) {
|
2017 |
-
$numeric_slugs[] = $name;
|
2018 |
-
} else {
|
2019 |
-
if ( isset( $term->term_id ) ) {
|
2020 |
-
$name = sanitize_title( $name );
|
2021 |
-
$term_id = $term->term_id;
|
2022 |
-
$name_in = "'$name'";
|
2023 |
-
}
|
2024 |
-
}
|
2025 |
-
}
|
2026 |
-
if ( ! empty( $name_in ) ) {
|
2027 |
-
$row_taxonomy = sanitize_text_field( $row['taxonomy'] );
|
2028 |
-
|
2029 |
-
$tt_q = "SELECT tt.term_taxonomy_id
|
2030 |
-
FROM $wpdb->term_taxonomy AS tt
|
2031 |
-
LEFT JOIN $wpdb->terms AS t ON (tt.term_id=t.term_id)
|
2032 |
-
WHERE tt.taxonomy = '$row_taxonomy' AND t.name IN ($name_in)";
|
2033 |
-
// Clean: $row_taxonomy is sanitized, each name in $name_in is sanitized.
|
2034 |
-
$term_tax_id = $wpdb->get_col( $tt_q ); // WPCS: unprepared SQL ok.
|
2035 |
-
}
|
2036 |
-
if ( ! empty( $numeric_names ) ) {
|
2037 |
-
$row['field'] = 'term_id';
|
2038 |
-
}
|
2039 |
-
}
|
2040 |
-
if ( 'id' === $row['field'] || 'term_id' === $row['field'] ) {
|
2041 |
-
$id = $row['terms'];
|
2042 |
-
$term_id = $id;
|
2043 |
-
if ( is_array( $id ) ) {
|
2044 |
-
$numeric_values = array();
|
2045 |
-
foreach ( $id as $t_id ) {
|
2046 |
-
if ( is_numeric( $t_id ) ) {
|
2047 |
-
$numeric_values[] = $t_id;
|
2048 |
-
}
|
2049 |
-
}
|
2050 |
-
$id = implode( ',', $numeric_values );
|
2051 |
-
}
|
2052 |
-
$row_taxonomy = sanitize_text_field( $row['taxonomy'] );
|
2053 |
-
|
2054 |
-
if ( ! empty( $id ) ) {
|
2055 |
-
$tt_q = "SELECT tt.term_taxonomy_id
|
2056 |
-
FROM $wpdb->term_taxonomy AS tt
|
2057 |
-
LEFT JOIN $wpdb->terms AS t ON (tt.term_id=t.term_id)
|
2058 |
-
WHERE tt.taxonomy = '$row_taxonomy' AND t.term_id IN ($id)";
|
2059 |
-
// Clean: $row_taxonomy is sanitized, $id is checked to be numeric.
|
2060 |
-
$id_term_tax_id = $wpdb->get_col( $tt_q ); // WPCS: unprepared SQL ok.
|
2061 |
-
if ( ! empty( $term_tax_id ) && is_array( $term_tax_id ) ) {
|
2062 |
-
$term_tax_id = array_unique( array_merge( $term_tax_id, $id_term_tax_id ) );
|
2063 |
-
} else {
|
2064 |
-
$term_tax_id = $id_term_tax_id;
|
2065 |
-
}
|
2066 |
-
}
|
2067 |
-
}
|
2068 |
-
if ( 'term_taxonomy_id' === $row['field'] ) {
|
2069 |
-
$using_term_tax_id = true;
|
2070 |
-
$id = $row['terms'];
|
2071 |
-
$term_tax_id = $id;
|
2072 |
-
if ( is_array( $id ) ) {
|
2073 |
-
$numeric_values = array();
|
2074 |
-
foreach ( $id as $t_id ) {
|
2075 |
-
if ( is_numeric( $t_id ) ) {
|
2076 |
-
$numeric_values[] = $t_id;
|
2077 |
-
}
|
2078 |
-
}
|
2079 |
-
$term_tax_id = implode( ',', $numeric_values );
|
2080 |
-
}
|
2081 |
-
}
|
2082 |
-
|
2083 |
-
if ( ! $exists_query && ( ! isset( $row['include_children'] ) || true === $row['include_children'] ) ) {
|
2084 |
-
if ( ! $using_term_tax_id && isset( $term_id ) ) {
|
2085 |
-
if ( ! is_array( $term_id ) ) {
|
2086 |
-
$term_id = array( $term_id );
|
2087 |
-
}
|
2088 |
-
} else {
|
2089 |
-
if ( ! is_array( $term_tax_id ) ) {
|
2090 |
-
$term_tax_id = array( $term_tax_id );
|
2091 |
-
$term_id = $term_tax_id;
|
2092 |
-
}
|
2093 |
-
}
|
2094 |
-
if ( empty( $term_tax_id ) ) {
|
2095 |
-
$term_tax_id = array();
|
2096 |
-
}
|
2097 |
-
if ( ! is_array( $term_tax_id ) ) {
|
2098 |
-
$term_tax_id = array( $term_tax_id );
|
2099 |
-
}
|
2100 |
-
if ( isset( $term_id ) && is_array( $term_id ) ) {
|
2101 |
-
foreach ( $term_id as $t_id ) {
|
2102 |
-
if ( $using_term_tax_id ) {
|
2103 |
-
$t_term = get_term_by( 'term_taxonomy_id', $t_id, $row['taxonomy'] );
|
2104 |
-
$t_id = $t_term->ID;
|
2105 |
-
}
|
2106 |
-
$kids = get_term_children( $t_id, $row['taxonomy'] );
|
2107 |
-
foreach ( $kids as $kid ) {
|
2108 |
-
$kid_term_tax_id = relevanssi_get_term_tax_id( $kid, $row['taxonomy'] );
|
2109 |
-
if ( $kid_term_tax_id ) {
|
2110 |
-
// In some weird cases, this may be null. See: https://wordpress.org/support/topic/childrens-of-chosen-product_cat-not-showing-up/.
|
2111 |
-
$term_tax_id[] = $kid_term_tax_id;
|
2112 |
-
}
|
2113 |
-
}
|
2114 |
-
}
|
2115 |
-
}
|
2116 |
-
}
|
2117 |
-
|
2118 |
-
$term_tax_id = array_unique( $term_tax_id );
|
2119 |
-
if ( ! empty( $term_tax_id ) ) {
|
2120 |
-
$n = count( $term_tax_id );
|
2121 |
-
$term_tax_id = implode( ',', $term_tax_id );
|
2122 |
-
|
2123 |
-
$tq_operator = 'IN'; // Assuming the default operator "IN", unless something else is provided.
|
2124 |
-
if ( isset( $row['operator'] ) ) {
|
2125 |
-
$tq_operator = strtoupper( $row['operator'] );
|
2126 |
-
}
|
2127 |
-
if ( ! in_array( $tq_operator, array( 'IN', 'NOT IN', 'AND' ), true ) ) {
|
2128 |
-
$tq_operator = 'IN';
|
2129 |
-
}
|
2130 |
-
if ( 'and' === $tax_query_relation ) {
|
2131 |
-
if ( 'AND' === $tq_operator ) {
|
2132 |
-
$query_restrictions .= " AND relevanssi.doc IN (
|
2133 |
-
SELECT ID FROM $wpdb->posts WHERE 1=1
|
2134 |
-
AND (
|
2135 |
-
SELECT COUNT(1)
|
2136 |
-
FROM $wpdb->term_relationships AS tr
|
2137 |
-
WHERE tr.term_taxonomy_id IN ($term_tax_id)
|
2138 |
-
AND tr.object_id = $wpdb->posts.ID ) = $n
|
2139 |
-
)";
|
2140 |
-
// Clean: $term_tax_id and $n are Relevanssi-generated.
|
2141 |
-
} else {
|
2142 |
-
$query_restrictions .= " AND relevanssi.doc $tq_operator (SELECT DISTINCT(tr.object_id) FROM $wpdb->term_relationships AS tr
|
2143 |
-
WHERE tr.term_taxonomy_id IN ($term_tax_id))";
|
2144 |
-
// Clean: all variables are Relevanssi-generated.
|
2145 |
-
}
|
2146 |
-
} else {
|
2147 |
-
if ( 'IN' === $tq_operator ) {
|
2148 |
-
$local_term_tax_ids[] = $term_tax_id;
|
2149 |
-
}
|
2150 |
-
if ( 'NOT IN' === $tq_operator ) {
|
2151 |
-
$local_not_term_tax_ids[] = $term_tax_id;
|
2152 |
-
}
|
2153 |
-
if ( 'AND' === $tq_operator ) {
|
2154 |
-
$local_and_term_tax_ids[] = $term_tax_id;
|
2155 |
-
}
|
2156 |
-
}
|
2157 |
-
} else {
|
2158 |
-
global $wp_query;
|
2159 |
-
$wp_query->is_category = false;
|
2160 |
-
}
|
2161 |
-
|
2162 |
-
if ( $is_sub_row && 'and' === $global_relation && 'or' === $tax_query_relation ) {
|
2163 |
-
$local_term_tax_ids = array_unique( $local_term_tax_ids );
|
2164 |
-
$local_not_term_tax_ids = array_unique( $local_not_term_tax_ids );
|
2165 |
-
$local_and_term_tax_ids = array_unique( $local_and_term_tax_ids );
|
2166 |
-
if ( count( $local_term_tax_ids ) > 0 ) {
|
2167 |
-
$local_term_tax_ids = implode( ',', $local_term_tax_ids );
|
2168 |
-
$query_restrictions .= " AND relevanssi.doc IN (SELECT DISTINCT(tr.object_id) FROM $wpdb->term_relationships AS tr
|
2169 |
-
WHERE tr.term_taxonomy_id IN ($local_term_tax_ids))";
|
2170 |
-
// Clean: all variables are Relevanssi-generated.
|
2171 |
-
}
|
2172 |
-
if ( count( $local_not_term_tax_ids ) > 0 ) {
|
2173 |
-
$local_not_term_tax_ids = implode( ',', $local_not_term_tax_ids );
|
2174 |
-
$query_restrictions .= " AND relevanssi.doc NOT IN (SELECT DISTINCT(tr.object_id) FROM $wpdb->term_relationships AS tr
|
2175 |
-
WHERE tr.term_taxonomy_id IN ($local_not_term_tax_ids))";
|
2176 |
-
// Clean: all variables are Relevanssi-generated.
|
2177 |
-
}
|
2178 |
-
if ( count( $local_and_term_tax_ids ) > 0 ) {
|
2179 |
-
$local_and_term_tax_ids = implode( ',', $local_and_term_tax_ids );
|
2180 |
-
$n = count( explode( ',', $local_and_term_tax_ids ) );
|
2181 |
-
$query_restrictions .= " AND relevanssi.doc IN (
|
2182 |
-
SELECT ID FROM $wpdb->posts WHERE 1=1
|
2183 |
-
AND (
|
2184 |
-
SELECT COUNT(1)
|
2185 |
-
FROM $wpdb->term_relationships AS tr
|
2186 |
-
WHERE tr.term_taxonomy_id IN ($local_and_term_tax_ids)
|
2187 |
-
AND tr.object_id = $wpdb->posts.ID ) = $n
|
2188 |
-
)";
|
2189 |
-
// Clean: all variables are Relevanssi-generated.
|
2190 |
-
}
|
2191 |
-
}
|
2192 |
-
|
2193 |
-
$copy_term_tax_ids = false;
|
2194 |
-
if ( ! $is_sub_row ) {
|
2195 |
-
$copy_term_tax_ids = true;
|
2196 |
-
}
|
2197 |
-
if ( $is_sub_row && 'or' === $global_relation ) {
|
2198 |
-
$copy_term_tax_ids = true;
|
2199 |
-
}
|
2200 |
-
|
2201 |
-
if ( $copy_term_tax_ids ) {
|
2202 |
-
$term_tax_ids = array_merge( $term_tax_ids, $local_term_tax_ids );
|
2203 |
-
$not_term_tax_ids = array_merge( $not_term_tax_ids, $local_not_term_tax_ids );
|
2204 |
-
$and_term_tax_ids = array_merge( $and_term_tax_ids, $local_and_term_tax_ids );
|
2205 |
-
}
|
2206 |
-
|
2207 |
-
if ( $exists_query ) {
|
2208 |
-
$taxonomy = $row['taxonomy'];
|
2209 |
-
$operator = 'IN';
|
2210 |
-
if ( 'not exists' === strtolower( $row['operator'] ) ) {
|
2211 |
-
$operator = 'NOT IN';
|
2212 |
-
}
|
2213 |
-
$query_restrictions .= " AND relevanssi.doc $operator (SELECT DISTINCT(tr.object_id) FROM $wpdb->term_relationships AS tr,
|
2214 |
-
$wpdb->term_taxonomy AS tt WHERE tr.term_taxonomy_id = tt.term_taxonomy_id AND tt.taxonomy = '$taxonomy')";
|
2215 |
-
}
|
2216 |
-
|
2217 |
-
return array( $query_restrictions, $term_tax_ids, $not_term_tax_ids, $and_term_tax_ids );
|
2218 |
-
}
|
2219 |
-
|
2220 |
/**
|
2221 |
* Generates the WHERE condition for terms.
|
2222 |
*
|
2223 |
* Trims the term, escapes it and places it in the template.
|
2224 |
*
|
|
|
|
|
2225 |
* @param string $term The search term.
|
2226 |
* @param string $o_term_cond The search condition template.
|
2227 |
*
|
@@ -2259,6 +1599,8 @@ function relevanssi_generate_term_cond( $term, $o_term_cond ) {
|
|
2259 |
* If there's a taxonomy weight in $post_type_weights, that is used, otherwise
|
2260 |
* assume weight 1.
|
2261 |
*
|
|
|
|
|
2262 |
* @since 2.1.5
|
2263 |
*
|
2264 |
* @param object $match The match object, used as a reference.
|
116 |
*
|
117 |
* @param array The search parameters.
|
118 |
*/
|
119 |
+
$filtered_args = apply_filters( 'relevanssi_search_filters', $args );
|
120 |
+
$meta_query = $filtered_args['meta_query'];
|
121 |
+
$operator = $filtered_args['operator'];
|
122 |
+
$orderby = $filtered_args['orderby'];
|
123 |
+
$order = $filtered_args['order'];
|
124 |
+
$fields = $filtered_args['fields'];
|
125 |
+
$meta_query = $filtered_args['meta_query'];
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
126 |
|
127 |
+
$hits = array();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
128 |
|
129 |
+
$query_data = relevanssi_process_query_args( $filtered_args );
|
130 |
+
$query_restrictions = $query_data['query_restrictions'];
|
131 |
+
$query_join = $query_data['query_join'];
|
132 |
+
$q = $query_data['query_query'];
|
|
|
|
|
133 |
|
134 |
/**
|
135 |
* Filters whether stopwords are removed from titles.
|
139 |
$remove_stopwords = apply_filters( 'relevanssi_remove_stopwords_in_titles', true );
|
140 |
|
141 |
$terms = relevanssi_tokenize( $q, $remove_stopwords );
|
|
|
142 |
if ( count( $terms ) < 1 ) {
|
143 |
// Tokenizer killed all the search terms.
|
144 |
return $hits;
|
145 |
}
|
146 |
$terms = array_keys( $terms ); // Don't care about tf in query.
|
147 |
|
148 |
+
if ( function_exists( 'relevanssi_process_terms' ) ) {
|
149 |
+
$process_terms_results = relevanssi_process_terms( $terms, $q );
|
150 |
+
$query_restrictions .= $process_terms_results['query_restrictions'];
|
151 |
+
$terms = $process_terms_results['terms'];
|
152 |
}
|
153 |
|
154 |
+
/**
|
155 |
+
* Filters the query restrictions for the Relevanssi query.
|
156 |
+
*
|
157 |
+
* Equivalent to the 'posts_where' filter.
|
158 |
+
*
|
159 |
+
* @author Charles St-Pierre
|
160 |
+
*
|
161 |
+
* @param string The MySQL code that restricts the query.
|
162 |
+
*/
|
163 |
+
$query_restrictions = apply_filters( 'relevanssi_where', $query_restrictions );
|
164 |
+
|
165 |
+
/**
|
166 |
+
* Filters the meta query JOIN for the Relevanssi search query.
|
167 |
+
*
|
168 |
+
* Somewhat equivalent to the 'posts_join' filter.
|
169 |
+
*
|
170 |
+
* @param string The JOINed query.
|
171 |
+
*/
|
172 |
+
$query_join = apply_filters( 'relevanssi_join', $query_join );
|
173 |
+
|
174 |
// Go get the count from the options, but run the full query if it's not available.
|
175 |
$doc_count = get_option( 'relevanssi_doc_count' );
|
176 |
if ( ! $doc_count || $doc_count < 1 ) {
|
191 |
|
192 |
$fuzzy = get_option( 'relevanssi_fuzzy' );
|
193 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
194 |
$no_matches = true;
|
195 |
if ( 'always' === $fuzzy ) {
|
196 |
/**
|
217 |
$recency_bonus = false;
|
218 |
$recency_cutoff_date = false;
|
219 |
if ( function_exists( 'relevanssi_get_recency_bonus' ) ) {
|
220 |
+
$recency_details = relevanssi_get_recency_bonus();
|
221 |
+
$recency_bonus = $recency_details['bonus'];
|
222 |
+
$recency_cutoff_date = $recency_details['cutoff'];
|
223 |
}
|
224 |
|
225 |
$exact_match_bonus = false;
|
337 |
} else {
|
338 |
$no_matches = false;
|
339 |
if ( count( $include_these_posts ) > 0 ) {
|
340 |
+
$existing_ids = array();
|
|
|
341 |
foreach ( $matches as $match ) {
|
342 |
$existing_ids[] = $match->doc;
|
343 |
}
|
344 |
+
$existing_ids = array_keys( array_flip( $existing_ids ) );
|
345 |
+
$added_post_ids = array_diff( array_keys( $include_these_posts ), $existing_ids );
|
346 |
+
if ( count( $added_post_ids ) > 0 ) {
|
347 |
+
$offset = 0;
|
348 |
+
$slice_length = 1;
|
349 |
+
$total_ids = count( $added_post_ids );
|
350 |
+
do {
|
351 |
+
$current_slice = array_slice( $added_post_ids, $offset, $slice_length );
|
352 |
+
$post_ids_to_add = implode( ',', $current_slice );
|
353 |
+
if ( ! empty( $post_ids_to_add ) ) {
|
354 |
+
$query = "SELECT relevanssi.*, relevanssi.title * $title_boost +
|
355 |
+
relevanssi.content * $content_boost + relevanssi.comment * $comment_boost +
|
356 |
+
relevanssi.tag * $tag + relevanssi.link * $link_boost +
|
357 |
+
relevanssi.author + relevanssi.category * $cat + relevanssi.excerpt +
|
358 |
+
relevanssi.taxonomy + relevanssi.customfield + relevanssi.mysqlcolumn AS tf
|
359 |
+
FROM $relevanssi_table AS relevanssi WHERE relevanssi.doc IN ($post_ids_to_add)
|
360 |
+
AND $term_cond";
|
361 |
+
|
362 |
+
// Clean: no unescaped user inputs.
|
363 |
+
$matches_to_add = $wpdb->get_results( $query ); // WPCS: unprepared SQL ok.
|
364 |
+
$matches = array_merge( $matches, $matches_to_add );
|
365 |
+
}
|
366 |
+
$offset += $slice_length;
|
367 |
+
} while ( $offset <= $total_ids );
|
368 |
+
}
|
369 |
}
|
370 |
if ( count( $include_these_items ) > 0 ) {
|
|
|
371 |
$existing_items = array();
|
372 |
foreach ( $matches as $match ) {
|
373 |
if ( 0 !== intval( $match->item ) ) {
|
375 |
}
|
376 |
}
|
377 |
$existing_items = array_keys( array_flip( $existing_items ) );
|
378 |
+
$items_to_add = implode( ',', array_diff( array_keys( $include_these_items ), $existing_items ) );
|
379 |
+
|
380 |
+
if ( ! empty( $items_to_add ) ) {
|
381 |
+
$query = "SELECT relevanssi.*, relevanssi.title * $title_boost +
|
382 |
+
relevanssi.content * $content_boost + relevanssi.comment * $comment_boost +
|
383 |
+
relevanssi.tag * $tag + relevanssi.link * $link_boost +
|
384 |
+
relevanssi.author + relevanssi.category * $cat + relevanssi.excerpt +
|
385 |
+
relevanssi.taxonomy + relevanssi.customfield + relevanssi.mysqlcolumn AS tf
|
386 |
+
FROM $relevanssi_table AS relevanssi WHERE relevanssi.item IN ($items_to_add)
|
387 |
+
AND $term_cond";
|
388 |
+
|
389 |
+
// Clean: no unescaped user inputs.
|
390 |
+
$matches_to_add = $wpdb->get_results( $query ); // WPCS: unprepared SQL ok.
|
391 |
+
$matches = array_merge( $matches, $matches_to_add );
|
392 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
393 |
}
|
394 |
}
|
395 |
|
403 |
if ( $idf < 1 ) {
|
404 |
$idf = 1;
|
405 |
}
|
406 |
+
|
407 |
foreach ( $matches as $match ) {
|
408 |
if ( 'user' === $match->type ) {
|
409 |
$match->doc = 'u_' . $match->item;
|
940 |
/**
|
941 |
* Filters the default tax_query relation.
|
942 |
*
|
943 |
+
* @param string The default relation, default 'AND'.
|
944 |
*/
|
945 |
+
$tax_query_relation = apply_filters( 'relevanssi_default_tax_query_relation', 'AND' );
|
946 |
if ( isset( $query->tax_query ) && empty( $query->tax_query->queries ) ) {
|
947 |
// Tax query is empty, let's get rid of it.
|
948 |
$query->tax_query = null;
|
1167 |
$parent_query = array( 'parent not in' => $query->query_vars['post_parent__not_in'] );
|
1168 |
}
|
1169 |
|
1170 |
+
$meta_query = array();
|
|
|
|
|
|
|
|
|
|
|
|
|
1171 |
if ( ! empty( $query->query_vars['meta_query'] ) ) {
|
1172 |
$meta_query = $query->query_vars['meta_query'];
|
1173 |
}
|
1228 |
} else {
|
1229 |
$date_query = new WP_Date_Query( $query->date_query );
|
1230 |
}
|
1231 |
+
} elseif ( ! empty( $query->query_vars['date_query'] ) ) {
|
1232 |
+
// The official date query is in $query->date_query, but this allows
|
1233 |
+
// users to set the date query from query variables.
|
1234 |
+
$date_query = new WP_Date_Query( $query->query_vars['date_query'] );
|
1235 |
}
|
1236 |
|
1237 |
$search_blogs = false;
|
1490 |
/**
|
1491 |
* Limits the search queries to restrict the number of posts handled.
|
1492 |
*
|
1493 |
+
* Tested.
|
1494 |
+
*
|
1495 |
* @param string $query The MySQL query.
|
1496 |
*
|
1497 |
* @return string The query with the LIMIT parameter added, if necessary.
|
1516 |
*
|
1517 |
* Figures out the post types that are not included in the search.
|
1518 |
*
|
1519 |
+
* Tested.
|
1520 |
+
*
|
1521 |
* @param string $include_attachments Whether to include attachments or not.
|
1522 |
*
|
1523 |
* @return string SQL escaped list of excluded post types.
|
1526 |
$negative_post_type = null;
|
1527 |
$negative_post_type_list = array();
|
1528 |
|
1529 |
+
if ( isset( $include_attachments ) && in_array( $include_attachments, array( '0', 'off', 'false', false ), true ) ) {
|
1530 |
$negative_post_type_list[] = 'attachment';
|
1531 |
}
|
1532 |
|
1555 |
return $negative_post_type;
|
1556 |
}
|
1557 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1558 |
/**
|
1559 |
* Generates the WHERE condition for terms.
|
1560 |
*
|
1561 |
* Trims the term, escapes it and places it in the template.
|
1562 |
*
|
1563 |
+
* Tested.
|
1564 |
+
*
|
1565 |
* @param string $term The search term.
|
1566 |
* @param string $o_term_cond The search condition template.
|
1567 |
*
|
1599 |
* If there's a taxonomy weight in $post_type_weights, that is used, otherwise
|
1600 |
* assume weight 1.
|
1601 |
*
|
1602 |
+
* Tested.
|
1603 |
+
*
|
1604 |
* @since 2.1.5
|
1605 |
*
|
1606 |
* @param object $match The match object, used as a reference.
|
lib/shortcodes.php
CHANGED
@@ -110,12 +110,33 @@ function relevanssi_search_form( $atts ) {
|
|
110 |
if ( is_array( $atts ) ) {
|
111 |
$additional_fields = array();
|
112 |
foreach ( $atts as $key => $value ) {
|
113 |
-
|
114 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
115 |
|
116 |
-
|
|
|
117 |
}
|
118 |
-
$form = str_replace( '
|
119 |
}
|
120 |
/**
|
121 |
* Filters the Relevanssi shortcode search form before it's used.
|
110 |
if ( is_array( $atts ) ) {
|
111 |
$additional_fields = array();
|
112 |
foreach ( $atts as $key => $value ) {
|
113 |
+
if ( 'dropdown' === $key ) {
|
114 |
+
switch ( $value ) {
|
115 |
+
case 'category':
|
116 |
+
$name = 'cat';
|
117 |
+
break;
|
118 |
+
case 'post_tag':
|
119 |
+
$name = 'tag';
|
120 |
+
break;
|
121 |
+
default:
|
122 |
+
$name = $value;
|
123 |
+
}
|
124 |
+
$args = array(
|
125 |
+
'taxonomy' => $value,
|
126 |
+
'echo' => 0,
|
127 |
+
'hide_if_empty' => true,
|
128 |
+
'show_option_none' => __( 'None' ),
|
129 |
+
'name' => $name,
|
130 |
+
);
|
131 |
+
$additional_fields[] = wp_dropdown_categories( $args );
|
132 |
+
} else {
|
133 |
+
$key = esc_attr( $key );
|
134 |
+
$value = esc_attr( $value );
|
135 |
|
136 |
+
$additional_fields[] = "<input type='hidden' name='$key' value='$value' />";
|
137 |
+
}
|
138 |
}
|
139 |
+
$form = str_replace( '<input type="submit"', implode( "\n", $additional_fields ) . '<input type="submit"', $form );
|
140 |
}
|
141 |
/**
|
142 |
* Filters the Relevanssi shortcode search form before it's used.
|
lib/sorting.php
CHANGED
@@ -198,7 +198,7 @@ function relevanssi_get_compare_values( $key, $item_1, $item_2 ) {
|
|
198 |
$key2 = get_post_meta( $item_2->ID, $key, true );
|
199 |
if ( empty( $key2 ) ) {
|
200 |
/**
|
201 |
-
* Documented in lib/
|
202 |
*/
|
203 |
$key2 = apply_filters( 'relevanssi_missing_sort_key', $key2, $key );
|
204 |
}
|
@@ -211,7 +211,7 @@ function relevanssi_get_compare_values( $key, $item_1, $item_2 ) {
|
|
211 |
$key1 = get_post_meta( $item_1->ID, $relevanssi_meta_query[ $key ]['key'], true );
|
212 |
} else {
|
213 |
/**
|
214 |
-
* Documented in lib/
|
215 |
*/
|
216 |
$key1 = apply_filters( 'relevanssi_missing_sort_key', $key1, $key );
|
217 |
}
|
@@ -222,7 +222,7 @@ function relevanssi_get_compare_values( $key, $item_1, $item_2 ) {
|
|
222 |
$key2 = get_post_meta( $item_2->ID, $relevanssi_meta_query[ $key ]['key'], true );
|
223 |
} else {
|
224 |
/**
|
225 |
-
* Documented in lib/
|
226 |
*/
|
227 |
$key2 = apply_filters( 'relevanssi_missing_sort_key', $key2, $key );
|
228 |
}
|
198 |
$key2 = get_post_meta( $item_2->ID, $key, true );
|
199 |
if ( empty( $key2 ) ) {
|
200 |
/**
|
201 |
+
* Documented in lib/sorting.php.
|
202 |
*/
|
203 |
$key2 = apply_filters( 'relevanssi_missing_sort_key', $key2, $key );
|
204 |
}
|
211 |
$key1 = get_post_meta( $item_1->ID, $relevanssi_meta_query[ $key ]['key'], true );
|
212 |
} else {
|
213 |
/**
|
214 |
+
* Documented in lib/sorting.php.
|
215 |
*/
|
216 |
$key1 = apply_filters( 'relevanssi_missing_sort_key', $key1, $key );
|
217 |
}
|
222 |
$key2 = get_post_meta( $item_2->ID, $relevanssi_meta_query[ $key ]['key'], true );
|
223 |
} else {
|
224 |
/**
|
225 |
+
* Documented in lib/sorting.php.
|
226 |
*/
|
227 |
$key2 = apply_filters( 'relevanssi_missing_sort_key', $key2, $key );
|
228 |
}
|
lib/stopwords.php
CHANGED
@@ -67,8 +67,6 @@ function relevanssi_fetch_stopwords() {
|
|
67 |
/**
|
68 |
* Adds a stopword to the list of stopwords.
|
69 |
*
|
70 |
-
* @global object $wpdb The WP database interface.
|
71 |
-
*
|
72 |
* @param string $term The stopword that is added.
|
73 |
* @param boolean $verbose If true, print out notice. If false, be silent. Default
|
74 |
* true.
|
@@ -76,7 +74,6 @@ function relevanssi_fetch_stopwords() {
|
|
76 |
* @return boolean True, if success; false otherwise.
|
77 |
*/
|
78 |
function relevanssi_add_stopword( $term, $verbose = true ) {
|
79 |
-
global $wpdb;
|
80 |
if ( empty( $term ) ) {
|
81 |
return;
|
82 |
}
|
67 |
/**
|
68 |
* Adds a stopword to the list of stopwords.
|
69 |
*
|
|
|
|
|
70 |
* @param string $term The stopword that is added.
|
71 |
* @param boolean $verbose If true, print out notice. If false, be silent. Default
|
72 |
* true.
|
74 |
* @return boolean True, if success; false otherwise.
|
75 |
*/
|
76 |
function relevanssi_add_stopword( $term, $verbose = true ) {
|
|
|
77 |
if ( empty( $term ) ) {
|
78 |
return;
|
79 |
}
|
lib/tabs/searching-tab.php
CHANGED
@@ -120,6 +120,10 @@ function relevanssi_searching_tab() {
|
|
120 |
<option value='always' <?php echo esc_html( $fuzzy_always ); ?>><?php esc_html_e( 'Partial words', 'relevanssi' ); ?></option>
|
121 |
<option value='sometimes' <?php echo esc_html( $fuzzy_sometimes ); ?>><?php esc_html_e( 'Partial words if no hits for whole words', 'relevanssi' ); ?></option>
|
122 |
</select>
|
|
|
|
|
|
|
|
|
123 |
<p class="description"><?php esc_html_e( 'Whole words means Relevanssi only finds posts that include the whole search term.', 'relevanssi' ); ?></p>
|
124 |
<p class="description"><?php esc_html_e( "Partial words also includes cases where the word in the index begins or ends with the search term (searching for 'ana' will match 'anaconda' or 'banana', but not 'banal'). See Help, if you want to make Relevanssi match also inside words.", 'relevanssi' ); ?></p>
|
125 |
</td>
|
120 |
<option value='always' <?php echo esc_html( $fuzzy_always ); ?>><?php esc_html_e( 'Partial words', 'relevanssi' ); ?></option>
|
121 |
<option value='sometimes' <?php echo esc_html( $fuzzy_sometimes ); ?>><?php esc_html_e( 'Partial words if no hits for whole words', 'relevanssi' ); ?></option>
|
122 |
</select>
|
123 |
+
<?php if ( $fuzzy_sometimes ) : ?>
|
124 |
+
<?php // Translators: %1$s is the "partial words if no hits" option and %2$s is the "partial words" option. ?>
|
125 |
+
<p class="description important"><?php printf( esc_html__( 'Choosing the "%1$s" option may lead to unexpected results. Most of the time the "%2$s" option is the better choice.', 'relevanssi' ), esc_html__( 'Partial words if not hits for whole words', 'relevanssi' ), esc_html__( 'Partial words', 'relevanssi' ) ); ?></p>
|
126 |
+
<?php endif; ?>
|
127 |
<p class="description"><?php esc_html_e( 'Whole words means Relevanssi only finds posts that include the whole search term.', 'relevanssi' ); ?></p>
|
128 |
<p class="description"><?php esc_html_e( "Partial words also includes cases where the word in the index begins or ends with the search term (searching for 'ana' will match 'anaconda' or 'banana', but not 'banal'). See Help, if you want to make Relevanssi match also inside words.", 'relevanssi' ); ?></p>
|
129 |
</td>
|
lib/tabs/stopwords-tab.php
CHANGED
@@ -20,6 +20,17 @@ function relevanssi_stopwords_tab() {
|
|
20 |
|
21 |
relevanssi_show_stopwords();
|
22 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
23 |
/**
|
24 |
* Filters whether the common words list is displayed or not.
|
25 |
*
|
@@ -45,11 +56,6 @@ function relevanssi_stopwords_tab() {
|
|
45 |
function relevanssi_show_stopwords() {
|
46 |
global $wpdb, $relevanssi_variables;
|
47 |
|
48 |
-
$plugin = 'relevanssi';
|
49 |
-
if ( RELEVANSSI_PREMIUM ) {
|
50 |
-
$plugin = 'relevanssi-premium';
|
51 |
-
}
|
52 |
-
|
53 |
printf( '<p>%s</p>', esc_html__( 'Enter a word here to add it to the list of stopwords. The word will automatically be removed from the index, so re-indexing is not necessary. You can enter many words at the same time, separate words with commas.', 'relevanssi' ) );
|
54 |
?>
|
55 |
<table class="form-table">
|
20 |
|
21 |
relevanssi_show_stopwords();
|
22 |
|
23 |
+
?>
|
24 |
+
|
25 |
+
<h3 id="bodystopwords"><?php esc_html_e( 'Content stopwords', 'relevanssi' ); ?></h3>
|
26 |
+
|
27 |
+
<?php
|
28 |
+
if ( function_exists( 'relevanssi_show_body_stopwords' ) ) {
|
29 |
+
relevanssi_show_body_stopwords();
|
30 |
+
} else {
|
31 |
+
printf( '<p>%s</p>', esc_html__( 'Content stopwords are a premium feature where you can set stopwords that only apply to the post content. Those stopwords will still be indexed if they appear in post titles, tags, categories, custom fields or other parts of the post. To use content stopwords, you need Relevanssi Premium.', 'relevanssi' ) );
|
32 |
+
}
|
33 |
+
|
34 |
/**
|
35 |
* Filters whether the common words list is displayed or not.
|
36 |
*
|
56 |
function relevanssi_show_stopwords() {
|
57 |
global $wpdb, $relevanssi_variables;
|
58 |
|
|
|
|
|
|
|
|
|
|
|
59 |
printf( '<p>%s</p>', esc_html__( 'Enter a word here to add it to the list of stopwords. The word will automatically be removed from the index, so re-indexing is not necessary. You can enter many words at the same time, separate words with commas.', 'relevanssi' ) );
|
60 |
?>
|
61 |
<table class="form-table">
|
readme.txt
CHANGED
@@ -3,9 +3,9 @@ Contributors: msaari
|
|
3 |
Donate link: https://www.relevanssi.com/buy-premium/
|
4 |
Tags: search, relevance, better search
|
5 |
Requires at least: 4.8.3
|
6 |
-
Tested up to: 5.2
|
7 |
Requires PHP: 5.6
|
8 |
-
Stable tag: 4.
|
9 |
License: GPLv2 or later
|
10 |
License URI: http://www.gnu.org/licenses/gpl-2.0.html
|
11 |
|
@@ -129,6 +129,22 @@ Each document database is full of useless words. All the little words that appea
|
|
129 |
* John Calahan for extensive 4.0 beta testing.
|
130 |
|
131 |
== Changelog ==
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
132 |
= 4.1.4 =
|
133 |
* `EXISTS` and `NOT EXISTS` didn’t work for taxonomy terms in searches.
|
134 |
* WPML post type handling has been improved. If post type allows fallback for default language, Relevanssi will support that.
|
@@ -193,6 +209,9 @@ Each document database is full of useless words. All the little words that appea
|
|
193 |
* WP Search Suggest compatibility added.
|
194 |
|
195 |
== Upgrade notice ==
|
|
|
|
|
|
|
196 |
= 4.1.4 =
|
197 |
* Restrict Content Pro support, bug fixes and small improvements.
|
198 |
|
3 |
Donate link: https://www.relevanssi.com/buy-premium/
|
4 |
Tags: search, relevance, better search
|
5 |
Requires at least: 4.8.3
|
6 |
+
Tested up to: 5.2.1
|
7 |
Requires PHP: 5.6
|
8 |
+
Stable tag: 4.2.0
|
9 |
License: GPLv2 or later
|
10 |
License URI: http://www.gnu.org/licenses/gpl-2.0.html
|
11 |
|
129 |
* John Calahan for extensive 4.0 beta testing.
|
130 |
|
131 |
== Changelog ==
|
132 |
+
= 4.2.0 =
|
133 |
+
* New feature: The search form shortcode has a new parameter `dropdown` which can be used to add a category dropdown, like this: `[searchform dropdown="category"]`.
|
134 |
+
* New feature: Relevanssi can now use the contents of the PDF files indexed with WP File Download.
|
135 |
+
* New filter: `relevanssi_indexing_tokens` can be used to filter the tokens (individual words) before they are indexed.
|
136 |
+
* Removed filter: `relevanssi_default_meta_query_relation` did not have any effect anymore.
|
137 |
+
* Changed behaviour: The default taxonomy relation was set to AND in 4.1.4, but wasn't properly applied before. Now it is really switched.
|
138 |
+
* Changed behaviour: New post types have been added to list of forbidden post types Relevanssi won't show as indexing options (ACF, TablePress and WooCommerce).
|
139 |
+
* Major fix: Tax query processing has been completely refactored, eliminating all sorts of bugs, especially with various edge cases.
|
140 |
+
* Major fix: Gutenberg block indexing only worked with the Gutenberg plugin enabled. It now works with WP 5.0 built-in Gutenberg as well. If you use Gutenberg blocks, reindex to get all the block content in the index.
|
141 |
+
* Major fix: Excerpt-building and highlighting did not respect the "Keyword matching" setting. They do now, and the excerpts should be better now.
|
142 |
+
* Major fix: AND searches needed queries that could get too long for the database to handle. This has been fixed and optimized.
|
143 |
+
* Major fix: Taxonomy term subquery relations didn't work; now they are applied.
|
144 |
+
* Minor fix: iOS uses curly quotes by default, and that didn't work as a phrase operator. Now phrase operator works with curly quotes and straight quotes.
|
145 |
+
* Minor fix: The Did you mean broke with search terms longer than 255 characters.
|
146 |
+
* Minor fix: Phrases with numbers and one word like "team 17" didn't work, because numbers weren't counted as words.
|
147 |
+
|
148 |
= 4.1.4 =
|
149 |
* `EXISTS` and `NOT EXISTS` didn’t work for taxonomy terms in searches.
|
150 |
* WPML post type handling has been improved. If post type allows fallback for default language, Relevanssi will support that.
|
209 |
* WP Search Suggest compatibility added.
|
210 |
|
211 |
== Upgrade notice ==
|
212 |
+
= 4.2.0 =
|
213 |
+
* New features, bug fixes, smaller improvements.
|
214 |
+
|
215 |
= 4.1.4 =
|
216 |
* Restrict Content Pro support, bug fixes and small improvements.
|
217 |
|
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
|
@@ -58,15 +58,17 @@ $relevanssi_variables['database_version'] = 5;
|
|
58 |
$relevanssi_variables['file'] = __FILE__;
|
59 |
$relevanssi_variables['plugin_dir'] = plugin_dir_path( __FILE__ );
|
60 |
|
61 |
-
require_once 'lib/
|
|
|
|
|
|
|
62 |
require_once 'lib/init.php';
|
|
|
63 |
require_once 'lib/interface.php';
|
64 |
-
require_once 'lib/indexing.php';
|
65 |
require_once 'lib/log.php';
|
66 |
-
require_once 'lib/sorting.php';
|
67 |
-
require_once 'lib/stopwords.php';
|
68 |
require_once 'lib/search.php';
|
69 |
-
require_once 'lib/
|
|
|
70 |
require_once 'lib/shortcodes.php';
|
71 |
-
require_once 'lib/
|
72 |
-
require_once 'lib/
|
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.2.0
|
17 |
* Author: Mikko Saari
|
18 |
* Author URI: http://www.mikkosaari.fi/
|
19 |
* Text Domain: relevanssi
|
58 |
$relevanssi_variables['file'] = __FILE__;
|
59 |
$relevanssi_variables['plugin_dir'] = plugin_dir_path( __FILE__ );
|
60 |
|
61 |
+
require_once 'lib/admin-ajax.php';
|
62 |
+
require_once 'lib/common.php';
|
63 |
+
require_once 'lib/excerpts-highlights.php';
|
64 |
+
require_once 'lib/indexing.php';
|
65 |
require_once 'lib/init.php';
|
66 |
+
require_once 'lib/install.php';
|
67 |
require_once 'lib/interface.php';
|
|
|
68 |
require_once 'lib/log.php';
|
|
|
|
|
69 |
require_once 'lib/search.php';
|
70 |
+
require_once 'lib/search-tax-query.php';
|
71 |
+
require_once 'lib/search-query-restrictions.php';
|
72 |
require_once 'lib/shortcodes.php';
|
73 |
+
require_once 'lib/sorting.php';
|
74 |
+
require_once 'lib/stopwords.php';
|
relevanssi.po
CHANGED
@@ -2,7 +2,7 @@ msgid ""
|
|
2 |
msgstr ""
|
3 |
"Project-Id-Version: Relevanssi\n"
|
4 |
"Report-Msgid-Bugs-To: \n"
|
5 |
-
"POT-Creation-Date: 2019-
|
6 |
"PO-Revision-Date: \n"
|
7 |
"Last-Translator: Mikko Saari <mikko@mikkosaari.fi>\n"
|
8 |
"Language-Team: \n"
|
@@ -12,7 +12,7 @@ msgstr ""
|
|
12 |
"Content-Transfer-Encoding: 8bit\n"
|
13 |
"X-Poedit-KeywordsList: _e;__;esc_html__;esc_html_e;_n\n"
|
14 |
"X-Poedit-Basepath: .\n"
|
15 |
-
"X-Generator: Poedit 2.2.
|
16 |
"X-Poedit-SearchPath-0: .\n"
|
17 |
"X-Poedit-SearchPath-1: lib\n"
|
18 |
|
@@ -21,40 +21,56 @@ msgstr ""
|
|
21 |
msgid "Indexed %1$d post (total %2$d), processed %3$d / %4$d."
|
22 |
msgstr ""
|
23 |
|
24 |
-
#: lib/admin-ajax.php:
|
25 |
msgid "Results"
|
26 |
msgstr ""
|
27 |
|
28 |
-
#: lib/admin-ajax.php:
|
29 |
#, php-format
|
30 |
msgid "Found a total of %1$d posts, showing %2$d posts from offset %3$s."
|
31 |
msgstr ""
|
32 |
|
33 |
-
#: lib/admin-ajax.php:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
34 |
msgid "Score:"
|
35 |
msgstr ""
|
36 |
|
37 |
-
#: lib/admin-ajax.php:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
38 |
msgid "Query variables"
|
39 |
msgstr ""
|
40 |
|
41 |
-
#: lib/admin-ajax.php:
|
42 |
msgid "Filters"
|
43 |
msgstr ""
|
44 |
|
45 |
-
#: lib/admin-ajax.php:
|
46 |
msgid "show"
|
47 |
msgstr ""
|
48 |
|
49 |
-
#: lib/admin-ajax.php:
|
50 |
msgid "hide"
|
51 |
msgstr ""
|
52 |
|
53 |
-
#: lib/common.php:
|
54 |
msgid "25 most common words in the index"
|
55 |
msgstr ""
|
56 |
|
57 |
-
#: lib/common.php:
|
58 |
msgid ""
|
59 |
"These words are excellent stopword material. A word that appears in most of "
|
60 |
"the posts in the database is quite pointless when searching. This is also an "
|
@@ -64,15 +80,19 @@ msgid ""
|
|
64 |
"necessary."
|
65 |
msgstr ""
|
66 |
|
67 |
-
#: lib/common.php:
|
68 |
msgid "Stopword Candidates"
|
69 |
msgstr ""
|
70 |
|
71 |
-
#: lib/common.php:
|
72 |
msgid "Add to stopwords"
|
73 |
msgstr ""
|
74 |
|
75 |
-
#: lib/
|
|
|
|
|
|
|
|
|
76 |
#: lib/tabs/overview-tab.php:56
|
77 |
msgid "Searching"
|
78 |
msgstr ""
|
@@ -298,56 +318,65 @@ msgid ""
|
|
298 |
"search to categories 10, 14 and 17, you can use %2$s and so on."
|
299 |
msgstr ""
|
300 |
|
301 |
-
#: lib/contextual-help.php:
|
302 |
-
|
|
|
|
|
|
|
|
|
|
|
303 |
msgstr ""
|
304 |
|
305 |
#: lib/contextual-help.php:139
|
|
|
|
|
|
|
|
|
306 |
msgid ""
|
307 |
"If your SKUs include hyphens or other punctuation, do note that Relevanssi "
|
308 |
"replaces most punctuation with spaces. That's going to cause issues with SKU "
|
309 |
"searches."
|
310 |
msgstr ""
|
311 |
|
312 |
-
#: lib/contextual-help.php:
|
313 |
#, php-format
|
314 |
msgid ""
|
315 |
"For more details how to fix that issue, see <a href='%s'>WooCommerce tips in "
|
316 |
"Relevanssi user manual</a>."
|
317 |
msgstr ""
|
318 |
|
319 |
-
#: lib/contextual-help.php:
|
320 |
msgid ""
|
321 |
"If you don't want to index products that are out of stock, excluded from the "
|
322 |
"catalog or excluded from the search, there's a product visibility filtering "
|
323 |
"method that is described in the user manual (see link above)."
|
324 |
msgstr ""
|
325 |
|
326 |
-
#: lib/contextual-help.php:
|
327 |
msgid "Exact match bonus"
|
328 |
msgstr ""
|
329 |
|
330 |
-
#: lib/contextual-help.php:
|
331 |
#, php-format
|
332 |
msgid ""
|
333 |
"To adjust the amount of the exact match bonus, you can use the %s filter "
|
334 |
"hook. It works like this:"
|
335 |
msgstr ""
|
336 |
|
337 |
-
#: lib/contextual-help.php:
|
338 |
#, php-format
|
339 |
msgid "The default values are %1$s for titles and %2$s for content."
|
340 |
msgstr ""
|
341 |
|
342 |
-
#: lib/contextual-help.php:
|
343 |
msgid "For more information:"
|
344 |
msgstr ""
|
345 |
|
346 |
-
#: lib/contextual-help.php:
|
347 |
msgid "Plugin knowledge base"
|
348 |
msgstr ""
|
349 |
|
350 |
-
#: lib/contextual-help.php:
|
351 |
msgid "WordPress.org forum"
|
352 |
msgstr ""
|
353 |
|
@@ -376,20 +405,20 @@ msgid ""
|
|
376 |
"extension."
|
377 |
msgstr ""
|
378 |
|
379 |
-
#: lib/init.php:
|
380 |
#: lib/tabs/logging-tab.php:47
|
381 |
msgid "User searches"
|
382 |
msgstr ""
|
383 |
|
384 |
-
#: lib/init.php:
|
385 |
msgid "Admin search"
|
386 |
msgstr ""
|
387 |
|
388 |
-
#: lib/init.php:
|
389 |
msgid "Settings"
|
390 |
msgstr ""
|
391 |
|
392 |
-
#: lib/init.php:
|
393 |
msgid "Go Premium!"
|
394 |
msgstr ""
|
395 |
|
@@ -401,286 +430,286 @@ msgstr ""
|
|
401 |
msgid "Relevanssi Premium Search Options"
|
402 |
msgstr ""
|
403 |
|
404 |
-
#: lib/interface.php:
|
405 |
msgid "Relevanssi User Searches"
|
406 |
msgstr ""
|
407 |
|
408 |
-
#: lib/interface.php:
|
409 |
msgid "Enable query logging to see stats here."
|
410 |
msgstr ""
|
411 |
|
412 |
-
#: lib/interface.php:
|
413 |
msgid "Admin Search"
|
414 |
msgstr ""
|
415 |
|
416 |
-
#: lib/interface.php:
|
417 |
msgid "Logs clear!"
|
418 |
msgstr ""
|
419 |
|
420 |
-
#: lib/interface.php:
|
421 |
msgid "Clearing the logs failed."
|
422 |
msgstr ""
|
423 |
|
424 |
-
#: lib/interface.php:
|
425 |
msgid "Total Searches"
|
426 |
msgstr ""
|
427 |
|
428 |
-
#: lib/interface.php:
|
429 |
msgid "Totals"
|
430 |
msgstr ""
|
431 |
|
432 |
-
#: lib/interface.php:
|
433 |
msgid "Common Queries"
|
434 |
msgstr ""
|
435 |
|
436 |
-
#: lib/interface.php:
|
437 |
#, php-format
|
438 |
msgid ""
|
439 |
"Here you can see the %d most common user search queries, how many times "
|
440 |
"those queries were made and how many results were found for those queries."
|
441 |
msgstr ""
|
442 |
|
443 |
-
#: lib/interface.php:
|
444 |
msgid "Today and yesterday"
|
445 |
msgstr ""
|
446 |
|
447 |
-
#: lib/interface.php:
|
448 |
-
#: lib/interface.php:
|
449 |
#, php-format
|
450 |
msgid "Last %d days"
|
451 |
msgstr ""
|
452 |
|
453 |
-
#: lib/interface.php:
|
454 |
msgid "Unsuccessful Queries"
|
455 |
msgstr ""
|
456 |
|
457 |
-
#: lib/interface.php:
|
458 |
msgid "Last 7 days"
|
459 |
msgstr ""
|
460 |
|
461 |
-
#: lib/interface.php:
|
462 |
msgid "Reset Logs"
|
463 |
msgstr ""
|
464 |
|
465 |
-
#: lib/interface.php:
|
466 |
#, php-format
|
467 |
msgid "To reset the logs, type \"reset\" into the box here %1$s and click %2$s"
|
468 |
msgstr ""
|
469 |
|
470 |
-
#: lib/interface.php:
|
471 |
msgid "Last 30 days"
|
472 |
msgstr ""
|
473 |
|
474 |
-
#: lib/interface.php:
|
475 |
msgid "Forever"
|
476 |
msgstr ""
|
477 |
|
478 |
-
#: lib/interface.php:
|
479 |
msgid "When"
|
480 |
msgstr ""
|
481 |
|
482 |
-
#: lib/interface.php:
|
483 |
msgid "Searches"
|
484 |
msgstr ""
|
485 |
|
486 |
-
#: lib/interface.php:
|
487 |
msgid "Query"
|
488 |
msgstr ""
|
489 |
|
490 |
-
#: lib/interface.php:
|
491 |
msgid "Hits"
|
492 |
msgstr ""
|
493 |
|
494 |
-
#: lib/interface.php:
|
495 |
msgid "Overview"
|
496 |
msgstr ""
|
497 |
|
498 |
-
#: lib/interface.php:
|
499 |
msgid "Indexing"
|
500 |
msgstr ""
|
501 |
|
502 |
-
#: lib/interface.php:
|
503 |
msgid "Attachments"
|
504 |
msgstr ""
|
505 |
|
506 |
-
#: lib/interface.php:
|
507 |
msgid "Logging"
|
508 |
msgstr ""
|
509 |
|
510 |
-
#: lib/interface.php:
|
511 |
msgid "Excerpts and highlights"
|
512 |
msgstr ""
|
513 |
|
514 |
-
#: lib/interface.php:
|
515 |
#: lib/tabs/synonyms-tab.php:30
|
516 |
msgid "Synonyms"
|
517 |
msgstr ""
|
518 |
|
519 |
-
#: lib/interface.php:
|
520 |
msgid "Stopwords"
|
521 |
msgstr ""
|
522 |
|
523 |
-
#: lib/interface.php:
|
524 |
msgid "Redirects"
|
525 |
msgstr ""
|
526 |
|
527 |
-
#: lib/interface.php:
|
528 |
msgid "Related"
|
529 |
msgstr ""
|
530 |
|
531 |
-
#: lib/interface.php:
|
532 |
msgid "Import / Export options"
|
533 |
msgstr ""
|
534 |
|
535 |
-
#: lib/interface.php:
|
536 |
msgid "Click OK to copy Relevanssi options to all subsites"
|
537 |
msgstr ""
|
538 |
|
539 |
-
#: lib/interface.php:
|
540 |
msgid "Are you sure you want to remove all stopwords?"
|
541 |
msgstr ""
|
542 |
|
543 |
-
#: lib/interface.php:
|
544 |
msgid "Wiping out the index..."
|
545 |
msgstr ""
|
546 |
|
547 |
-
#: lib/interface.php:
|
548 |
msgid "Done."
|
549 |
msgstr ""
|
550 |
|
551 |
-
#: lib/interface.php:
|
552 |
msgid "Indexing users..."
|
553 |
msgstr ""
|
554 |
|
555 |
-
#: lib/interface.php:
|
556 |
msgid "Indexing the following taxonomies:"
|
557 |
msgstr ""
|
558 |
|
559 |
-
#: lib/interface.php:
|
560 |
msgid "Indexing attachments..."
|
561 |
msgstr ""
|
562 |
|
563 |
-
#: lib/interface.php:
|
564 |
msgid "Counting posts..."
|
565 |
msgstr ""
|
566 |
|
567 |
-
#: lib/interface.php:
|
568 |
msgid "Counting taxonomy terms..."
|
569 |
msgstr ""
|
570 |
|
571 |
-
#: lib/interface.php:
|
572 |
msgid "Counting users..."
|
573 |
msgstr ""
|
574 |
|
575 |
-
#: lib/interface.php:
|
576 |
msgid "Counting attachments..."
|
577 |
msgstr ""
|
578 |
|
579 |
-
#: lib/interface.php:
|
580 |
msgid "posts found."
|
581 |
msgstr ""
|
582 |
|
583 |
-
#: lib/interface.php:
|
584 |
msgid "taxonomy terms found."
|
585 |
msgstr ""
|
586 |
|
587 |
-
#: lib/interface.php:
|
588 |
msgid "users found."
|
589 |
msgstr ""
|
590 |
|
591 |
-
#: lib/interface.php:
|
592 |
msgid "attachments found."
|
593 |
msgstr ""
|
594 |
|
595 |
-
#: lib/interface.php:
|
596 |
msgid "Taxonomy term indexing is disabled."
|
597 |
msgstr ""
|
598 |
|
599 |
-
#: lib/interface.php:
|
600 |
msgid "User indexing is disabled."
|
601 |
msgstr ""
|
602 |
|
603 |
-
#: lib/interface.php:
|
604 |
msgid "Indexing complete."
|
605 |
msgstr ""
|
606 |
|
607 |
-
#: lib/interface.php:
|
608 |
msgid "posts excluded."
|
609 |
msgstr ""
|
610 |
|
611 |
-
#: lib/interface.php:
|
612 |
msgid "Settings have changed, please save the options before indexing."
|
613 |
msgstr ""
|
614 |
|
615 |
-
#: lib/interface.php:
|
616 |
msgid "Reload the page to refresh the state of the index."
|
617 |
msgstr ""
|
618 |
|
619 |
-
#: lib/interface.php:
|
620 |
msgid "Are you sure you want to delete all attachment content from the index?"
|
621 |
msgstr ""
|
622 |
|
623 |
-
#: lib/interface.php:
|
624 |
msgid "Relevanssi attachment data wiped clean."
|
625 |
msgstr ""
|
626 |
|
627 |
-
#: lib/interface.php:
|
628 |
msgid "hour"
|
629 |
msgstr ""
|
630 |
|
631 |
-
#: lib/interface.php:
|
632 |
msgid "hours"
|
633 |
msgstr ""
|
634 |
|
635 |
-
#: lib/interface.php:
|
636 |
msgid "about"
|
637 |
msgstr ""
|
638 |
|
639 |
-
#: lib/interface.php:
|
640 |
msgid "about an hour"
|
641 |
msgstr ""
|
642 |
|
643 |
-
#: lib/interface.php:
|
644 |
msgid "about an hour and a half"
|
645 |
msgstr ""
|
646 |
|
647 |
-
#: lib/interface.php:
|
648 |
msgid "minute"
|
649 |
msgstr ""
|
650 |
|
651 |
-
#: lib/interface.php:
|
652 |
msgid "minutes"
|
653 |
msgstr ""
|
654 |
|
655 |
-
#: lib/interface.php:
|
656 |
msgid "less than a minute"
|
657 |
msgstr ""
|
658 |
|
659 |
-
#: lib/interface.php:
|
660 |
msgid "we're done!"
|
661 |
msgstr ""
|
662 |
|
663 |
-
#: lib/interface.php:
|
664 |
msgid "Tag weight"
|
665 |
msgstr ""
|
666 |
|
667 |
-
#: lib/interface.php:
|
668 |
msgid "Category weight"
|
669 |
msgstr ""
|
670 |
|
671 |
-
#: lib/log.php:
|
672 |
msgid "Logged seaches"
|
673 |
msgstr ""
|
674 |
|
675 |
-
#: lib/log.php:
|
676 |
msgid "Time"
|
677 |
msgstr ""
|
678 |
|
679 |
-
#: lib/log.php:
|
680 |
msgid "Hits found"
|
681 |
msgstr ""
|
682 |
|
683 |
-
#: lib/log.php:
|
684 |
msgid "IP address"
|
685 |
msgstr ""
|
686 |
|
@@ -725,35 +754,39 @@ msgstr ""
|
|
725 |
msgid "Relevanssi Search Logs"
|
726 |
msgstr ""
|
727 |
|
728 |
-
#: lib/
|
|
|
|
|
|
|
|
|
729 |
#, php-format
|
730 |
msgid "Successfully added %1$d/%2$d terms to stopwords!"
|
731 |
msgstr ""
|
732 |
|
733 |
-
#: lib/stopwords.php:
|
734 |
#, php-format
|
735 |
msgid "Term '%s' added to stopwords!"
|
736 |
msgstr ""
|
737 |
|
738 |
-
#: lib/stopwords.php:
|
739 |
#, php-format
|
740 |
msgid "Couldn't add term '%s' to stopwords!"
|
741 |
msgstr ""
|
742 |
|
743 |
-
#: lib/stopwords.php:
|
744 |
msgid "All stopwords removed! Remember to re-index."
|
745 |
msgstr ""
|
746 |
|
747 |
-
#: lib/stopwords.php:
|
748 |
msgid "There was a problem, and stopwords couldn't be removed."
|
749 |
msgstr ""
|
750 |
|
751 |
-
#: lib/stopwords.php:
|
752 |
#, php-format
|
753 |
msgid "Term '%s' removed from stopwords! Re-index to get it back to index."
|
754 |
msgstr ""
|
755 |
|
756 |
-
#: lib/stopwords.php:
|
757 |
#, php-format
|
758 |
msgid "Couldn't remove term '%s' from stopwords!"
|
759 |
msgstr ""
|
@@ -1421,20 +1454,26 @@ msgstr ""
|
|
1421 |
msgid "How many days of logs to keep in the database."
|
1422 |
msgstr ""
|
1423 |
|
1424 |
-
#: lib/tabs/logging-tab.php:
|
|
|
|
|
|
|
|
|
|
|
|
|
1425 |
#, php-format
|
1426 |
msgid " Set to %d for no trimming."
|
1427 |
msgstr ""
|
1428 |
|
1429 |
-
#: lib/tabs/logging-tab.php:
|
1430 |
msgid "Export logs"
|
1431 |
msgstr ""
|
1432 |
|
1433 |
-
#: lib/tabs/logging-tab.php:
|
1434 |
msgid "Export the log as a CSV file"
|
1435 |
msgstr ""
|
1436 |
|
1437 |
-
#: lib/tabs/logging-tab.php:
|
1438 |
msgid "Push the button to export the search log as a CSV file."
|
1439 |
msgstr ""
|
1440 |
|
@@ -1747,7 +1786,7 @@ msgstr ""
|
|
1747 |
msgid "Whole words"
|
1748 |
msgstr ""
|
1749 |
|
1750 |
-
#: lib/tabs/searching-tab.php:120
|
1751 |
msgid "Partial words"
|
1752 |
msgstr ""
|
1753 |
|
@@ -1755,13 +1794,24 @@ msgstr ""
|
|
1755 |
msgid "Partial words if no hits for whole words"
|
1756 |
msgstr ""
|
1757 |
|
1758 |
-
#: lib/tabs/searching-tab.php:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1759 |
msgid ""
|
1760 |
"Whole words means Relevanssi only finds posts that include the whole search "
|
1761 |
"term."
|
1762 |
msgstr ""
|
1763 |
|
1764 |
-
#: lib/tabs/searching-tab.php:
|
1765 |
msgid ""
|
1766 |
"Partial words also includes cases where the word in the index begins or ends "
|
1767 |
"with the search term (searching for 'ana' will match 'anaconda' or 'banana', "
|
@@ -1769,46 +1819,46 @@ msgid ""
|
|
1769 |
"words."
|
1770 |
msgstr ""
|
1771 |
|
1772 |
-
#: lib/tabs/searching-tab.php:
|
1773 |
msgid "Weights"
|
1774 |
msgstr ""
|
1775 |
|
1776 |
-
#: lib/tabs/searching-tab.php:
|
1777 |
msgid ""
|
1778 |
"All the weights in the table are multipliers. To increase the weight of an "
|
1779 |
"element, use a higher number. To make an element less significant, use a "
|
1780 |
"number lower than 1."
|
1781 |
msgstr ""
|
1782 |
|
1783 |
-
#: lib/tabs/searching-tab.php:
|
1784 |
msgid "Element"
|
1785 |
msgstr ""
|
1786 |
|
1787 |
-
#: lib/tabs/searching-tab.php:
|
1788 |
msgid "Weight"
|
1789 |
msgstr ""
|
1790 |
|
1791 |
-
#: lib/tabs/searching-tab.php:
|
1792 |
msgid "Content"
|
1793 |
msgstr ""
|
1794 |
|
1795 |
-
#: lib/tabs/searching-tab.php:
|
1796 |
msgid "Titles"
|
1797 |
msgstr ""
|
1798 |
|
1799 |
-
#: lib/tabs/searching-tab.php:
|
1800 |
msgid "Comment text"
|
1801 |
msgstr ""
|
1802 |
|
1803 |
-
#: lib/tabs/searching-tab.php:
|
1804 |
msgid "Boost exact matches"
|
1805 |
msgstr ""
|
1806 |
|
1807 |
-
#: lib/tabs/searching-tab.php:
|
1808 |
msgid "Give boost to exact matches."
|
1809 |
msgstr ""
|
1810 |
|
1811 |
-
#: lib/tabs/searching-tab.php:
|
1812 |
#, php-format
|
1813 |
msgid ""
|
1814 |
"If you enable this option, matches where the search query appears in title "
|
@@ -1816,144 +1866,156 @@ msgid ""
|
|
1816 |
"use the %s filter hook. See Help for more details."
|
1817 |
msgstr ""
|
1818 |
|
1819 |
-
#: lib/tabs/searching-tab.php:
|
1820 |
msgid "WPML"
|
1821 |
msgstr ""
|
1822 |
|
1823 |
-
#: lib/tabs/searching-tab.php:
|
1824 |
msgid "Limit results to current language."
|
1825 |
msgstr ""
|
1826 |
|
1827 |
-
#: lib/tabs/searching-tab.php:
|
1828 |
msgid ""
|
1829 |
"Enabling this option will restrict the results to the currently active "
|
1830 |
"language. If the option is disabled, results will include posts in all "
|
1831 |
"languages."
|
1832 |
msgstr ""
|
1833 |
|
1834 |
-
#: lib/tabs/searching-tab.php:
|
1835 |
msgid "Polylang"
|
1836 |
msgstr ""
|
1837 |
|
1838 |
-
#: lib/tabs/searching-tab.php:
|
1839 |
msgid "Allow results from all languages."
|
1840 |
msgstr ""
|
1841 |
|
1842 |
-
#: lib/tabs/searching-tab.php:
|
1843 |
msgid ""
|
1844 |
"By default Polylang restricts the search to the current language. Enabling "
|
1845 |
"this option will lift this restriction."
|
1846 |
msgstr ""
|
1847 |
|
1848 |
-
#: lib/tabs/searching-tab.php:
|
1849 |
msgid "Use Relevanssi for admin searches."
|
1850 |
msgstr ""
|
1851 |
|
1852 |
-
#: lib/tabs/searching-tab.php:
|
1853 |
msgid ""
|
1854 |
"If checked, Relevanssi will be used for searches in the admin interface. The "
|
1855 |
"page search doesn't use Relevanssi, because WordPress works like that."
|
1856 |
msgstr ""
|
1857 |
|
1858 |
-
#: lib/tabs/searching-tab.php:
|
1859 |
#, php-format
|
1860 |
msgid "Respect %s"
|
1861 |
msgstr ""
|
1862 |
|
1863 |
-
#: lib/tabs/searching-tab.php:
|
1864 |
msgid "Respect exclude_from_search for custom post types"
|
1865 |
msgstr ""
|
1866 |
|
1867 |
-
#: lib/tabs/searching-tab.php:
|
1868 |
#, php-format
|
1869 |
msgid "Respect %s for custom post types"
|
1870 |
msgstr ""
|
1871 |
|
1872 |
-
#: lib/tabs/searching-tab.php:
|
1873 |
msgid ""
|
1874 |
"If checked, Relevanssi won't display posts of custom post types that have "
|
1875 |
"'exclude_from_search' set to true."
|
1876 |
msgstr ""
|
1877 |
|
1878 |
-
#: lib/tabs/searching-tab.php:
|
1879 |
msgid ""
|
1880 |
"You probably should uncheck this option, because you've set Relevanssi to "
|
1881 |
"index the following non-public post types:"
|
1882 |
msgstr ""
|
1883 |
|
1884 |
-
#: lib/tabs/searching-tab.php:
|
1885 |
msgid "Throttle searches"
|
1886 |
msgstr ""
|
1887 |
|
1888 |
-
#: lib/tabs/searching-tab.php:
|
1889 |
msgid "Throttling the search does not work when sorting the posts by date."
|
1890 |
msgstr ""
|
1891 |
|
1892 |
-
#: lib/tabs/searching-tab.php:
|
1893 |
msgid "Throttle searches."
|
1894 |
msgstr ""
|
1895 |
|
1896 |
-
#: lib/tabs/searching-tab.php:
|
1897 |
msgid "Your database is so small that you don't need to enable this."
|
1898 |
msgstr ""
|
1899 |
|
1900 |
-
#: lib/tabs/searching-tab.php:
|
1901 |
msgid ""
|
1902 |
"If this option is checked, Relevanssi will limit search results to at most "
|
1903 |
"500 results per term. This will improve performance, but may cause some "
|
1904 |
"relevant documents to go unfound. See Help for more details."
|
1905 |
msgstr ""
|
1906 |
|
1907 |
-
#: lib/tabs/searching-tab.php:
|
1908 |
msgid "Category restriction"
|
1909 |
msgstr ""
|
1910 |
|
1911 |
-
#: lib/tabs/searching-tab.php:
|
1912 |
msgid ""
|
1913 |
"You can restrict search results to a category for all searches. For "
|
1914 |
"restricting on a per-search basis and more options (eg. tag restrictions), "
|
1915 |
"see Help."
|
1916 |
msgstr ""
|
1917 |
|
1918 |
-
#: lib/tabs/searching-tab.php:
|
1919 |
msgid "Category exclusion"
|
1920 |
msgstr ""
|
1921 |
|
1922 |
-
#: lib/tabs/searching-tab.php:
|
1923 |
msgid ""
|
1924 |
"Posts in these categories are not included in search results. To exclude the "
|
1925 |
"posts completely from the index, see Help."
|
1926 |
msgstr ""
|
1927 |
|
1928 |
-
#: lib/tabs/searching-tab.php:
|
1929 |
msgid "Post exclusion"
|
1930 |
msgstr ""
|
1931 |
|
1932 |
-
#: lib/tabs/searching-tab.php:
|
1933 |
msgid ""
|
1934 |
"Enter a comma-separated list of post or page ID's to exclude those pages "
|
1935 |
"from the search results."
|
1936 |
msgstr ""
|
1937 |
|
1938 |
-
#: lib/tabs/searching-tab.php:
|
1939 |
msgid ""
|
1940 |
"With Relevanssi Premium, it's better to use the check box on post edit "
|
1941 |
"pages. That will remove the posts completely from the index, and will work "
|
1942 |
"with multisite searches unlike this setting."
|
1943 |
msgstr ""
|
1944 |
|
1945 |
-
#: lib/tabs/stopwords-tab.php:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1946 |
msgid ""
|
1947 |
"Enter a word here to add it to the list of stopwords. The word will "
|
1948 |
"automatically be removed from the index, so re-indexing is not necessary. "
|
1949 |
"You can enter many words at the same time, separate words with commas."
|
1950 |
msgstr ""
|
1951 |
|
1952 |
-
#: lib/tabs/stopwords-tab.php:
|
1953 |
msgid "Stopword(s) to add"
|
1954 |
msgstr ""
|
1955 |
|
1956 |
-
#: lib/tabs/stopwords-tab.php:
|
1957 |
msgid ""
|
1958 |
"Here's a list of stopwords in the database. Click a word to remove it from "
|
1959 |
"stopwords. Removing stopwords won't automatically return them to index, so "
|
@@ -1961,15 +2023,15 @@ msgid ""
|
|
1961 |
"back to index."
|
1962 |
msgstr ""
|
1963 |
|
1964 |
-
#: lib/tabs/stopwords-tab.php:
|
1965 |
msgid "Current stopwords"
|
1966 |
msgstr ""
|
1967 |
|
1968 |
-
#: lib/tabs/stopwords-tab.php:
|
1969 |
msgid "Exportable list of stopwords"
|
1970 |
msgstr ""
|
1971 |
|
1972 |
-
#: lib/tabs/stopwords-tab.php:
|
1973 |
msgid ""
|
1974 |
"You can copy the list of stopwords here if you want to back up the list, "
|
1975 |
"copy it to a different blog or otherwise need the list."
|
2 |
msgstr ""
|
3 |
"Project-Id-Version: Relevanssi\n"
|
4 |
"Report-Msgid-Bugs-To: \n"
|
5 |
+
"POT-Creation-Date: 2019-05-27 11:38+0300\n"
|
6 |
"PO-Revision-Date: \n"
|
7 |
"Last-Translator: Mikko Saari <mikko@mikkosaari.fi>\n"
|
8 |
"Language-Team: \n"
|
12 |
"Content-Transfer-Encoding: 8bit\n"
|
13 |
"X-Poedit-KeywordsList: _e;__;esc_html__;esc_html_e;_n\n"
|
14 |
"X-Poedit-Basepath: .\n"
|
15 |
+
"X-Generator: Poedit 2.2.3\n"
|
16 |
"X-Poedit-SearchPath-0: .\n"
|
17 |
"X-Poedit-SearchPath-1: lib\n"
|
18 |
|
21 |
msgid "Indexed %1$d post (total %2$d), processed %3$d / %4$d."
|
22 |
msgstr ""
|
23 |
|
24 |
+
#: lib/admin-ajax.php:199
|
25 |
msgid "Results"
|
26 |
msgstr ""
|
27 |
|
28 |
+
#: lib/admin-ajax.php:201
|
29 |
#, php-format
|
30 |
msgid "Found a total of %1$d posts, showing %2$d posts from offset %3$s."
|
31 |
msgstr ""
|
32 |
|
33 |
+
#: lib/admin-ajax.php:203
|
34 |
+
msgid "Previous page"
|
35 |
+
msgstr ""
|
36 |
+
|
37 |
+
#: lib/admin-ajax.php:206
|
38 |
+
msgid "Next page"
|
39 |
+
msgstr ""
|
40 |
+
|
41 |
+
#: lib/admin-ajax.php:210
|
42 |
msgid "Score:"
|
43 |
msgstr ""
|
44 |
|
45 |
+
#: lib/admin-ajax.php:232
|
46 |
+
msgid "View"
|
47 |
+
msgstr ""
|
48 |
+
|
49 |
+
#: lib/admin-ajax.php:233
|
50 |
+
msgid "Edit"
|
51 |
+
msgstr ""
|
52 |
+
|
53 |
+
#: lib/admin-ajax.php:276
|
54 |
msgid "Query variables"
|
55 |
msgstr ""
|
56 |
|
57 |
+
#: lib/admin-ajax.php:322
|
58 |
msgid "Filters"
|
59 |
msgstr ""
|
60 |
|
61 |
+
#: lib/admin-ajax.php:323
|
62 |
msgid "show"
|
63 |
msgstr ""
|
64 |
|
65 |
+
#: lib/admin-ajax.php:324
|
66 |
msgid "hide"
|
67 |
msgstr ""
|
68 |
|
69 |
+
#: lib/common.php:1598
|
70 |
msgid "25 most common words in the index"
|
71 |
msgstr ""
|
72 |
|
73 |
+
#: lib/common.php:1599
|
74 |
msgid ""
|
75 |
"These words are excellent stopword material. A word that appears in most of "
|
76 |
"the posts in the database is quite pointless when searching. This is also an "
|
80 |
"necessary."
|
81 |
msgstr ""
|
82 |
|
83 |
+
#: lib/common.php:1605
|
84 |
msgid "Stopword Candidates"
|
85 |
msgstr ""
|
86 |
|
87 |
+
#: lib/common.php:1610
|
88 |
msgid "Add to stopwords"
|
89 |
msgstr ""
|
90 |
|
91 |
+
#: lib/common.php:1613
|
92 |
+
msgid "Add to content stopwords"
|
93 |
+
msgstr ""
|
94 |
+
|
95 |
+
#: lib/contextual-help.php:24 lib/interface.php:810
|
96 |
#: lib/tabs/overview-tab.php:56
|
97 |
msgid "Searching"
|
98 |
msgstr ""
|
318 |
"search to categories 10, 14 and 17, you can use %2$s and so on."
|
319 |
msgstr ""
|
320 |
|
321 |
+
#: lib/contextual-help.php:134
|
322 |
+
#, php-format
|
323 |
+
msgid ""
|
324 |
+
"You can use the %1$s parameter to add a taxonomy dropdown to the search "
|
325 |
+
"form. Just use the name of the taxonomy, like %2$s. This works best with "
|
326 |
+
"hierarchical taxonomies like categories with relatively few options "
|
327 |
+
"available."
|
328 |
msgstr ""
|
329 |
|
330 |
#: lib/contextual-help.php:139
|
331 |
+
msgid "WooCommerce"
|
332 |
+
msgstr ""
|
333 |
+
|
334 |
+
#: lib/contextual-help.php:141
|
335 |
msgid ""
|
336 |
"If your SKUs include hyphens or other punctuation, do note that Relevanssi "
|
337 |
"replaces most punctuation with spaces. That's going to cause issues with SKU "
|
338 |
"searches."
|
339 |
msgstr ""
|
340 |
|
341 |
+
#: lib/contextual-help.php:143
|
342 |
#, php-format
|
343 |
msgid ""
|
344 |
"For more details how to fix that issue, see <a href='%s'>WooCommerce tips in "
|
345 |
"Relevanssi user manual</a>."
|
346 |
msgstr ""
|
347 |
|
348 |
+
#: lib/contextual-help.php:144
|
349 |
msgid ""
|
350 |
"If you don't want to index products that are out of stock, excluded from the "
|
351 |
"catalog or excluded from the search, there's a product visibility filtering "
|
352 |
"method that is described in the user manual (see link above)."
|
353 |
msgstr ""
|
354 |
|
355 |
+
#: lib/contextual-help.php:149
|
356 |
msgid "Exact match bonus"
|
357 |
msgstr ""
|
358 |
|
359 |
+
#: lib/contextual-help.php:152
|
360 |
#, php-format
|
361 |
msgid ""
|
362 |
"To adjust the amount of the exact match bonus, you can use the %s filter "
|
363 |
"hook. It works like this:"
|
364 |
msgstr ""
|
365 |
|
366 |
+
#: lib/contextual-help.php:158
|
367 |
#, php-format
|
368 |
msgid "The default values are %1$s for titles and %2$s for content."
|
369 |
msgstr ""
|
370 |
|
371 |
+
#: lib/contextual-help.php:161
|
372 |
msgid "For more information:"
|
373 |
msgstr ""
|
374 |
|
375 |
+
#: lib/contextual-help.php:162
|
376 |
msgid "Plugin knowledge base"
|
377 |
msgstr ""
|
378 |
|
379 |
+
#: lib/contextual-help.php:163
|
380 |
msgid "WordPress.org forum"
|
381 |
msgstr ""
|
382 |
|
405 |
"extension."
|
406 |
msgstr ""
|
407 |
|
408 |
+
#: lib/init.php:190 lib/init.php:191 lib/interface.php:472
|
409 |
#: lib/tabs/logging-tab.php:47
|
410 |
msgid "User searches"
|
411 |
msgstr ""
|
412 |
|
413 |
+
#: lib/init.php:202 lib/init.php:203 lib/tabs/searching-tab.php:248
|
414 |
msgid "Admin search"
|
415 |
msgstr ""
|
416 |
|
417 |
+
#: lib/init.php:394
|
418 |
msgid "Settings"
|
419 |
msgstr ""
|
420 |
|
421 |
+
#: lib/init.php:397
|
422 |
msgid "Go Premium!"
|
423 |
msgstr ""
|
424 |
|
430 |
msgid "Relevanssi Premium Search Options"
|
431 |
msgstr ""
|
432 |
|
433 |
+
#: lib/interface.php:474
|
434 |
msgid "Relevanssi User Searches"
|
435 |
msgstr ""
|
436 |
|
437 |
+
#: lib/interface.php:497
|
438 |
msgid "Enable query logging to see stats here."
|
439 |
msgstr ""
|
440 |
|
441 |
+
#: lib/interface.php:509
|
442 |
msgid "Admin Search"
|
443 |
msgstr ""
|
444 |
|
445 |
+
#: lib/interface.php:539
|
446 |
msgid "Logs clear!"
|
447 |
msgstr ""
|
448 |
|
449 |
+
#: lib/interface.php:541
|
450 |
msgid "Clearing the logs failed."
|
451 |
msgstr ""
|
452 |
|
453 |
+
#: lib/interface.php:575
|
454 |
msgid "Total Searches"
|
455 |
msgstr ""
|
456 |
|
457 |
+
#: lib/interface.php:577
|
458 |
msgid "Totals"
|
459 |
msgstr ""
|
460 |
|
461 |
+
#: lib/interface.php:581
|
462 |
msgid "Common Queries"
|
463 |
msgstr ""
|
464 |
|
465 |
+
#: lib/interface.php:591
|
466 |
#, php-format
|
467 |
msgid ""
|
468 |
"Here you can see the %d most common user search queries, how many times "
|
469 |
"those queries were made and how many results were found for those queries."
|
470 |
msgstr ""
|
471 |
|
472 |
+
#: lib/interface.php:595 lib/interface.php:617 lib/interface.php:658
|
473 |
msgid "Today and yesterday"
|
474 |
msgstr ""
|
475 |
|
476 |
+
#: lib/interface.php:598 lib/interface.php:604 lib/interface.php:609
|
477 |
+
#: lib/interface.php:626
|
478 |
#, php-format
|
479 |
msgid "Last %d days"
|
480 |
msgstr ""
|
481 |
|
482 |
+
#: lib/interface.php:614
|
483 |
msgid "Unsuccessful Queries"
|
484 |
msgstr ""
|
485 |
|
486 |
+
#: lib/interface.php:621 lib/interface.php:659
|
487 |
msgid "Last 7 days"
|
488 |
msgstr ""
|
489 |
|
490 |
+
#: lib/interface.php:632
|
491 |
msgid "Reset Logs"
|
492 |
msgstr ""
|
493 |
|
494 |
+
#: lib/interface.php:636
|
495 |
#, php-format
|
496 |
msgid "To reset the logs, type \"reset\" into the box here %1$s and click %2$s"
|
497 |
msgstr ""
|
498 |
|
499 |
+
#: lib/interface.php:660
|
500 |
msgid "Last 30 days"
|
501 |
msgstr ""
|
502 |
|
503 |
+
#: lib/interface.php:661
|
504 |
msgid "Forever"
|
505 |
msgstr ""
|
506 |
|
507 |
+
#: lib/interface.php:669
|
508 |
msgid "When"
|
509 |
msgstr ""
|
510 |
|
511 |
+
#: lib/interface.php:669
|
512 |
msgid "Searches"
|
513 |
msgstr ""
|
514 |
|
515 |
+
#: lib/interface.php:726 lib/log.php:167
|
516 |
msgid "Query"
|
517 |
msgstr ""
|
518 |
|
519 |
+
#: lib/interface.php:726
|
520 |
msgid "Hits"
|
521 |
msgstr ""
|
522 |
|
523 |
+
#: lib/interface.php:807
|
524 |
msgid "Overview"
|
525 |
msgstr ""
|
526 |
|
527 |
+
#: lib/interface.php:808 lib/tabs/overview-tab.php:44
|
528 |
msgid "Indexing"
|
529 |
msgstr ""
|
530 |
|
531 |
+
#: lib/interface.php:809
|
532 |
msgid "Attachments"
|
533 |
msgstr ""
|
534 |
|
535 |
+
#: lib/interface.php:811
|
536 |
msgid "Logging"
|
537 |
msgstr ""
|
538 |
|
539 |
+
#: lib/interface.php:812 lib/tabs/overview-tab.php:60
|
540 |
msgid "Excerpts and highlights"
|
541 |
msgstr ""
|
542 |
|
543 |
+
#: lib/interface.php:813 lib/tabs/synonyms-tab.php:25
|
544 |
#: lib/tabs/synonyms-tab.php:30
|
545 |
msgid "Synonyms"
|
546 |
msgstr ""
|
547 |
|
548 |
+
#: lib/interface.php:814 lib/tabs/stopwords-tab.php:18
|
549 |
msgid "Stopwords"
|
550 |
msgstr ""
|
551 |
|
552 |
+
#: lib/interface.php:815 lib/tabs/redirects-tab.php:18
|
553 |
msgid "Redirects"
|
554 |
msgstr ""
|
555 |
|
556 |
+
#: lib/interface.php:817
|
557 |
msgid "Related"
|
558 |
msgstr ""
|
559 |
|
560 |
+
#: lib/interface.php:818
|
561 |
msgid "Import / Export options"
|
562 |
msgstr ""
|
563 |
|
564 |
+
#: lib/interface.php:937
|
565 |
msgid "Click OK to copy Relevanssi options to all subsites"
|
566 |
msgstr ""
|
567 |
|
568 |
+
#: lib/interface.php:938
|
569 |
msgid "Are you sure you want to remove all stopwords?"
|
570 |
msgstr ""
|
571 |
|
572 |
+
#: lib/interface.php:939
|
573 |
msgid "Wiping out the index..."
|
574 |
msgstr ""
|
575 |
|
576 |
+
#: lib/interface.php:940
|
577 |
msgid "Done."
|
578 |
msgstr ""
|
579 |
|
580 |
+
#: lib/interface.php:941
|
581 |
msgid "Indexing users..."
|
582 |
msgstr ""
|
583 |
|
584 |
+
#: lib/interface.php:942
|
585 |
msgid "Indexing the following taxonomies:"
|
586 |
msgstr ""
|
587 |
|
588 |
+
#: lib/interface.php:943
|
589 |
msgid "Indexing attachments..."
|
590 |
msgstr ""
|
591 |
|
592 |
+
#: lib/interface.php:944
|
593 |
msgid "Counting posts..."
|
594 |
msgstr ""
|
595 |
|
596 |
+
#: lib/interface.php:945
|
597 |
msgid "Counting taxonomy terms..."
|
598 |
msgstr ""
|
599 |
|
600 |
+
#: lib/interface.php:946
|
601 |
msgid "Counting users..."
|
602 |
msgstr ""
|
603 |
|
604 |
+
#: lib/interface.php:947
|
605 |
msgid "Counting attachments..."
|
606 |
msgstr ""
|
607 |
|
608 |
+
#: lib/interface.php:948
|
609 |
msgid "posts found."
|
610 |
msgstr ""
|
611 |
|
612 |
+
#: lib/interface.php:949
|
613 |
msgid "taxonomy terms found."
|
614 |
msgstr ""
|
615 |
|
616 |
+
#: lib/interface.php:950
|
617 |
msgid "users found."
|
618 |
msgstr ""
|
619 |
|
620 |
+
#: lib/interface.php:951
|
621 |
msgid "attachments found."
|
622 |
msgstr ""
|
623 |
|
624 |
+
#: lib/interface.php:952
|
625 |
msgid "Taxonomy term indexing is disabled."
|
626 |
msgstr ""
|
627 |
|
628 |
+
#: lib/interface.php:953
|
629 |
msgid "User indexing is disabled."
|
630 |
msgstr ""
|
631 |
|
632 |
+
#: lib/interface.php:954
|
633 |
msgid "Indexing complete."
|
634 |
msgstr ""
|
635 |
|
636 |
+
#: lib/interface.php:955
|
637 |
msgid "posts excluded."
|
638 |
msgstr ""
|
639 |
|
640 |
+
#: lib/interface.php:956
|
641 |
msgid "Settings have changed, please save the options before indexing."
|
642 |
msgstr ""
|
643 |
|
644 |
+
#: lib/interface.php:957
|
645 |
msgid "Reload the page to refresh the state of the index."
|
646 |
msgstr ""
|
647 |
|
648 |
+
#: lib/interface.php:958
|
649 |
msgid "Are you sure you want to delete all attachment content from the index?"
|
650 |
msgstr ""
|
651 |
|
652 |
+
#: lib/interface.php:959
|
653 |
msgid "Relevanssi attachment data wiped clean."
|
654 |
msgstr ""
|
655 |
|
656 |
+
#: lib/interface.php:960
|
657 |
msgid "hour"
|
658 |
msgstr ""
|
659 |
|
660 |
+
#: lib/interface.php:961
|
661 |
msgid "hours"
|
662 |
msgstr ""
|
663 |
|
664 |
+
#: lib/interface.php:962
|
665 |
msgid "about"
|
666 |
msgstr ""
|
667 |
|
668 |
+
#: lib/interface.php:963
|
669 |
msgid "about an hour"
|
670 |
msgstr ""
|
671 |
|
672 |
+
#: lib/interface.php:964
|
673 |
msgid "about an hour and a half"
|
674 |
msgstr ""
|
675 |
|
676 |
+
#: lib/interface.php:965
|
677 |
msgid "minute"
|
678 |
msgstr ""
|
679 |
|
680 |
+
#: lib/interface.php:966
|
681 |
msgid "minutes"
|
682 |
msgstr ""
|
683 |
|
684 |
+
#: lib/interface.php:967
|
685 |
msgid "less than a minute"
|
686 |
msgstr ""
|
687 |
|
688 |
+
#: lib/interface.php:968
|
689 |
msgid "we're done!"
|
690 |
msgstr ""
|
691 |
|
692 |
+
#: lib/interface.php:1000
|
693 |
msgid "Tag weight"
|
694 |
msgstr ""
|
695 |
|
696 |
+
#: lib/interface.php:1008
|
697 |
msgid "Category weight"
|
698 |
msgstr ""
|
699 |
|
700 |
+
#: lib/log.php:160
|
701 |
msgid "Logged seaches"
|
702 |
msgstr ""
|
703 |
|
704 |
+
#: lib/log.php:163
|
705 |
msgid "Time"
|
706 |
msgstr ""
|
707 |
|
708 |
+
#: lib/log.php:171
|
709 |
msgid "Hits found"
|
710 |
msgstr ""
|
711 |
|
712 |
+
#: lib/log.php:175
|
713 |
msgid "IP address"
|
714 |
msgstr ""
|
715 |
|
754 |
msgid "Relevanssi Search Logs"
|
755 |
msgstr ""
|
756 |
|
757 |
+
#: lib/shortcodes.php:128
|
758 |
+
msgid "None"
|
759 |
+
msgstr ""
|
760 |
+
|
761 |
+
#: lib/stopwords.php:96
|
762 |
#, php-format
|
763 |
msgid "Successfully added %1$d/%2$d terms to stopwords!"
|
764 |
msgstr ""
|
765 |
|
766 |
+
#: lib/stopwords.php:107
|
767 |
#, php-format
|
768 |
msgid "Term '%s' added to stopwords!"
|
769 |
msgstr ""
|
770 |
|
771 |
+
#: lib/stopwords.php:110
|
772 |
#, php-format
|
773 |
msgid "Couldn't add term '%s' to stopwords!"
|
774 |
msgstr ""
|
775 |
|
776 |
+
#: lib/stopwords.php:162
|
777 |
msgid "All stopwords removed! Remember to re-index."
|
778 |
msgstr ""
|
779 |
|
780 |
+
#: lib/stopwords.php:164
|
781 |
msgid "There was a problem, and stopwords couldn't be removed."
|
782 |
msgstr ""
|
783 |
|
784 |
+
#: lib/stopwords.php:187
|
785 |
#, php-format
|
786 |
msgid "Term '%s' removed from stopwords! Re-index to get it back to index."
|
787 |
msgstr ""
|
788 |
|
789 |
+
#: lib/stopwords.php:193
|
790 |
#, php-format
|
791 |
msgid "Couldn't remove term '%s' from stopwords!"
|
792 |
msgstr ""
|
1454 |
msgid "How many days of logs to keep in the database."
|
1455 |
msgstr ""
|
1456 |
|
1457 |
+
#: lib/tabs/logging-tab.php:91
|
1458 |
+
msgid ""
|
1459 |
+
"Big log database table will eventually start to slow down the search, so "
|
1460 |
+
"it's a good idea to use some level of automatic log trimming."
|
1461 |
+
msgstr ""
|
1462 |
+
|
1463 |
+
#: lib/tabs/logging-tab.php:96
|
1464 |
#, php-format
|
1465 |
msgid " Set to %d for no trimming."
|
1466 |
msgstr ""
|
1467 |
|
1468 |
+
#: lib/tabs/logging-tab.php:105
|
1469 |
msgid "Export logs"
|
1470 |
msgstr ""
|
1471 |
|
1472 |
+
#: lib/tabs/logging-tab.php:108
|
1473 |
msgid "Export the log as a CSV file"
|
1474 |
msgstr ""
|
1475 |
|
1476 |
+
#: lib/tabs/logging-tab.php:109
|
1477 |
msgid "Push the button to export the search log as a CSV file."
|
1478 |
msgstr ""
|
1479 |
|
1786 |
msgid "Whole words"
|
1787 |
msgstr ""
|
1788 |
|
1789 |
+
#: lib/tabs/searching-tab.php:120 lib/tabs/searching-tab.php:125
|
1790 |
msgid "Partial words"
|
1791 |
msgstr ""
|
1792 |
|
1794 |
msgid "Partial words if no hits for whole words"
|
1795 |
msgstr ""
|
1796 |
|
1797 |
+
#: lib/tabs/searching-tab.php:125
|
1798 |
+
#, php-format
|
1799 |
+
msgid ""
|
1800 |
+
"Choosing the \"%1$s\" option may lead to unexpected results. Most of the "
|
1801 |
+
"time the \"%2$s\" option is the better choice."
|
1802 |
+
msgstr ""
|
1803 |
+
|
1804 |
+
#: lib/tabs/searching-tab.php:125
|
1805 |
+
msgid "Partial words if not hits for whole words"
|
1806 |
+
msgstr ""
|
1807 |
+
|
1808 |
+
#: lib/tabs/searching-tab.php:127
|
1809 |
msgid ""
|
1810 |
"Whole words means Relevanssi only finds posts that include the whole search "
|
1811 |
"term."
|
1812 |
msgstr ""
|
1813 |
|
1814 |
+
#: lib/tabs/searching-tab.php:128
|
1815 |
msgid ""
|
1816 |
"Partial words also includes cases where the word in the index begins or ends "
|
1817 |
"with the search term (searching for 'ana' will match 'anaconda' or 'banana', "
|
1819 |
"words."
|
1820 |
msgstr ""
|
1821 |
|
1822 |
+
#: lib/tabs/searching-tab.php:133
|
1823 |
msgid "Weights"
|
1824 |
msgstr ""
|
1825 |
|
1826 |
+
#: lib/tabs/searching-tab.php:136
|
1827 |
msgid ""
|
1828 |
"All the weights in the table are multipliers. To increase the weight of an "
|
1829 |
"element, use a higher number. To make an element less significant, use a "
|
1830 |
"number lower than 1."
|
1831 |
msgstr ""
|
1832 |
|
1833 |
+
#: lib/tabs/searching-tab.php:140
|
1834 |
msgid "Element"
|
1835 |
msgstr ""
|
1836 |
|
1837 |
+
#: lib/tabs/searching-tab.php:141
|
1838 |
msgid "Weight"
|
1839 |
msgstr ""
|
1840 |
|
1841 |
+
#: lib/tabs/searching-tab.php:146
|
1842 |
msgid "Content"
|
1843 |
msgstr ""
|
1844 |
|
1845 |
+
#: lib/tabs/searching-tab.php:154
|
1846 |
msgid "Titles"
|
1847 |
msgstr ""
|
1848 |
|
1849 |
+
#: lib/tabs/searching-tab.php:167
|
1850 |
msgid "Comment text"
|
1851 |
msgstr ""
|
1852 |
|
1853 |
+
#: lib/tabs/searching-tab.php:196
|
1854 |
msgid "Boost exact matches"
|
1855 |
msgstr ""
|
1856 |
|
1857 |
+
#: lib/tabs/searching-tab.php:200 lib/tabs/searching-tab.php:203
|
1858 |
msgid "Give boost to exact matches."
|
1859 |
msgstr ""
|
1860 |
|
1861 |
+
#: lib/tabs/searching-tab.php:207
|
1862 |
#, php-format
|
1863 |
msgid ""
|
1864 |
"If you enable this option, matches where the search query appears in title "
|
1866 |
"use the %s filter hook. See Help for more details."
|
1867 |
msgstr ""
|
1868 |
|
1869 |
+
#: lib/tabs/searching-tab.php:215
|
1870 |
msgid "WPML"
|
1871 |
msgstr ""
|
1872 |
|
1873 |
+
#: lib/tabs/searching-tab.php:219 lib/tabs/searching-tab.php:222
|
1874 |
msgid "Limit results to current language."
|
1875 |
msgstr ""
|
1876 |
|
1877 |
+
#: lib/tabs/searching-tab.php:225
|
1878 |
msgid ""
|
1879 |
"Enabling this option will restrict the results to the currently active "
|
1880 |
"language. If the option is disabled, results will include posts in all "
|
1881 |
"languages."
|
1882 |
msgstr ""
|
1883 |
|
1884 |
+
#: lib/tabs/searching-tab.php:232
|
1885 |
msgid "Polylang"
|
1886 |
msgstr ""
|
1887 |
|
1888 |
+
#: lib/tabs/searching-tab.php:236 lib/tabs/searching-tab.php:239
|
1889 |
msgid "Allow results from all languages."
|
1890 |
msgstr ""
|
1891 |
|
1892 |
+
#: lib/tabs/searching-tab.php:242
|
1893 |
msgid ""
|
1894 |
"By default Polylang restricts the search to the current language. Enabling "
|
1895 |
"this option will lift this restriction."
|
1896 |
msgstr ""
|
1897 |
|
1898 |
+
#: lib/tabs/searching-tab.php:252 lib/tabs/searching-tab.php:255
|
1899 |
msgid "Use Relevanssi for admin searches."
|
1900 |
msgstr ""
|
1901 |
|
1902 |
+
#: lib/tabs/searching-tab.php:258
|
1903 |
msgid ""
|
1904 |
"If checked, Relevanssi will be used for searches in the admin interface. The "
|
1905 |
"page search doesn't use Relevanssi, because WordPress works like that."
|
1906 |
msgstr ""
|
1907 |
|
1908 |
+
#: lib/tabs/searching-tab.php:264
|
1909 |
#, php-format
|
1910 |
msgid "Respect %s"
|
1911 |
msgstr ""
|
1912 |
|
1913 |
+
#: lib/tabs/searching-tab.php:268
|
1914 |
msgid "Respect exclude_from_search for custom post types"
|
1915 |
msgstr ""
|
1916 |
|
1917 |
+
#: lib/tabs/searching-tab.php:272
|
1918 |
#, php-format
|
1919 |
msgid "Respect %s for custom post types"
|
1920 |
msgstr ""
|
1921 |
|
1922 |
+
#: lib/tabs/searching-tab.php:274
|
1923 |
msgid ""
|
1924 |
"If checked, Relevanssi won't display posts of custom post types that have "
|
1925 |
"'exclude_from_search' set to true."
|
1926 |
msgstr ""
|
1927 |
|
1928 |
+
#: lib/tabs/searching-tab.php:286
|
1929 |
msgid ""
|
1930 |
"You probably should uncheck this option, because you've set Relevanssi to "
|
1931 |
"index the following non-public post types:"
|
1932 |
msgstr ""
|
1933 |
|
1934 |
+
#: lib/tabs/searching-tab.php:299
|
1935 |
msgid "Throttle searches"
|
1936 |
msgstr ""
|
1937 |
|
1938 |
+
#: lib/tabs/searching-tab.php:309
|
1939 |
msgid "Throttling the search does not work when sorting the posts by date."
|
1940 |
msgstr ""
|
1941 |
|
1942 |
+
#: lib/tabs/searching-tab.php:319 lib/tabs/searching-tab.php:322
|
1943 |
msgid "Throttle searches."
|
1944 |
msgstr ""
|
1945 |
|
1946 |
+
#: lib/tabs/searching-tab.php:326
|
1947 |
msgid "Your database is so small that you don't need to enable this."
|
1948 |
msgstr ""
|
1949 |
|
1950 |
+
#: lib/tabs/searching-tab.php:328
|
1951 |
msgid ""
|
1952 |
"If this option is checked, Relevanssi will limit search results to at most "
|
1953 |
"500 results per term. This will improve performance, but may cause some "
|
1954 |
"relevant documents to go unfound. See Help for more details."
|
1955 |
msgstr ""
|
1956 |
|
1957 |
+
#: lib/tabs/searching-tab.php:334
|
1958 |
msgid "Category restriction"
|
1959 |
msgstr ""
|
1960 |
|
1961 |
+
#: lib/tabs/searching-tab.php:354
|
1962 |
msgid ""
|
1963 |
"You can restrict search results to a category for all searches. For "
|
1964 |
"restricting on a per-search basis and more options (eg. tag restrictions), "
|
1965 |
"see Help."
|
1966 |
msgstr ""
|
1967 |
|
1968 |
+
#: lib/tabs/searching-tab.php:359
|
1969 |
msgid "Category exclusion"
|
1970 |
msgstr ""
|
1971 |
|
1972 |
+
#: lib/tabs/searching-tab.php:379
|
1973 |
msgid ""
|
1974 |
"Posts in these categories are not included in search results. To exclude the "
|
1975 |
"posts completely from the index, see Help."
|
1976 |
msgstr ""
|
1977 |
|
1978 |
+
#: lib/tabs/searching-tab.php:384
|
1979 |
msgid "Post exclusion"
|
1980 |
msgstr ""
|
1981 |
|
1982 |
+
#: lib/tabs/searching-tab.php:388
|
1983 |
msgid ""
|
1984 |
"Enter a comma-separated list of post or page ID's to exclude those pages "
|
1985 |
"from the search results."
|
1986 |
msgstr ""
|
1987 |
|
1988 |
+
#: lib/tabs/searching-tab.php:390
|
1989 |
msgid ""
|
1990 |
"With Relevanssi Premium, it's better to use the check box on post edit "
|
1991 |
"pages. That will remove the posts completely from the index, and will work "
|
1992 |
"with multisite searches unlike this setting."
|
1993 |
msgstr ""
|
1994 |
|
1995 |
+
#: lib/tabs/stopwords-tab.php:25
|
1996 |
+
msgid "Content stopwords"
|
1997 |
+
msgstr ""
|
1998 |
+
|
1999 |
+
#: lib/tabs/stopwords-tab.php:31
|
2000 |
+
msgid ""
|
2001 |
+
"Content stopwords are a premium feature where you can set stopwords that "
|
2002 |
+
"only apply to the post content. Those stopwords will still be indexed if "
|
2003 |
+
"they appear in post titles, tags, categories, custom fields or other parts "
|
2004 |
+
"of the post. To use content stopwords, you need Relevanssi Premium."
|
2005 |
+
msgstr ""
|
2006 |
+
|
2007 |
+
#: lib/tabs/stopwords-tab.php:59
|
2008 |
msgid ""
|
2009 |
"Enter a word here to add it to the list of stopwords. The word will "
|
2010 |
"automatically be removed from the index, so re-indexing is not necessary. "
|
2011 |
"You can enter many words at the same time, separate words with commas."
|
2012 |
msgstr ""
|
2013 |
|
2014 |
+
#: lib/tabs/stopwords-tab.php:64
|
2015 |
msgid "Stopword(s) to add"
|
2016 |
msgstr ""
|
2017 |
|
2018 |
+
#: lib/tabs/stopwords-tab.php:72
|
2019 |
msgid ""
|
2020 |
"Here's a list of stopwords in the database. Click a word to remove it from "
|
2021 |
"stopwords. Removing stopwords won't automatically return them to index, so "
|
2023 |
"back to index."
|
2024 |
msgstr ""
|
2025 |
|
2026 |
+
#: lib/tabs/stopwords-tab.php:77
|
2027 |
msgid "Current stopwords"
|
2028 |
msgstr ""
|
2029 |
|
2030 |
+
#: lib/tabs/stopwords-tab.php:98
|
2031 |
msgid "Exportable list of stopwords"
|
2032 |
msgstr ""
|
2033 |
|
2034 |
+
#: lib/tabs/stopwords-tab.php:102
|
2035 |
msgid ""
|
2036 |
"You can copy the list of stopwords here if you want to back up the list, "
|
2037 |
"copy it to a different blog or otherwise need the list."
|