Skip to content

feat: Allow global/db IDs in connection where args#2340

Closed
justlevine wants to merge 7 commits intowp-graphql:developfrom
justlevine:feat/connection-id-inputs
Closed

feat: Allow global/db IDs in connection where args#2340
justlevine wants to merge 7 commits intowp-graphql:developfrom
justlevine:feat/connection-id-inputs

Conversation

@justlevine
Copy link
Copy Markdown
Collaborator

@justlevine justlevine commented Apr 10, 2022

What does this implement/fix? Explain your changes.

This PR allows GraphQL connection where args with a type ID to accept either global IDs or database IDs.
The method proposed is non-breaking, works uniformly across all connections, and is easily extendable both by custom connection resolvers and with WP filters.

It follows the pattern used by AbstractConnectionResolver::get_query_args().

As with other PRs addressing #998 , this can be implemented piece-meal for each connection, but only once the primary change to AbstractConnectionResolver has been changed. For this reason, I've also included CommentsConnectionResolver in the PR, and can either break that to a separate PR or add the other updated resolvers to this one. 🤷

How it works:

  1. AbstractConnectionResolver::$args is now passed through the graphql_connection_args filter.
  2. AbstractConnectionResolver::getArgs() has been deprecated in favor of AbstractConnectionResolver::get_args(), which provides a way for resolvers to modify the connection args before they are passed to AbstractConnectionResolver::get_query_args().
  3. [👀] Added CommentConnectionResolver::get_args() to map all inputs of type ID to their database ID.

Alternatives considered:

  • Converting the ID value in {Type}ConnectionResolver::get_query_args(). This adds additional mess and complexity to an already complex method, and requires duplicate logic for each input arg.
  • Using the parseValues config callable.
    The theory is that using parseValues on the input config, would allow us to improve separation of concerns, at the cost of significant code duplication. However, I either misunderstood the GraphQL-PHP docs, or this isnt currently supported by WPGraphQL. (You can see this approach implemented - and failing! - for Data\Connection\PostObjects here ).

Does this close any currently open issues?

#998

Any other comments?

  1. The graphql_connection_args filter only passes the $args parameter, as the class instance is not in a place yet where its public methods can be called consistently. Now working.

  2. Tests are going to be a huge PITA opportunity to improve coverall scores, since most connections dont currently have many of these where args tested. Could use help implementing these.

  3. the version number on the deprecations and new filters will need to be updated before release

Where has this been tested?

Operating System: Ubuntu 20.04 (wsl2 + devilbox + php 8.0.19)

WordPress Version: 6.0.1

@justlevine justlevine marked this pull request as draft April 10, 2022 12:42
*
* @return array
*/
public function get_args() {
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Function get_args has a Cognitive Complexity of 18 (exceeds 5 allowed). Consider refactoring.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

There's definitely a way to simplify this - open to suggestions. My focus was providing a working example of implementation.

@justlevine justlevine added type: enhancement Improvements to existing functionality needs: reviewer response This needs the attention of a codeowner or maintainer component: connections Relating to GraphQL Connections scope: api Issues related to access functions, actions, and filters component: input Relating to GraphQL Input Types needs: tests Tests should be added to be sure this works as expected labels Apr 10, 2022
@justlevine
Copy link
Copy Markdown
Collaborator Author

@jasonbahl let me know if this approach looks good to you, and if so whether I should move CommentsResolver to its own PR or update the other resolvers on this one.

@coveralls
Copy link
Copy Markdown

coveralls commented Apr 10, 2022

Coverage Status

Coverage decreased (-0.2%) to 81.861% when pulling e4683a0 on justlevine:feat/connection-id-inputs into 2ee6fc8 on wp-graphql:develop.

*
* @return array
*/
public function get_args() {
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Function get_args has a Cognitive Complexity of 13 (exceeds 5 allowed). Consider refactoring.

@justlevine
Copy link
Copy Markdown
Collaborator Author

Related: #1779

@justlevine justlevine force-pushed the feat/connection-id-inputs branch from 1399f17 to 49e39d5 Compare May 17, 2022 23:38
@stale
Copy link
Copy Markdown

stale bot commented Aug 2, 2022

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.

@stale stale bot added the stale label Aug 2, 2022
@justlevine justlevine force-pushed the feat/connection-id-inputs branch from 49e39d5 to 2c1e3fb Compare August 13, 2022 09:08
@stale stale bot removed the stale label Aug 13, 2022
@justlevine justlevine changed the title Feat: Allow global/db IDs in connection where args feat: Allow global/db IDs in connection where args Aug 13, 2022
],
'description' => __( 'Specify IDs NOT to retrieve. If this is used in the same query as "in", it will be ignored', 'wp-graphql' ),
'parseValue' => function ( $value ) {
return Utils::parse_input_ids( $value );
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Avoid too many return statements within this method.

],
'description' => __( 'Find objects connected to author(s) in the array of author\'s userIds', 'wp-graphql' ),
'parseValue' => function ( $value ) {
return Utils::parse_input_ids( $value );
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Avoid too many return statements within this method.

],
'description' => __( 'Find objects NOT connected to author(s) in the array of author\'s userIds', 'wp-graphql' ),
'parseValue' => function ( $value ) {
return Utils::parse_input_ids( $value );
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Avoid too many return statements within this method.

],
'description' => __( 'Array of category IDs, used to display objects from one category OR another', 'wp-graphql' ),
'parseValue' => function ( $value ) {
return Utils::parse_input_ids( $value );
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Avoid too many return statements within this method.

],
'description' => __( 'Array of category IDs, used to display objects from one category OR another', 'wp-graphql' ),
'parseValue' => function ( $value ) {
return Utils::parse_input_ids( $value );
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Avoid too many return statements within this method.

@qlty-cloud-legacy
Copy link
Copy Markdown

Code Climate has analyzed commit e4683a0 and detected 13 issues on this pull request.

Here's the issue category breakdown:

Category Count
Complexity 11
Duplication 2

View more on Code Climate.

@justlevine
Copy link
Copy Markdown
Collaborator Author

justlevine commented Aug 13, 2022

Updates:

  • Rebased onto develop.
  • Changed when apply_filters() is applied to $this->args for better lifecycle consistency.
  • Implemented a 'proof of concept' test for this approach, and a failed approach using $config['parseValues']. Details in the (updated) PR description.

@jasonbahl :
I feel confident in this approach since the pattern used for $this->args is already established throughout the codebase and the WP filter adds modification parity in line with other WPGraphQL types. Additionally it's both backward-compatible, and 'forward-compatible' with either an Interface or Model approach to connections.
While the logic necessary in the individual resolver get_args() might be a bit messy, I think this is justified the same way in the same way as `sanitize_input_fields().

With your approval, I will close this in favor of a series of PRs: first the new filter and method in AbstractConnectionResolver, and then a separate one for each Connection Resolver type - so the obscene number of connection where arg tests that need to get backfilled don't freeze other work with merge conflicts.

@justlevine justlevine added status: in review Awaiting review before merging or closing and removed needs: tests Tests should be added to be sure this works as expected labels Aug 13, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

component: connections Relating to GraphQL Connections component: input Relating to GraphQL Input Types needs: reviewer response This needs the attention of a codeowner or maintainer scope: api Issues related to access functions, actions, and filters status: in review Awaiting review before merging or closing type: enhancement Improvements to existing functionality

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants