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

feat: Adds terms querying functionality for the CorePostTerms Block. #339

Merged
merged 12 commits into from
Feb 10, 2025
Merged
40 changes: 40 additions & 0 deletions .changeset/calm-socks-battle.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
---
"@wpengine/wp-graphql-content-blocks": minor
---

Adds support for resolving and returning related term items as a `terms` connection for the CorePostTerms block along with `taxonomy` connection.
Adds support for resolving and returning the `prefix` and `suffix` items within the correspondent fields of the CorePostTerms block.

```graphql
query TestPostTerms($uri: String! = "test-terms") {
nodeByUri(uri: $uri) {
id
uri
... on NodeWithPostEditorBlocks {
editorBlocks {
__typename
... on CorePostTerms {
prefix
suffix
taxonomy {
__typename
node {
__typename
id
name
}
}
terms {
__typename
nodes {
__typename
id
name
}
}
}
}
}
}
}
```
104 changes: 104 additions & 0 deletions includes/Blocks/CorePostTerms.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
<?php
/**
* Core Post Terms Block
*
* @package WPGraphQL\ContentBlocks\Blocks
*/

namespace WPGraphQL\ContentBlocks\Blocks;

use WPGraphQL\AppContext;
use WPGraphQL\ContentBlocks\Registry\Registry;
use WPGraphQL\Data\Connection\TaxonomyConnectionResolver;
use WPGraphQL\Data\Connection\TermObjectConnectionResolver;
use WP_Block_Type;

/**
* Class CorePostTerms.
*/
class CorePostTerms extends Block {
/**
* {@inheritDoc}
*/
public function __construct( WP_Block_Type $block, Registry $block_registry ) {
parent::__construct( $block, $block_registry );

$this->register_fields();
$this->register_connections();
}

/**
* Registers custom fields for the block.
*/
private function register_fields(): void {
register_graphql_fields(
$this->type_name,
[
'prefix' => [
'type' => 'String',
'description' => __( 'Prefix to display before the post terms', 'wp-graphql-content-blocks' ),
'resolve' => static fn ( $block ) => isset( $block['attrs']['prefix'] ) ? (string) $block['attrs']['prefix'] : null,
],
'suffix' => [
'type' => 'String',
'description' => __( 'Suffix to display after the post terms', 'wp-graphql-content-blocks' ),
'resolve' => static fn ( $block ) => isset( $block['attrs']['suffix'] ) ? (string) $block['attrs']['suffix'] : null,
],
]
);
}

/**
* Registers a list of terms field for the block.
*
* @return void
* @throws \Exception
*/
protected function register_connections() {
// Register connection to terms.
register_graphql_connection(
[
'fromType' => $this->type_name,
'toType' => 'TermNode',
'fromFieldName' => 'terms',
'resolve' => static function ( $block, array $args, AppContext $context, $info ) {
$taxonomy = $block['attrs']['term'] ?? null;
if ( empty( $taxonomy ) ) {
return null;
}

$post_id = get_the_ID();
if ( ! $post_id ) {
return null;
}

$args['where']['objectIds'] = $post_id;
$resolver = new TermObjectConnectionResolver( $block, $args, $context, $info, $taxonomy );

return $resolver->get_connection();
},
]
);

// Register connection to the taxonomy.
register_graphql_connection(
[
'fromType' => $this->type_name,
'toType' => 'Taxonomy',
'fromFieldName' => 'taxonomy',
'oneToOne' => true,
'resolve' => static function ( $block, array $args, AppContext $context, $info ) {
$taxonomy = $block['attrs']['term'] ?? null;
if ( empty( $taxonomy ) ) {
return null;
}

$resolver = new TaxonomyConnectionResolver( $block, $args, $context, $info );
$resolver->set_query_arg( 'name', $taxonomy );

return $resolver->one_to_one()->get_connection();
},
]
);
}
}
132 changes: 132 additions & 0 deletions tests/unit/CorePostTermsTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
<?php

namespace WPGraphQL\ContentBlocks\Unit;

final class CorePostTermsTest extends PluginTestCase {

/**
* The URI of the post created for the test.
*
* @var string
*/
public $post_uri;

/**
* The ID of the post created for the test.
*
* @var int
*/
public $post_id;

public function setUp(): void {
parent::setUp();

$this->post_id = wp_insert_post(
[
'post_title' => 'Test Terms',
'post_name' => 'test-terms',
'post_content' => '',
'post_status' => 'publish',
]
);

$this->post_uri = get_permalink($this->post_id);

\WPGraphQL::clear_schema();
}

public function tearDown(): void {
wp_delete_post($this->post_id, true);
\WPGraphQL::clear_schema();

parent::tearDown();
}

/**
* Get the updated GraphQL query for the CorePostTerms block.
*/
public function query(): string {
return '
query TestPostTerms($uri: String! = "test-terms") {
nodeByUri(uri: $uri) {
id
uri
... on NodeWithPostEditorBlocks {
editorBlocks {
__typename
... on CorePostTerms {
prefix
suffix
taxonomy {
__typename
node {
__typename
id
name
}
}
terms {
__typename
nodes {
__typename
id
name
}
}
}
}
}
}
}
';
}

/**
* Test that the CorePostTerms block retrieves attributes, taxonomy, and terms correctly.
*/
public function test_retrieve_core_post_terms(): void {
$block_content = '<!-- wp:post-terms {"prefix":"Before","suffix":"After","term":"category"} /-->';

wp_update_post(
[
'ID' => $this->post_id,
'post_content' => $block_content,
]
);

$variables = [ 'uri' => 'test-terms' ];
$query = $this->query();
$actual = graphql(compact('query', 'variables'));

$node = $actual['data']['nodeByUri'];

$this->assertArrayHasKey('editorBlocks', $node);
$this->assertCount(1, $node['editorBlocks']);

$block = $node['editorBlocks'][0];

$this->assertEquals('CorePostTerms', $block['__typename']);
$this->assertEquals('Before', $block['prefix']);
$this->assertEquals('After', $block['suffix']);

$this->assertArrayHasKey('taxonomy', $block);
$this->assertArrayHasKey('node', $block['taxonomy']);
$this->assertArrayHasKey('__typename', $block['taxonomy']['node']);
$this->assertArrayHasKey('id', $block['taxonomy']['node']);
$this->assertArrayHasKey('name', $block['taxonomy']['node']);

$this->assertArrayHasKey('terms', $block);
$this->assertArrayHasKey('nodes', $block['terms']);
$this->assertIsArray($block['terms']['nodes']);
$this->assertEquals('CorePostTermsToTermNodeConnection', $block['terms']['__typename']);
$this->assertEquals('Category', $block['terms']['nodes'][0]['__typename']);

$this->assertArrayHasKey('taxonomy', $block);
$this->assertArrayHasKey('node', $block['taxonomy']);
$this->assertIsArray($block['taxonomy']['node']);
$this->assertEquals('CorePostTermsToTaxonomyConnectionEdge', $block['taxonomy']['__typename']);
$this->assertEquals('category', $block['taxonomy']['node']['name']);


}
}
Loading