Take the 2-minute tour ×
WordPress Development Stack Exchange is a question and answer site for WordPress developers and administrators. It's 100% free, no registration required.

I'm filtering the main query of Jigoshop with my own taxonomy with this hook (The file responsible for Jigoshop queries that I'm hooking, Jigoshop hooks onto WP 'request' 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;
}

I want to filter every Jigoshop query this way (all products display, category display & search display). This is working as intended but wp_title() in the html head is causing the error:

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

I've tracked this down in general-template.php and is_post_type_archive() is returning true even though get_tax() is also returning true. get_queried_object() is returning my taxonomy object (normally the Jigoshop product custom post type object).

I need get_queried_object() to still return the Jigoshop product custom post type object and get_tax() should return false, I want to filter the posts with my taxonomy but I want to keep displaying a post type archive (is this even possible?)

Just before the request is sent back to WP for 'request' filter, it looks like this:

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 ) )

I hope this isn't too specific and makes sense, I'm really at my wit's end here, any help would be greatly appreciated.

share|improve this question
add comment

1 Answer

up vote 2 down vote accepted

The simplest way is, in all honesty, to hook into wp_title and change things, and just be aware that the warnings are there but not showing in production (because you've property configured your server).

What follows is a kind of hacky solution.

If you take a look at get_queried_object...

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

Just a thin wrapper around WP_Query::get_queried_object, so let's take a look at that.

<?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;
}

As you can see, WordPress checks a bunch of stuff to see just what type of query this is and where it's set. The first check is to see if this is a category, tag, or taxonomy archive. Since that succeeds, the post type archive object is never set.

What's really weird is why both is_post_type_archive and is_tax are returning true. Due to the way WP_Query::parse_query works, it's possible that an archive can be both a post type archive as well as a taxonomy archive.

Anyway, WP_Query::$queried_object is a public property, do just hook into someplace before wp_title fires and replace it. template_redirect would work.

This is very much a hack, but there's no pre_wp_title filter or the like where you could prevent the warnings. Untested example below. Be aware that if the WP core decides to make $queried_object a private or protected property in future release this will not work. It could also negatively impact other areas of your 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');
    }
}
share|improve this answer
    
I appreciate the answer Chris but I ended up hooking 'loop-shop-posts-in' in the Jigo query and using get_posts to get the ID's of every product with my tax query. Jigo then uses these ID's with 'post__in' for their main query which produces exactly what I want. It's an extra database call but it's a lot cleaner. –  wickedbroccoli Feb 17 '13 at 5:31
1  
You should post your solution and mark that as accepted, not mine! Folks down the line will likely have a similar question, tell them how you really solved it. –  chrisguitarguy Feb 17 '13 at 7:49
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.