Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Error when querying products that are ACF relationship field items within a Flexible Content #449

Closed
boxxroom opened this issue Mar 4, 2021 · 16 comments

Comments

@boxxroom
Copy link

boxxroom commented Mar 4, 2021

Describe the bug
Attaching a product relationship within a Flexible content ACF field on to a Page post type renders an Abstract type error due to the resolve. The resolve is expected to resolve to an Object type.

To Reproduce
Steps to reproduce the behavior:

  1. ACF JSON Export File OR
    Create a new ACF Field Group (named WPGraphQL Example) with a Location > Rules equal to Page
    Add a Flexible Content (named Flexible Content)
    Field Type: Relationship (Layout name: Relationship Field, Field Label: Product Relationship)
    Filter by Post Type: Product
    Filter by Taxonomy: Simple (optional)
    Filters: All Checked
    Elements: Featured Image Checked
    Return Object: Post Object
    Save.

  2. Navigate to Pages
    Choose a page: Home (take note of page ID)
    Add ACF Flexible Content
    Relationship Field
    Select 1+ products
    Save

  3. Navigate to GraphiQL IDE > Add GraphQL statement (GraphQL Statement) OR

query PageById($id: Int!) {
  pageBy(pageId: $id) {
    id
    isFrontPage
    wpgraphqlExample {
      flexibleContent {
        ... on Page_Wpgraphqlexample_FlexibleContent_RelationshipField {
          fieldGroupName
          productRelationship {
            ... on SimpleProduct {
              id
              name
            }
          }
        }
      }
    }
  }
}

// Query Variables

{"id": 33}
  1. Press Play > See error

Expected behavior
A list of product objects

Screenshots
WPGraphQL-Example-Error

Desktop (please complete the following information):

  • OS: macOS Big Sur 11.2.1
  • Browser Chrome
  • Version 88.0.4324.182 (Official Build) (x86_64)

Plugin Versions

  • WooGraphQL Version: 0.6.1
  • WPGraphQL Version: 1.2.5
  • WordPress Version: 5.6.2 (Bedrock)
  • WooCommerce Version: 4.8.0
  • WPGraphQL for Advanced Custom Fields: 0.3.5
  • WPGraphQL JWT Authentication: 0.4.1
  • Disable Gutenberg: 2.4
  • Safe SVG: 1.9.9
  • WooCommerce Accommodation Bookings: 1.1.23
  • WooCommerce Bookings: 1.15.31
  • WooCommerce Product Vendors: 2.1.45

Additional context
I have also added to this thread with a information, findings and debug #253 (comment)

@boxxroom
Copy link
Author

boxxroom commented Mar 11, 2021

Attempting to find a work around or at the very least a quick fix for the above issue.

The Attempt

add_filter('graphql_Page_Wpgraphqlexample_FlexibleContent_RelationshipField_fields', function ($fields) {
    if (isset($fields['productRelationship'])) {
        $fields['productRelationship']['resolve'] = function ($root, $args, $context, $info) {
            return array_map(function ($id) {
                return new \WPGraphQL\WooCommerce\Model\Product($id);
            }, $root['field_6041494b07558']);
        };
    }
    return $fields;
}, 10, 1);

The Output

Flexi-content-relationship-GraphQL-output

Understanding this falls all over the place, (not dynamic for a start), such as:

  1. It relies on a new filter created if the relationship structure is used else where or the graphql_interface_fields filter could be used but it would still require work.
  2. You would need to hard code the ACF field in the array_map or write code to extract the key => value
  3. This only works with SimpleProduct types, in this instance an AccommodationBookingProduct type is required.

Could I possibly have your thoughts @jasonbahl @kidunot89

@kidunot89
Copy link
Member

kidunot89 commented Mar 12, 2021

@boxxroom You want this filter. This example should work as a workaround.

function workaround( $type, $object, $wp_union ) {
  if ( 'Product' === $type ) {
     $type_name = \WPGraphQL\WooCommerce\Data\Factory::resolve_type( $type );
     $type      = $wp_union->type_registry->get_type( $type );
  }

  return $type;
}
add_filter( 'graphql_union_resolve_type', 'workaround', 10, 3 );

@boxxroom
Copy link
Author

Thanks for the reply and the code @kidunot89

This filter graphql_union_resolve_type is one we have looked at and also attempted to use, however, as strange as this may sound, it never seems to be invoked. I'm not sure if this is the case for you.

