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

Introduce register_graphql_connection_where_arg API #3065

Open
jasonbahl opened this issue Mar 1, 2024 · 0 comments
Open

Introduce register_graphql_connection_where_arg API #3065

jasonbahl opened this issue Mar 1, 2024 · 0 comments
Labels
component: connections Relating to GraphQL Connections component: query Relating to GraphQL Queries scope: api Issues related to access functions, actions, and filters type: enhancement Improvements to existing functionality

Comments

@jasonbahl
Copy link
Collaborator

jasonbahl commented Mar 1, 2024

What problem does this address?

When trying to do things like add Where Args to all connections to a specific type it's cumbersome to do so.

With Object Types, we can add a field to ContentNode and all Types that implement the interface get the field.

But with Input Types there's no concept of Input Interfaces, so each unique connection cannot inherit a general set of fields like Object Types can.

If we wanted to add a custom where arg to all "post" connections, it becomes tricky.

If using register_graphql_field() I would have to know the names of all possible Post connections and do something like:

register_graphql_field( 'RootQueryToPostConnectionWhereArgs', 'myCustomInputField', [] );
register_graphql_field( 'UserToPostConnectionWhereArgs', 'myCustomInputField', [] );
register_graphql_field( 'TagToPostConnectionWhereArgs', 'myCustomInputField', [] );
register_graphql_field( 'CategoryToPostConnectionWhereArgs', 'myCustomInputField', [] );
...

...and so on

This doesn't scale!

I can't / don't want to attempt to keep up with all the possible types I would need to filter. When it comes to things like ACF that add even more Types to the Schema, etc it is essentially impossible to know all the connections that may exist in the schema.

To get around this, we could add a filter like so:

add_filter( 'graphql_input_fields', function( $fields, $type_name, $config, $type_registry ) {

	$post_connection = 'ToPostConnectionWhereArgs';

	// If the Input Type is NOT where args on a connection "To Post", don't apply any changes
	if ( substr( $type_name, -strlen( $post_connection ) ) !== $post_connection ) {
		return $fields;
	}

	$fields['offsetPagination'] = [
		'type' => 'OffsetPagination',
		'description' => __( 'Paginate content nodes with offsets', 'your-textdomain' ),
	];

    return $fields;


}, 10, 4 );

This should work and is certainly better than register_graphql_field() for unknown to add a where arg to all Post connections, but feels clunky. . .and I'd still have to map how the input argument impacts the underlying resolution.

Another (cleaner) option would be hooking into the connection Instantiation like so:

add_action( 'graphql_wp_connection_type', function( array $connection_config, \WPGraphQL\Type\WPConnectionType $wp_connection_type ) {

  if ( 'product' !== $connection_config['toType'] ) {
    return;
  }

  $wp_connection_type->where_args[ 'offsetPagination' ] = [
    'type' => 'OffsetPagination',
	'description' => __( 'Paginate content nodes with offsets', 'your-textdomain' ),
  ];

} );

This is looking much better!

But I still need to map the new arg to underlying resolution.

What is your proposed solution?

I propose we introduce a register_graphql_connection_where_arg() API that makes it easier to add an argument to connection(s) AND map the argument to the underlying execution.

Something to the tune of:

function register_graphql_connection_where_arg( $to_type, $arg_name, $arg_config ) { ... };

which could be used like so:

register_graphql_connection_where_arg( 'Product', 'offsetPagination' [
  'type' => 'OffsetPagination',
  'description' => __( 'Paginate content nodes with offsets', 'your-textdomain' ),
  'map_input_arg' => function( $input ) { // this would be where we define how the input field maps to the underlying WP_Query (or similar) that would execute },
] );

What alternatives have you considered?

(see possible alternatives above)

Additional Context

No response

@jasonbahl jasonbahl added type: enhancement Improvements to existing functionality component: connections Relating to GraphQL Connections scope: api Issues related to access functions, actions, and filters component: query Relating to GraphQL Queries labels Mar 1, 2024
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: query Relating to GraphQL Queries scope: api Issues related to access functions, actions, and filters type: enhancement Improvements to existing functionality
Projects
Status: 🆕 New
Development

No branches or pull requests

1 participant