wp-graphql / wp-graphql-woocommerce

Add WooCommerce support and functionality to your WPGraphQL server
https://woographql.com
GNU General Public License v3.0
644 stars 131 forks source link

Enable support for product types: subscription and bundle #247

Closed ranaaterning closed 3 years ago

ranaaterning commented 4 years ago

Is your feature request related to a problem? Please describe. We are using woocommerce subscription products and bundle products, and as there is a feature in wp graphql woo that allows us to filter on a products type, we would like to be able to filter on the types subscription and bundle which is not possible at the moment.

Describe the solution you'd like Extend the ProductTypesEnum to allow bundle and subscription

ranaaterning commented 4 years ago

Just realised this is possible with the taxonomyFilter like so: { products(where: {taxonomyFilter: {AND: {taxonomy: TYPE, terms: ["bundle", "subscription"]}} }) { nodes { id name } } }

Although, when trying to fetch the type here on the product it will give you an internal server error.

kidunot89 commented 4 years ago

@ranaaterning This is because the Product Interface type doesn't know how to resolve Subscriptions or Bundle product types.

Before they can be used in the WooGraphQL schema.

  1. They must have types created and registered using register_graphql_object_type().
  2. Then they must be added to the enabled product types using this hook here.
    • key is the product type slug
    • value is the GraphQL object type for the product type.
niklaslovgren commented 4 years ago

Also trying to use Bundle product types.

I've created and registered the type using register_graphql_object_type() and I've added the type to the enabled product types using the hook graphql_enabled_wc_product_types.

(We are currently at version 0.2.0 and upgrading to latest version broke too many things, so trying to upgrade version by version to see what breaks and when. At 0.4.1 now, which is why graphql_enabled_wc_product_types is used instead of graphql_woocommerce_product_types.)

function add_bundle_to_product_types($enabled_product_types) {
    $enabled_product_types['bundle'] = "BundledProduct";
    return $enabled_product_types;
}
add_filter( 'graphql_enabled_wc_product_types', 'add_bundle_to_product_types' );

This gives me this error:

"Runtime Object type \"BundledProduct\" is not a possible type for \"Product\"."

Apart from the two steps listed above, does something else need to be done?

zamson commented 4 years ago

@niklaslovgren did you ever make any progress with product bundles?

niklaslovgren commented 4 years ago

@zamson Haven't had time to dive deeper yet, unfortunately. @kidunot89, maybe you can point us in the right direction?

kidunot89 commented 4 years ago

@niklaslovgren are you implementing the Product interface?

You can learn more about interfaces here

Also note that the parent interface fields don't have to be redefined in WPGraphQL.

jacobarriola commented 4 years ago

@kidunot89 I tried to implement this for bundles as well with some success, but am still missing something.

Here are the problems that I'm facing:

  1. The inline fragment for my new BundleProduct type does not show
  2. A test field for the new type does not show

Is/are there some steps that I'm missing? Thanks!

Here's my implementation 👇🏽


// Register the BundleProduct type with wp-graphql
add_action( 'graphql_register_types', function () {
    register_graphql_object_type(
        'BundleProduct',
        [
            'description' => 'A product bundle object',
            'interfaces'  => [ 'Node', 'Product' ],
            'fields'      => array_merge(
                \WPGraphQL\WooCommerce\Type\WPInterface\Product::get_fields(),
                [
                    'test' => [
                        'type'     => 'String',
                        'resolve' => function () {
                            return 'hello';
                        },
                    ],
                ]
            ),
        ]
    );
} );

// Add the new type to wp-graphql-woocommerce
add_filter( 'graphql_woocommerce_product_types', function ( $product_types ) {
    $product_types['bundle'] = 'BundleProduct';

    return $product_types;
} );

No errors 🙌, but limited querying without an inline fragment image

My new BundleProduct type does not show as an inline fragment 👇🏽 image

My new test field doesn't show 🤔 image

kidunot89 commented 4 years ago

@jacobarriola Have you tried it like this? :point_down:

// Register the BundleProduct type with wp-graphql
add_action( 'graphql_register_types', function () {
    register_graphql_object_type(
        'BundleProduct',
        [
            'description' => 'A product bundle object',
            'interfaces'  => [ 'Node', 'Product' ],
            'fields'      => [
                'test' => [
                    'type'     => 'String',
                    'resolver' => function () {
                        return 'hello';
                    },
                ],
            ]
        ]
    );
} );

// Add the new type to wp-graphql-woocommerce
add_filter( 'graphql_woocommerce_product_types', function ( $product_types ) {
    $product_types['bundle'] = 'BundleProduct';

    return $product_types;
} );
jacobarriola commented 4 years ago

@kidunot89 it's the same result.

jacobarriola commented 4 years ago

@kidunot89 it oddly works as expected when I fire off a random register_graphql_field() and return the new BundleProduct type. Not sure why this works, but it doesn't feel like this is the correct way to set it up.

Perhaps I'm missing something?

BTW, I'm on:

wp-graphql: 0.10.0 wp-graphql-woocommerce: 0.5.1

