Skip to content

Conversation

@Konamiman
Copy link
Contributor

@Konamiman Konamiman commented Apr 23, 2020

All Submissions:

Changes proposed in this Pull Request:

This PR fixes an issue that appears when using the layered nav widget (which allows filtering the listed products by an attribute) and there are variable products where some variations have stock and others don't. The issue is that when an attribute is selected for filtering, all variable products having a variation that corresponds to that attribute will be displayed, even those not having stock for that variation (as long as at least one variation has stock).

Example: you sell shoes in two colors, black and blue. Black is out of stock but there's stock for blue. You select "black" (but not "blue") in the widget. The shoes will be included in the products list, but they shouldn't.

Additionally, the count of products that appear in the widget for each attribute is also wrongly including the variable products that don't have stock for the attribute corresponding to that variation.

Note that the original issue is about products out of stock, but the changes act actually on the more wide visibility condition. A product is "visible" if it's published, not excluded for catalog, and has stock. Additionally, a variable product will not be considered visible if the parent product is not.

New behavior of the counters

Now the counters count all the variations that are in stock, regardless of whether the filter uses OR or AND logic; that's because one given variation has always one single value for the attribute, so the logic in use is irrelevant. For non-variable products they continue working as usual.

Variation counts will be equivalent to product counts when one single attribute is used to define variations, but if more than one attribute is used that could not be the case. For example you have a "shoes" product with two attributes used for variations, "color" and "style"; if you define variations as "black classic" and "black sport" then "black" will be counted twice in the filter (if both variations have stock).

Also, when using multiple filters they interact with AND logic as usual: only variations that have both attributes in its definition are counted.

Closes #25524.

How to test the changes in this Pull Request:

NOTE: You need to run database updates for the widget counters to work properly!

  1. Go to Settings > Products > Inventory, mark "Hide out of stock items from the catalog".
  2. Create an attribute named "Color", with the following terms: Black, Brown, Blue, Green, Pink.
  3. Create the following variable products: Big shoes, Medium shoes, Small shoes, Kid shoes. Create variations for all the existing colors on all of them. Assign any regular price to all the variations. (Hint: create one product, then duplicate)
  4. Modify the products so the following variations are in stock and the others are out of stock:
  • Big: black, brown.
  • Medium: blue, brown.
  • Small: blue, green.
  • Kids: green, pink.
  1. Add the "Filter by attribute" widget, filtering by color with OR.
  2. Try filtering by one or two colors and verify that the results make sense. For example when filtering by "blue" you should see only "Medium shoes" and "Small shoes" (without the fix you would see all four shoe types). Verify also that the results count that appear at the beginning and the end of the list is correct.
  3. Change the widget filtering type to AND and try different combinations again. Verify that selecting pink and black displays the "No products available" message.

How to test the counters

With the same setup, verify that the counters display the following, no matter what attributes you select in the widget:

image

Now make sure that nothing is selected, then go and change the widget operator to AND. Reload the products page and verify that the behavior is the same.

Testing counters with multiple attributes

  1. Create an attribute named "Style" with two terms: Classic, and Sport.
  2. Modify all the products so that all of them use the new style for variations, but leave the value for all variations as "Any style".
  3. Modify the Big shoes product so that the Black variation is Classic, and create a new variation that is Black Sport (leave both in stock).
  4. Modify the Medium shoes product so that the Brown variation is Sport (and still has stock).
  5. Add the "Filter by attribute" widget, filtering by style with any logic.
  6. Reload the page and verify that the counters now appear like this:

image

Note how there are two variations listed for Black, since we added a new one to the Big shoes. Also note how the two classic variations and the single sport variation are listed in the style filter.

  1. Select "Black" in the color filter and note how the style filter now displays a value of 1 for classic and 1 for sport, since there's one visible variation of each.
  2. Unselect all and select "Blue" in the color filter and note how the style filter disappears, since there's no variation that is blue and has a style associated.
  3. Unselect all in the color filter and select "Sport" in the style filter, you will see this:

image

Testing visibility with multiple filters

