Adding Custom Blocks
Block registration
First, register the block.
add_action(
'acf/init',
function () {
acf_register_block_type(
[
'name' => 'block-name',
'title' => 'Block Title',
'category' => 'acf-blocks',
'mode' => 'edit',
'keywords' => 'block,keywords',
'show_in_graphql' => true,
]
);
},
10
);
Fields registration
Then, register ACF fields for the block.
use StoutLogic\AcfBuilder\FieldsBuilder;
add_action(
'acf/init',
function () {
$builder = new FieldsBuilder(
'block-name',
[
'title' => 'Block Title',
]
);
$builder
->addText( 'field' )
->addImage( 'image', [ 'return_format' => 'array' ] )
->addPostObject(
'post',
[
'label' => 'Post',
'post_type' => [ 'post' ],
'return_format' => 'id',
]
)
->setLocation( 'block', '==', 'acf/block-name' );
acf_add_local_field_group($builder->build());
},
10
);
See also:
Graphql request
The block name in the Graphql scheme generated by the pattern: Acf
+ the block name defined on
registration in pascal case + Block
The block data will be available in CMS editor and might be
requested by graphql query.
fragment AcfBlockNameBlockFragment on AcfBlockNameBlock {
name
attributesJSON
}
{
resolveUrl(url: "/") {
node {
... on Post {
blocksLight {
...AcfBlockNameBlockFragment
}
}
... on Page {
blocksLight {
...AcfBlockNameBlockFragment
}
}
}
}
}
See also:
Custom resolvers
Scalar values fields (string, numeric, etc) will be available in attributes field automatically. But for complex values (Posts, list of Post, Category, Image, etc.) we have to implement a custom resolvers.
See also:
Post
We return the WP_Post object wrapped by the WPGraphQL\Model\Post
object.
use WPGraphQL\Model\Post;
add_action( 'graphql_register_types', function () {
register_graphql_field(
'AcfBlockNameBlock',
'post',
[
'type' => 'Post',
'resolve' => function ( $block ) {
$post_id = $block->attributes['data']['post'];
$post = get_post( $post_id );
if ( ! $post ) {
return null;
}
return new Post( $post );
},
]
);
}, 10 );
Image
The image is similar to the Post resolver with 'type' => 'MediaItem'
.
use WPGraphQL\Model\Post;
add_action( 'graphql_register_types', function () {
register_graphql_field(
'AcfBlockNameBlock',
'image',
[
'type' => 'MediaItem',
'resolve' => function( $block ) {
$image_id = $block->attributes['data']['image'];
if ( ! $image_id ) {
return null;
}
$post_object = get_post( $image_id );
if ( $post_object instanceof \WP_Post ) {
return new Post( $post_object );
}
return null;
},
]
);
}, 10 );
Category
The image is similar to the Post resolver with 'type' => 'Category'
, wrapped by
WPGraphQL\Model\Term
object.
use WPGraphQL\Model\Term;
add_action( 'graphql_register_types', function () {
register_graphql_field(
'AcfBlockNameBlock',
'category',
[
'type' => 'Category',
'resolve' => function( $block ) {
$category_id = $block->attributes['data']['category'];
$category = get_category( $category_id );
if ( $category instanceof \WP_Term ) {
return new Term( $category );
}
return null;
},
]
);
}, 10 );
List of Posts
To resolve a list of posts (with pagination and deduplication), we recommend using the
register_gutenberg_block_posts_connection
helper.
use function SWPCore\HeadlessFrontend\register_gutenberg_block_posts_connection;
public function posts_query_builder( array $attributes ): array {
$category_id = $attributes['data']['category'];
return [
'posts_per_page' => 4,
'paged' => 1,
'post_type' => 'post',
'cat' => $category_id,
'orderby' => 'date',
'order' => 'DESC',
];
}
add_action( 'graphql_register_types', function () {
register_gutenberg_block_posts_connection( 'AcfBlockNameBlock', posts_query_builder );
}, 10 );
Querying custom fields
fragment AcfBlockNameBlockFragment on AcfBlockNameBlock {
name
attributesJSON
post {
title
}
image {
sourceUrl
}
posts {
nodes {
title
}
}
}