Cette solution filtre les chaînes de recherche en appliquant une expression régulière qui ne correspond qu'aux caractères des scripts Unicode commun et latin.
Faire correspondre les caractères latins aux expressions régulières
Je venais juste d' avoir le souffle coupé à Stack Overflow . Il s'avère que les expressions régulières ont un mécanisme pour faire correspondre des catégories Unicode entières, y compris des valeurs pour spécifier des "scripts" Unicode entiers , chacun correspondant à des groupes de caractères utilisés dans différents systèmes d'écriture.
Cela se fait en utilisant le \p
méta-caractère suivi d'un identifiant de catégorie Unicode entre accolades - [\p{Common}\p{Latin}]
correspond donc à un seul caractère dans les scripts latin ou commun - cela inclut la ponctuation, les chiffres et les symboles divers.
Comme le souligne @Paul 'Sparrow Hawk' Biron , l' u
indicateur de modificateur de modèle doit être défini à la fin de l'expression régulière afin que les fonctions PCRE de PHP traitent la chaîne en question comme UTF-8
codée Unicode.
Tous ensemble alors, le motif
/^[\p{Latin}\p{Common}]+$/u
correspondra à une chaîne entière composée d'un ou plusieurs caractères dans les scripts Latin et Common Unicode.
Filtrage de la chaîne de recherche
Un bon endroit pour intercepter une chaîne de recherche est l' pre_get_posts
action car elle se déclenche immédiatement avant que WordPress n'exécute la requête. Avec plus de soin , cela pourrait également être accompli en utilisant un request
filtre .
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' );
Répondre aux recherches non autorisées
Une fois qu'il a été déterminé qu'une chaîne de recherche contient des caractères non latins, vous pouvez utiliser WP_Query::set()
afin de modifier la requête en changeant son nom de variable de requête - affectant ainsi la requête SQL que WordPress compose et exécute ensuite.
Les variables de requête les plus pertinentes sont probablement les suivantes:
s
est la variable de requête correspondant à une chaîne de recherche. Si vous le définissez sur null
ou une chaîne vide ( ''
), WordPress ne traitera plus la requête comme une recherche - cela aboutit souvent à un modèle d'archive affichant toutes les publications ou la première page du site, selon les valeurs de l'autre requête vars. ' '
Cependant, si vous le définissez sur un seul espace ( ), WordPress le reconnaîtra comme une recherche et tentera donc d'afficher le search.php
modèle.
page_id
pourrait être utilisé pour diriger l'utilisateur vers une page spécifique de votre choix.
post__in
peut restreindre la requête à une sélection spécifique de publications. En le définissant sur un tableau avec un ID de publication impossible, il peut servir de mesure pour garantir que la requête ne renvoie absolument rien .
Ce qui précède à l'esprit, vous pouvez faire ce qui suit afin de répondre à une mauvaise recherche en chargeant le search.php
modèle sans résultat:
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' );
Affichage d'une erreur
La façon dont vous affichez réellement le message d'erreur dépend fortement de votre application et des capacités de votre thème - il y a plusieurs façons de le faire. Si votre thème appelle get_search_form()
dans son modèle de recherche, la solution la plus simple consiste probablement à utiliser un crochet d' pre_get_search_form
action pour afficher votre erreur immédiatement au-dessus du formulaire de recherche:
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>';
}
Voici d'autres possibilités pour afficher un message d'erreur:
- Si votre site utilise JavaScript qui peut afficher des messages "flash" ou "modaux" (ou si vous ajoutez de telles capacités par vous-même), ajoutez-y la logique pour afficher les messages au chargement de la page lorsqu'une variable spécifique est définie, puis ajoutez un
wp_enqueue_script
crochet avec un $priority
plus grand que celui qui met en file d'attente ce JavaScript, et utilisez wp_localize_script()
pour définir cette variable pour inclure votre message d'erreur.
- Utilisez
wp_redirect()
pour envoyer l'utilisateur à l'URL de votre choix (cette méthode nécessite un chargement de page supplémentaire).
- Définissez une variable PHP ou appelez une méthode qui informera votre thème / plugin de l'erreur de sorte qu'il puisse l'afficher le cas échéant.
- Définissez la
s
variable de requête à la ''
place de ' '
et utilisez page_id
à la place de post__in
afin de retourner une page de votre choix.
- Utilisez un
loop_start
crochet pour injecter un faux WP_Post
objet contenant votre erreur dans les résultats de la requête - il s'agit certainement d'un vilain hack et peut ne pas convenir à votre thème particulier, mais il a l'effet secondaire potentiellement souhaitable de supprimer le message "Aucun résultat".
- Utilisez un
template_include
crochet de filtre pour échanger le modèle de recherche avec un modèle personnalisé dans votre thème ou plug-in qui affiche votre erreur.
Sans examiner le thème en question, il est difficile de déterminer l'itinéraire à suivre.