TASK: Change KnownDirectives rule to match reference

https://github.com/graphql/graphql-js/blob/master/src/validation/rules/KnownDirectives.js
This commit is contained in:
Torsten Blindert 2018-10-01 19:48:56 +02:00
parent b1cd086177
commit b65aa4e657

View File

@ -11,6 +11,7 @@ use GraphQL\Language\AST\Node;
use GraphQL\Language\AST\NodeKind; use GraphQL\Language\AST\NodeKind;
use GraphQL\Language\AST\NodeList; use GraphQL\Language\AST\NodeList;
use GraphQL\Language\DirectiveLocation; use GraphQL\Language\DirectiveLocation;
use GraphQL\Type\Definition\Directive;
use GraphQL\Validator\ValidationContext; use GraphQL\Validator\ValidationContext;
use function count; use function count;
use function in_array; use function in_array;
@ -18,40 +19,51 @@ use function sprintf;
class KnownDirectives extends ValidationRule class KnownDirectives extends ValidationRule
{ {
/**
* @param ValidationContext $context
* @return array
*/
public function getVisitor(ValidationContext $context) public function getVisitor(ValidationContext $context)
{ {
return [ $locationsMap = [];
NodeKind::DIRECTIVE => function (DirectiveNode $node, $key, $parent, $path, $ancestors) use ($context) { $schema = $context->getSchema();
$directiveDef = null;
foreach ($context->getSchema()->getDirectives() as $def) {
if ($def->name === $node->name->value) {
$directiveDef = $def;
break;
}
}
if (! $directiveDef) { $definedDirectives = $schema ? $schema->getDirectives() : Directive::getInternalDirectives();
foreach ($definedDirectives as $directive) {
$locationsMap[$directive->name] = $directive->locations;
}
$astDefinition = $context->getDocument()->definitions;
foreach ($astDefinition as $def) {
if ($def->kind === NodeKind::DIRECTIVE_DEFINITION) {
$locationsMap[$def->name->value] = array_map(function ($name) {
return $name->value;
}, $def->locations);
}
}
return [
NodeKind::DIRECTIVE => function (DirectiveNode $node, $key, $parent, $path, $ancestors) use ($context, $locationsMap) {
$name = $node->name->value;
$locations = $locationsMap[$name] ?? null;
if (!$locations) {
$context->reportError(new Error( $context->reportError(new Error(
self::unknownDirectiveMessage($node->name->value), self::unknownDirectiveMessage($name),
[$node] [$node]
)); ));
return; return;
} }
$candidateLocation = $this->getDirectiveLocationForASTPath($ancestors); $candidateLocation = $this->getDirectiveLocationForASTPath($ancestors);
if (! $candidateLocation) { if ($candidateLocation && !in_array($candidateLocation, $locations)) {
$context->reportError(new Error( $context->reportError(new Error(
self::misplacedDirectiveMessage($node->name->value, $node->type), self::misplacedDirectiveMessage($name, $candidateLocation),
[$node]
));
} elseif (! in_array($candidateLocation, $directiveDef->locations)) {
$context->reportError(new Error(
self::misplacedDirectiveMessage($node->name->value, $candidateLocation),
[$node] [$node]
)); ));
} }
}, }
]; ];
} }
@ -88,6 +100,7 @@ class KnownDirectives extends ValidationRule
case NodeKind::FRAGMENT_DEFINITION: case NodeKind::FRAGMENT_DEFINITION:
return DirectiveLocation::FRAGMENT_DEFINITION; return DirectiveLocation::FRAGMENT_DEFINITION;
case NodeKind::SCHEMA_DEFINITION: case NodeKind::SCHEMA_DEFINITION:
case NodeKind::SCHEMA_EXTENSION:
return DirectiveLocation::SCHEMA; return DirectiveLocation::SCHEMA;
case NodeKind::SCALAR_TYPE_DEFINITION: case NodeKind::SCALAR_TYPE_DEFINITION:
case NodeKind::SCALAR_TYPE_EXTENSION: case NodeKind::SCALAR_TYPE_EXTENSION: