Це рішення фільтрує рядки пошуку, застосовуючи регулярний вираз, який відповідає лише символам із загального та латинського сценаріїв Unicode.
Збіг латинських символів з регулярними виразами
Мені просто спалахнув розум під час переповнення стека . Як виявляється, регулярні вирази мають механізм узгодження цілих категорій Unicode, включаючи значення, щоб вказати цілі "сценарії" Unicode , кожен відповідає групам символів, що використовуються в різних системах запису.
Це робиться за допомогою \p
мета-символу, за яким слідує ідентифікатор категорії Unicode у фігурних дужках - таким чином, [\p{Common}\p{Latin}]
відповідає одному символу в латинських або загальних сценаріях - це включає розділові знаки, цифри та інші символи.
Як зазначає @Paul 'Sparrow Hawk' Biron , u
прапор модифікатора шаблону повинен бути встановлений в кінці регулярного виразу, щоб функції PCRE 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()
для зміни запиту, змінивши його на ім'я vars vars - таким чином впливаючи на SQL-запит, WordPress згодом створює та виконує.
Напевно, найбільш відповідні змінні запиту:
s
- змінна запиту, що відповідає пошуковому рядку. Якщо встановити його null
або порожній рядок ( ''
), це призведе до того, що WordPress більше не розглядає запит як пошук - часто це призводить до того, що в шаблоні архіву відображаються всі повідомлення або титульна сторінка сайту, залежно від значень іншого запит vars. Якщо встановити його в єдиному просторі ( ' '
), це призведе до того, що 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
гачок фільтра, щоб поміняти шаблон пошуку на спеціальний у вашій темі чи плагіні, який відображає вашу помилку.
Без вивчення теми, про яку йдеться, важко визначити, яким маршрутом слід скористатися.