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

Fix QueryScaffolder not using inheritance types #176

Merged
merged 1 commit into from
Dec 6, 2018

Conversation

unclecheese
Copy link

@unclecheese unclecheese commented Aug 7, 2018

@@ -85,7 +85,7 @@ public function getTypeName()
protected function getType(Manager $manager)
{
// If an explicit type name has been provided, use it.
$typeName = $this->getTypeName();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If getTypeName() is returning the wrong value, I wonder if we can fix it there?

This logic defers auto-type scaffolding from StaticSchema, which may in some cases be the correct behaviour. It fixes one use case but breaks others.

It seems like the fundamental problem is "typeName" can't be determined without a manager. In that case, this issue is a symptom of a fundamental problem of manager-gnostic type resolution.

Looking back at 7c3980a, it seems like we introduced prefer_union = true.

Perhaps that logic needs to be available to getTypeName() as well, so it returns the union type name?

Do both getType() / getTypeName() need manager to be present?

Copy link
Contributor

@maxime-rainville maxime-rainville left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What Damian said.

@unclecheese
Copy link
Author

The follow up discussion on this happened on Slack:

tl;dr rewrite all these methods to be more semantically correct.

unclecheese [12:11 PM]
@tractorcow how do you feel about clearing up the semantics a bit?

getTypeName() // gets the type name as assigned to the scaffolder. Falls back on typename for $dataObjectClass

getResolvedTypeName(Manager $manager) // gets the typename that will actually be used in the schema based on manager state

exact naming TBD, but you get the gist

tractorcow [12:35 PM]
Yeah that would be ideal IMO

we can't remove getTypeName() but we should be using the resolved name where possible right?
we'd have like 4-5 different "get name" failovers lol

by this point

I dunno, I guess I'm really just pointing out problems without giving solutions, I'm sorry
Normally I'd properly investigate and come up with something

unclecheese [12:44 PM]
I'd also love to get rid of DataObjectTrait.. that introduces yet another ambiguous method name `typeName()`

tractorcow [12:49 PM]
hah yeah

that was a holdover from the proof of concept

@unclecheese
Copy link
Author

The ideal fix for this involves refactoring that is much more appropriate for the 3 branch. Recommend we merge this into 2 in spite of its flaws. A more thorough fix for the 3 branch is here: #182

@tractorcow
Copy link
Contributor

tractorcow commented Sep 5, 2018

Issue is that typeName() from DataObjectTypeTrait bypasses the logic in StaticSchema::fetchFromManager()

Solution is to add getResolvedTypeName() that uses the manager to resolve the name always.

Suggestion:

  • Add $manager arg to getTypeName(). Make it optional for now, but warn if missing (deprecation notice).
  • Alternatively, add new getResolvedTypeName(), deprecate entire getTypeName() method.
  • Validate that getType() and getTypeName() both behave consistently. You may want to refactor part of StaticSchema::fetchFromManager() a little so that you can use the schema to resolve either the name, or the type directly.
  • Make sure that usages of getTypeName() always passes is the appropriate $manager instance. You may need to inject it into a few top level entry points to the code.

Copy link
Contributor

@tractorcow tractorcow left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As per last comment.

@unclecheese
Copy link
Author

A more thorough fix, with API changes is against the 3 branch in #182.

I don't see the case for passing Manager to getTypeName. Maybe as an optional argument, but we certainly shouldn't throw a deprecation warning. We need to afford the flexibility use any arbitrary name you want, and not couple it so tightly to dataobjects.

It gets really confusing, and I've tried to clean up the semantics a bit in the 3 PR, but basically:

  • getTypeName() a simple getter for a property that is set via setTypeName() (or a constructor arg). It's arbitrary, and manager-unaware.
  • getDataObjectTypeName() - Generate a typename based on the dataobject being used. This isn't necessarily the same as the type that is returned by the resolver. For all wants and purposes, it too, is arbitrary. It's for naming purposes, so we get readProducts instead of readProductsWithDescendants.
  • getType(Manager) is used to get the concrete type that is returned by the resolver. In theory you should never have to know the name of this type. It's computed just-in-time when the scaffolder is added to the manager, and the manager state is guaranteed to be frozen.

@maxime-rainville
Copy link
Contributor

@ScopeyNZ @robbieaverill We got a bit of a deadlock on this one and we're not quite sure how to proceed. Would you care to throw your two cents on this?

@robbieaverill
Copy link
Contributor

robbieaverill commented Nov 19, 2018

I'm not familiar enough with this part of the code TBH. I can say that it's preventing us from using dynamic fragments, which we'll need to start using at some point for the CWP modules. It's also come up in Stackoverflow, and apparently this PR fixes the problem: https://stackoverflow.com/questions/53184168/silverstripe-graphql-error-when-querying-types-with-descendants

My assumption is that the blocking comments here are mostly semantic

Copy link
Contributor

@maxime-rainville maxime-rainville left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Following some back and forth. I'm OK with this being merge.

Calling parent::getTypeName() from getType() is weird, but in the context that this is a low level abstract class and that this will only affect the 2 branch we can probably live with it.

@tractorcow
Copy link
Contributor

Sorry @unclecheese I'll just leave this to you. I don't have much time these days to get too deep into graphql. =(

@maxime-rainville maxime-rainville merged commit f821804 into silverstripe:2 Dec 6, 2018
@maxime-rainville maxime-rainville deleted the pulls/2/not-my-type branch December 6, 2018 21:04
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

Successfully merging this pull request may close these issues.

5 participants