Skip to content

feat: introduce common interfaces#2617

Merged
jasonbahl merged 22 commits intowp-graphql:developfrom
jasonbahl:feat/#1738-introduce-common-interfaces-2
Nov 23, 2022
Merged

feat: introduce common interfaces#2617
jasonbahl merged 22 commits intowp-graphql:developfrom
jasonbahl:feat/#1738-introduce-common-interfaces-2

Conversation

@jasonbahl
Copy link
Copy Markdown
Collaborator

@jasonbahl jasonbahl commented Nov 22, 2022

What does this implement/fix? Explain your changes.

This introduces common interfaces. This PR is a fresh take on #2022

Interfaces introduced in this PR are:

  • Connection
  • ConnectionEdge
  • Edge
  • OneToOneConnection
  • ContentNodeConnection
  • ContentTypeConnection
  • CommentConnection
  • CommenterConnection
  • ContentNodeConnection
  • HierarchicalNode
  • MenuConnection
  • MenuItemConnection
  • MenuItemLinkableConnection
  • Previewable
  • TaxonomyConnection
  • TermNodeConnection
  • UserConnection

Does this close any currently open issues?

closes #1738

Any other comments?

These connections add a lot of value to Schema organization, code reusability, and introspection.

One can now use GraphiQL to find all instances of Connections in the Schema like so:

connection-interface-implementations

One could also look for all Connections that implement a more specific Connection Interface, such as ContentNodeConnection. This interface is applied to any node that has a connection to any type of Content Node. So a User to Post connection is a ContentNodeConnection and a User to Page connection is also a ContentNodeConnection.

content-node-connection-implementations

These shared connection interfaces allow client developers to have a better understanding of shared properties of connections and can allow for reduced code when querying similar data from the Graph.

On the server side, developers can more easily add features to specific connections or general connection interfaces.

…v1.13.0

# Conflicts:
#	.github/workflows/deploy-docker-image.yml
… `RootQuery` and 'User'

- Remove ContentRevisionUnion type
- Update WPConnectionType so that all connections implement `Connection` and `Edge` Interfaces
- Add Connection interfaces (Connection, Edge, SingularConnection)
- Add node, DatabaseIdentifier interfaces to MenuItemLinkable
- update deregister_graphql_field test to assert contentNodes returns null instead of asserting an individual node returns null
- separate registration for ConnectionInterface, Edge, SingularConnection
- add early returns to WPConnectionType to prevent duplicate registration of connection types
- rename file/class for CommenterInterface to be Commenter to be consistent with the other Interface naming conventions
- Introduce `ContentNodeConnection` Interface, apply it to all connections with toType 'ContentNode`
- revert composer.lock
- rename SingularConnectionEdge to SingularConnection
@coveralls
Copy link
Copy Markdown

coveralls commented Nov 22, 2022

Coverage Status

Coverage increased (+0.08%) to 81.796% when pulling e96a0c5 on jasonbahl:feat/#1738-introduce-common-interfaces-2 into 6e63a79 on wp-graphql:develop.

- Add `CommentConnection` Interface to connections to the `Comment` type
- deprecate PostObjectUnion class
- deprecate TermObjectUnion class
- add ConnectionInterfaceTest.php to test connections (breaking tests now as we implement the rest of the planned Interfaces)
- Apply SingularCommenterConnection on the Comment->Commenter connection
- Update test for CommenterConnection to properly test for one-to-one connection instead of plural connection
- Apply HierarchicalNode Interface to HierarchicalTermNode and HierarchicalContentNode
- apply MenuConnection interface to connections to the `Menu` type
- apply MenuItemConnection interface to connections to the `MenuItem` type
…nEdge`

- Rename `SingularContentTypeConnection` to `SingularContentTypeConnectionEdge`
- Update connection interfaces referencing them
-
- apply MenuItemLinkableConnection interface to connections to the `MenuItem` type
- Apply Previewable Interface to public post types
- Introduce TaxonomyConnection
- Apply TaxonomyConnection Interface to connections to the Taxonomy type
- apply TermNodeConnection interface to connections to the `MenuItem` type
- apply UserConnection interface to connections to the `User` type
…tentTypeConnectionEdge in favor of simplifying with `edge`

- composer run fix-cs
…Singular` terminology already has meaning in WordPress (singular Post, Page, etc) and we _might_ see that terminology in the Graph in the future. Trying to avoid possible conflict with existing terminology
@qlty-cloud-legacy
Copy link
Copy Markdown

Code Climate has analyzed commit e96a0c5 and detected 58 issues on this pull request.

Here's the issue category breakdown:

Category Count
Complexity 36
Duplication 22

View more on Code Climate.

@justlevine
Copy link
Copy Markdown
Collaborator

