1111
1212use GraphQL \Type \Definition \ResolveInfo ;
1313use WPGraphQL \AppContext ;
14- use WPGraphQL \Data \Connection \PostObjectConnectionResolver ;
14+ use WPGraphQL \WooCommerce \ Data \Connection \Product_Connection_Resolver ;
1515use WPGraphQL \WooCommerce \WP_GraphQL_WooCommerce ;
1616
1717/**
@@ -33,17 +33,9 @@ public static function register_connections() {
3333 [
3434 'fromType ' => 'Coupon ' ,
3535 'resolve ' => static function ( $ source , array $ args , AppContext $ context , ResolveInfo $ info ) {
36- add_filter ( 'graphql_post_object_connection_args ' , [ self ::class, 'bypass_get_args_sanitization ' ], 10 , 3 );
37- $ resolver = new PostObjectConnectionResolver ( $ source , $ args , $ context , $ info , 'product ' );
38- remove_filter ( 'graphql_post_object_connection_args ' , [ self ::class, 'bypass_get_args_sanitization ' ], 10 );
39-
36+ $ resolver = new Product_Connection_Resolver ( $ source , $ args , $ context , $ info );
4037 $ resolver ->set_query_arg ( 'post__in ' , $ source ->product_ids );
4138
42- // Change default ordering.
43- if ( ! in_array ( 'orderby ' , array_keys ( $ resolver ->get_query_args () ), true ) ) {
44- $ resolver ->set_query_arg ( 'orderby ' , 'post__in ' );
45- }
46-
4739 return $ resolver ->get_connection ();
4840 },
4941 ]
@@ -55,10 +47,7 @@ public static function register_connections() {
5547 'fromType ' => 'Coupon ' ,
5648 'fromFieldName ' => 'excludedProducts ' ,
5749 'resolve ' => static function ( $ source , array $ args , AppContext $ context , ResolveInfo $ info ) {
58- add_filter ( 'graphql_post_object_connection_args ' , [ self ::class, 'bypass_get_args_sanitization ' ], 10 , 3 );
59- $ resolver = new PostObjectConnectionResolver ( $ source , $ args , $ context , $ info , 'product ' );
60- remove_filter ( 'graphql_post_object_connection_args ' , [ self ::class, 'bypass_get_args_sanitization ' ], 10 );
61-
50+ $ resolver = new Product_Connection_Resolver ( $ source , $ args , $ context , $ info );
6251 $ resolver ->set_query_arg ( 'post__in ' , $ source ->excluded_product_ids );
6352
6453 // Change default ordering.
@@ -78,8 +67,7 @@ public static function register_connections() {
7867 [
7968 'fromType ' => 'Product ' ,
8069 'fromFieldName ' => 'related ' ,
81- 'connectionArgs ' => array_merge (
82- self ::get_connection_args (),
70+ 'connectionArgs ' => self ::get_connection_args (
8371 [
8472 'shuffle ' => [
8573 'type ' => 'Boolean ' ,
@@ -88,9 +76,7 @@ public static function register_connections() {
8876 ]
8977 ),
9078 'resolve ' => static function ( $ source , array $ args , AppContext $ context , ResolveInfo $ info ) {
91- add_filter ( 'graphql_post_object_connection_args ' , [ self ::class, 'bypass_get_args_sanitization ' ], 10 , 3 );
92- $ resolver = new PostObjectConnectionResolver ( $ source , $ args , $ context , $ info , 'product ' );
93- remove_filter ( 'graphql_post_object_connection_args ' , [ self ::class, 'bypass_get_args_sanitization ' ], 10 );
79+ $ resolver = new Product_Connection_Resolver ( $ source , $ args , $ context , $ info );
9480
9581 // Bypass randomization by default for pagination support.
9682 if ( empty ( $ args ['where ' ]['shuffle ' ] ) ) {
@@ -105,11 +91,6 @@ static function () {
10591 $ related_ids = wc_get_related_products ( $ source ->ID , $ resolver ->get_query_amount () );
10692 $ resolver ->set_query_arg ( 'post__in ' , $ related_ids );
10793
108- // Change default ordering.
109- if ( ! in_array ( 'orderby ' , array_keys ( $ resolver ->get_query_args () ), true ) ) {
110- $ resolver ->set_query_arg ( 'orderby ' , 'post__in ' );
111- }
112-
11394 return $ resolver ->get_connection ();
11495 },
11596 ]
@@ -121,17 +102,9 @@ static function () {
121102 'fromType ' => 'Product ' ,
122103 'fromFieldName ' => 'upsell ' ,
123104 'resolve ' => static function ( $ source , array $ args , AppContext $ context , ResolveInfo $ info ) {
124- add_filter ( 'graphql_post_object_connection_args ' , [ self ::class, 'bypass_get_args_sanitization ' ], 10 , 3 );
125- $ resolver = new PostObjectConnectionResolver ( $ source , $ args , $ context , $ info , 'product ' );
126- remove_filter ( 'graphql_post_object_connection_args ' , [ self ::class, 'bypass_get_args_sanitization ' ], 10 );
127-
105+ $ resolver = new Product_Connection_Resolver ( $ source , $ args , $ context , $ info );
128106 $ resolver ->set_query_arg ( 'post__in ' , $ source ->upsell_ids );
129107
130- // Change default ordering.
131- if ( ! in_array ( 'orderby ' , array_keys ( $ resolver ->get_query_args () ), true ) ) {
132- $ resolver ->set_query_arg ( 'orderby ' , 'post__in ' );
133- }
134-
135108 return $ resolver ->get_connection ();
136109 },
137110 ]
@@ -144,17 +117,9 @@ static function () {
144117 [
145118 'fromType ' => 'GroupProduct ' ,
146119 'resolve ' => static function ( $ source , array $ args , AppContext $ context , ResolveInfo $ info ) {
147- add_filter ( 'graphql_post_object_connection_args ' , [ self ::class, 'bypass_get_args_sanitization ' ], 10 , 3 );
148- $ resolver = new PostObjectConnectionResolver ( $ source , $ args , $ context , $ info , 'product ' );
149- remove_filter ( 'graphql_post_object_connection_args ' , [ self ::class, 'bypass_get_args_sanitization ' ], 10 );
150-
120+ $ resolver = new Product_Connection_Resolver ( $ source , $ args , $ context , $ info );
151121 $ resolver ->set_query_arg ( 'post__in ' , $ source ->grouped_ids );
152122
153- // Change default ordering.
154- if ( ! in_array ( 'orderby ' , array_keys ( $ resolver ->get_query_args () ), true ) ) {
155- $ resolver ->set_query_arg ( 'orderby ' , 'post__in ' );
156- }
157-
158123 return $ resolver ->get_connection ();
159124 },
160125 ]
@@ -165,17 +130,8 @@ static function () {
165130 $ cross_sell_config = [
166131 'fromFieldName ' => 'crossSell ' ,
167132 'resolve ' => static function ( $ source , array $ args , AppContext $ context , ResolveInfo $ info ) {
168- add_filter ( 'graphql_post_object_connection_args ' , [ self ::class, 'bypass_get_args_sanitization ' ], 10 , 3 );
169- $ resolver = new PostObjectConnectionResolver ( $ source , $ args , $ context , $ info , 'product ' );
170- remove_filter ( 'graphql_post_object_connection_args ' , [ self ::class, 'bypass_get_args_sanitization ' ], 10 );
171-
133+ $ resolver = new Product_Connection_Resolver ( $ source , $ args , $ context , $ info );
172134 $ resolver ->set_query_arg ( 'post__in ' , $ source ->cross_sell_ids );
173-
174- // Change default ordering.
175- if ( ! in_array ( 'orderby ' , array_keys ( $ resolver ->get_query_args () ), true ) ) {
176- $ resolver ->set_query_arg ( 'orderby ' , 'post__in ' );
177- }
178-
179135 return $ resolver ->get_connection ();
180136 },
181137 ];
@@ -198,21 +154,12 @@ static function () {
198154 'toType ' => 'ProductVariation ' ,
199155 'fromFieldName ' => 'variations ' ,
200156 'resolve ' => static function ( $ source , array $ args , AppContext $ context , ResolveInfo $ info ) {
201- add_filter ( 'graphql_post_object_connection_args ' , [ self ::class, 'bypass_get_args_sanitization ' ], 10 , 3 );
202- $ resolver = new PostObjectConnectionResolver ( $ source , $ args , $ context , $ info , 'product ' );
203- remove_filter ( 'graphql_post_object_connection_args ' , [ self ::class, 'bypass_get_args_sanitization ' ], 10 );
157+ $ resolver = new Product_Connection_Resolver ( $ source , $ args , $ context , $ info );
204158
205159 $ resolver ->set_query_arg ( 'post_parent ' , $ source ->ID );
206160 $ resolver ->set_query_arg ( 'post_type ' , 'product_variation ' );
207161 $ resolver ->set_query_arg ( 'post__in ' , $ source ->variation_ids );
208162
209- // Change default ordering.
210- if ( ! in_array ( 'orderby ' , array_keys ( $ resolver ->get_query_args () ), true ) ) {
211- $ resolver ->set_query_arg ( 'orderby ' , 'post__in ' );
212- }
213-
214- $ resolver = self ::set_ordering_query_args ( $ resolver , $ args );
215-
216163 return $ resolver ->get_connection ();
217164 },
218165 ]
@@ -232,14 +179,9 @@ static function () {
232179 return null ;
233180 }
234181
235- add_filter ( 'graphql_post_object_connection_args ' , [ self ::class, 'bypass_get_args_sanitization ' ], 10 , 3 );
236- $ resolver = new PostObjectConnectionResolver ( $ source , $ args , $ context , $ info , 'product ' );
237- remove_filter ( 'graphql_post_object_connection_args ' , [ self ::class, 'bypass_get_args_sanitization ' ], 10 );
238-
182+ $ resolver = new Product_Connection_Resolver ( $ source , $ args , $ context , $ info );
239183 $ resolver ->set_query_arg ( 'p ' , $ source ->parent_id );
240184
241- $ resolver = self ::set_ordering_query_args ( $ resolver , $ args );
242-
243185 return $ resolver ->one_to_one ()->get_connection ();
244186 },
245187 ]
@@ -255,30 +197,16 @@ static function () {
255197 'toType ' => 'ProductVariation ' ,
256198 'fromFieldName ' => 'variations ' ,
257199 'resolve ' => static function ( $ source , array $ args , AppContext $ context , ResolveInfo $ info ) {
258- global $ wpdb ;
259- add_filter ( 'graphql_post_object_connection_args ' , [ self ::class, 'bypass_get_args_sanitization ' ], 10 , 3 );
260- $ resolver = new PostObjectConnectionResolver ( $ source , $ args , $ context , $ info , 'product_variation ' );
261- remove_filter ( 'graphql_post_object_connection_args ' , [ self ::class, 'bypass_get_args_sanitization ' ], 10 );
262-
263- // phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase
264- $ attribute_meta_key = 'attribute_ ' . strtolower ( preg_replace ( '/([A-Z])/ ' , '_$1 ' , $ source ->taxonomyName ) );
265- // phpcs:ignore WordPress.DB.DirectDatabaseQuery
266- $ variation_ids = $ wpdb ->get_col (
267- $ wpdb ->prepare (
268- "SELECT ID
269- FROM {$ wpdb ->prefix }posts
270- WHERE ID IN (SELECT post_id FROM {$ wpdb ->prefix }postmeta WHERE meta_key = %s AND meta_value = %s)
271- AND post_type = 'product_variation' " ,
272- $ attribute_meta_key ,
273- $ source ->slug
274- )
275- );
276-
277- $ variation_ids = ! empty ( $ variation_ids ) ? $ variation_ids : [ '0 ' ];
278-
279- $ resolver ->set_query_arg ( 'post__in ' , $ variation_ids );
200+ $ attribute_meta_key = 'attribute_ ' . strtolower ( preg_replace ( '/([A-Z])/ ' , '_$1 ' , $ source ->taxonomyName ) ); // phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase
201+ $ meta_query = [
202+ 'key ' => $ attribute_meta_key ,
203+ 'value ' => $ source ->slug ,
204+ 'compare ' => '= ' ,
205+ ];
280206
281- $ resolver = self ::set_ordering_query_args ( $ resolver , $ args );
207+ $ resolver = new Product_Connection_Resolver ( $ source , $ args , $ context , $ info );
208+ $ resolver ->set_query_arg ( 'post_type ' , 'product_variation ' );
209+ $ resolver ->add_meta_query ( $ meta_query );
282210
283211 return $ resolver ->get_connection ();
284212 },
@@ -319,26 +247,20 @@ public static function set_connection_config( $config ) {
319247 $ from_type = $ config ['fromType ' ];
320248 if ( 'Product ' === $ to_type ) {
321249 $ config ['connectionArgs ' ] = self ::get_connection_args ();
322- $ config ['queryClass ' ] = '\WC_Product_Query ' ;
323250 }
324251
325252 $ taxonomies = self ::get_product_connected_taxonomies ();
326253 if ( 'Product ' === $ to_type && in_array ( $ from_type , $ taxonomies , true ) ) {
327254 $ config ['resolve ' ] = static function ( $ source , array $ args , AppContext $ context , ResolveInfo $ info ) {
328- add_filter ( 'graphql_post_object_connection_args ' , [ self ::class, 'bypass_get_args_sanitization ' ], 10 , 3 );
329- $ resolver = new PostObjectConnectionResolver ( $ source , $ args , $ context , $ info , 'product ' );
330- remove_filter ( 'graphql_post_object_connection_args ' , [ self ::class, 'bypass_get_args_sanitization ' ], 10 );
331255 $ tax_query = [
332256 [
333- 'taxonomy ' => $ source ->taxonomyName , // phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase
334- 'terms ' => [ $ source ->term_id ],
335- 'field ' => 'term_id ' ,
336- 'include_children ' => false ,
257+ 'taxonomy ' => $ source ->taxonomyName , // phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase
258+ 'operator ' => 'EXISTS ' ,
337259 ],
338260 ];
339- $ resolver ->set_query_arg ( 'tax_query ' , $ tax_query );
340261
341- $ resolver = self ::set_ordering_query_args ( $ resolver , $ args );
262+ $ resolver = new Product_Connection_Resolver ( $ source , $ args , $ context , $ info );
263+ $ resolver ->add_tax_query ( $ tax_query );
342264
343265 return $ resolver ->get_connection ();
344266 };
@@ -359,14 +281,9 @@ public static function get_connection_config( $args = [] ): array {
359281 'fromType ' => 'RootQuery ' ,
360282 'toType ' => 'Product ' ,
361283 'fromFieldName ' => 'products ' ,
362- 'queryClass ' => '\WC_Product_Query ' ,
363284 'connectionArgs ' => self ::get_connection_args (),
364285 'resolve ' => static function ( $ source , array $ args , AppContext $ context , ResolveInfo $ info ) {
365- add_filter ( 'graphql_post_object_connection_args ' , [ self ::class, 'bypass_get_args_sanitization ' ], 10 , 3 );
366- $ resolver = new PostObjectConnectionResolver ( $ source , $ args , $ context , $ info , 'product ' );
367- remove_filter ( 'graphql_post_object_connection_args ' , [ self ::class, 'bypass_get_args_sanitization ' ], 10 );
368-
369- $ resolver = self ::set_ordering_query_args ( $ resolver , $ args );
286+ $ resolver = new Product_Connection_Resolver ( $ source , $ args , $ context , $ info );
370287
371288 return $ resolver ->get_connection ();
372289 },
@@ -375,19 +292,6 @@ public static function get_connection_config( $args = [] ): array {
375292 );
376293 }
377294
378- /**
379- * Bypass arg sanization in Post Object Connection Resolver.
380- *
381- * @param array $args Sanitized GraphQL args passed to the resolver.
382- * @param \WPGraphQL\Data\Connection\PostObjectConnectionResolver $connection_resolver Instance of the ConnectionResolver.
383- * @param array $all_args array of arguments input in the field as part of the GraphQL query.
384-
385- * @return array
386- */
387- public static function bypass_get_args_sanitization ( $ args , $ connection_resolver , $ all_args ) {
388- return $ all_args ;
389- }
390-
391295 /**
392296 * Undocumented function
393297 *
@@ -432,10 +336,12 @@ public static function set_ordering_query_args( $resolver, $args ) {
432336
433337 /**
434338 * Returns array of where args.
339+ *
340+ * @param array $extra_args Extra connection args.
435341 *
436342 * @return array
437343 */
438- public static function get_connection_args (): array {
344+ public static function get_connection_args ( $ extra_args = [] ): array {
439345 $ args = [
440346 'slugIn ' => [
441347 'type ' => [ 'list_of ' => 'String ' ],
@@ -561,6 +467,10 @@ public static function get_connection_args(): array {
561467 'type ' => 'Boolean ' ,
562468 'description ' => __ ( 'Limit result types to types supported by WooGraphQL. ' , 'wp-graphql-woocommerce ' ),
563469 ],
470+ 'includeVariations ' => [
471+ 'type ' => 'Boolean ' ,
472+ 'description ' => __ ( 'Include variations in the result set. ' , 'wp-graphql-woocommerce ' ),
473+ ],
564474 ];
565475
566476 if ( wc_tax_enabled () ) {
@@ -570,7 +480,7 @@ public static function get_connection_args(): array {
570480 ];
571481 }
572482
573- return array_merge ( get_wc_cpt_connection_args (), $ args );
483+ return array_merge ( get_wc_cpt_connection_args (), $ args, $ extra_args );
574484 }
575485
576486 /**
@@ -610,6 +520,10 @@ public static function map_input_fields_to_wp_query( $query_args, $args, $source
610520 'tag__not_in ' ,
611521 ];
612522
523+ if ( isset ( $ where_args ['includeVariations ' ] ) && $ where_args ['includeVariations ' ] ) {
524+ $ query_args ['post_type ' ] = [ 'product ' , 'product_variation ' ];
525+ }
526+
613527 $ query_args = array_diff_key ( $ query_args , array_flip ( $ remove ) );
614528
615529 if ( ! empty ( $ where_args ['slugIn ' ] ) ) {
0 commit comments