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

WPGraphQL v2.0 (DRAFT) #1936

Conversation

jasonbahl
Copy link
Collaborator

@jasonbahl jasonbahl commented Jun 1, 2021

I converted this to a DRAFT PR as this is getting broken up into smaller pieces as much of this can be introduced as 1.. non-breaking releases.


This updates WPGraphQL to use GraphQL-PHP v14.5.1 which allows Interfaces to implement other Interfaces.

Along with this update, comes the implementation of Interfaces implementing other Interfaces, which moves some things around in the Schema and causes some breaking changes to the schema.

Of course, whether the changes are breaking for your applications are relative to the queries/mutations your application executes. There's a good chance that you could upgrade from 1.x.x to 2.0 with no changes needed to your client applications or WPGraphQL server extensions, but depending on your use of WPGraphQL, you may need to do some legwork to get other parts of your applications updated.

Breaking Changes

Below is a summary of breaking changes to be aware of and to look for when upgrading from 1.x.x to 2.0

  • WPPageInfo type removed, replaced with PageInfo to follow the Relay spec.
    • This will impact any plugins that are filtering the WPPageInfo type to add additional fields
  • uri field has changed from String! to String. While this is technically a breaking change to the Schema, this is a bugfix as errors are thrown when querying Post / Term Nodes of non-public post types or taxonomies as they don't have a uri (because they're not public).
  • the isPreview field was removed from the ContentNode Interface and added to the Previewable Interface
  • The previewRevisionDatabaseId field was removed from the ContentNode Interface and added to the Previewable Interface
  • The previewRevisionId field was removed from the ContentNode Interface and added to the the Previewable Interface
  • Removes HierarchicalContentNode from MediaItem and introduces HierarchicalNode instead.
    • This is a bugfix, as MediaItem should not have had children fields
  • Removes isPreview, previewRevisionDatabaseId and previewRevisionId fields from MediaItem type field from MediaItem.
    • This is a bugfix, as these fields were not properly resolvable as media are not previewable nodes
  • MediaItem.parent field changed from HierarchicalContentNodeToParentContentNodeConnectionEdge to MediaItemToParentContentNodeConnectionEdge
  • Deprecated MenuItem.connectedObject field has been removed. Use connectedNode field instead.
  • MenuItemObjectUnion type has been removed from the Schema.
  • RootQuery.revisions type changed from RootQueryToContentRevisionUnionConnection to RootQueryToRevisionsConnection
  • User.revisions field changed type from UserToContentRevisionUnionConnection to UserToContentNodeConnection

New Features

  • Add new API to register connections when registering a Type. (more details below)
  • Update GraphQL-PHP dependency from v14.4.0 to v14.5.1
    • This adds the ability for Interfaces to implement interfaces, which is a large focus of this PR (read more below)
    • Many new Interfaces introduced an implemented
  • WPPageInfo type removed, replaced with PageInfo to follow the Relay spec

Bugfixes

  • Update hook priority for the deregister_graphql_mutation
  • Removes deprecated MenuItemObjectUnion Type from the Schema (read more below)
  • Changes uri field from String! to String to support Types that do not have a uri (private taxonomy terms, private post types)
  • Removes deprecated ContentRevisionUnion type from the Schema

NEW: Register Connections when Registering a Type

Prior to this, Types and Connections needed to be registered independently, like so:

Register an Object Type

register_graphql_field( 'RootQuery', 'typeA', [
  'type' => 'TypeA', 
  'args' => [
    'id' => [
      'type' => [ 'non_null' => 'ID' ]
    ],
    'resolve' => function() {
      // return an object that matches the shape of TypeA
    }
  ]
] );

register_graphql_object_type( 'TypeA', [
  'description' => __( 'Example Type', 'your-textdomain' ),
  'fields' => [
    'testField' => [
      'type' => 'String',
      'description' => __( 'Description of the test field', 'your-textdomain' ),
    ],
  ]
 ]);

Register a Connection From the Type

Now, if we wanted TypeA to have a connection to Posts, we'd have to register this separately:

register_graphql_connection([
  'fromType' => 'TypeA',
  'toType' => 'Post',
  'fromFieldName' => 'posts',
  'resolve' => function( $root, $args, $context, $info ) { 
    // return a connection of Posts
  }
]);

Then you would be able to query something like so:

{
  typeA( id: 123 ) {
    testField
    posts {
      nodes {
        id
        title
      }
    }
  }
}

Register the connection as part of the Type

Now, with this PR, the connection from TypeA to Post can be registered when TypeA is registered, like so:

register_graphql_object_type( 'TypeA', [
  'description' => __( 'Example Type', 'your-textdomain' ),
  'fields' => [
    'testField' => [
      'type' => 'String',
      'description' => __( 'Description of the test field', 'your-textdomain' ),
    ],
    'connections' => [
      'posts' => [ // The key of the connection serves as the field name that exposes the connection
        'toType' => 'Post',
        'resolve' => function( $root, $args, $context, $info ) { 
          // return a connection of Posts
        }
      ]
    ]
  ]
 ]);

Now the connections from TypeA to Post can be defined at the time of registering TypeA.

Of course, register_graphql_connection() still exists, so you can still create connections between Types your code doesn't define, but for Types you define in your codebase, this new method of registering connections can come in handy and reduce overall amount of code needed.

You can see how core WPGraphQL is updating code to make use of this change here.

NEW: Interfaces Implementing Interfaces

The main reason for updating GraphQL-PHP was to enable Interfaces to implement other Interfaces, a feature that was updated in the GraphQL Spec in 2020 and brought to GraphQL-PHP in early 2021.

This now allows Interfaces to be defined more concisely. For example, WPGraphQL now has a DatabaseIdentifier Interface that defines the databaseId field. Any Type in the Schema, including other Interfaces, that support a databaseId field, can implement this interface. For example, the ContentNode Interface, which is implemented by all Post Types, now implements the DatabaseIdentifier Interface. So, any query for content nodes clearly documents that ContentNodes all have a databaseId field.

Another benefit is Connections can all implement shared interfaces.

Now, there's a common Connection Interface that all plural connections share. So it's much easier for client developers to understand what's available in the graph via introspection. One can simply look at the Connection interface in documentation and see all Types that implement this. Tooling can be built to aid in consuming connections, etc.

For example, we can search Connection in the GraphiQL Docs to find all Connections:

Screen Shot 2021-06-02 at 12 52 12 PM

Or we can search SingleNodeConnection to find all one-to-one connections in the Graph:

Screen Shot 2021-06-02 at 12 51 23 PM

On the server side, modifying connections, say, to add different query arguments and adjust resolver behavior, can be done by targeting connection interfaces, either broadly (Connection) or specifically, like TermNodeToContentNodeConnection or even more specifically like CategoryToPostConnection.

This will also make it easier for extensions to re-use core features.

For example, WPGraphQL for Advanced Custom Fields will now be able to share Interfaces for Cloned Field Groups with other Field Groups, making it easier for client developers to write re-usable fragments. Super cool!

Removal of MenuItemObjectUnion

At one point in WPGraphQL, querying objects connected to Menu Items (posts, pages, etc) required querying a field named connectedObject. This was deprecated in favor of the connectedNode field that is of Type MenuItemToMenuItemLinkableConnectionEdge (which implements SingleNodeConnectionEdge Interface).

This deprecated connection and the deprecated MenuItemObjectUnion has been removed from the codebase.

If you're not ready for this removal, you can see the code that tests backward compatibility, and register the Union and Connection back in your codebase.

Removal of ContentRevisionUnion, PostObjectUnion, TermObjectUnion

These Unions have been replaced by Interfaces, but have been left to support extensions that might return these Types.

It's recommended that extensions referencing these Types upgrade to reference the equivalent Interface, as listed below:

  • ContentRevisionUnion => ContentNode
  • PostObjectUnion => ContentNode
  • TermObjectUnion => TermNode

closes #1751
closes #1923

…plemented by other interfaces

- Update WPInterfaceType to support passing connections that the Interface can have when registering an InterfaceType
…y implement the databaseIdentifier Interface
…with the User type that implements the databaseIdentifier interface
… registrars to the Types being registered. So now, for many connections, instead of directly using `register_graphql_connection` the Type and/or Interface can define connections when being registered.

- Updated several interfaces to declare other interfaces they implement
- Introduced a new ConnectionInterface and Edge Interface
- Introduced a new HierarchicalNode interface
- Introduced a new Previewable Interface
- Removed the ContentRevisionUnion and MenuItemObjectUnion Types
- Updated tests to include back compat checks for users that need the MenuItemObjectUnion in their queries. They can drop in a snippet to add it back to their API if they need it.
…p-to-14.5.1

# Conflicts:
#	.gitignore
#	composer.lock
#	src/Type/ObjectType/PostObject.php
#	src/Type/ObjectType/RootQuery.php
#	src/Type/Union/ContentRevisionUnion.php
#	src/Type/Union/MenuItemObjectUnion.php
#	tests/wpunit/MediaItemQueriesTest.php
…p-to-14.5.1

# Conflicts:
#	composer.lock
#	src/Type/InterfaceType/ContentTemplate.php
#	src/Type/InterfaceType/DatabaseIdentifier.php
#	src/Type/WPInterfaceType.php
#	tests/wpunit/AccessFunctionsTest.php
- Update composer.lock
- Update ContentNode.php to remove unused use statements
- Update ContentTemplate to add `use Exception` statement
- Update DatabaseIdentifier to add `use Exception` statement, remove extra bracket
- Update TermNode.php to remove unused use statements
- Update code style in RootQuery.php
@coveralls
Copy link

coveralls commented Jun 1, 2021

Coverage Status

Coverage increased (+0.07%) to 79.323% when pulling 188a0c1 on jasonbahl:feature/#1751-update-graphql-php-to-14.5.1 into 7708b4e on wp-graphql:develop.

…l oneToOne connections

- Back out change to CLI script
- Back out change to register_graphql_connection hook priority
- Update code styling
…n, ContentNodeConnection, ContentTypeConnection, MenuConnection, MenuItemConnection, MenuItemLinkableConnection, TaxonomyConnection, TermNodeConnection, UserConnection

- Adds tests to ensure the interfaces exist and implement the Connection Interface and their edges implement the ConnectionEdge interface
…p-to-14.5.1

# Conflicts:
#	composer.lock
#	src/Registry/TypeRegistry.php
- Change `WpPageInfo` to `PageInfo`
- Remove ContentRevisionUnion, TermObjectUnion, PostObjectUnion in favor of interfaces (ContentNode, TermNode)
@jasonbahl jasonbahl changed the title Feature/#1751 update graphql php to 14.5.1 WPGraphQL v2.0 Jun 9, 2021
@jasonbahl jasonbahl marked this pull request as draft June 10, 2021 19:13
@jasonbahl jasonbahl changed the title WPGraphQL v2.0 WPGraphQL v2.0 (DRAFT) Jun 10, 2021
@jasonbahl jasonbahl closed this Jul 22, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Cannot return null for non-nullable field "CommentAuthor.databaseId". Update GraphQL-PHP to v14.5.1
2 participants