Created
July 12, 2020 22:11
-
-
Save jacobarriola/76ba565039c0e32f484be385969d4aca to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace App\GraphQL; | |
use WC_Bundled_Item_Data; | |
use WC_PB_DB; | |
use WPGraphQL\AppContext; | |
use WPGraphQL\WooCommerce\Data\Connection\Product_Connection_Resolver; | |
/** | |
* Register a GraphQL Connection between Product and BundleProduct in order to return the | |
* bundle items for a given Product Bundle | |
*/ | |
add_action( 'graphql_register_types', function () { | |
register_graphql_connection( [ | |
'fromType' => TYPE_BUNDLE_PRODUCT, | |
'toType' => 'Product', | |
'fromFieldName' => 'bundleItems', | |
'resolve' => function ( $source, $args, $context, $info ) { | |
$resolver = new Product_Connection_Resolver( $source, $args, $context, $info ); | |
return $resolver->get_connection(); | |
}, | |
'edgeFields' => [ | |
'quantityMin' => [ | |
'type' => 'Int', | |
'resolve' => function ( $source ) { | |
wp_send_json($source); | |
/* @var $bundledItem WC_Bundled_Item_Data */ | |
$bundledItem = $source['bundledItem']; | |
return $bundledItem->get_meta( 'quantity_min' ); | |
}, | |
], | |
'quantityMax' => [ | |
'type' => 'Int', | |
'resolve' => function ( $source ) { | |
/* @var $bundledItem WC_Bundled_Item_Data */ | |
$bundledItem = $source['bundledItem']; | |
return $bundledItem->get_meta( 'quantity_max' ); | |
}, | |
], | |
], | |
] ); | |
} ); | |
/** | |
* Short-circuit WP_Query to ensure we only query bundle items for a given post. Ideally | |
* would like to set query_args at the resolver level during the | |
* register_graphql_connection(), but query args don't take effect there. | |
* | |
* see https://github.com/wp-graphql/wp-graphql-woocommerce/issues/321 | |
*/ | |
add_filter( 'graphql_product_connection_query_args', function ( $query_args, $source, $args, $context, $info ) { | |
// Bail if this isn't a bundle | |
if ( 'bundle' !== $source->type ) { | |
return $query_args; | |
} | |
// Get the product id of the Product Bundle parent | |
$productId = $source->productId; | |
// Bail if we don't have a product id to run our query | |
if ( empty( $productId ) ) { | |
return $query_args; | |
} | |
global $wpdb; | |
/** | |
* Allow for LIMIT overwrites if greater than n is needed for a use-case | |
* | |
* @param array $query_args The args that will be passed to the WP_Query. | |
* @param mixed $source The source that's passed down the GraphQL queries. | |
* @param array $args The inputArgs on the field. | |
* @param AppContext $context The AppContext passed down the GraphQL tree. | |
* @param ResolveInfo $info The ResolveInfo passed down the GraphQL tree. | |
*/ | |
$bundle_item_limit = apply_filters( 'graphql_product_bundle_item_connector_limit', 10, $source, $args, $context, $info ); | |
// Run our query - get me all of the post ids of the bundle items | |
$bundle_item_ids = $wpdb->get_results( $wpdb->prepare( " | |
SELECT | |
product_id | |
FROM | |
{$wpdb->prefix}woocommerce_bundled_items | |
WHERE | |
bundle_id = %d | |
LIMIT %d | |
", | |
intval( $productId ), | |
intval( $bundle_item_limit ) | |
) ); | |
// Extract IDs from query result with some wp_list_pluck magic and set post__in args | |
$query_args['post__in'] = wp_list_pluck( $bundle_item_ids, 'product_id' ); | |
return $query_args; | |
}, 10, 5 ); | |
/** | |
* Inject the WC_Bundled_Item_Data Class into the resolver so that fields can access | |
* edge data | |
*/ | |
add_filter( 'graphql_connection_edges', function ( $edges, $resolver ) { | |
$source = $resolver->getSource(); | |
// Bail if we don't have a source | |
if ( empty( $source ) ) { | |
return $edges; | |
} | |
// Bail if we don't have a type to check against | |
if ( empty( $source->type ) ) { | |
return $edges; | |
} | |
// Bail if our $source isn't a bundle | |
if ( 'bundle' !== $source->type ) { | |
return $edges; | |
} | |
// Get some info about the $resolver | |
$resolverInfo = $resolver->getInfo(); | |
// Bail if there isn't any info | |
if ( empty( $resolverInfo ) ) { | |
return $edges; | |
} | |
// Get the name of the field we are resolving | |
$fieldName = $resolverInfo->fieldName; | |
// Bail if there's nothing to check against | |
if ( empty( $fieldName ) ) { | |
return $edges; | |
} | |
// Bail if our field isn't bundleItems | |
if ( 'bundleItems' !== $fieldName ) { | |
return $edges; | |
} | |
$bundled_data_items = $resolver->getSource()->get_bundled_data_items(); | |
// Go through each edge, find the bundle item id, and set the bundleItem | |
foreach ( $edges as $key => $edge ) { | |
$raw_bundled_data_item = array_filter( $bundled_data_items, function ( WC_Bundled_Item_Data $item ) use ( $edge ) { | |
return $item->get_product_id() === $edge['node']->ID; | |
} ); | |
if ( empty( $raw_bundled_data_item ) ) { | |
$edges[ $key ]['bundledItem'] = []; | |
continue; | |
} | |
$bundled_data_item = array_values( $raw_bundled_data_item ); | |
// Expose the bundleItem so that the resolver can get edge data | |
$edges[ $key ]['bundledItem'] = WC_PB_DB::get_bundled_item( $bundled_data_item[0]->get_bundled_item_id() ); | |
} | |
return $edges; | |
}, 10, 2 ); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment