-
Notifications
You must be signed in to change notification settings - Fork 10.7k
Fix the visibility of partially out of stock variable products when using the layered nav widget #26260
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
a14b1ef to
9965951
Compare
f6c8fc2 to
0466c0b
Compare
claudiosanches
left a comment
There was a problem hiding this 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.
claudiosanches
left a comment
There was a problem hiding this 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.
|
@Konamiman I found a strange problem. the filter is working but a bit buggy. in frontend the filter works but buggy for example
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. I think its only working in the Order their Variation attributes are selected from the backend. |
|
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.
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.
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! |
I believe this is the correct behaviour.
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 |
398d568 to
e26ddf4
Compare
|
Hi @MohsinQK and @IlPicasso, I have made changes so that:
I hope those changes are sensible and useful. |
|
@Konamiman yes the Point 2 is correct it's my misunderstanding. but point 4 was not fine for which you made some changes already. |
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.
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.
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.
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.
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.
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.
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.
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.
|
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:
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. |
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.
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.
|
@B-Anders (and everybody having similar issues), please take a look at this: #27419 (comment) |
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.
|
Hi, I know it's a complex thing, that is discuss since years. (See #20800 from 2018). 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 ! |
|
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 This was reverted in 4.5 because it introduced new bugs. |








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!
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:
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
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.
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:
Changelog entry