To double check this, we have added your code and additional logging inside the workaround function (logging the $type variable). This tends to break the GraphiQL IDE interface (when pressed play) but logs out the result to file. The output in the log is empty. Moving the logging inside the conditional if ( 'Product' === $type ) allows the GraphiQL IDE interface to work as expected but the log shows no output with the GraphiQL IDE error message returning Abstract type Page_Wpgraphqlexample_FlexibleContent_RelationshipField_ProductRelationship must resolve to an Object type at runtime..... this would suggest this conditional is never satisfied.

@kidunot89
Copy link
Member

kidunot89 commented Mar 13, 2021

@boxxroom There's an error in my example. This is the correction.

function workaround( $type, $object, $wp_union ) {
  if ( 'Product' === $type ) {
     $type_name = \WPGraphQL\WooCommerce\Data\Factory::resolve_type( $type, $object );
     $type      = $wp_union->type_registry->get_type( $type );
  }

  return $type;
}
add_filter( 'graphql_union_resolve_type', 'workaround', 10, 3 );

@boxxroom
Copy link
Author

@kidunot89 Thanks for looking in to this.

Even with the updated code, the previous statement still applies with the conditional. The $type variable never resolves to a string in turn never being satisfied.

Also to note, we were unable to locate the method resolve_type within the \WPGraphQL\WooCommerce\Data\Factory class, but did locate a resolve_node_type method.

Attached below is the filter code with a var_dump checking for a string with the output in the developers console.

is_string-code

is_string-output

Attached below is the filter code with a var_dump checking what/if classes output in the developers console.

get_class-code

get_class-output

@boxxroom
Copy link
Author

boxxroom commented Mar 15, 2021

@kidunot89 We think we have found the issue and it's to do with the booking plugins.

WooCommerce Accommodation Bookings: 1.1.23
https://woocommerce.com/products/woocommerce-accommodation-bookings/

WooCommerce Bookings: 1.15.31
https://woocommerce.com/products/woocommerce-bookings/

In the admin area when editing a product and updating its Product data to Accommodation product or Booking product the error occurs, when using as a Simple product it works but not with the filter code you provided with the workaround filter code we provided:

add_filter('graphql_Page_Wpgraphqlexample_FlexibleContent_RelationshipField_fields', function ($fields) {
    if (isset($fields['productRelationship'])) {
        $fields['productRelationship']['resolve'] = function ($root, $args, $context, $info) {
            return array_map(function ($id) {
                return new \WPGraphQL\WooCommerce\Model\Product($id);
            }, $root['field_6041494b07558']);
        };
    }
    return $fields;
}, 10, 1);

We have created two plugins to add BookingProduct and AccommodationBookingProduct as unions of a Product which can be downloaded here in an attempt to resolve this issue but the error Abstract type Page_Wpgraphqlexample_FlexibleContent_RelationshipField_ProductRelationship must resolve to an Object type at runtime..... still occurs.

Thanks in advance.

@jacobarriola
Copy link
Contributor