While testing counters with multiple filters you may have noticed that regardless of what filters you selected in the style filter you were still seeing all the products in the catalog (if you don't filter by color). That's because all of the products have visible variations with "Any style" and thus they always match the style filter.

Modify the "Kid shoes" product so that all the variations have the sport style, then select "Classic" in the style filter while not filtering by color, and you'll see that the product disappears from the catalog.

Other information:

  • Have you added an explanation of what your changes do and why you'd like us to include them?
  • Have you written new tests for your changes, as applicable?
  • Have you successfully run tests with your changes locally?

Changelog entry

Fix - The filtering widget now works as expected with variable products, displaying those products for which visible variations are available.

@Konamiman Konamiman added the Bug The issue is a confirmed bug. label Apr 23, 2020
@Konamiman Konamiman self-assigned this Apr 23, 2020
@Konamiman Konamiman force-pushed the fix/25524 branch 4 times, most recently from a14b1ef to 9965951 Compare April 30, 2020 08:11
@Konamiman Konamiman force-pushed the fix/25524 branch 2 times, most recently from f6c8fc2 to 0466c0b Compare May 5, 2020 15:06
@Konamiman Konamiman marked this pull request as ready for review May 5, 2020 15:30
Copy link
Contributor

@claudiosanches claudiosanches left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I still need to test it in full, but here's some coding standards that can be fixed without excluding from PHPCS.

Copy link
Contributor

@claudiosanches claudiosanches left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I left some code suggestions for you.

@claudiosanches claudiosanches added needs: author feedback The issue/PR needs a response from any of the parties involved in the issue. and removed status: needs review labels Jun 24, 2020
@MohsinQK
Copy link

MohsinQK commented Jul 3, 2020

@Konamiman I found a strange problem. the filter is working but a bit buggy.
I have one test Product with the Quantities as shown in the screenshot.
image

in frontend the filter works but buggy for example

  1. if I select Green Color (Only) from the color Filter the Product disappears as expected because it's not available in Green Color. (✅)
  2. if I select Large Size (Only) Product appears in the list even its not available in Large Size.(❌)
  3. if I select Green Color First AND then select Large Size Product not get listed Which is correct.(✅)
  4. if I select Large Size First AND then select Green Color Product gets listed which is wrong(❌)

below are all screenshots of the use cases in the order mentioned above in each use case Product must NOT appear in the list but in 2 cases it's listing even its Quantity is zero.

This is the Product I am testing on.
image

image
2.
image
3.
image
4.
image

I think its only working in the Order their Variation attributes are selected from the backend.
Please let me know for any other information you need

@Konamiman
Copy link
Contributor Author

Hi @MohsinQK. Regarding your feedback, I assume you are using two separate filtering widgets, one for color and another one for size, at the same time.

  1. if I select Large Size (Only) Product appears in the list even its not available in Large Size.(❌)

The product is still available in large size, for the Black and Indigo colors. Therefore it should still be listed, right? Please tell me if I'm missing something else.

  1. if I select Green Color First AND then select Large Size Product not get listed Which is correct.(✅)
  2. if I select Large Size First AND then select Green Color Product gets listed which is wrong(❌)

This is indeed inconsistent. I'm not sure if the product should be listed or not in these cases (we have "AND"/"OR" behavior selection for each individual widget, but when using two filters at the same time I don't know how it's supposed to behave), but what's for sure is that it should act in the same way in both cases.

I'll have to take a look at this and check with my team, thanks for reporting!

@IlPicasso
Copy link

IlPicasso commented Jul 8, 2020

  1. if I select Large Size (Only) Product appears in the list even its not available in Large Size.(❌)
    The product is still available in large size, for the Black and Indigo colors. Therefore it should still be listed, right? Please tell me if I'm missing something else.

I believe this is the correct behaviour.

  1. if I select Large Size First AND then select Green Color Product gets listed which is wrong(❌)
    This is indeed inconsistent. I'm not sure if the product should be listed or not in these cases (we have "AND"/"OR" behavior selection for each individual widget, but when using two filters at the same time I don't know how it's supposed to behave), but what's for sure is that it should act in the same way in both cases.

If I choose Large and Green, it is supposed that I am searching for an item that HAS Large Size and green color so everything else should dissapear if there is not those attributes, otherwise I wouldnt filter it that way

@Konamiman Konamiman force-pushed the fix/25524 branch 4 times, most recently from 398d568 to e26ddf4 Compare July 13, 2020 15:28
@Konamiman
Copy link
Contributor Author

Hi @MohsinQK and @IlPicasso, I have made changes so that:

  • The special behavior for the AND filtering case has been removed. One doesn't usually think "I want to see shoes that have stock of blue AND have stock of green" so that logic was unnecessarily complex and confusing. Now the filters have always OR behavior as far as variations are concerned, since one given variation will always have one single value for a given attribute.
  • Filtering by multiple attributes works as expected, regardless of the order in which you select them.

I hope those changes are sensible and useful.

@peterfabian peterfabian added status: needs review and removed needs: author feedback The issue/PR needs a response from any of the parties involved in the issue. labels Jul 14, 2020
@MohsinQK
Copy link

@Konamiman yes the Point 2 is correct it's my misunderstanding. but point 4 was not fine for which you made some changes already.

vedanshujain pushed a commit that referenced this pull request Jul 31, 2020
PR #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.
Konamiman added a commit that referenced this pull request Jul 31, 2020
This bug was introduced in #26260. The sequence is:

1. WC_Query::adjust_posts_count runs, to handle found_posts filter,
   this indirectly executes wc_setup_loop.
2. At this point $GLOBALS['wp_query']->max_num_pages hasn't been set
   yet, and has a value of 0. Thus the loop variable total_pages
   is set to 0.
3. Later wc_setup_loop runs again and this time
   $GLOBALS['wp_query']->max_num_pages is already set, but since
   the loop variable total_pages already exists, it keeps its
   value of 0.
4. The pagination controls never show if total_pages is less than 2.

The fix consists of hooking into the_posts to set the value of
total_pages again, at that point $GLOBALS['wp_query']->max_num_pages
is already set.
Konamiman added a commit that referenced this pull request Jul 31, 2020
This bug was introduced in #26260. The sequence is:

1. WC_Query::adjust_posts_count runs, to handle found_posts filter,
   this indirectly executes wc_setup_loop.
2. At this point $GLOBALS['wp_query']->max_num_pages hasn't been set
   yet, and has a value of 0. Thus the loop variable total_pages
   is set to 0.
3. Later wc_setup_loop runs again and this time
   $GLOBALS['wp_query']->max_num_pages is already set, but since
   the loop variable total_pages already exists, it keeps its
   value of 0.
4. The pagination controls never show if total_pages is less than 2.

The fix consists of hooking into the_posts to set the value of
total_pages again, at that point $GLOBALS['wp_query']->max_num_pages
is already set.
Konamiman added a commit that referenced this pull request Jul 31, 2020
This bug was introduced in #26260. The sequence is:

1. WC_Query::adjust_posts_count runs, to handle found_posts filter,
   this indirectly executes wc_setup_loop.
2. At this point $GLOBALS['wp_query']->max_num_pages hasn't been set
   yet, and has a value of 0. Thus the loop variable total_pages
   is set to 0.
3. Later wc_setup_loop runs again and this time
   $GLOBALS['wp_query']->max_num_pages is already set, but since
   the loop variable total_pages already exists, it keeps its
   value of 0.
4. The pagination controls never show if total_pages is less than 2.

The fix consists of hooking into the_posts to set the value of
total_pages again, at that point $GLOBALS['wp_query']->max_num_pages
is already set.
Konamiman added a commit that referenced this pull request Aug 3, 2020
PR #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.
Konamiman added a commit that referenced this pull request Aug 3, 2020
This bug was introduced in #26260. The sequence is:

1. WC_Query::adjust_posts_count runs, to handle found_posts filter,
   this indirectly executes wc_setup_loop.
2. At this point $GLOBALS['wp_query']->max_num_pages hasn't been set
   yet, and has a value of 0. Thus the loop variable total_pages
   is set to 0.
3. Later wc_setup_loop runs again and this time
   $GLOBALS['wp_query']->max_num_pages is already set, but since
   the loop variable total_pages already exists, it keeps its
   value of 0.
4. The pagination controls never show if total_pages is less than 2.

The fix consists of hooking into the_posts to set the value of
total_pages again, at that point $GLOBALS['wp_query']->max_num_pages
is already set.
Konamiman added a commit that referenced this pull request Aug 28, 2020
When a variation product has an attribute with a value of "Any...",
and there's a filter by attribute widget for that attribute, then
that product won't be included in the counts displayed in the widget
(and if the count ends up being zero, the attribute won't be shown
in the widget).

This happens before since Woo 4.4, this widget works by looking at
entries in the term relationships table for varitions too
(used to do so for simple products and for "main" variable products
only), see PR #26260; but there are no such entries for
"Any..." attributes.

This commit fixes that by extending the SQL query used by the widget
to look for variations that have empty attribute values in the meta
table too.
jonathansadowski pushed a commit that referenced this pull request Sep 2, 2020
When a variation product has an attribute with a value of "Any...",
and there's a filter by attribute widget for that attribute, then
that product won't be included in the counts displayed in the widget
(and if the count ends up being zero, the attribute won't be shown
in the widget).

This happens before since Woo 4.4, this widget works by looking at
entries in the term relationships table for varitions too
(used to do so for simple products and for "main" variable products
only), see PR #26260; but there are no such entries for
"Any..." attributes.

This commit fixes that by extending the SQL query used by the widget
to look for variations that have empty attribute values in the meta
table too.
@B-Anders
Copy link

B-Anders commented Sep 8, 2020

I've noticed a bunch of other strange behavior from that filter. I hope @Konamiman can take a look and make some sense.

To reproduce:

  1. Start with one simple product (Product1). It has 2 attributes, "ARTIST" and "COLOR".
    ARTIST is used in the attribute filter widget and everything works as expected.
  2. Change product to variable and generate two (or more) variations with (only) the second attribute "COLOR". Give it some quantity to have the variations on stock.
  3. Check: product shows on the shop and category pages, variations are correct on the single product page.
    Problem: the filter for attribute ARTIST doesn't count the product and the whole widget isn't showing on any pages.
  4. Add a second product (Product2): simple, with attribute ARTIST, same value as the first product.
    Now the filter widget is displayed again and filters both products correctly. So now it's counting the variable product too?!?
  5. Edit the variable "Product1" and make variations with the attribute ARTIST and COLOR so that all variations have both attributes (in my case it doesn't make sense to show variation options for ARTIST, but we need this step).
    Now the filter is showing on pages as expected even if we delete Product1 > filter is counting the ARTIST attribute.
  6. Edit the Product1 again, by unchecking attribute ARTIST from 'use for variations'. Don't touch anything else, just save. The product still has the variations with the COLOR attribute.
    Now the filter is counting the product with ARTIST attribute correctly!!!
  7. ...but the last step only works for the Shop page. The widget isn't showing on the product's category page.

If you know a fix, please let me know, I have just three days left on this project.

PS Just tested 4.5 RC3 and the issues described above persist.

Konamiman added a commit that referenced this pull request Sep 9, 2020
This commit reverts the functionality introduced in PR #26260
(later refined by #27175, #27190, #27508) in which filtering by
attribute using the layered nav widget was improved to handle the
cases of variations out of stock. The revert is a response to the
numerous problems reported by users in Woo 4.4 and 4.5

Not all the code has been reverted, only the code that resulted in
visible functionality changes. Thus, the code that generates
term relationships for variations is still in place to keep database
consistency and to keep the reverting changes to the minimum needed.
Konamiman added a commit that referenced this pull request Sep 9, 2020
This commit reverts the functionality introduced in PR #26260
(later refined by #27175, #27190, #27508) in which filtering by
attribute using the layered nav widget was improved to handle the
cases of variations out of stock. The revert is a response to the
numerous problems reported by users in Woo 4.4 and 4.5

Not all the code has been reverted, only the code that resulted in
visible functionality changes. Thus, the code that generates
term relationships for variations is still in place to keep database
consistency and to keep the reverting changes to the minimum needed.
@Konamiman
Copy link
Contributor Author

@B-Anders (and everybody having similar issues), please take a look at this: #27419 (comment)

@vedanshujain vedanshujain restored the fix/25524 branch September 10, 2020 08:29
jonathansadowski pushed a commit that referenced this pull request Sep 10, 2020
This commit reverts the functionality introduced in PR #26260
(later refined by #27175, #27190, #27508) in which filtering by
attribute using the layered nav widget was improved to handle the
cases of variations out of stock. The revert is a response to the
numerous problems reported by users in Woo 4.4 and 4.5

Not all the code has been reverted, only the code that resulted in
visible functionality changes. Thus, the code that generates
term relationships for variations is still in place to keep database
consistency and to keep the reverting changes to the minimum needed.
@TheGranadilla
Copy link

TheGranadilla commented Oct 2, 2020

Hi,
I was wondering if you were still planning to improve nav filtering by attributes for variables products.
Just to hide results for not in stock items.

I know it's a complex thing, that is discuss since years. (See #20800 from 2018).
But it's also something important. Actually, the filtering return out of stock variations, which is a big user experience killer!
I'm verry suprise this issue is pending since so long!?

The only solution at the moment, would be to delete the out-of-stockvariations, but this is going to be a nightmare, especially since those variations might get back in stock one day...

Is fixing this still an objective?

Thanks !

@Konamiman
Copy link
Contributor Author

Hi @TheGranadilla,

Yes, we plan to take on this problem again at some point in the future. Please see this comment in the original issue.

@MohsinQK
Copy link

This feature stopped working again in the latest releases of woocommerce.
in 4.4 it works as expected, but in 4.7 it's not working as expected.
this is a very important feature. is this removed in the latest version or its by mistake?

WooCommerce 4.7
image

Just Changed the woocommerce version to 4.4 and it works again. out of stock(Red Background) is not in the listing any more.
image

@TheGranadilla
Copy link

@MohsinQK This was reverted in 4.5 because it introduced new bugs.
But it seems they aren't working anymore on variables products Filtering........
@Konamiman Any update on this? Woocmmerce widget still return out of stock variations....

@Konamiman Konamiman mentioned this pull request Feb 5, 2021
7 tasks
@kalessil kalessil deleted the fix/25524 branch September 24, 2024 06:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Bug The issue is a confirmed bug. release: add testing instructions PRs that have not had testing instructions added to the wiki. [auto] release: highlight Issues that have a high user impact and need to be discussed/paid attention to.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Explore the feasibility of improved filtering of variations