Skip to content

Commit 11a1b13

Browse files
author
Pascal de Vink
committed
Use directives to calculate query complexity
1 parent 5948d51 commit 11a1b13

File tree

2 files changed

+79
-0
lines changed

2 files changed

+79
-0
lines changed

src/Validator/Rules/QueryComplexity.php

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
use GraphQL\Language\AST\OperationDefinitionNode;
1313
use GraphQL\Language\AST\SelectionSetNode;
1414
use GraphQL\Language\Visitor;
15+
use GraphQL\Type\Definition\Directive;
1516
use GraphQL\Type\Definition\FieldDefinition;
1617
use GraphQL\Validator\ValidationContext;
1718

@@ -138,6 +139,10 @@ private function nodeComplexity(Node $node, $complexity = 0)
138139
$fieldDef = $astFieldInfo[1];
139140

140141
if ($fieldDef instanceof FieldDefinition) {
142+
if ($this->directiveExcludesField($node)) {
143+
break;
144+
}
145+
141146
$args = $this->buildFieldArguments($node);
142147
//get complexity fn using fieldDef complexity
143148
if (method_exists($fieldDef, 'getComplexityFn')) {
@@ -205,6 +210,32 @@ private function buildFieldArguments(FieldNode $node)
205210
return $args;
206211
}
207212

213+
private function directiveExcludesField(FieldNode $node) {
214+
foreach ($node->directives as $directiveNode) {
215+
if ($directiveNode->name->value === 'deprecated') {
216+
return false;
217+
}
218+
219+
$variableValues = Values::getVariableValues(
220+
$this->context->getSchema(),
221+
$this->variableDefs,
222+
$this->getRawVariableValues()
223+
);
224+
225+
if ($directiveNode->name->value === 'include') {
226+
$directive = Directive::includeDirective();
227+
$directiveArgs = Values::getArgumentValues($directive, $directiveNode, $variableValues);
228+
229+
return !$directiveArgs['if'];
230+
} else {
231+
$directive = Directive::skipDirective();
232+
$directiveArgs = Values::getArgumentValues($directive, $directiveNode, $variableValues);
233+
234+
return $directiveArgs['if'];
235+
}
236+
}
237+
}
238+
208239
protected function isEnabled()
209240
{
210241
return $this->getMaxQueryComplexity() !== static::DISABLED;

tests/Validator/QueryComplexityTest.php

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,54 @@ public function testCustomComplexityWithVariablesQueries()
8686
$this->assertDocumentValidators($query, 3, 4);
8787
}
8888

89+
public function testQueryWithEnabledIncludeDirectives()
90+
{
91+
$query = 'query MyQuery($withDogs: Boolean!) { human { dogs(name: "Root") @include(if:$withDogs) { name } } }';
92+
93+
$this->getRule()->setRawVariableValues(['withDogs' => true]);
94+
95+
$this->assertDocumentValidators($query, 3, 4);
96+
}
97+
98+
public function testQueryWithDisabledIncludeDirectives()
99+
{
100+
$query = 'query MyQuery($withDogs: Boolean!) { human { dogs(name: "Root") @include(if:$withDogs) { name } } }';
101+
102+
$this->getRule()->setRawVariableValues(['withDogs' => false]);
103+
104+
$this->assertDocumentValidators($query, 1, 2);
105+
}
106+
107+
public function testQueryWithEnabledSkipDirectives()
108+
{
109+
$query = 'query MyQuery($withoutDogs: Boolean!) { human { dogs(name: "Root") @skip(if:$withoutDogs) { name } } }';
110+
111+
$this->getRule()->setRawVariableValues(['withoutDogs' => true]);
112+
113+
$this->assertDocumentValidators($query, 1, 2);
114+
}
115+
116+
public function testQueryWithDisabledSkipDirectives()
117+
{
118+
$query = 'query MyQuery($withoutDogs: Boolean!) { human { dogs(name: "Root") @skip(if:$withoutDogs) { name } } }';
119+
120+
$this->getRule()->setRawVariableValues(['withoutDogs' => false]);
121+
122+
$this->assertDocumentValidators($query, 3, 4);
123+
}
124+
125+
public function testQueryWithMultipleDirectives()
126+
{
127+
$query = 'query MyQuery($withDogs: Boolean!, $withoutDogName: Boolean!) { human { dogs(name: "Root") @include(if:$withDogs) { name @skip(if:$withoutDogName) } } }';
128+
129+
$this->getRule()->setRawVariableValues([
130+
'withDogs' => true,
131+
'withoutDogName' => true
132+
]);
133+
134+
$this->assertDocumentValidators($query, 2, 3);
135+
}
136+
89137
public function testComplexityIntrospectionQuery()
90138
{
91139
$this->assertIntrospectionQuery(181);

0 commit comments

Comments
 (0)