diff --git a/src/Data/DataSource.php b/src/Data/DataSource.php index 97dc7b8b4..f079c2fee 100755 --- a/src/Data/DataSource.php +++ b/src/Data/DataSource.php @@ -179,14 +179,6 @@ public static function resolve_post_object( $id, $post_type ) { remove_filter( 'the_content', 'prepend_attachment' ); } - /** - * Set the resolving post to the global $post. That way any filters that - * might be applied when resolving fields can rely on global post and - * post data being set up. - */ - $GLOBALS['post'] = $post_object; - setup_postdata( $post_object ); - return $post_object; } diff --git a/src/Request.php b/src/Request.php index 6030d84e0..9c6409c65 100644 --- a/src/Request.php +++ b/src/Request.php @@ -139,9 +139,14 @@ private function after_execute( $response ) { * This allows for a GraphQL query to be used in the middle of post content, such as in a Shortcode * without disrupting the flow of the post as the global POST before and after GraphQL execution will be * the same. + * + * We cannot use wp_reset_postdata here because it just resets the post from the global query which can + * be anything the because the resolvers themself can set it to whatever. So we just manually reset the + * post with setup_postdata we cached before this request. */ if ( ! empty( $this->global_post ) ) { $GLOBALS['post'] = $this->global_post; + setup_postdata( $this->global_post ); } /** diff --git a/src/Utils/InstrumentSchema.php b/src/Utils/InstrumentSchema.php index 8fb9ddad4..70cc9ce40 100644 --- a/src/Utils/InstrumentSchema.php +++ b/src/Utils/InstrumentSchema.php @@ -17,6 +17,12 @@ */ class InstrumentSchema { + /** + * Cache post for the resolvers so we can call the setup_postdata only when the actual + * source post changes + */ + private static $cached_post = null; + /** * @param \WPGraphQL\WPSchema $schema * @@ -110,6 +116,17 @@ protected static function wrap_fields( $fields, $type_name ) { */ $field->resolveFn = function( $source, array $args, AppContext $context, ResolveInfo $info ) use ( $field_resolver, $type_name, $field_key, $field ) { + /** + * Setup the global post to the current post (if a post) + * This ensures that functions like get_the_content() work correctly + * so graphql queries can be used in the loop without issues. + */ + if ( is_a( $source, 'WP_Post' ) && self::$cached_post !== $source ) { + self::$cached_post = $source; + $GLOBALS['post'] = $source; + setup_postdata( $source ); + } + /** * Fire an action BEFORE the field resolves * diff --git a/tests/wpunit/PostObjectConnectionQueriesTest.php b/tests/wpunit/PostObjectConnectionQueriesTest.php index a88745ab8..7ac108257 100644 --- a/tests/wpunit/PostObjectConnectionQueriesTest.php +++ b/tests/wpunit/PostObjectConnectionQueriesTest.php @@ -732,12 +732,12 @@ public function testPostExcerptsAreDifferent() { $post_1_args = [ 'post_content' => 'Post content 1', - 'post_excerpt' => 'Post excerpt 1', + 'post_excerpt' => '', ]; $post_2_args = [ 'post_content' => 'Post content 2', - 'post_excerpt' => 'Post excerpt 2', + 'post_excerpt' => '', ]; $post_1_id = $this->createPostObject( $post_1_args ); diff --git a/tests/wpunit/PostObjectQueriesTest.php b/tests/wpunit/PostObjectQueriesTest.php index 4c7e9fe6f..71d343001 100644 --- a/tests/wpunit/PostObjectQueriesTest.php +++ b/tests/wpunit/PostObjectQueriesTest.php @@ -1355,9 +1355,15 @@ public function testPostQueryPostDataReset() { do_graphql_request( $graphql_query ); /** - * Asset that the query has been reset to the main query. + * Assert that the query has been reset to the main query. */ $this->assertEquals( $main_query_post_id, $post->ID ); + + // setup_postdata sets the global $id too so assert it is reset back to + // original + // https://github.com/WordPress/WordPress/blob/b5542c6b1b41d69b4e5c26ef8280c6e85de67224/wp-includes/class-wp-query.php#L4158 + $this->assertEquals( $main_query_post_id, $GLOBALS['id'] ); + } /**