add_action( 'graphql_register_types', function () {
    register_graphql_object_type( 'BundleProduct', [
            'description' => 'A product bundle object',
            'interfaces'  => [ 'Node', 'Product' ],
            'fields'      => array_merge(
                \WPGraphQL\WooCommerce\Type\WPInterface\Product::get_fields(),
                [
                    'test' => [
                        'type'     => 'String',
                        'resolve' => function () {
                            return 'hello';
                        },
                    ],
                ]
            )
        ]
    );

        // The BundleProduct type only works when I have this function running
    register_graphql_field(
        'Product',
        'something',
        [
            'type'=> 'BundleProduct'
        ]
    );
} );

add_filter( 'graphql_woocommerce_product_types', function ( $product_types ) {
    $product_types['bundle'] = 'BundleProduct';

    return $product_types;
} );
jacobarriola commented 4 years ago

@kidunot89 looks like this is expected behavior for registering a new object type on wp-graphql.

I ended up doing a RootQuery for my register_graphql_field() to mimic the other product types 👍

I had to review a pair-programming session that Jason did with me to debug this issue 🙌 https://youtu.be/afEKFwGUiyE?t=1299

kidunot89 commented 4 years ago

@jacobarriola Does it appear as a child type of the Product interface?

jacobarriola commented 4 years ago

@kidunot89

It's listed as an implementation of Product when I explore the schema on graphiql. Is that what you mean by 'child type of the the Product interface'?

image

kidunot89 commented 4 years ago

@jacobarriola Yep. Also in case you didn't know you can use the $source object to resolve the product fields, like this $source->get_regular_price(). The Product model forwards all unknown method calls to the source WC_Product object, which in this case would be the product bundles object.

jacobarriola commented 4 years ago

@kidunot89 Oh great. Thanks for that.

Looks like product bundles are instances of the WC_Product_Bundle object, so I'll see what's available to me out-of-the-box with WC_Product. I may have to find a way to short-circuit $source to be an instance of WC_Product_Bundle instead.

ref: https://docs.woocommerce.com/document/bundles/bundles-data-structures-storage/#section-3

kidunot89 commented 4 years ago

@jacobarriola the hook you need is here

Just use this filter to return instance of WC_Product_Bundle to be used as the source by the Product model.

kidunot89 commented 4 years ago

@jacobarriola Also you don't have to redefine fields defined in the Product interface in you BundleProduct type. See definition for the core product types that implement the Product interface here to get a better understanding.

zamson commented 4 years ago

@jacobarriola is it working for you? Would you mind sharing a gist of this implementation? Also looking to implement this for a project this upcoming week.

jacobarriola commented 4 years ago

@zamson I'm close. I'll share something real soon, ok 👍

jacobarriola commented 4 years ago

@zamson I started writing a blog post on this. It's still a work-in-progress, but hopefully it'll help you get started on your implementation.

Post: https://jacobarriola.com/post/woocommerce-graphql-product-bundles Gist: https://gist.github.com/jacobarriola/5d055ba102c001f0c556427a1ae78cd2

kidunot89 commented 4 years ago

@jacobarriola Love the blog post.

zamson commented 4 years ago

@jacobarriola Love the blog post.

+1

super helpful with the write up @jacobarriola

jacobarriola commented 3 years ago

I just published a WooGraphQL extension for Product Bundles if anyone is looking to support this type in their schema: https://github.com/jacobarriola/woographql-product-bundles

@zamson sorry it took so long, but let me know if it helps you 👍🏽

@kidunot89 we can probably close this out since you published the Subscription as well 🙌🏽

chekdotdev commented 3 years ago

All of this is awesome, thank you!

@jacobarriola you mention that @kidunot89 "published the Subscription" – Am I missing a link somewhere where I can snag a snippet for creating an extension for Subscriptions?

kidunot89 commented 3 years ago

@jchekanoff https://github.com/wp-graphql/woographql-subscriptions

Note that it's kinda buggy. I've been too swarmed to get back to it. So contributions are very welcome.

sorensenjg commented 3 years ago

Thanks to the existing work by @jacobarriola and @kidunot89, Ive started another extension for Composite Product support. It is a WIP and i would appreciate any help getting it production ready. Currently, composite products and their components are being returned. You can also drill down to their associated settings and products. I need to figure out the necessary mutations still. Bring on the PRs!

https://github.com/sorensenjg/woographql-composite-products

kidunot89 commented 3 years ago

Awesome, feel free to reach out in Slack, and I'll try to provide whatever help I can.

alexkey89 commented 6 months ago

Bit late into this but is there a way for wpgraphql to support this gift card product type "wgm_gift_card" that is being added by this plugin "woo-gift-cards-lite"? (or any type that is added dynamically by any other plugin?)

I query via the IDE this:

query GET_PRODUCTS {
  products(first: 10) {
    nodes {
      name
      ... on SimpleProduct {
        databaseId
        image {
          sourceUrl
        }
        price
        sku
        salePrice
        onSale
        regularPrice
      }
    }
  }
}
Error:
"The \"wgm_gift_card\" product type is not supported by the core WPGraphQL WooCommerce (WooGraphQL) schema"