Skip to content

Commit de8cad3

Browse files
authored
fix: Fixed all product connection filtering regressions (#704)
* fix: Fixed all product connection filtering regressions * chore: WPCS compliance met * fix: Unsupport syntax refactored
1 parent 18e66cd commit de8cad3

File tree

5 files changed

+198
-159
lines changed

5 files changed

+198
-159
lines changed

includes/class-core-schema-filters.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,11 @@ public static function add_filters() {
123123
10,
124124
2
125125
);
126+
127+
add_filter(
128+
'graphql_wp_connection_type_config',
129+
[ '\WPGraphQL\WooCommerce\Connection\Products', 'set_connection_config' ]
130+
);
126131
}
127132

128133
/**

includes/connection/class-products.php

Lines changed: 63 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,7 @@ function() {
225225
'fromFieldName' => 'parent',
226226
'description' => __( 'The parent of the node. The parent object can be of various types', 'wp-graphql-woocommerce' ),
227227
'oneToOne' => true,
228+
'queryClass' => '\WC_Product_Query',
228229
'resolve' => function( $source, $args, AppContext $context, ResolveInfo $info ) {
229230
if ( empty( $source->parent_id ) ) {
230231
return null;
@@ -243,27 +244,6 @@ function() {
243244
]
244245
);
245246

246-
// Taxonomy To Product resolver.
247-
$resolve_product_from_taxonomy = function( $source, array $args, AppContext $context, ResolveInfo $info ) {
248-
add_filter( 'graphql_post_object_connection_args', [ __CLASS__, 'bypass_get_args_sanitization' ], 10, 3 );
249-
$resolver = new PostObjectConnectionResolver( $source, $args, $context, $info, 'product' );
250-
remove_filter( 'graphql_post_object_connection_args', [ __CLASS__, 'bypass_get_args_sanitization' ], 10, 3 );
251-
252-
$tax_query = [
253-
[
254-
// WPCS: slow query ok.
255-
'taxonomy' => $source->taxonomyName, // phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase
256-
'field' => 'term_id',
257-
'terms' => $source->term_id,
258-
],
259-
];
260-
$resolver->set_query_arg( 'tax_query', $tax_query );
261-
262-
$resolver = self::set_ordering_query_args( $resolver, $args );
263-
264-
return $resolver->get_connection();
265-
};
266-
267247
// From WooCommerce product attributes.
268248
$attributes = WP_GraphQL_WooCommerce::get_product_attribute_taxonomies();
269249
foreach ( $attributes as $attribute ) {
@@ -275,7 +255,9 @@ function() {
275255
'fromFieldName' => 'variations',
276256
'resolve' => function( $source, array $args, AppContext $context, ResolveInfo $info ) {
277257
global $wpdb;
258+
add_filter( 'graphql_post_object_connection_args', [ __CLASS__, 'bypass_get_args_sanitization' ], 10, 3 );
278259
$resolver = new PostObjectConnectionResolver( $source, $args, $context, $info, 'product_variation' );
260+
remove_filter( 'graphql_post_object_connection_args', [ __CLASS__, 'bypass_get_args_sanitization' ], 10, 3 );
279261

280262
// phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase
281263
$attribute_meta_key = 'attribute_' . strtolower( preg_replace( '/([A-Z])/', '_$1', $source->taxonomyName ) );
@@ -291,8 +273,9 @@ function() {
291273
)
292274
);
293275

276+
$variation_ids = ! empty( $variation_ids ) ? $variation_ids : [ '0' ];
277+
294278
$resolver->set_query_arg( 'post__in', $variation_ids );
295-
$resolver->set_query_arg( 'post_type', 'product_variation' );
296279

297280
$resolver = self::set_ordering_query_args( $resolver, $args );
298281

@@ -304,6 +287,64 @@ function() {
304287
}//end foreach
305288
}
306289

290+
/**
291+
* Returns the singular name of all registered taxonomies connected the products.
292+
*
293+
* @return array
294+
*/
295+
private static function get_product_connected_taxonomies() {
296+
$taxonomies = [];
297+
$allowed_taxonomies = \WPGraphQL::get_allowed_taxonomies( 'objects' );
298+
299+
foreach ( $allowed_taxonomies as $tax_object ) {
300+
if ( ! in_array( 'product', $tax_object->object_type, true ) ) {
301+
continue;
302+
}
303+
304+
$taxonomies[] = ucfirst( $tax_object->graphql_single_name );
305+
}
306+
307+
return $taxonomies;
308+
}
309+
310+
/**
311+
* Ensures all connection the `Product` type have proper connection config upon registration.
312+
*
313+
* @param array $config Connection config.
314+
* @return array
315+
*/
316+
public static function set_connection_config( $config ) {
317+
$to_type = $config['toType'];
318+
$from_type = $config['fromType'];
319+
if ( 'Product' === $to_type ) {
320+
$config['connectionArgs'] = self::get_connection_args();
321+
$config['queryClass'] = '\WC_Product_Query';
322+
}
323+
324+
$taxonomies = self::get_product_connected_taxonomies();
325+
if ( 'Product' === $to_type && in_array( $from_type, $taxonomies, true ) ) {
326+
$config['resolve'] = function( $source, array $args, AppContext $context, ResolveInfo $info ) {
327+
add_filter( 'graphql_post_object_connection_args', [ __CLASS__, 'bypass_get_args_sanitization' ], 10, 3 );
328+
$resolver = new PostObjectConnectionResolver( $source, $args, $context, $info, 'product' );
329+
remove_filter( 'graphql_post_object_connection_args', [ __CLASS__, 'bypass_get_args_sanitization' ], 10, 3 );
330+
$tax_query = [
331+
[
332+
'taxonomy' => $source->taxonomyName, // phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase
333+
'terms' => [ $source->term_id ],
334+
'field' => 'term_id',
335+
'include_children' => false,
336+
],
337+
];
338+
$resolver->set_query_arg( 'tax_query', $tax_query );
339+
340+
$resolver = self::set_ordering_query_args( $resolver, $args );
341+
342+
return $resolver->get_connection();
343+
};
344+
}
345+
return $config;
346+
}
347+
307348
/**
308349
* Given an array of $args, this returns the connection config, merging the provided args
309350
* with the defaults

tests/_support/Factory/ProductVariationFactory.php

Lines changed: 23 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -32,14 +32,26 @@ public function create_object( $args ) {
3232

3333
// Create variation.
3434
$variation = new $variation_class();
35-
$variation->set_props( $args );
36-
if ( ! empty( $args['meta_data'] ) ) {
37-
$variation->set_meta_data( $args['meta_data'] );
38-
}
39-
if ( ! empty( $args['attributes'] ) ) {
40-
$variation->set_attributes( $args['attributes'] );
35+
foreach ( $args as $field => $field_value ) {
36+
if ( ! is_callable( [ $variation, "set_{$field}" ] ) ) {
37+
throw new \Exception(
38+
sprintf( '"%1$s" is not a valid %2$s product variation field.', $field, $variation->get_type() )
39+
);
40+
}
41+
42+
$variation->{"set_{$field}"}( $field_value );
4143
}
4244

45+
// if ( ! empty( $args['meta_data'] ) ) {
46+
// $variation->set_meta_data( $args['meta_data'] );
47+
// unset( $args['meta_data'] );
48+
// }
49+
// if ( ! empty( $args['attributes'] ) ) {
50+
// $variation->set_attributes( $args['attributes'] );
51+
// unset( $args['attributes'] );
52+
// }
53+
// $variation->set_props( $args );
54+
4355
return $variation->save();
4456
}
4557

@@ -51,7 +63,7 @@ public function update_object( $object, $fields ) {
5163
foreach ( $fields as $field => $field_value ) {
5264
if ( ! is_callable( [ $object, "set_{$field}" ] ) ) {
5365
throw new \Exception(
54-
sprintf( '"%1$s" is not a valid %2$s product field.', $field, $object->get_type() )
66+
sprintf( '"%1$s" is not a valid %2$s product variation field.', $field, $object->get_type() )
5567
);
5668
}
5769

@@ -73,12 +85,14 @@ public function createSome( $product = null, $args = [] ) {
7385
// Create variation stub data.
7486
$variation_data = [
7587
[
88+
'parent_id' => $product,
7689
'attributes' => [ 'pa_size' => 'small' ],
7790
'image_id' => null,
7891
'downloads' => [ $this->factory->product->createDownload() ],
7992
'regular_price' => 10,
8093
],
8194
[
95+
'parent_id' => $product,
8296
'attributes' => [ 'pa_size' => 'medium' ],
8397
'image_id' => $this->factory->post->create(
8498
[
@@ -91,6 +105,7 @@ public function createSome( $product = null, $args = [] ) {
91105
'regular_price' => 15,
92106
],
93107
[
108+
'parent_id' => $product,
94109
'attributes' => [ 'pa_size' => 'large' ],
95110
'image_id' => null,
96111
'downloads' => [],
@@ -101,14 +116,7 @@ public function createSome( $product = null, $args = [] ) {
101116
$variations = [];
102117
foreach ( $variation_data as $data ) {
103118
$args = array_merge( $data, $args );
104-
$variation = $this->create_and_get(
105-
$args,
106-
[
107-
'parent_id' => $product,
108-
'sku' => uniqid(),
109-
'variation_class' => '\WC_Product_Variation',
110-
]
111-
);
119+
$variation = $this->create_and_get( $args, [ 'variation_class' => '\WC_Product_Variation' ] );
112120

113121
$variations[] = $variation->get_id();
114122
}

0 commit comments

Comments
 (0)