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