Это решение фильтрует строки поиска путем применения регулярного выражения, которое соответствует только символам из сценариев 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_postsrequest
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ловушку фильтра, чтобы заменить шаблон поиска на собственный в вашей теме или плагине, который отображает вашу ошибку.
Не изучая обсуждаемую тему, сложно определить, по какому маршруту следует идти.