Skip to content

Commit

Permalink
Fix: incorrect adjustment of post count in WC_Query.
Browse files Browse the repository at this point in the history
PR woocommerce#26260 introduced a handler for 'found_posts' filter in WC_Query
class in order to adjust the count depending on the visibility
of variation products. However the handler incorrectly assumed
that the filter was triggered only when listing products, when
actually it's also triggered for any post type e.g. pages.
In these cases the post count was set to zero, which caused bugs.

Now the handler starts with the originally supplied posts count,
and only decrements it when a post is a product AND is not visible.
  • Loading branch information
Konamiman committed Jul 30, 2020
1 parent d5bedd8 commit 86c88f1
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 14 deletions.
21 changes: 13 additions & 8 deletions includes/class-wc-query.php
Original file line number Diff line number Diff line change
Expand Up @@ -368,8 +368,9 @@ public function remove_product_query_filters( $posts ) {
}

/**
* When the request is filtering by attributes via layered nav plugin we need to adjust the total posts count
* to account for variable products having stock in some variations but not in others.
* When we are listing products and the request is filtering by attributes via layered nav plugin
* we need to adjust the total posts count to account for variable products having stock
* in some variations but not in others.
* We do that by just checking if each product is visible.
*
* We also cache the post visibility so that it isn't checked again when displaying the posts list.
Expand All @@ -385,18 +386,22 @@ public function adjust_posts_count( $count ) {
return $count;
}

$count = 0;
foreach ( $posts as $post ) {
$id = is_object( $post ) ? $post->ID : $post;
$product = wc_get_product( $id );
if ( is_object( $post ) && 'product' !== $post->post_type ) {
continue;
}

$product_id = is_object( $post ) ? $post->ID : $post;
$product = wc_get_product( $product_id );
if ( ! is_object( $product ) ) {
continue;
}

if ( $product->is_visible() ) {
wc_set_loop_product_visibility( $id, true );
$count++;
wc_set_loop_product_visibility( $product_id, true );
} else {
wc_set_loop_product_visibility( $id, false );
wc_set_loop_product_visibility( $product_id, false );
$count--;
}
}

Expand Down
28 changes: 22 additions & 6 deletions tests/legacy/unit-tests/util/class-wc-tests-wc-query.php
Original file line number Diff line number Diff line change
Expand Up @@ -441,12 +441,13 @@ public function test_catalog_order_by_rating() {
/**
* Setup for a test for adjust_posts.
*
* @param bool $with_nav_filtering_data Should WC_Query::get_layered_nav_chosen_attributes return filtering data?.
* @param bool $use_objects If true, get_current_posts will return objects with an ID property; if false, it will returns the ids.
* @param bool $with_nav_filtering_data Should WC_Query::get_layered_nav_chosen_attributes return filtering data?.
* @param bool $use_objects If true, get_current_posts will return objects with an ID property; if false, it will returns the ids.
* @param string $post_type The value of the 'post_type' property for the objects generated when $use_objects is true.
*
* @return array An array where the first element is the instance of WC_Query, and the second is an array of sample products created.
*/
private function setup_adjust_posts_test( $with_nav_filtering_data, $use_objects ) {
private function setup_adjust_posts_test( $with_nav_filtering_data, $use_objects, $post_type = 'product' ) {
update_option( 'woocommerce_hide_out_of_stock_items', 'yes' );

if ( $with_nav_filtering_data ) {
Expand All @@ -460,7 +461,10 @@ private function setup_adjust_posts_test( $with_nav_filtering_data, $use_objects
for ( $i = 0; $i < 5; $i++ ) {
$product = WC_Helper_Product::create_simple_product();
array_push( $products, $product );
$post = $use_objects ? (object) array( 'ID' => $product->get_id() ) : $product->get_id();
$post = $use_objects ? (object) array(
'ID' => $product->get_id(),
'post_type' => $post_type,
) : $product->get_id();
array_push( $posts, $post );
}

Expand Down Expand Up @@ -495,8 +499,8 @@ public function test_adjust_posts_count_with_nav_filtering_attributes( $with_nav
$products[1]->set_stock_status( 'outofstock' );
$products[1]->save();

$this->assertEquals( 3, $sut->adjust_posts_count( 34 ) );
$this->assertEquals( 3, wc_get_loop_prop( 'total' ) );
$this->assertEquals( 32, $sut->adjust_posts_count( 34 ) );
$this->assertEquals( 32, wc_get_loop_prop( 'total' ) );
$this->assertEquals( false, wc_get_loop_product_visibility( $products[0]->get_id() ) );
$this->assertEquals( false, wc_get_loop_product_visibility( $products[1]->get_id() ) );
foreach ( array_slice( $products, 2 ) as $product ) {
Expand All @@ -517,4 +521,16 @@ public function test_adjust_posts_count_when_there_are_no_posts() {

$this->assertEquals( 34, $sut->adjust_posts_count( 34 ) );
}

/**
* @testdox adjust_posts should return the input unmodified if the posts do not represent products.
*/
public function test_adjust_posts_count_when_the_posts_are_not_products() {
list($sut, $products) = $this->setup_adjust_posts_test( true, true, 'page' );

$products[0]->set_stock_status( 'outofstock' );
$products[0]->save();

$this->assertEquals( 34, $sut->adjust_posts_count( 34 ) );
}
}

0 comments on commit 86c88f1

Please sign in to comment.