10
10
11
11
use WPGraphQL \Connection \PostObjects ;
12
12
use WPGraphQL \Data \Connection \PostObjectConnectionResolver ;
13
+ use WPGraphQL \FacetWP \Type \Enum \SortOptionsEnum ;
13
14
use WPGraphQL \FacetWP \Type \Input ;
14
15
15
16
/**
@@ -104,6 +105,10 @@ public static function get_facet_input_type( array $config ) {
104
105
// Single Int.
105
106
$ type = 'Int ' ;
106
107
108
+ break ;
109
+ case 'sort ' :
110
+ $ type = SortOptionsEnum::get_type_name ( $ config ['name ' ] );
111
+
107
112
break ;
108
113
case 'autocomplete ' :
109
114
case 'checkboxes ' :
@@ -217,6 +222,20 @@ private static function register_root_field( array $facet_config ) :void {
217
222
],
218
223
];
219
224
225
+ // Stash the sort settings, since we don't get them from the payload.
226
+ $ sort_settings = [];
227
+
228
+ // Apply the orderby args.
229
+ foreach ( $ fwp_args ['facets ' ] as $ key => $ facet_args ) {
230
+ if ( ! empty ( $ facet_args ['is_sort ' ] ) ) {
231
+ $ fwp_args ['query_args ' ] = array_merge_recursive ( $ fwp_args ['query_args ' ], $ facet_args ['query_args ' ] );
232
+ $ sort_settings [ $ key ] = $ facet_args ['settings ' ];
233
+
234
+ // Set the selected facet back to a string.
235
+ $ fwp_args ['facets ' ][ $ key ] = $ facet_args ['selected ' ];
236
+ }
237
+ }
238
+
220
239
$ filtered_ids = [];
221
240
if ( $ use_graphql_pagination ) {
222
241
@@ -241,8 +260,11 @@ function ( $post_ids ) use ( &$filtered_ids ) {
241
260
242
261
// @todo helper function.
243
262
foreach ( $ payload ['facets ' ] as $ key => $ facet ) {
263
+ // Try to get the settings from the payload, otherwise fallback to the parsed query args.
244
264
if ( isset ( $ facet ['settings ' ] ) ) {
245
265
$ facet ['settings ' ] = self ::to_camel_case ( $ facet ['settings ' ] );
266
+ } elseif ( isset ( $ sort_settings [ $ key ] ) ) {
267
+ $ facet ['settings ' ] = self ::to_camel_case ( $ sort_settings [ $ key ] );
246
268
}
247
269
248
270
$ payload ['facets ' ][ $ key ] = $ facet ;
@@ -256,6 +278,7 @@ function ( $post_ids ) use ( &$filtered_ids ) {
256
278
'facets ' => array_values ( $ payload ['facets ' ] ),
257
279
'results ' => count ( $ results ) ? $ results : null ,
258
280
'pager ' => $ payload ['pager ' ] ?? [],
281
+ 'is_sort ' => ! empty ( $ fwp_args ['query_args ' ]['orderby ' ] ),
259
282
];
260
283
},
261
284
]
@@ -450,10 +473,16 @@ private static function register_facet_connection( array $facet_config ) : void
450
473
}
451
474
452
475
$ resolver = new PostObjectConnectionResolver ( $ source , $ args , $ context , $ info , $ type );
476
+
453
477
if ( ! empty ( $ source ['results ' ] ) ) {
454
478
$ resolver ->set_query_arg ( 'post__in ' , $ source ['results ' ] );
455
479
}
456
480
481
+ // Use post__in when delegating sorting to FWP.
482
+ if ( ! empty ( $ source ['is_sort ' ] ) ) {
483
+ $ resolver ->set_query_arg ( 'orderby ' , 'post__in ' );
484
+ }
485
+
457
486
return $ resolver ->get_connection ();
458
487
},
459
488
];
@@ -489,41 +518,79 @@ private static function parse_query( array $query ) : array {
489
518
$ reduced_query = array_reduce (
490
519
$ facets ,
491
520
function ( $ prev , $ cur ) use ( $ query ) {
492
- $ name = $ cur ['name ' ];
493
- $ facet = isset ( $ query [ $ name ] ) ? $ query [ $ name ] : null ;
494
-
495
- if ( isset ( $ facet ) ) {
496
- switch ( $ cur ['type ' ] ) {
497
- case 'checkboxes ' :
498
- case 'fselect ' :
499
- case 'rating ' :
500
- case 'radio ' :
501
- case 'dropdown ' :
502
- case 'hierarchy ' :
503
- case 'search ' :
504
- case 'autocomplete ' :
505
- $ prev [ $ name ] = $ facet ;
506
- break ;
507
- case 'slider ' :
508
- case 'date_range ' :
509
- case 'number_range ' :
510
- $ input = $ facet ;
511
- $ prev [ $ name ] = [
512
- $ input ['min ' ],
513
- $ input ['max ' ],
514
- ];
521
+ // Get the facet name.
522
+ $ name = $ cur ['name ' ] ?? '' ;
523
+ $ camel_cased_name = ! empty ( $ name ) ? self ::to_camel_case ( $ name ) : '' ;
524
+ $ facet = is_string ( $ camel_cased_name ) && isset ( $ query [ $ camel_cased_name ] ) ? $ query [ $ camel_cased_name ] : null ;
525
+
526
+ // Fallback to snakeCased name.
527
+ if ( ! isset ( $ facet ) ) {
528
+ $ facet = isset ( $ query [ $ name ] ) ? $ query [ $ name ] : null ;
529
+ }
515
530
516
- break ;
517
- case 'proximity ' :
518
- $ input = $ facet ;
519
- $ prev [ $ name ] = [
520
- $ input ['latitude ' ],
521
- $ input ['longitude ' ],
522
- $ input ['chosenRadius ' ],
523
- $ input ['locationName ' ],
524
- ];
525
- break ;
526
- }
531
+ switch ( $ cur ['type ' ] ) {
532
+ case 'checkboxes ' :
533
+ case 'fselect ' :
534
+ case 'rating ' :
535
+ case 'radio ' :
536
+ case 'dropdown ' :
537
+ case 'hierarchy ' :
538
+ case 'search ' :
539
+ case 'autocomplete ' :
540
+ $ prev [ $ name ] = $ facet ;
541
+ break ;
542
+ case 'slider ' :
543
+ case 'date_range ' :
544
+ case 'number_range ' :
545
+ $ input = $ facet ;
546
+ $ prev [ $ name ] = [
547
+ $ input ['min ' ] ?? null ,
548
+ $ input ['max ' ] ?? null ,
549
+ ];
550
+
551
+ break ;
552
+ case 'proximity ' :
553
+ $ input = $ facet ;
554
+ $ prev [ $ name ] = [
555
+ $ input ['latitude ' ] ?? null ,
556
+ $ input ['longitude ' ] ?? null ,
557
+ $ input ['chosenRadius ' ] ?? null ,
558
+ $ input ['locationName ' ] ?? null ,
559
+ ];
560
+
561
+ break ;
562
+
563
+ case 'sort ' :
564
+ $ input = $ facet ;
565
+ $ sort_options = self ::parse_sort_facet_options ( $ cur );
566
+
567
+ // We pass these through to create our sort args.
568
+ $ prev [ $ name ] = [
569
+ 'is_sort ' => true ,
570
+ 'selected ' => $ facet ,
571
+ 'settings ' => [
572
+ 'default_label ' => $ cur ['default_label ' ],
573
+ 'sort_options ' => $ cur ['sort_options ' ],
574
+ ],
575
+ 'query_args ' => [],
576
+ ];
577
+
578
+ /**
579
+ * Define the query args for the sort.
580
+ *
581
+ * This is a shim of FacetWP_Facet_Sort::apply_sort()
582
+ */
583
+ if ( ! empty ( $ sort_options [ $ facet ] ) ) {
584
+ $ qa = $ sort_options [ $ facet ]['query_args ' ];
585
+
586
+ if ( isset ( $ qa ['meta_query ' ] ) ) {
587
+ $ prev [ $ name ]['query_args ' ]['meta_query ' ] = $ qa ['meta_query ' ];
588
+ }
589
+
590
+ $ prev [ $ name ]['query_args ' ]['orderby ' ] = $ qa ['orderby ' ];
591
+ }
592
+
593
+ break ;
527
594
}
528
595
529
596
return $ prev ;
@@ -617,4 +684,41 @@ private static function register_facet_settings() : void {
617
684
public static function use_graphql_pagination () : bool {
618
685
return apply_filters ( 'wpgraphql_facetwp_user_graphql_pagination ' , false );
619
686
}
687
+
688
+ /**
689
+ * Parses the sort options for a sort facet into a WP_Query compatible array.
690
+ *
691
+ * @see \FacetWP_Facet_Sort::parse_sort_facet()
692
+ *
693
+ * @param array<string, mixed> $facet The facet configuration.
694
+ */
695
+ private static function parse_sort_facet_options ( array $ facet ) : array {
696
+ $ sort_options = [];
697
+
698
+ foreach ( $ facet ['sort_options ' ] as $ row ) {
699
+ $ parsed = FWP ()->builder ->parse_query_obj ( [ 'orderby ' => $ row ['orderby ' ] ] );
700
+
701
+ $ sort_options [ $ row ['name ' ] ] = [
702
+ 'label ' => $ row ['label ' ],
703
+ 'query_args ' => array_intersect_key (
704
+ $ parsed ,
705
+ [
706
+ 'meta_query ' => true ,
707
+ 'orderby ' => true ,
708
+ ]
709
+ ),
710
+ ];
711
+ }
712
+
713
+ $ sort_options = apply_filters (
714
+ 'facetwp_facet_sort_options ' ,
715
+ $ sort_options ,
716
+ [
717
+ 'facet ' => $ facet ,
718
+ 'template_name ' => 'graphql ' ,
719
+ ]
720
+ );
721
+
722
+ return $ sort_options ;
723
+ }
620
724
}
0 commit comments