web-dev-qa-db-fra.com

Comment interroger un type de publication personnalisé avec un filtre de taxonomie mais afficher la page d'archive de type de publication?

Je filtre la requête principale de Jigoshop avec ma propre taxonomie avec ce hook ( ). Le fichier responsable des requêtes Jigoshop que je raccorde, Jigoshop accroche à la demande WP ' 'filter ):

add_filter( 'loop_shop_tax_query', 'my_loop_shop_tax_query', 11 );
function loop_shop_tax_query( $request )
{
    $region = 'dublin';
    if ( ! empty( $region ) ) {
        $request[] = array(
            'taxonomy'  => 'product_region',
            'field'     => 'slug',
            'terms'     => $region,
            'operator'  => 'IN',
        );
    }

    return $request;
}

Je souhaite filtrer chaque requête Jigoshop de cette manière (affichage de tous les produits, affichage des catégories et affichage de la recherche). Cela fonctionne comme prévu mais wp_title () dans la tête html est à l'origine de l'erreur:

Notice: Undefined property: stdClass::$labels in /var/www/wp/wp-includes/general-template.php on line 658

Notice: Trying to get property of non-object in /var/www/wp/wp-includes/general-template.php on line 658

J'ai repéré cela dans general-template.php et is_post_type_archive() renvoie true, même si get_tax() renvoie également true. get_queried_object() renvoie mon objet taxonomy (normalement, l'objet de type publication personnalisé du produit Jigoshop).

J'ai besoin de get_queried_object() pour toujours renvoyer l'objet de type de message personnalisé du produit Jigoshop et get_tax() doit renvoyer false, je souhaite filtrer les messages avec ma taxonomie mais je souhaite continuer à afficher une archive de type de message (est-ce même possible?)

Juste avant que la demande ne soit renvoyée à WP pour le filtre 'request', cela ressemble à ceci:

Array ( [post_type] => product [post_status] => publish [posts_per_page] => 12 [orderby] => post_date [order] => asc [tax_query] => Array ( [relation] => AND [0] => Array ( [taxonomy] => product_region [field] => slug [terms] => dublin [operator] => IN ) ) [meta_query] => Array ( [0] => Array ( [key] => visibility [value] => Array ( [0] => visible [1] => catalog ) [compare] => IN ) ) [post__in] => Array ( [0] => 293 [1] => 291 [2] => 289 [3] => 18 [4] => 0 ) )

J'espère que ce n'est pas trop spécifique et que cela a du sens, je suis vraiment à bout de forces, toute aide serait grandement appréciée.

1
wickedbroccoli

Le moyen le plus simple est, en toute honnêteté, de connecter wp_title et de changer les choses, et sachez simplement que les avertissements sont là mais ne s'affichent pas en production (car vous avez configuré votre serveur par propriété).

Ce qui suit est une sorte de solution de hacky.

Si vous jetez un oeil à get_queried_object...

<?php
function get_queried_object() {
    global $wp_query;
    return $wp_query->get_queried_object();
}

Juste une mince couche autour de WP_Query::get_queried_object, regardons-le.

<?php
function get_queried_object() {
    if ( isset($this->queried_object) )
        return $this->queried_object;

    $this->queried_object = null;
    $this->queried_object_id = 0;

    if ( $this->is_category || $this->is_tag || $this->is_tax ) {
        $tax_query_in_and = wp_list_filter( $this->tax_query->queries, array( 'operator' => 'NOT IN' ), 'NOT' );

        $query = reset( $tax_query_in_and );

        if ( 'term_id' == $query['field'] )
            $term = get_term( reset( $query['terms'] ), $query['taxonomy'] );
        elseif ( $query['terms'] )
            $term = get_term_by( $query['field'], reset( $query['terms'] ), $query['taxonomy'] );

        if ( ! empty( $term ) && ! is_wp_error( $term ) )  {
            $this->queried_object = $term;
            $this->queried_object_id = (int) $term->term_id;

            if ( $this->is_category )
                _make_cat_compat( $this->queried_object );
        }
    } elseif ( $this->is_post_type_archive ) {
        $this->queried_object = get_post_type_object( $this->get('post_type') );
    } elseif ( $this->is_posts_page ) {
        $page_for_posts = get_option('page_for_posts');
        $this->queried_object = get_post( $page_for_posts );
        $this->queried_object_id = (int) $this->queried_object->ID;
    } elseif ( $this->is_singular && !is_null($this->post) ) {
        $this->queried_object = $this->post;
        $this->queried_object_id = (int) $this->post->ID;
    } elseif ( $this->is_author ) {
        $this->queried_object_id = (int) $this->get('author');
        $this->queried_object = get_userdata( $this->queried_object_id );
    }

    return $this->queried_object;
}

Comme vous pouvez le constater, WordPress vérifie un tas de choses pour voir exactement quel type de requête il s'agit et où il est défini. La première vérification consiste à vérifier s’il s’agit d’une archive de catégorie, de balise ou de taxonomie. Comme cela réussit, l'objet archive de type post n'est jamais défini.

Ce qui est vraiment étrange, c'est pourquoi is_post_type_archive et is_tax renvoient true. En raison du fonctionnement de WP_Query::parse_query, il est possible qu'une archive soit à la fois une archive de type publication et une archive de taxonomie.

Quoi qu'il en soit, WP_Query::$queried_object est une propriété publique, connectez-vous simplement avant le déclenchement de wp_title et remplacez-le. template_redirect fonctionnerait.

C'est vraiment un hack, mais il n'y a pas de filtre pre_wp_title ou similaire où vous pourriez empêcher les avertissements. Exemple non testé ci-dessous. Sachez que si le WP noyau décide de faire de $queried_object une propriété privée ou protégée dans une version ultérieure, cela ne fonctionnera pas. Cela pourrait également avoir un impact négatif sur d'autres zones de votre site.

<?php
add_action('template_redirect', 'wpse87222_change_object');
function wpse87222_change_object()
{
    global $wp_the_query;

    // check for post type archive
    if (is_post_type_archive('product')) {
        $wp_the_query->queried_object = get_post_type_object('product');
    }
}
2
chrisguitarguy