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

Interface Recursion Issues #3106

Open
1 of 3 tasks
zngly-vlad opened this issue Apr 25, 2024 · 7 comments
Open
1 of 3 tasks

Interface Recursion Issues #3106

zngly-vlad opened this issue Apr 25, 2024 · 7 comments
Assignees
Labels
Component: Interfaces Regression Bug that caused a regression to a previously working feature scope: tests Status: 🚀 Actionable Issues that have been curated, have enough info to take action, and are ready to be worked on Type: Bug Something isn't working

Comments

@zngly-vlad
Copy link

zngly-vlad commented Apr 25, 2024

Description

possible regression from #3100

In v1.24.0 - interface resolvers no longer run when similar pre-existing fields exist

Steps to reproduce

example code:

$type_registry->register_interface_type('MyTestNodeInterface', [
    'fields' => [
        'id' => [
            'type' => ['non_null' => 'ID'],
            'resolve' => function ($source, $args, $context, $info) {
                // check correct format
                return 'correctFormat==';
            },
        ],
        'databaseId' => [
            'type' => 'ID',
            'resolve' => function ($source, $args, $context, $info) {
                return 'interface_db_id==';
            },
        ],
    ]
]);

$type_registry->register_object_type('MyTestObject', [
    'interfaces' => ['MyTestNodeInterface'],
    'fields' => [
        'id' => [
            'type' => ['non_null' => 'ID'],
            'resolve' => function ($source, $args, $context, $info) {
                return 'not_correct_format==';
            },
        ],
        'hello' => [
            'type' => 'String',
            'resolve' => function ($source, $args, $context, $info) {
                return 'hello from object';
            },
        ],
    ],
]);

$type_registry->register_field('RootQuery', 'myTestQuery', [
    'type' => 'MyTestObject',
    'description' => 'A field that returns a MyTestObject',
    'resolve' => function ($source, $args, $context, $info) {
        return [];
    },
]);

actual:

{
  "data": {
    "myTestQuery": {
      "id": "not_correct_format==",
      "databaseId": "interface_db_id==",
      "hello": "hello from object"
    }
}

expected:

{
  "data": {
    "myTestQuery": {
      "id": "correctFormat==",
      "databaseId": "interface_db_id==",
      "hello": "hello from object"
    }
}

Additional context

For my use case I use interfaces to ensure data is formatted correctly on existing fields.

WPGraphQL Version

1.24.0

WordPress Version

Version 6.5.2

PHP Version

8.2.17

Additional environment details

No response

Please confirm that you have searched existing issues in the repo.

  • Yes

Please confirm that you have disabled ALL plugins except for WPGraphQL.

  • Yes
  • My issue is with compatibility with a specific WordPress plugin, and I have listed all my installed plugins (and version info) above.
@justlevine
Copy link
Collaborator

Related #3100 , #3096

(I'm not entirely sure the implications of the recursion issue, but at a glance this seems like a "feature not bug" situation. Logically, interfaces are broader than objects, so it makes sense that resolver inheritence would follow register_interface_type > register_object_type > register_field, with the latter ones taking precedence for specificity).

@justlevine justlevine added Type: Bug Something isn't working Needs: Reproduction This issue needs to be reproduced independently. Needs: Reviewer Response This needs the attention of a codeowner or maintainer. scope: API Issues related to access functions, actions, and filters labels Apr 25, 2024
@justlevine
Copy link
Collaborator

PS: @zngly-vlad , can you please update the ticket to include the explicit PHP and WordPress versions you're using, so we can replicate this accurately? "Latest" today is not the same as "latest" tomorrow, (It's only been two weeks since WP 6.5, and there's already been two patch updates with a third already queued up) 🙏

@jasonbahl
Copy link
Collaborator

@zngly-vlad thank you for opening this issue! I originally thought this might have been a regression, but after reading the scenario, I believe you might have been using a bug as a feature.

As @justlevine pointed out:

register_interface_type > register_object_type > register_field, with the latter ones taking precedence for specificity.

I would expect a resolver on an Interface field to work unless it was overridden by a field on an Object Type. The resolver of a field on an object type should override the resolver of the same field on an Interface.

If it wasn't working properly before, then I do think a bug was fixed here and folks benefitting from the "bug as a feature" will need to make adjustments.

In any case, this does expose some gaps in testing that we can shore up.

For example, we can / should explicitly test that a resolver of an Interface field should NOT override the resolver of the field on an object type that implements the Interface.

@jasonbahl jasonbahl self-assigned this Apr 25, 2024
@zngly-vlad
Copy link
Author

@justlevine @jasonbahl That is exactly what I was thinking with the "feature not bug"

Would this still be the case if there was no resolver on the object field. e.g.

$type_registry->register_object_type('MyTestObject', [
    'interfaces' => ['MyTestNodeInterface'],
    'fields' => [
        'id' => [
            'type' => ['non_null' => 'ID'],
            // 'resolve' => function ($source, $args, $context, $info) {
            //     return 'not_correct_format==';
            // },
        ],
        'hello' => [
            'type' => 'String',
            'resolve' => function ($source, $args, $context, $info) {
               return 'hello from object';
            },
        ],
    ],
]);

@justlevine justlevine added scope: tests and removed Needs: Reviewer Response This needs the attention of a codeowner or maintainer. scope: API Issues related to access functions, actions, and filters labels Apr 25, 2024
@justlevine
Copy link
Collaborator

Would this still be the case if there was no resolver on the object field. e.g.

@zngly-vlad I'm not 100% percent sure I understand the question, so to be safe I'm going to lay out the inheritance.

  1. GraphQL looks for the resolver registered by register_field().
  2. If it doesnt exist on register_field(), GraphQL looks for the resolver registered by register_object_type().
  3. If it doesn't exist on register_object_type(), GraphQL looks for the resolver registered by register_interface_type().

As @jasonbahl noted, we definitely need to get more unit tests shipped to ensure that we're enforcing that order of operations IRL.

@justlevine justlevine added Component: Interfaces Status: Discussion Requires a discussion to proceed labels Apr 25, 2024
@zngly-vlad
Copy link
Author

Thats fine, I think it might just be my general understanding but I am satisfied with the explanations above.

Thank you for all the help.

@josephfusco josephfusco added the Close Candidate Needs confirmation before closing label Apr 29, 2024
@justlevine
Copy link
Collaborator

While this particular issue is solved , and some recursion issues were fixed in #3100, I'm hesitant to close this because there seemingly still are recursion regressions, as reported in wpengine/wp-graphql-content-blocks#240 (Discord ).

Leaving this open until we have that fixed or a different ticket to track.

@justlevine justlevine added Regression Bug that caused a regression to a previously working feature Status: 🚀 Actionable Issues that have been curated, have enough info to take action, and are ready to be worked on and removed Close Candidate Needs confirmation before closing Status: Discussion Requires a discussion to proceed Needs: Reproduction This issue needs to be reproduced independently. labels May 11, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Component: Interfaces Regression Bug that caused a regression to a previously working feature scope: tests Status: 🚀 Actionable Issues that have been curated, have enough info to take action, and are ready to be worked on Type: Bug Something isn't working
Projects
Status: 🎯Actionable
Development

No branches or pull requests

4 participants