Skip to content

Acquiring the WP_Query instance within a wp-graphql filter causes post hooks to fire again #2715

@ToughCrab24

Description

@ToughCrab24

Description

When acquiring the WP_Query instance inside of wp-graphql filters, it causes post hooks such as posts_pre_query to fire a second time within the wp-graphql request lifecyle.

Example

function filter_graphql_connection_page_info(
  $page_info,
  AbstractConnectionResolver $resolver,
) {
  $query = $resolver->get_query();
  return $query->query_args;
}

add_filter(
  'graphql_connection_page_info',
  ['filter_graphql_connection_page_info'],
  10,
  2
);

Explanation

In the case the AbstractConnectionResolver is an instance of PostObjectConnectionResolver
we can see that the WP_Query class is instantiated

public function get_query() {
// Get query class.
$queryClass = ! empty( $this->context->queryClass )
? $this->context->queryClass
: '\WP_Query';
$query = new $queryClass( $this->query_args );
if ( isset( $query->query_vars['suppress_filters'] ) && true === $query->query_vars['suppress_filters'] ) {
throw new InvariantViolation( __( 'WP_Query has been modified by a plugin or theme to suppress_filters, which will cause issues with WPGraphQL Execution. If you need to suppress filters for a specific reason within GraphQL, consider registering a custom field to the WPGraphQL Schema with a custom resolver.', 'wp-graphql' ) );
}
return $query;
}

Digging into WordPress core we can see the side-effect of instantiating a new instance of WP_Query calls $this->query( $query ) in its constructor and then calls $this->get_posts()

https://github.com/WordPress/WordPress/blob/master/wp-includes/class-wp-query.php#L3787

This results in applying the posts_pre_query and other hooks https://github.com/WordPress/WordPress/blob/master/wp-includes/class-wp-query.php#L3136

Steps to reproduce

Define hooks:

function filter_graphql_connection_page_info(
  $page_info,
  AbstractConnectionResolver $resolver,
) {
  $query = $resolver->get_query();
  return $query->query_args;
}

add_filter(
  'graphql_connection_page_info',
  ['filter_graphql_connection_page_info'],
  10,
  2
);

function filter_posts_pre_query($posts, WP_Query $query) {
   graphql_debug("Triggered posts_pre_query");
   return $posts;
}

add_filter('posts_pre_query', 'filter_posts_pre_query', 10, 2);

With wp-graphql debug enabled run the query

{
  posts {
    nodes {
      title
    }
  }
}

Additional context

No response

WPGraphQL Version

1.13.8

WordPress Version

6.1.1

PHP Version

7.4 & 8

Additional enviornment details

Observed in wp-graphql-offset-pagination https://github.com/valu-digital/wp-graphql-offset-pagination/blob/master/src/Loader.php#L128

Please confirm that you have searched existing issues in the repo.

  • Yes

Please confirm that you have disabled ALL plugins except for WPGraphQL.

  • Yes
  • My issue is with compatibility with a specific WordPress plugin, and I have listed all my installed plugins (and version info) above.

Metadata

Metadata

Assignees

No one assigned

    Labels

    status: actionableReady for work to begintype: bugIssue that causes incorrect or unexpected behavior

    Type

    No type

    Projects

    Status

    ✅ Done

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions