0

I know there are plenty of solutions on the internet about how to get WooCommerce products on sale, by doing a WP_Query. However, WooCommerce doesn't seem to work fully if it's WC_Query object is not populated. For example: filter or sorting

Both these templates call:

woocommerce_products_will_display()

Which check's to see if the page is a taxonomy page (obvious false if you're using your own custom template):

if ( ! is_product_taxonomy() ) return false;

This is an example of a simple solution if you just want the products: WooCommerce: Display ONLY on-sale products in Shop

So, I there seems to be a couple of issues I need to solve here:

1) How to tell WC that my "Sale" page is a taxonomy page? Is there some sort of trick I need to do to force it into a taxonomy?

2) How do I get get WC_Query filled with the sales query (rather than just the WP_Query)

I have plugins that depend on:

$woocommerce->query->layered_nav_product_ids

being populated.

Any help is appreciated! Thanks!!!

Community
  • 1
  • 1
joelataylor
  • 193
  • 1
  • 4
  • 13

1 Answers1

2

Well woocommerce_products_will_display() is pluggable, meaning you can define it in your own functions.php (or site-specific plugin) and alter it, having it return true for your specific template/page.

I think it could stand for some tweaking and a filter.

EDIT

I played around with this a bit more. Typically changing the posts that you want to retrieve is done in the pre_get_posts hook. I took a look at what WooCommerce is doing. They are adding something to the pre_get_posts hook and calling their special query stuff from there.

But their special query stuff dies if you aren't on a WooCommerce page. So, it made me thing that maybe we could just call it ourselves from our own function. I put this together and coupled with a special page template for a page called "on-sale" (basically just a copy of the shop template), seems to show just the for sale items with proper sorting and pagination.

Your mileage may vary, but I hope it helps.

function kia_pre_get_posts( $q ){

    // We only want to affect the main query
    if ( ! $q->is_main_query() ) {
        return;
    }

    // Fix for verbose page rules
    if ( is_page('on-sale') ) {
        $q->set( 'post_type', 'product' );
        $q->set( 'page_id', '' );
        $q->set( 'page', '' );
        $q->set( 'pagename', '' );

        $meta_query = array( array(
            'key'     => '_sale_price',
            'value'   => 0,
            'compare' => '>'
        ) );

        $q->set( 'meta_query', $meta_query );

        if ( isset( $q->query['paged'] ) ) {
            $q->set( 'paged', $q->query['paged'] );
        }

        // Fix conditional Functions
        $q->is_archive           = true;
        $q->is_post_type_archive = true;
        $q->is_singular          = false;
        $q->is_page              = false;

    }

    $wc_query = WC()->query;

    $wc_query->product_query( $q );

    if ( is_search() ) {
        add_filter( 'posts_where', array( $wc_query, 'search_post_excerpt' ) );
        add_filter( 'wp', array( $wc_query, 'remove_posts_where' ) );
    }

    add_filter( 'posts_where', array( $wc_query, 'exclude_protected_products' ) );

    // We're on a shop page so queue the woocommerce_get_products_in_view function
    add_action( 'wp', array( $wc_query, 'get_products_in_view' ), 2);

    // And remove the pre_get_posts hook
    $wc_query->remove_product_query();

}
add_action( 'pre_get_posts', 'kia_pre_get_posts' );
helgatheviking
  • 25,596
  • 11
  • 95
  • 152
  • Yep - I guess I could create my own version. However, that still won't solve the issue of WC_Query not getting populated which means the filters and product counts, etc won't work. – joelataylor Jul 16 '14 at 20:57
  • That's true. I took another look and came up with something new. No guarantees, but I hope it helps. – helgatheviking Jul 16 '14 at 22:06
  • Good work, dug me out of a hole and opened up some possibilities :) – Sam Holguin Aug 19 '18 at 11:25