Really cool stuff. Do we want to keep the old (admittedly poorly-named) ContentRevisionUnion instead of ContentRevision for back-compat?

@jasonbahl
Copy link
Copy Markdown
Collaborator Author

Really cool stuff. Do we want to keep the old (admittedly poorly-named) ContentRevisionUnion instead of ContentRevision for back-compat?

Ya, perhaps we keep the ContentRevisionUnion Type, and deprecate the revisions connections that resolve to it, then introduce a new field with a new name that resolves as a ContentNode connection. . .then remove the deprecated type and field later.

Thoughts on a new name for the field?

post.revisions @deprecated
post.contentRevisions?

@jasonbahl
Copy link
Copy Markdown
Collaborator Author

jasonbahl commented Nov 23, 2022

There's only 2 places the ContentRevisionUnion was referenced:

RootQuery.revisions
User.revisions

I'm thinking we can deprecate these and introduce:

RootQuery.revisedNodes
User.revisedNodes

@justlevine
Copy link
Copy Markdown
Collaborator

justlevine commented Nov 23, 2022

Not sure about revisedNodes, since semantically it implies nodes that have been revised and not individual revision snapshots of the particular node... But idk naming things is hard 😵‍💫

@jasonbahl
Copy link
Copy Markdown
Collaborator Author

jasonbahl commented Nov 23, 2022

@justlevine ah! I remember why I had to make this change.

With the introduction of the Connection and Edge interfaces applied to all connections, we get errors like this now:

Interface field Connection.nodes expects type [Node!]! but UserToRevisionsConnection.nodes is type [ContentRevisionUnion!]!.

This is because all connections now expect to connect to a Node type, and a Union can't be a node type, because unions can't implement interfaces.

I think the best way forward is to make this "technically" breaking change.

For most use (99%+?) cases, it won't actually be a breaking change.

Because the previous connection returned a Union instead of an Interface, the only way to query was like so (using the ...on syntax for every single type)

{
  viewer {
    revisions {
      nodes {
        __typename
        ... on Post {
          id
          uri
          isRevision
        }
        ... on Page {
          id
          uri
          isRevision
        }
      }
    }
  }
  revisions {
    nodes {
      __typename
      ... on Post {
        id
        uri
        isRevision
      }
      ... on Page {
        id
        uri
        isRevision
      }
    }
  }
}

Since the new connection is an Interface, the same queries will still work.

v1.12.2

Here's the same query on WPGraphQL v1.12.2 (ContentRevisionUnion)

CleanShot 2022-11-23 at 14 23 46

Current PR

And here's the same query with the changes from this PR applied

CleanShot 2022-11-23 at 14 22 23@2x


The only way it would cause a break would be if someone were querying like so:

{
  viewer {
    revisions {
      ... on UserToContentRevisionUnionConnection {
        nodes {
          __typename
          ... on Post {
            id
            uri
            isRevision
          }
          ... on Page {
            id
            uri
            isRevision
          }
        }
      }
    }
  }
  revisions {
    ... on RootQueryToContentRevisionUnionConnection {
      nodes {
        __typename
        ... on Post {
          id
          uri
          isRevision
        }
        ... on Page {
          id
          uri
          isRevision
        }
      }
    }
  }
}

Which seems highly unlikely, but something we can call out in the release notes.

@jasonbahl
Copy link
Copy Markdown
Collaborator Author

jasonbahl commented Nov 23, 2022

fwiw, on a different note, working on this makes me want to re-visit #2355. I still don't quite now how to resolve that "problem" but it keeps haunting me.

I have several one-off utility post types that I don't want to be lumped together as "content" but they keep showing up in my contentNodes { ... } queries. lol

@jasonbahl
Copy link
Copy Markdown
Collaborator Author

jasonbahl commented Nov 23, 2022

@justlevine we could potentially add something to the connection config for exluding the Connection and Edge interfaces too 🤔

like:

register_graphql_connection( [
  'fromType' => 'RootQuery',
  'toType'               => 'ContentRevisionUnion',
  ...
  'exclude_interfaces' => [ 'Connection' ],
  'exclude_edge_interfces' => [ 'Edge' ],
] );

🤔


I think it might be best to rip the bandaid off though, as the breaking change will likely not affect anyone, as explained above, and now we can ensure going forward that all connections properly lead to Nodes.

@jasonbahl jasonbahl merged commit 9f7a310 into wp-graphql:develop Nov 23, 2022
@jasonbahl jasonbahl mentioned this pull request Nov 23, 2022
@jasonbahl jasonbahl changed the title feat: introduce common interfaces (again) feat: introduce common interfaces Dec 5, 2022
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.

Common Interfaces that other Interfaces can Implement

3 participants