Version 4.6.0

This commit is contained in:
Neo committed 2025-12-19 05:55:31 -08:00
1 parent f79dcf067a
commit 517a5e1f70
2036 files changed
+110041 -26162

No files matched your search

@@ -1,38 +1,89 @@
<?php
declare(strict_types=1);
namespace GraphQL\Validator\Rules;
use GraphQL\Error\Error;
use GraphQL\Language\AST\DirectiveDefinitionNode;
use GraphQL\Language\AST\DirectiveNode;
use GraphQL\Language\AST\Node;
use GraphQL\Type\Definition\Directive;
use GraphQL\Validator\ASTValidationContext;
use GraphQL\Validator\SDLValidationContext;
use GraphQL\Validator\ValidationContext;
use function sprintf;
class UniqueDirectivesPerLocation extends AbstractValidationRule
/**
* Unique directive names per location
*
* A GraphQL document is only valid if all non-repeatable directives at
* a given location are uniquely named.
*/
class UniqueDirectivesPerLocation extends ValidationRule
{
static function duplicateDirectiveMessage($directiveName)
{
return 'The directive "'.$directiveName.'" can only be used once at this location.';
}
public function getVisitor(ValidationContext $context)
{
return $this->getASTVisitor($context);
}
public function getSDLVisitor(SDLValidationContext $context)
{
return $this->getASTVisitor($context);
}
public function getASTVisitor(ASTValidationContext $context)
{
$uniqueDirectiveMap = [];
$schema = $context->getSchema();
$definedDirectives = $schema !== null
? $schema->getDirectives()
: Directive::getInternalDirectives();
foreach ($definedDirectives as $directive) {
$uniqueDirectiveMap[$directive->name] = ! $directive->isRepeatable;
}
$astDefinitions = $context->getDocument()->definitions;
foreach ($astDefinitions as $definition) {
if (! ($definition instanceof DirectiveDefinitionNode)) {
continue;
}
$uniqueDirectiveMap[$definition->name->value] = $definition->repeatable;
}
return [
'enter' => function(Node $node) use ($context) {
if (isset($node->directives)) {
$knownDirectives = [];
foreach ($node->directives as $directive) {
/** @var DirectiveNode $directive */
$directiveName = $directive->name->value;
if (isset($knownDirectives[$directiveName])) {
$context->reportError(new Error(
self::duplicateDirectiveMessage($directiveName),
[$knownDirectives[$directiveName], $directive]
));
} else {
$knownDirectives[$directiveName] = $directive;
}
'enter' => static function (Node $node) use ($uniqueDirectiveMap, $context) : void {
if (! isset($node->directives)) {
return;
}
$knownDirectives = [];
/** @var DirectiveNode $directive */
foreach ($node->directives as $directive) {
$directiveName = $directive->name->value;
if (! isset($uniqueDirectiveMap[$directiveName])) {
continue;
}
if (isset($knownDirectives[$directiveName])) {
$context->reportError(new Error(
self::duplicateDirectiveMessage($directiveName),
[$knownDirectives[$directiveName], $directive]
));
} else {
$knownDirectives[$directiveName] = $directive;
}
}
}
},
];
}
public static function duplicateDirectiveMessage($directiveName)
{
return sprintf('The directive "%s" can only be used once at this location.', $directiveName);
}
}