Skip to content

Commit e2b2ac3

Browse files
authored
Merge pull request #156 from wp-graphql/fix/acf-fields-not-resolving-with-preview
fix: acf fields not resolving with preview
2 parents 250b4e2 + 469c9ab commit e2b2ac3

File tree

4 files changed

+120
-12
lines changed

4 files changed

+120
-12
lines changed

src/Registry.php

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ class Registry {
2828
*/
2929
protected $type_registry;
3030

31+
3132
/**
3233
* @param \WPGraphQL\Registry\TypeRegistry|null $type_registry
3334
*
@@ -46,6 +47,13 @@ public function __construct( TypeRegistry $type_registry = null ) {
4647
do_action( 'wpgraphql/acf/type_registry/init', $this );
4748
}
4849

50+
/**
51+
* @return array<mixed>
52+
*/
53+
public function get_registered_fields() {
54+
return $this->registered_fields;
55+
}
56+
4957
/**
5058
* Get the TypeRegistry instance
5159
*/
@@ -467,7 +475,18 @@ public function get_fields_for_field_group( array $acf_field_group ): array {
467475
* @throws \Exception
468476
*/
469477
public function map_acf_field_to_graphql( array $acf_field, array $acf_field_group ): ?array {
470-
return ( new FieldConfig( $acf_field, $acf_field_group, $this ) )->get_graphql_field_config();
478+
$field_config = ( new FieldConfig( $acf_field, $acf_field_group, $this ) )->get_graphql_field_config();
479+
480+
if ( ! empty( $field_config['acf_field'] ) ) {
481+
if ( isset( $field_config['acf_field']['key'] ) && ! in_array( $field_config['acf_field']['key'], $this->registered_fields, true ) ) {
482+
$this->registered_fields[] = $field_config['acf_field']['key'];
483+
}
484+
if ( isset( $field_config['acf_field']['name'] ) && ! in_array( $field_config['acf_field']['name'], $this->registered_fields, true ) ) {
485+
$this->registered_fields[] = $field_config['acf_field']['name'];
486+
}
487+
}
488+
489+
return $field_config;
471490
}
472491

473492

src/Utils.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -274,7 +274,7 @@ public static function should_field_group_show_in_graphql( array $acf_field_grou
274274
if (
275275
( isset( $acf_field_group['is_options_page'] ) && false === $acf_field_group['is_options_page'] ) &&
276276
! isset( $acf_field_group['show_in_graphql'] ) ) {
277-
$acf_field_group['show_in_graphql'] = $show_in_rest ?? false;
277+
$acf_field_group['show_in_graphql'] = $show_in_rest;
278278
}
279279

280280
if ( isset( $acf_field_group['show_in_graphql'] ) && false === $acf_field_group['show_in_graphql'] ) {

src/WPGraphQLAcf.php

Lines changed: 93 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,12 @@ class WPGraphQLAcf {
2121
protected $plugin_load_error_messages = [];
2222

2323
/**
24+
* @var \WPGraphQL\Acf\Registry|null
25+
*/
26+
protected $registry;
27+
28+
/**
29+
* @return void
2430
* Initialize the plugin
2531
*/
2632
public function init(): void {
@@ -38,6 +44,8 @@ public function init(): void {
3844
add_action( 'after_setup_theme', [ $this, 'acf_internal_post_type_support' ] );
3945
add_action( 'graphql_register_types', [ $this, 'init_registry' ] );
4046

47+
add_filter( 'graphql_resolve_revision_meta_from_parent', [ $this, 'preview_support' ], 10, 4 );
48+
4149
add_filter( 'graphql_data_loaders', [ $this, 'register_loaders' ], 10, 2 );
4250
add_filter( 'graphql_resolve_node_type', [ $this, 'resolve_acf_options_page_node' ], 10, 2 );
4351
/**
@@ -89,19 +97,99 @@ public function init_registry( TypeRegistry $type_registry ): void {
8997

9098
// Register general types that should be available to the Schema regardless
9199
// of the specific fields and field groups registered by ACF
92-
$registry = new Registry( $type_registry );
93-
$registry->register_initial_graphql_types();
94-
$registry->register_options_pages();
100+
$this->registry = new Registry( $type_registry );
101+
$this->registry->register_initial_graphql_types();
102+
$this->registry->register_options_pages();
95103

96104
// Get the field groups that should be mapped to the Schema
97-
$acf_field_groups = $registry->get_acf_field_groups();
105+
$acf_field_groups = $this->registry->get_acf_field_groups();
98106

99107
// If there are no acf field groups to show in GraphQL, do nothing
100108
if ( empty( $acf_field_groups ) ) {
101109
return;
102110
}
103111

104-
$registry->register_acf_field_groups_to_graphql( $acf_field_groups );
112+
$this->registry->register_acf_field_groups_to_graphql( $acf_field_groups );
113+
}
114+
115+
/**
116+
* @param int $post_id The ID of the post to check if it's a preview of another post
117+
*
118+
* @return bool|\WP_Post
119+
*/
120+
protected function is_preview_post( int $post_id ) {
121+
$post = get_post( $post_id );
122+
123+
if ( ! $post ) {
124+
return false; // Post does not exist
125+
}
126+
127+
// Check if it's a revision (autosave)
128+
if ( 'revision' === $post->post_type && 'inherit' === $post->post_status ) {
129+
$parent_post = get_post( $post->post_parent );
130+
131+
// Check if parent post is either a draft or published
132+
if ( $parent_post && in_array( $parent_post->post_status, [ 'draft', 'publish' ], true ) ) {
133+
return $parent_post; // It's a preview of a draft or published post
134+
}
135+
}
136+
137+
return false; // Not a preview post
138+
}
139+
140+
141+
/**
142+
* Add support for resolving ACF Fields when queried for asPreview
143+
*
144+
* NOTE: this currently only works if classic editor is not being used
145+
*
146+
* @param bool $should Whether to resolve using the parent object. Default true.
147+
* @param int $object_id The ID of the object to resolve meta for
148+
* @param string $meta_key The key for the meta to resolve
149+
* @param bool $single Whether a single value should be returned
150+
*/
151+
public function preview_support( bool $should, int $object_id, string $meta_key, bool $single ): bool {
152+
if ( ! $this->registry instanceof Registry ) {
153+
return (bool) $should;
154+
}
155+
156+
$preview_post = $this->is_preview_post( $object_id );
157+
if ( ! $preview_post instanceof WP_Post ) {
158+
return (bool) $should;
159+
}
160+
161+
// If the block editor is being used for the post, bail early as the Block Editor doesn't
162+
// properly support revisions of post meta
163+
// see: https://github.com/WordPress/gutenberg/issues/16006#issuecomment-657965028
164+
if ( use_block_editor_for_post( $preview_post ) ) {
165+
graphql_debug( __( 'The post you are querying as a preview uses the Block Editor and saving & previewing meta is not fully supported by the block editor. This is a WordPress block editor bug. See: https://github.com/WordPress/gutenberg/issues/16006#issuecomment-657965028', 'wpgraphql-acf' ) );
166+
return (bool) $should;
167+
}
168+
169+
$registered_fields = $this->registry->get_registered_fields();
170+
171+
if ( in_array( $meta_key, $registered_fields, true ) ) {
172+
return false;
173+
}
174+
175+
foreach ( $registered_fields as $field_name ) {
176+
// For flex fields/repeaters, the meta keys are structured a bit funky.
177+
// This checks to see if the $meta_key starts with the same string as one of the
178+
// acf fields (a flex/repeater field) and then checks if it's preceeded by an underscore and a number.
179+
if ( strpos( $meta_key, $field_name ) === 0 ) {
180+
// match any string that starts with the field name, followed by an underscore, followed by a number, followed by another string
181+
// ex my_flex_field_0_text_field or some_repeater_field_12_25MostPopularDogToys
182+
$pattern = '/' . $field_name . '_\d+_\w+/m';
183+
preg_match( $pattern, $meta_key, $matches );
184+
185+
// If the meta key matches the pattern, treat it as a sub-field of an ACF Field Group
186+
if ( null !== $matches ) {
187+
return false;
188+
}
189+
}
190+
}
191+
192+
return $should;
105193
}
106194

107195
/**

tests/wpunit/FieldTypes/TaxonomyFieldTest.php

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ public function testQueryTaxononomyFieldOnBlock() {
104104
if ( ! defined( 'WPGRAPHQL_CONTENT_BLOCKS_DIR' ) ) {
105105
$this->markTestSkipped( 'This test is skipped when WPGraphQL Content Blocks is not active' );
106106
}
107-
107+
108108
acf_register_block_type([
109109
'name' => 'block_with_category_field',
110110
'title' => 'Block with Category Field',
@@ -282,10 +282,11 @@ interfaces {
282282
'__typename' => 'Category',
283283
'databaseId' => $category_id,
284284
], 0 ),
285-
$this->expectedNode( 'blockTaxonomyTest.category.nodes', [
286-
'__typename' => 'Category',
287-
'databaseId' => $category_2_id,
288-
], 0 ),
285+
// Only the first node will be returned because the taxonomy field is set to "multiple: 0" so ACF will only return a single value
286+
// $this->expectedNode( 'blockTaxonomyTest.category.nodes', [
287+
// '__typename' => 'Category',
288+
// 'databaseId' => $category_2_id,
289+
// ], 1 ),
289290
], 0 ),
290291
]);
291292

0 commit comments

Comments
 (0)