Это решение фильтрует строки поиска путем применения регулярного выражения, которое соответствует только символам из сценариев Common и Latin Unicode.
Сопоставление латинских символов с регулярными выражениями
Я только что заболел умом в переполнении стека . Как выясняется, регулярные выражения имеют механизм для сопоставления целых категорий Юникода, включая значения для указания целых «сценариев» Юникода , каждый из которых соответствует группам символов, используемых в разных системах письма.
Это делается с помощью \p
метасимвола, за которым следует идентификатор категории Юникод в фигурных скобках - так что [\p{Common}\p{Latin}]
соответствует одному символу в латинских или общих сценариях - это включает знаки препинания, цифры и прочие символы.
Как указывает @Paul «Sparrow Hawk» Бирон , u
флаг модификатора шаблона должен быть установлен в конце регулярного выражения, чтобы функции PHPRE PHP обрабатывали строку-тему как UTF-8
кодировку Unicode.
Все вместе, то шаблон
/^[\p{Latin}\p{Common}]+$/u
будет соответствовать всей строке, состоящей из одного или нескольких символов в латинском и общем Unicode-скриптах.
Фильтрация строки поиска
Хорошее место , чтобы перехватить строку поиска является действие , как это срабатывает непосредственно перед WordPress выполняет запрос. С большей осторожностью это также может быть достигнуто с помощью фильтра .pre_get_posts
request
function wpse261038_validate_search_characters( $query ) {
// Leave admin, non-main query, and non-search queries alone
if( is_admin() || !$query->is_main_query() || !$query->is_seach() )
return;
// Check if the search string contains only Latin/Common Unicode characters
$match_result = preg_match( '/^[\p{Latin}\p{Common}]+$/u', $query->get( 's' ) );
// If the search string only contains Latin/Common characters, let it continue
if( 1 === $match_result )
return;
// If execution reaches this point, the search string contains non-Latin characters
//TODO: Handle non-Latin search strings
//TODO: Set up logic to display error message
}
add_action( 'pre_get_posts', 'wpse261038_validate_search_characters' );
Отвечая на запрещенные поиски
После того, как будет определено, что строка поиска содержит нелатинские символы, вы можете использовать ее WP_Query::set()
для изменения запроса, изменив его именованные переменные запроса - таким образом влияя на SQL-запрос, который WordPress впоследствии создает и выполняет.
Наиболее важные переменные запроса, вероятно, следующие:
s
переменная запроса, соответствующая строке поиска. Установка этого параметра null
или пустой строки ( ''
) приведет к тому, что WordPress больше не будет обрабатывать запрос как поиск - часто это приводит к тому, что шаблон архива отображает все сообщения или первую страницу сайта, в зависимости от значений других запрос вари. ' '
Однако, если задать для него один пробел ( ), WordPress распознает его как поиск и попытается отобразить search.php
шаблон.
page_id
может использоваться для направления пользователя на определенную страницу по вашему выбору.
post__in
Можно ограничить запрос конкретным выбором сообщений. Устанавливая его в массив с невозможным идентификатором записи, он может служить мерой, гарантирующей, что запрос не даст абсолютно ничего .
Принимая во внимание вышесказанное, вы можете сделать следующее, чтобы ответить на неправильный поиск, загрузив search.php
шаблон без результатов:
function wpse261038_validate_search_characters( $query ) {
// Leave admin, non-main query, and non-search queries alone
if( is_admin() || !$query->is_main_query() || !$query->is_seach() )
return;
// Check if the search string contains only Latin/Common Unicode characters
$match_result = preg_match( '/^[\p{Latin}\p{Common}]+$/u', $query->get( 's' ) );
// If the search string only contains Latin/Common characters, let it continue
if( 1 === $match_result )
return;
$query->set( 's', ' ' ); // Replace the non-latin search with an empty one
$query->set( 'post__in', array(0) ); // Make sure no post is ever returned
//TODO: Set up logic to display error message
}
add_action( 'pre_get_posts', 'wpse261038_validate_search_characters' );
Отображение ошибки
То, как вы на самом деле отображаете сообщение об ошибке, сильно зависит от вашего приложения и возможностей вашей темы - есть много способов, которыми это можно сделать. Если ваша тема вызывает get_search_form()
в своем шаблоне поиска, простейшим решением, вероятно, является использование ловушки pre_get_search_form
действий для вывода вашей ошибки непосредственно над формой поиска:
function wpse261038_validate_search_characters( $query ) {
// Leave admin, non-main query, and non-search queries alone
if( is_admin() || !$query->is_main_query() || !$query->is_seach() )
return;
// Check if the search string contains only Latin/Common Unicode characters
$match_result = preg_match( '/^[\p{Latin}\p{Common}]+$/u', $query->get( 's' ) );
// If the search string only contains Latin/Common characters, let it continue
if( 1 === $match_result )
return;
$query->set( 's', ' ' ); // Replace the non-latin search with an empty one
$query->set( 'post__in', array(0) ); // Make sure no post is ever returned
add_action( 'pre_get_search_form', 'wpse261038_display_search_error' );
}
add_action( 'pre_get_posts', 'wpse261038_validate_search_characters' );
function wpse261038_display_search_error() {
echo '<div class="notice notice-error"><p>Your search could not be completed as it contains characters from non-Latin alphabets.<p></div>';
}
Некоторые другие возможности для отображения сообщения об ошибке включают в себя:
- Если ваш сайт использует JavaScript, который может отображать «флэш» или «модальные» сообщения (или вы добавляете такие возможности самостоятельно), добавьте к нему логику для отображения сообщений при загрузке страницы, когда задана определенная переменная, затем добавьте
wp_enqueue_script
ловушку с $priority
большим, чем тот, который ставит в очередь этот JavaScript, и используйте wp_localize_script()
для установки этой переменной, чтобы включить ваше сообщение об ошибке.
- Используется
wp_redirect()
для отправки пользователя по выбранному вами URL-адресу (этот метод требует дополнительной загрузки страницы).
- Установите переменную PHP или вызовите метод, который сообщит вашей теме / плагину об ошибке так, что он может отобразить ее при необходимости.
- Установите
s
переменную запроса ''
вместо ' '
и используйте page_id
вместо post__in
, чтобы вернуть страницу по вашему выбору.
- Используйте
loop_start
ловушку, чтобы WP_Post
вставить поддельный объект, содержащий вашу ошибку, в результаты запроса - это, безусловно, уродливый хак, который может не соответствовать вашей конкретной теме, но имеет потенциально желательный побочный эффект - подавление сообщения «Нет результатов».
- Используйте
template_include
ловушку фильтра, чтобы заменить шаблон поиска на собственный в вашей теме или плагине, который отображает вашу ошибку.
Не изучая обсуждаемую тему, сложно определить, по какому маршруту следует идти.