Skip to content

Commit 3baeb2b

Browse files
authored
fix: "menu_order" pagination fixed (#922)
* fix: "menu_order" pagination fixed * devops: More unit tests added for product pagination
1 parent aff0437 commit 3baeb2b

File tree

3 files changed

+214
-10
lines changed

3 files changed

+214
-10
lines changed

bin/_lib.sh

-1
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,6 @@ remove_wordpress() {
5050

5151
# Remove WordPress dependencies
5252
composer remove --dev wp-graphql/wp-graphql-jwt-authentication \
53-
axepress/wp-graphql-headless-login \
5453
wpackagist-plugin/woocommerce-gateway-stripe \
5554
wpackagist-plugin/wp-graphql \
5655
wpackagist-theme/twentytwentyone \

includes/data/connection/class-product-connection-resolver.php

+9-9
Original file line numberDiff line numberDiff line change
@@ -196,23 +196,23 @@ public function get_query_args() {
196196
$query_args['graphql_cursor_compare_by_price_key'] = 'wc_product_meta_lookup.max_price';
197197
$query_args['graphql_cursor_compare_by_price_value'] = $price;
198198
}
199-
}
200-
201-
if ( $offset_product && 'popularity' === $query_args['orderby'] ) {
199+
} elseif ( $offset_product && 'popularity' === $query_args['orderby'] ) {
202200
$query_args['graphql_cursor_compare_by_popularity_value'] = $offset_product->get_total_sales();
203201
$query_args['graphql_cursor_compare_by_popularity_key'] = 'wc_product_meta_lookup.total_sales';
204-
}
205-
206-
if ( $offset_product && 'rating' === $query_args['orderby'] ) {
202+
} elseif ( $offset_product && 'rating' === $query_args['orderby'] ) {
207203
$query_args['graphql_cursor_compare_by_rating_value'] = $offset_product->get_average_rating();
208204
$query_args['graphql_cursor_compare_by_rating_key'] = 'wc_product_meta_lookup.average_rating';
209-
}
210-
211-
if ( $offset_product && 'comment_count' === $query_args['orderby'] ) {
205+
} elseif ( $offset_product && 'comment_count' === $query_args['orderby'] ) {
212206
$query_args['graphql_cursor_compare_by_comment_count_value'] = $offset_product->get_rating_count();
213207
$query_args['graphql_cursor_compare_by_comment_count_key'] = 'wc_product_meta_lookup.rating_count';
214208
$query_args['graphql_cursor_compare_by_rating_value'] = $offset_product->get_average_rating();
215209
$query_args['graphql_cursor_compare_by_rating_key'] = 'wc_product_meta_lookup.average_rating';
210+
} elseif ( $offset_product && 'menu_order title' === $query_args['orderby'] ) {
211+
$query_args['orderby'] = [
212+
'menu_order' => $query_args['order'],
213+
'post_title' => isset( $this->args['last'] ) ? 'ASC' : 'DESC',
214+
];
215+
unset( $query_args['order'] );
216216
}
217217

218218
/**

tests/wpunit/ConnectionPaginationTest.php

+205
Original file line numberDiff line numberDiff line change
@@ -246,6 +246,211 @@ static function ( $key_a, $key_b ) {
246246
$this->assertQuerySuccessful( $response, $expected );
247247
}
248248

249+
public function testProductsPaginationWithOrderby() {
250+
$products = [
251+
$this->factory->product->createSimple( [ 'menu_order' => 0, 'regular_price' => 5 ] ),
252+
$this->factory->product->createSimple( [ 'menu_order' => 1, 'regular_price' => 4 ] ),
253+
$this->factory->product->createSimple( [ 'menu_order' => 2, 'regular_price' => 3, 'sale_price' => 0.50 ] ),
254+
$this->factory->product->createSimple( [ 'menu_order' => 3, 'regular_price' => 2 ] ),
255+
$this->factory->product->createSimple( [ 'menu_order' => 4, 'regular_price' => 1 ] ),
256+
];
257+
258+
usort(
259+
$products,
260+
static function ( $key_a, $key_b ) {
261+
return $key_a < $key_b;
262+
}
263+
);
264+
265+
$query = '
266+
query ($first: Int, $last: Int, $after: String, $before: String, $where: RootQueryToProductUnionConnectionWhereArgs) {
267+
products(first: $first, last: $last, after: $after, before: $before, where: $where) {
268+
found
269+
nodes {
270+
databaseId
271+
menuOrder
272+
}
273+
pageInfo {
274+
hasPreviousPage
275+
hasNextPage
276+
startCursor
277+
endCursor
278+
}
279+
}
280+
}
281+
';
282+
283+
/**
284+
* Assertion One
285+
*
286+
* Test "first" parameter with the "orderby.MENU_ORDER".
287+
*/
288+
$variables = [ 'first' => 2, 'where' => [ 'orderby' => [ [ 'field' => 'MENU_ORDER', 'order' => 'DESC' ] ] ] ];
289+
$response = $this->graphql( compact( 'query', 'variables' ) );
290+
$expected = [
291+
$this->expectedField( 'products.found', 5 ),
292+
$this->expectedField( 'products.pageInfo.hasPreviousPage', false ),
293+
$this->expectedField( 'products.pageInfo.hasNextPage', true ),
294+
$this->expectedField( 'products.pageInfo.startCursor', $this->toCursor( $products[0] ) ),
295+
$this->expectedField( 'products.pageInfo.endCursor', $this->toCursor( $products[1] ) ),
296+
$this->expectedField( 'products.nodes.0.databaseId', $products[0] ),
297+
$this->expectedField( 'products.nodes.1.databaseId', $products[1] ),
298+
];
299+
300+
$this->assertQuerySuccessful( $response, $expected );
301+
302+
/**
303+
* Assertion Two
304+
*
305+
* Test "after" parameter with the "orderby.MENU_ORDER".
306+
*/
307+
$variables = [
308+
'first' => 3,
309+
'after' => $this->toCursor( $products[1] ),
310+
'where' => [ 'orderby' => [ [ 'field' => 'MENU_ORDER', 'order' => 'DESC' ] ] ],
311+
];
312+
$response = $this->graphql( compact( 'query', 'variables' ) );
313+
$expected = [
314+
$this->expectedField( 'products.found', static::IS_NULL ),
315+
$this->expectedField( 'products.pageInfo.hasPreviousPage', true ),
316+
$this->expectedField( 'products.pageInfo.hasNextPage', false ),
317+
$this->expectedField( 'products.pageInfo.startCursor', $this->toCursor( $products[2] ) ),
318+
$this->expectedField( 'products.pageInfo.endCursor', $this->toCursor( $products[4] ) ),
319+
$this->expectedField( 'products.nodes.0.databaseId', $products[2] ),
320+
$this->expectedField( 'products.nodes.1.databaseId', $products[3] ),
321+
$this->expectedField( 'products.nodes.2.databaseId', $products[4] ),
322+
];
323+
324+
$this->assertQuerySuccessful( $response, $expected );
325+
326+
/**
327+
* Assertion Three
328+
*
329+
* Test "last" parameter with the "orderby.MENU_ORDER".
330+
*/
331+
$variables = [ 'last' => 2, 'where' => [ 'orderby' => [ [ 'field' => 'MENU_ORDER', 'order' => 'DESC' ] ] ] ];
332+
$response = $this->graphql( compact( 'query', 'variables' ) );
333+
$expected = [
334+
$this->expectedField( 'products.found', 5 ),
335+
$this->expectedField( 'products.pageInfo.hasPreviousPage', true ),
336+
$this->expectedField( 'products.pageInfo.hasNextPage', false ),
337+
$this->expectedField( 'products.pageInfo.startCursor', $this->toCursor( $products[1] ) ),
338+
$this->expectedField( 'products.pageInfo.endCursor', $this->toCursor( $products[0] ) ),
339+
$this->expectedField( 'products.nodes.0.databaseId', $products[1] ),
340+
$this->expectedField( 'products.nodes.1.databaseId', $products[0] ),
341+
];
342+
343+
$this->assertQuerySuccessful( $response, $expected );
344+
345+
/**
346+
* Assertion Four
347+
*
348+
* Test "before" parameter with the "orderby.MENU_ORDER".
349+
*/
350+
$variables = [
351+
'last' => 2,
352+
'before' => $this->toCursor( $products[1] ),
353+
'where' => [ 'orderby' => [ [ 'field' => 'MENU_ORDER', 'order' => 'DESC' ] ] ]
354+
];
355+
$response = $this->graphql( compact( 'query', 'variables' ) );
356+
$expected = [
357+
$this->expectedField( 'products.found', static::IS_NULL ),
358+
$this->expectedField( 'products.pageInfo.hasPreviousPage', true ),
359+
$this->expectedField( 'products.pageInfo.hasNextPage', true ),
360+
$this->expectedField( 'products.pageInfo.startCursor', $this->toCursor( $products[3] ) ),
361+
$this->expectedField( 'products.pageInfo.endCursor', $this->toCursor( $products[2] ) ),
362+
$this->expectedField( 'products.nodes.0.databaseId', $products[3] ),
363+
$this->expectedField( 'products.nodes.1.databaseId', $products[2] ),
364+
];
365+
366+
$this->assertQuerySuccessful( $response, $expected );
367+
368+
/**
369+
* Assertion Five
370+
*
371+
* Test "first" parameter with the "orderby.PRICE".
372+
*/
373+
$variables = [ 'first' => 2, 'where' => [ 'orderby' => [ [ 'field' => 'PRICE', 'order' => 'DESC' ] ] ] ];
374+
$response = $this->graphql( compact( 'query', 'variables' ) );
375+
$expected = [
376+
$this->expectedField( 'products.found', 5 ),
377+
$this->expectedField( 'products.pageInfo.hasPreviousPage', false ),
378+
$this->expectedField( 'products.pageInfo.hasNextPage', true ),
379+
$this->expectedField( 'products.pageInfo.startCursor', $this->toCursor( $products[4] ) ),
380+
$this->expectedField( 'products.pageInfo.endCursor', $this->toCursor( $products[3] ) ),
381+
$this->expectedField( 'products.nodes.0.databaseId', $products[4] ),
382+
$this->expectedField( 'products.nodes.1.databaseId', $products[3] ),
383+
];
384+
385+
$this->assertQuerySuccessful( $response, $expected );
386+
387+
/**
388+
* Assertion Six
389+
*
390+
* Test "after" parameter with the "orderby.PRICE".
391+
*/
392+
$variables = [
393+
'first' => 3,
394+
'after' => $this->toCursor( $products[3] ),
395+
'where' => [ 'orderby' => [ [ 'field' => 'PRICE', 'order' => 'DESC' ] ] ],
396+
];
397+
$response = $this->graphql( compact( 'query', 'variables' ) );
398+
$expected = [
399+
$this->expectedField( 'products.found', static::IS_NULL ),
400+
$this->expectedField( 'products.pageInfo.hasPreviousPage', true ),
401+
$this->expectedField( 'products.pageInfo.hasNextPage', false ),
402+
$this->expectedField( 'products.pageInfo.startCursor', $this->toCursor( $products[1] ) ),
403+
$this->expectedField( 'products.pageInfo.endCursor', $this->toCursor( $products[2] ) ),
404+
$this->expectedField( 'products.nodes.0.databaseId', $products[1] ),
405+
$this->expectedField( 'products.nodes.1.databaseId', $products[0] ),
406+
$this->expectedField( 'products.nodes.2.databaseId', $products[2] ),
407+
];
408+
409+
$this->assertQuerySuccessful( $response, $expected );
410+
411+
/**
412+
* Assertion Seven
413+
*
414+
* Test "last" parameter with the "orderby.PRICE".
415+
*/
416+
$variables = [ 'last' => 2, 'where' => [ 'orderby' => [ [ 'field' => 'PRICE', 'order' => 'ASC' ] ] ] ];
417+
$response = $this->graphql( compact( 'query', 'variables' ) );
418+
$expected = [
419+
$this->expectedField( 'products.found', 5 ),
420+
$this->expectedField( 'products.pageInfo.hasPreviousPage', true ),
421+
$this->expectedField( 'products.pageInfo.hasNextPage', false ),
422+
$this->expectedField( 'products.pageInfo.startCursor', $this->toCursor( $products[0] ) ),
423+
$this->expectedField( 'products.pageInfo.endCursor', $this->toCursor( $products[2] ) ),
424+
$this->expectedField( 'products.nodes.0.databaseId', $products[0] ),
425+
$this->expectedField( 'products.nodes.1.databaseId', $products[2] ),
426+
];
427+
428+
$this->assertQuerySuccessful( $response, $expected );
429+
430+
/**
431+
* Assertion Eight
432+
*
433+
* Test "before" parameter with the "orderby.PRICE".
434+
*/
435+
$variables = [
436+
'last' => 2,
437+
'before' => $this->toCursor( $products[0] ),
438+
'where' => [ 'orderby' => [ [ 'field' => 'PRICE', 'order' => 'ASC' ] ] ]
439+
];
440+
$response = $this->graphql( compact( 'query', 'variables' ) );
441+
$expected = [
442+
$this->expectedField( 'products.found', static::IS_NULL ),
443+
$this->expectedField( 'products.pageInfo.hasPreviousPage', true ),
444+
$this->expectedField( 'products.pageInfo.hasNextPage', true ),
445+
$this->expectedField( 'products.pageInfo.startCursor', $this->toCursor( $products[3] ) ),
446+
$this->expectedField( 'products.pageInfo.endCursor', $this->toCursor( $products[1] ) ),
447+
$this->expectedField( 'products.nodes.0.databaseId', $products[3] ),
448+
$this->expectedField( 'products.nodes.1.databaseId', $products[1] ),
449+
];
450+
451+
$this->assertQuerySuccessful( $response, $expected );
452+
}
453+
249454
public function testOrdersPagination() {
250455
$this->loginAsShopManager();
251456

0 commit comments

Comments
 (0)