mirror of
https://github.com/retailcrm/graphql-php.git
synced 2025-02-06 07:49:24 +03:00
Added validation rule for unique directives per location
This commit is contained in:
parent
8a676cde99
commit
f672f0c90c
@ -43,6 +43,7 @@ use GraphQL\Validator\Rules\QueryComplexity;
|
||||
use GraphQL\Validator\Rules\QueryDepth;
|
||||
use GraphQL\Validator\Rules\ScalarLeafs;
|
||||
use GraphQL\Validator\Rules\UniqueArgumentNames;
|
||||
use GraphQL\Validator\Rules\UniqueDirectivesPerLocation;
|
||||
use GraphQL\Validator\Rules\UniqueFragmentNames;
|
||||
use GraphQL\Validator\Rules\UniqueInputFieldNames;
|
||||
use GraphQL\Validator\Rules\UniqueOperationNames;
|
||||
@ -88,6 +89,7 @@ class DocumentValidator
|
||||
'NoUndefinedVariables' => new NoUndefinedVariables(),
|
||||
'NoUnusedVariables' => new NoUnusedVariables(),
|
||||
'KnownDirectives' => new KnownDirectives(),
|
||||
'UniqueDirectivesPerLocation' => new UniqueDirectivesPerLocation(),
|
||||
'KnownArgumentNames' => new KnownArgumentNames(),
|
||||
'UniqueArgumentNames' => new UniqueArgumentNames(),
|
||||
'ArgumentsOfCorrectType' => new ArgumentsOfCorrectType(),
|
||||
|
38
src/Validator/Rules/UniqueDirectivesPerLocation.php
Normal file
38
src/Validator/Rules/UniqueDirectivesPerLocation.php
Normal file
@ -0,0 +1,38 @@
|
||||
<?php
|
||||
namespace GraphQL\Validator\Rules;
|
||||
|
||||
use GraphQL\Error\Error;
|
||||
use GraphQL\Language\AST\Directive;
|
||||
use GraphQL\Language\AST\Node;
|
||||
use GraphQL\Validator\ValidationContext;
|
||||
|
||||
class UniqueDirectivesPerLocation
|
||||
{
|
||||
static function duplicateDirectiveMessage($directiveName)
|
||||
{
|
||||
return 'The directive "'.$directiveName.'" can only be used once at this location.';
|
||||
}
|
||||
|
||||
public function __invoke(ValidationContext $context)
|
||||
{
|
||||
return [
|
||||
'enter' => function(Node $node) use ($context) {
|
||||
if (isset($node->directives)) {
|
||||
$knownDirectives = [];
|
||||
foreach ($node->directives as $directive) {
|
||||
/** @var Directive $directive */
|
||||
$directiveName = $directive->name->value;
|
||||
if (isset($knownDirectives[$directiveName])) {
|
||||
$context->reportError(new Error(
|
||||
self::duplicateDirectiveMessage($directiveName),
|
||||
[$knownDirectives[$directiveName], $directive]
|
||||
));
|
||||
} else {
|
||||
$knownDirectives[$directiveName] = $directive;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
];
|
||||
}
|
||||
}
|
138
tests/Validator/UniqueDirectivesPerLocationTest.php
Normal file
138
tests/Validator/UniqueDirectivesPerLocationTest.php
Normal file
@ -0,0 +1,138 @@
|
||||
<?php
|
||||
namespace GraphQL\Tests\Validator;
|
||||
|
||||
use GraphQL\Validator\Rules\UniqueDirectivesPerLocation;
|
||||
|
||||
class UniqueDirectivesPerLocationTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* @it no directives
|
||||
*/
|
||||
public function testNoDirectives()
|
||||
{
|
||||
$this->expectPassesRule(new UniqueDirectivesPerLocation(), '
|
||||
fragment Test on Type {
|
||||
field
|
||||
}
|
||||
');
|
||||
}
|
||||
|
||||
/**
|
||||
* @it unique directives in different locations
|
||||
*/
|
||||
public function testUniqueDirectivesInDifferentLocations()
|
||||
{
|
||||
$this->expectPassesRule(new UniqueDirectivesPerLocation(), '
|
||||
fragment Test on Type @directiveA {
|
||||
field @directiveB
|
||||
}
|
||||
');
|
||||
}
|
||||
|
||||
/**
|
||||
* @it unique directives in same locations
|
||||
*/
|
||||
public function testUniqueDirectivesInSameLocations()
|
||||
{
|
||||
$this->expectPassesRule(new UniqueDirectivesPerLocation(), '
|
||||
fragment Test on Type @directiveA @directiveB {
|
||||
field @directiveA @directiveB
|
||||
}
|
||||
');
|
||||
}
|
||||
|
||||
/**
|
||||
* @it same directives in different locations
|
||||
*/
|
||||
public function testSameDirectivesInDifferentLocations()
|
||||
{
|
||||
$this->expectPassesRule(new UniqueDirectivesPerLocation(), '
|
||||
fragment Test on Type @directiveA {
|
||||
field @directiveA
|
||||
}
|
||||
');
|
||||
}
|
||||
|
||||
/**
|
||||
* @it same directives in similar locations
|
||||
*/
|
||||
public function testSameDirectivesInSimilarLocations()
|
||||
{
|
||||
$this->expectPassesRule(new UniqueDirectivesPerLocation(), '
|
||||
fragment Test on Type {
|
||||
field @directive
|
||||
field @directive
|
||||
}
|
||||
');
|
||||
}
|
||||
|
||||
/**
|
||||
* @it duplicate directives in one location
|
||||
*/
|
||||
public function testDuplicateDirectivesInOneLocation()
|
||||
{
|
||||
$this->expectFailsRule(new UniqueDirectivesPerLocation(), '
|
||||
fragment Test on Type {
|
||||
field @directive @directive
|
||||
}
|
||||
', [
|
||||
$this->duplicateDirective('directive', 3, 15, 3, 26)
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @it many duplicate directives in one location
|
||||
*/
|
||||
public function testManyDuplicateDirectivesInOneLocation()
|
||||
{
|
||||
$this->expectFailsRule(new UniqueDirectivesPerLocation(), '
|
||||
fragment Test on Type {
|
||||
field @directive @directive @directive
|
||||
}
|
||||
', [
|
||||
$this->duplicateDirective('directive', 3, 15, 3, 26),
|
||||
$this->duplicateDirective('directive', 3, 15, 3, 37)
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @it different duplicate directives in one location
|
||||
*/
|
||||
public function testDifferentDuplicateDirectivesInOneLocation()
|
||||
{
|
||||
$this->expectFailsRule(new UniqueDirectivesPerLocation, '
|
||||
fragment Test on Type {
|
||||
field @directiveA @directiveB @directiveA @directiveB
|
||||
}
|
||||
', [
|
||||
$this->duplicateDirective('directiveA', 3, 15, 3, 39),
|
||||
$this->duplicateDirective('directiveB', 3, 27, 3, 51)
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @it duplicate directives in many locations
|
||||
*/
|
||||
public function testDuplicateDirectivesInManyLocations()
|
||||
{
|
||||
$this->expectFailsRule(new UniqueDirectivesPerLocation(), '
|
||||
fragment Test on Type @directive @directive {
|
||||
field @directive @directive
|
||||
}
|
||||
', [
|
||||
$this->duplicateDirective('directive', 2, 29, 2, 40),
|
||||
$this->duplicateDirective('directive', 3, 15, 3, 26)
|
||||
]);
|
||||
}
|
||||
|
||||
private function duplicateDirective($directiveName, $l1, $c1, $l2, $c2)
|
||||
{
|
||||
return [
|
||||
'message' =>UniqueDirectivesPerLocation::duplicateDirectiveMessage($directiveName),
|
||||
'locations' => [
|
||||
['line' => $l1, 'column' => $c1],
|
||||
['line' => $l2, 'column' => $c2]
|
||||
]
|
||||
];
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user