@boxxroom I think I ran into something similar when working with the ProductBundle type (https://github.com/jacobarriola/woographql-product-bundles).

I had to to do 2 things to get it working:

  1. Fork ACF for WPGraphQL plugin and add a filter (graphql_acf_relationship_model) to be able to filter the post model getting set at the relationship field type. I have a PR open for this; it may no longer be necessary as @jasonbahl is going to make some changes to better filter this more centrally.
    -- this solves the problem of rendering standard WC types in relationship fields
  2. Use the graphql_union_resolve_type filter to eliminate the error for your custom types (looks like Accomodation and Booking in your case).
/**
 * Set source Type to correct WooCommerce Type when dealing with the Relationship field.
 *
 * Not doing so causes GraphQL to try and resolve a WC Type (ie Product) to the Post
 * model, which causes resolve errors.
 */
add_filter( 'graphql_acf_relationship_model', function ( $source, $value ) {
	$post = get_post( $value );

	// Bail if we're not dealing with a product
	if ( $post->post_type !== 'product' ) {
		return $source;
	}

	// Only allow published posts to go through. This causes GraphQL errors and breaks builds.
	if ( 'publish' !== $post->post_status ) {
		return;
	}

	if ( false === class_exists( 'WPGraphQL\WooCommerce\ACF_Schema_Filters' ) ) {
		return $source;
	}

	$source = ACF_Schema_Filters::resolve_post_object_source( $source, $value );

	return $source;
}, 10, 2 );

/**
 * Set correct product type so that ACF relationship -> product bundles can resolve. Without this, a bundle added to
 * an ACF relationship field will throw an error.
 */
add_filter( 'graphql_union_resolve_type', function ( $type, $object, $wp_union ) {
	// Bail if not a Product type
	if ( $type->name !== 'Product' ) {
		return $type;
	}

	// Bail if as_WC_Data() is not available
	if ( false === method_exists( $object, 'as_WC_Data') ) {
		return $type;
	}

	// Bail if $object is not a bundle
	if ( $object->as_WC_Data()->product_type !== 'bundle' ) {
		return $type;
	}

	// Set the correct type
	return $wp_union->type_registry->get_type( 'BundleProduct' );
}, 10, 3 );

@boxxroom
Copy link
Author

boxxroom commented Mar 17, 2021

@jacobarriola thanks very much for chiming in on this. We have this working with a tweak to the graphql_union_resolve_type filter.

To test - We initially added the WPGraphQL ACF graphql_acf_relationship_model filter to the production plugin.

We then set out adding the code you provided, but this still failed with the same error output Abstract type Page_Wpgraphqlexample_FlexibleContent_RelationshipField_ProductRelationship must resolve to an Object type at runtime...... After a bit of debugging and digging, we noted that as_WC_Data isn't available so bails (as expected). We were also unable to find this method in the codebase to confirm it exists.

The way we got this working was to build the product from factory and check it is an instance of WC_Product_Accommodation_Booking. Not sure what side effects this may have but initial tests suggest all is working ok.

/**
 * Set correct product type so that ACF relationship -> product accommodations can resolve. Without this, an accommodation added to
 * an ACF relationship field will throw an error.
 */
add_filter('graphql_union_resolve_type', function ($type, $object, $wp_union) {
    // Bail if not a Product type
    if ($type->name !== 'Product') {
        return $type;
    }

    $product = $object->product_factory()->get_product();

    // Bail if $product is not an instance of WC_Product_Accommodation_Booking
    if (! $product instanceof WC_Product_Accommodation_Booking) {
        return $type;
    }

    // Set the correct type
    return $wp_union->type_registry->get_type('AccommodationBookingProduct');
}, 10, 3);

Even if this is only a temporary/workaround fix. It's ideal and allows the build to move on.

Thank you @kidunot89, @jacobarriola for your time and help resolving this.

@jacobarriola
Copy link
Contributor

@boxxroom glad you got it working!

as_WC_Data() is a method of WC_Post: https://github.com/wp-graphql/wp-graphql-woocommerce/blob/develop/includes/model/class-wc-post.php#L138

@boxxroom
Copy link
Author

@jacobarriola. This is a small side note: Just checked this file in our codebase and it definitely doesn't have this as_WC_Data() method or the as_WP_Post() it finished with the delete() method. Is it perhaps because it is the development branch you have linked to as opposed to a release branch. https://github.com/wp-graphql/wp-graphql-woocommerce/blob/release/v0.6.0/includes/model/class-wc-post.php#L108

We are using plugin version: 0.6.1

@jacobarriola
Copy link
Contributor

@boxxroom Looks like it was added in 0.7.0 release. https://github.com/wp-graphql/wp-graphql-woocommerce/blob/release/v0.7.0/includes/model/class-wc-post.php#L135

Since you're on a recent version of core wp-graphql, I'd consider an update. There are some breaking changes from your version to 0.8.x, but a lot of good bug fixes too.

@boxxroom
Copy link
Author

boxxroom commented Apr 9, 2021

@jacobarriola updated to the latest versions, updated the code to reflect that of yours and all seems to be working perfect.

Thanks for your help on this.

@boxxroom boxxroom closed this as completed Apr 9, 2021
@RodrigoTomeES
Copy link

Hi,

I have the same issue but I couldn't fix it with the code of the comments. When it will be fixed? Thanks!

imagen

@hellopath
Copy link

Hi there,
Unfortunately I have the same issue even if i use the last version of WPGraphQL WooCommerce (WooGraphQL) v0.8.1
Screenshot 2021-05-17 at 23 45 54
Is there any other fix for that?
Thank you !

@gvocale
Copy link

gvocale commented Jun 16, 2021

Running into this issue as well.

I try to establish a relationship to WooCommerce Product (from WooCommerce). If I change the relationship instead to a different post type Gallery, it seems to work. Maybe WooCommerce assigns on its Product post type some private fields that are tripping GraphQL?

If so, how could we solve it?

@brianpereradap
Copy link

Having the same issue. Was anyone able to get is resolved with the above-mentioned filter changes? I tried but couldn't get it to work.
image

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

7 participants