web-dev-qa-db-fra.com

hook pour obtenir (et changer) la chaîne de recherche avant traitement

J'essaie d'intercepter la requête de recherche avant qu'elle ne soit exécutée dans Wordpress. J'ai essayé pas mal de choses mais ça ne marche pas.

Ainsi, par exemple, un utilisateur entre le terme de recherche RED SHOES. Je souhaite que toutes les occurrences de RED soient modifiées en ROSSO (c'est plus complexe que cela, mais vous en avez l'idée; il s'agit de traduire).

Je regarde quelque chose comme ceci:

function modify_search_vars($search_vars) {

    $change_to = array(
        "blue"  => "blu",
        "red"   => "rosso",
    );

    if ( !empty($search_vars['s']) ) {
        $search_vars['s'] = str_ireplace(array_keys($change_to), array_values($change_to), $search_vars['s']);
    }
    return $search_vars;

}
add_filter('request', 'modify_search_vars', 99);

Toute aide ou idées ici seraient très appréciées! Merci!

1
arathra

Afin de réaliser une "injection" plus profonde dans la recherche et de saisir ce que l'utilisateur a recherché dès que possible, nous devons examiner la classe WP_Query et voir comment elle traite une requête pour les publications:

Dans sa fonction parse_query, elle utilise un indicateur pour signaler à la classe entière que la requête est en fait une "recherche". Il n'est donc pas surprenant qu'elle recherche s dans la requête:

if ( isset( $this->query['s'] ) ) {
    $this->is_search = true;
}

Génial, mais il n’existe pas d’actions comme do_action( 'super_important_hook' . $handle_that_we_could_use, $query) où WordPress nous permet de prendre part à ce processus important et vital "nom par nom", que pouvons-nous donc faire?

Nous avons parse_query qui se déclenche avant pre_get_posts:

function replace_search( $query_object )
{
    if( $query_object->is_search() ) {
        $raw_search = $query_object->query['s'];

        $replacement = str_replace( 'red', 'rosso', $raw_search );

        if( $replacement ) {
            $query_object->set( 's', $replacement );
        }
    }
}

add_action( 'parse_query', 'replace_search' );

...et il fonctionne! Nous accrochons dès que possible et modifions la requête dès qu'elle survient. La fonction set fait exactement ce qu'elle dit, c'est un outil de définition pour n'importe laquelle des variables internes utilisées pour la classe.

Au fait, le hook parse_tax_query est déclenché avant le parse_querypuisque $this->parse_tax_query() qui contient parse_tax_query est appelé dans la fonction parse_query() de WP_Query qui transmet le même WP_Query Object à l’action. Mais voici mon opinion qui pourrait être très fausse: je n'utiliserais pas ce crochet, car il semble que parse_query est beaucoup plus populaire pour ce type de comportement.

Tout d’abord, Rappelez-vous que à moins que les plugins utilisent également ce crochet pour rechercher la chaîne de recherche, ils pourraient rechercher $_REQUEST['s'] qui précède ces points d’accès et il pourrait être modifié à ce moment-là. Quoi qu'il en soit, le premier point où la recherche de l'utilisateur entre dans le système est $_REQUEST['s']; vous devez donc vous en tenir à cette valeur le plus tôt possible. Ma réponse est plutôt bonne ici, mais je pense qu'il y a beaucoup plus de choses à prendre en compte lors de la lecture. rechercher, et bien sûr, si leurs fonctions ont une priorité plus élevée et qu'ils transforment la chaîne en quelque chose d'autre, vous êtes condamné.

De toute évidence, vous aurez un mécanisme de "remplacement" plus sophistiqué, mais ce n'est que pour montrer de quels crochets vous avez besoin.

Deuxièmement, un point intéressant à propos de ces actions est qu'elles transmettent leurs objets par référence:

/**
 * Fires after the main query vars have been parsed.
 *
 * @since 1.5.0
 *
 * @param WP_Query $this The WP_Query instance (passed by reference).
 */
do_action_ref_array( 'parse_query', array( &$this ) );

Ce que cela signifie et qu'il est bon de garder à l'esprit - chaque modification que vous apportez lorsque vos scripts sont connectés à parse_query est reflétée sur la classe elle-même qui est transmise au script suivant auquel elle est connectée ou, bien, vos modifications seront répercutées tout le cycle de vie de ladite classe. Je ne peux pas dire s'il s'agissait ou non d'un bon choix de conception. Je vous le ferais savoir au cas où vous auriez un "pourquoi cette variable ne réinitialise-t-elle pas? C'est une nouvelle instance de classe", la classe se comporte comme un singleton, mais ce n’est pas le cas, alors souvenez-vous que vous jouez avec la même classe jusqu’à ce que WP soit terminé et que tous les changements que vous apportez y soient appliqués par tout ce qui viendra après vous, bref: soyez très attentif avec Dans ce que vous faites, beaucoup de processus/plugins utilisent ceci car WP_Query est le coeur même de WP lui-même.


Si vous cherchez à "accrocher" le plus tard possible, cela modifiera toujours la requête elle-même, mais il accrochera (je crois) tardivement, ce qui donnera au thème/plugins la possibilité de jouer avec cette valeur avant que vous ne la voyiez:

add_filter( 'get_search_query', function( $user_search_query ) {
    $replacement = str_replace( 'red', 'rosso', $user_search_query );

    if( $replacement ) {
        return $replacement;
    }

    return $user_search_query;
}, 999);

Le hook que vous cherchez est get_search_query. Mais sachez qu'il y a beaucoup de plugins/éléments qui jouent avec cela, alors, soyez conscient des implications de changer cela. La fonction principale qui l'utilise est:

/**
 * Displays the contents of the search query variable.
 *
 * The search query string is passed through esc_attr() to ensure that it is safe
 * for placing in an html attribute.
 *
 * @since 2.1.0
 */
function the_search_query() {
    /**
     * Filters the contents of the search query variable for display.
     *
     * @since 2.3.0
     *
     * @param mixed $search Contents of the search query variable.
     */
    echo esc_attr( apply_filters( 'the_search_query', get_search_query( false ) ) );
}

De general-template.php dans WP Core. Ce paramètre est transmis à notre filtre à partir de get_search_query, qui est simplement un simple wrapper permettant d’obtenir le contenu de $_REQUEST['s'].

2
coolpasta