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

fix: prevent non-node types from being output in the query analyzer list type keys #2691

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
23 changes: 16 additions & 7 deletions src/Utils/QueryAnalyzer.php
Expand Up @@ -351,14 +351,15 @@ public function set_list_types( ?Schema $schema, ?string $query ): array {
// if the type is a list and the named type doesn't start
// with a double __, then it should be tracked
if ( $is_list_type && 0 !== strpos( $named_type, '__' ) ) {

// if the Type is not a Node, and has a "node" field,
// lets get the named type of the node, not the edge
if ( in_array( 'node', $named_type->getFieldNames(), true ) && ! in_array( 'Node', array_keys( $named_type->getInterfaces() ), true ) ) {
// if the type doesn't apply the node interface
if ( ! empty( $named_type->getInterfaces() ) && array_key_exists( 'Node', $named_type->getInterfaces() ) ) {
// if the Type is not a Node, and has a "node" field,
// lets get the named type of the node, not the edge
$type_map[] = 'list:' . strtolower( $named_type );
} elseif ( in_array( 'node', $named_type->getFieldNames(), true ) ) {
$named_type = $named_type->getField( 'node' )->getType();
$type_map[] = 'list:' . strtolower( $named_type );
}

$type_map[] = 'list:' . strtolower( $named_type );
}
}

Expand All @@ -369,7 +370,15 @@ public function set_list_types( ?Schema $schema, ?string $query ): array {
foreach ( $possible_types as $possible_type ) {
// if the type is a list, store it
if ( $is_list_type && 0 !== strpos( $possible_type, '__' ) ) {
$type_map[] = 'list:' . strtolower( $possible_type );
// if the type doesn't apply the node interface
if ( ! empty( $possible_type->getInterfaces() ) && array_key_exists( 'Node', $possible_type->getInterfaces() ) ) {
// if the Type is not a Node, and has a "node" field,
// lets get the named type of the node, not the edge
$type_map[] = 'list:' . strtolower( $possible_type );
} elseif ( in_array( 'node', $possible_type->getFieldNames(), true ) ) {
$named_type = $named_type->getField( 'node' )->getType();
$type_map[] = 'list:' . strtolower( $possible_type );
}
}
}
}
Expand Down
76 changes: 76 additions & 0 deletions tests/wpunit/QueryAnalyzerTest.php
Expand Up @@ -11,6 +11,8 @@ public function _setUp():void {
'post_title' => 'test post'
]);

WPGraphQL::clear_schema();

}

public function _tearDown():void {
Expand Down Expand Up @@ -79,4 +81,78 @@ public function testQueryTypes() {
$this->assertEqualSets( [ 'rootquery', 'rootquerytopostconnection', 'post' ], $types );
}

public function testQueryForListOfNonNodeInterfaceTypesDoesntAddKeys() {

// types that do not implement the "Node" interface shouldn't be tracked as keys
// in the Query Analyzer

add_action( 'graphql_register_types', function() {
register_graphql_interface_type( 'TestInterface', [
'eagerlyLoadType' => true,
'fields' => [
'test' => [
'type' => 'String',
],
],
'resolveType' => function () {
return 'TestType';
},
] );

register_graphql_object_type( 'TestType', [
'eagerlyLoadType' => true,
'interfaces' => [ 'TestInterface' ],
'fields' => [
'test' => [
'type' => 'String',
],
],
] );

register_graphql_field( 'Post', 'testField', [
'type' => [ 'list_of' => 'TestInterface' ],
'resolve' => function () {
return [
[
'test' => 'value',
],
[
'test' => 'value',
],
];
},
] );
} );


$query = '
{
posts {
nodes {
testField {
test
}
}
}
}
';

$request = graphql([
'query' => $query
], true );

$request->execute();

$list_types = $request->get_query_analyzer()->get_list_types();

codecept_debug( $list_types );
$keys_array = $list_types;
codecept_debug( $list_types );

$this->assertNotContains( 'list:testinterface', $list_types );
$this->assertNotContains( 'list:testtype', $list_types );
$this->assertContains( 'list:post', $list_types );

}

}