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
Register TermNode connections on ContentNode interface, not individual types #2026
base: develop
Are you sure you want to change the base?
Register TermNode connections on ContentNode interface, not individual types #2026
Conversation
Code Climate has analyzed commit 9f6ec6b and detected 0 issues on this pull request. View more on Code Climate. |
We (@chriszarate and I) talked a lot about this in Slack and I want to add some context of that conversation. I'm hesitant to add this as I feel like it exposes something in the Schema that shouldn't be exposed. If I were to register a post type with no taxonomy connections, but the schema showed that I can query:
That feels misleading as far as "Schema as documentation" is concerned. We know for a fact that It's one thing to have nullable types that are sometimes null and sometimes have value, but in this case we know ahead of time that the type will have no terms. I think it's irresponsible and misleading to expose this to the Schema. The Schema should show what's possible, and in this case we know that's not possible. After our conversation in Slack, I opened issue #2027 to discuss some ideas related to this. I think the general idea this PR from @chriszarate is trying to solve is having more general queries that can be used across types. It's annoying to have to write similar, but slightly different, queries for Page, Post, CustomPostType, etc. If we introduce a concept of Consider even core WordPress Post Types:
With the And leave the And now we could write a resilient query like: {
post( id: "id-of-post" ) {
...ResilientFragment
}
page( id: "id-of-page" ) {
...ResilientFragment
}
}
fragment ResilientFragment on ContentNode {
id
uri
...on NodeWithTitle {
title
}
...on NodeWithCategoryConnection {
categories {
nodes {
id
name
}
}
}
...on NodeWithTagConnection {
tags {
nodes {
id
name
}
}
}
...on NodeWithTermsConnection {
terms {
nodes {
id
name
}
}
}
} We could even go a step further, and apply the post( id: "id-of-post" ) {
...ResilientFragment
}
page( id: "id-of-page" ) {
...ResilientFragment
}
}
fragment ResilientFragment on ContentNode {
id
uri
...on NodeWithTitle {
title
}
...on NodeWithCategoryConnection {
categories {
...TermNodes
}
}
...on NodeWithTagConnection {
tags {
...TermNodes
}
}
...on NodeWithTermsConnection {
terms {
...TermNodes
}
}
}
fragment TermNodes on TermsConnection {
nodes {
id
name
}
} I believe this helps with the intent of this PR (creating re-usable, resilient fragments) but also keeps the integrity of the Schema as documentation aspect. |
I'm on board with this approach outlined here and in #2027, even if it complicates the generic queries that I find valuable. Should I retool this PR to introduce I'm a tiny bit concerned about what this looks like when consuming a query like this from a strongly typed language, but I can work on understanding that better in parallel. |
@chriszarate my thought is that this might actually be the responsibility of the At least to some level. 🤔 And another thought is that we could have some sort of connection that returns an Interface comprised of Taxonomies actually associated with the taxonomy. Like we have a And I think we could probably implement something similar for Connection Interfaces. 🤔 🤔 |
What I mean by this is that the So if I register a connection from User to Post like so: register_graphql_connection( [
'fromType' => 'User',
'toType' => 'Post',
'fromFieldName' => 'featuredPosts',
'description' => __( 'Featured posts by this author', 'text-domain' ),
...
] ); This would register an Interface: Interface NodeWithFeaturedPostsConnection {
featuredPosts: UserToFeaturedPostConnection
} And the return type of the type UserToFeatruedPostConnection implements UserToPostConnection {
nodes: [ Post ]
edges: [ UserToPostEdge ]
} And Then I could create a fragment like so: fragment FeaturedPosts on NodeWithFeaturedPostsConnection {
featuredPosts {
nodes {
id
}
}
} But the connection itself could also be a more generic fragment: fragment UserPosts on UserToPostConnection {
nodes {
id
}
}
fragment FeaturedPosts on NodeWithFeaturedPostsConnection {
featuredPosts {
...UserPosts
}
} |
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions. |
This issue has been automatically closed because it has not had recent activity. If you believe this issue is still valid, please open a new issue and mark this as a related issue. |
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions. |
This issue has been automatically closed because it has not had recent activity. If you believe this issue is still valid, please open a new issue and mark this as a related issue. |
What does this implement/fix? Explain your changes.
Testing the waters a bit on moving certain connections to interfaces instead of individual types. There is a limit on how much of this we can do while still retaining the information encoded by a good schema, but I think it makes sense for generic connections like
terms
andcontentNodes
.Therefore, this PR registers the
TermNode
connection (terms
) on theContentNode
interface, instead of on each individual post type.There is a slight change in result here: A post type will receive the
terms
connection even if it does not have any taxonomies registered against it. While this removes a small bit of information from the schema, I think the tradeoff is worth it, because:Post->Tag
orPost->Category
) and continue to convey the information that was removed.ContentNode->TermNode
connections resolves to theTermNode
type, which contains all of the available taxonomies, not just the ones registered to that post type. It doesn't really make sense to provide specificity only in the case where no taxonomies are registered. It is a generic connection, so let it be generic.ContentNode->TermNode
connection and aTermNode->ContentNode
connection.