-
Notifications
You must be signed in to change notification settings - Fork 10.8k
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
(HPOS/COT) Orders Admin List > Prevent user from paging out-of-bounds #34793
Conversation
…t table for orders).
$order_query_args = (array) apply_filters( 'woocommerce_order_list_table_prepare_items_query_args', $this->order_query_args ); | ||
|
||
// We must ensure the 'paginate' argument is set. | ||
$order_query_args['paginate'] = true; |
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.
This isn't directly related to the problem at hand, but I thought it was a sensible safeguard (since custom code hooked in to the above filter could remove it, but we depend on it being set to true).
Test Results SummaryCommit SHA: 2e43f52
To view the full E2E test report, click here. To view all test reports, visit the WooCommerce Test Reports Dashboard. |
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.
Hey @barryhughes!
This works perfectly. Thanks! 🥇
Not really a blocker, but I had a question about a particular line of code (marked in the review). Let me know what you think!
$count_query_args['page'] = 1; | ||
$count_query_args['limit'] = 1; | ||
$order_count = wc_get_orders( $count_query_args ); | ||
$max_num_pages = (int) ceil( $order_count->total / $order_query_args['limit'] ); |
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.
Can't we just use $order_count->max_num_pages
instead of calculating $max_num_pages
here? For that to work, we would have to not override the limit
arg, though, so that the one in $order_query_args
is used instead.
I might be missing something, though, so please let me know.
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.
Hi @jorgeatorres,
Yes—that would definitely make the code a lot cleaner/shorter (and it's what I tried first) ... but it doesn't work quite as one might expect.
Suppose we have 100 orders and we are fetching pages of 20 items (so, 5 pages in total). Regardless of whether the data-store is COT or CPT, once we are 'out of bounds' (in the following example I am trying to access page 20, which is not available) we aren't going to get back the information we need:
wc_get_orders( [
'limit' => 20,
'page' => 20,
'paginate' => true,
] )->max_num_pages;
# => (int) 0
In fact, the same thing can be observed if we use a WP_Query
(and in the case of the CPT data-store that is presumably the origin of this behavior):
( new WP_Query( [
'post_type' => 'shop_order',
'paged' => 20,
'posts_per_page' => 20,
'post_status' => 'any',
] ) )->max_num_pages;
# => (int) 0
So, in summary, we will get back useful pagination data so long as we are within the bounds of the available data. Outside of that, it zeroes out and we either need to workaround it as I did here or use direct queries (I'm trying to be data-store agnostic in my approach, though).
Please do let me know if you can see another path (or if I'm misunderstanding), though.
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.
Yes, I observed that same behavior (which can be argued is confusing), but in any case, I believe $order_count
should be within bounds because we're setting page
to 1 in the args for that specific query. So if we don't set limit = 1
we should be basically running the same query as the main query but on page 1, which would give us correct information... or am I missing something @barryhughes?
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.
Sorry, @jorgeatorres—I misunderstood your question 😓
Yes, I believe you are correct. It's more a question of trade-offs. If we retain the same limit (let's say it is 20) then we are also going to fetch upto that number of orders and load them into memory, simply to discard them and perform a redirect (via the call to set_pagination_args()
).
With this strategy, we fetch only 1 entity and the arithmetic to calculate $max_num_pages
is surely very fast. So, while we could shave off a couple of lines of code by keeping limit
(and in some cases, this may be a lot higher than 20—such as if the merchant configures the number of items per page to 100), it comes with a higher cost.
On the flip-side, your suggestion probably makes the code a bit more readable. What do you think?
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.
With this strategy, we fetch only 1 entity and the arithmetic to calculate $max_num_pages is surely very fast.
I wasn't considering performance when I posted my comment, but that makes sense. I still think it's not ideal that we have to do this, and possibly something to add/change in OrdersTableQuery
, but right now is probably not the best moment to do that 😅.
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 think it's not ideal that we have to do this, and possibly something to add/change in OrdersTableQuery, but right now is probably not the best moment to do that 😅.
Yep, I agree with both parts; though changing OrdersTableQuery
might mean we also need a corresponding change in WC_Order_Data_Store_CPT
. I think it would be a reasonable change to introduce, and could definitely simplify things.
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.
LGTM 🚢.
Hi @jorgeatorres, thanks for merging this pull request. Please take a look at these follow-up tasks you may need to perform:
|
…#34793) (HPOS/COT) prevent user from paging beyond available range (admin list table for orders).
With the 'legacy' admin list table for orders, or in fact any of the default CPT admin list tables, users are prevented from paging beyond the range of available pages. For example, suppose:
Due to an oversight, that same behavior does not currently happen with respect to the COT/HPOS admin list table. This change addresses that.
How to test the changes in this Pull Request:
Enable COT/HPOS.
FOR PR REVIEWER ONLY: