Skip to content

Commit bb60eb4

Browse files
authored
Fix overly eager validation of repeatable directive usage (#847)
1 parent b38c92e commit bb60eb4

File tree

3 files changed

+113
-77
lines changed

3 files changed

+113
-77
lines changed

CHANGELOG.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,19 @@
11
# Changelog
22

33
#### Unreleased
4+
Changed:
45
- PHP version required: 7.4+
6+
7+
Removed:
58
- Removed deprecated `Type::getInternalTypes()`
69
- Remove deprecated `GraphQL::execute()`
710
- Remove deprecated `GraphQL::executeAndReturnResult()`
811

12+
#### 14.6.2
13+
14+
Fix:
15+
- Fix overly eager validation of repeatable directive usage
16+
917
#### 14.6.1
1018

1119
Fix:

src/Type/SchemaValidationContext.php

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -62,13 +62,11 @@
6262
class SchemaValidationContext
6363
{
6464
/** @var array<int, Error> */
65-
private $errors = [];
65+
private array $errors = [];
6666

67-
/** @var Schema */
68-
private $schema;
67+
private Schema $schema;
6968

70-
/** @var InputObjectCircularRefs */
71-
private $inputObjectCircularRefs;
69+
private InputObjectCircularRefs $inputObjectCircularRefs;
7270

7371
public function __construct(Schema $schema)
7472
{
@@ -381,8 +379,9 @@ public function validateTypes(): void
381379
*/
382380
private function validateDirectivesAtLocation(NodeList $directives, string $location)
383381
{
384-
$directivesNamed = [];
385-
$schema = $this->schema;
382+
/** @var array<string, array<int, DirectiveNode>> $potentiallyDuplicateDirectives */
383+
$potentiallyDuplicateDirectives = [];
384+
$schema = $this->schema;
386385
foreach ($directives as $directive) {
387386
$directiveName = $directive->name->value;
388387

@@ -412,18 +411,22 @@ static function ($schemaLocation) use ($location): bool {
412411
);
413412
}
414413

415-
$existingNodes = $directivesNamed[$directiveName] ?? [];
416-
$existingNodes[] = $directive;
417-
$directivesNamed[$directiveName] = $existingNodes;
414+
if ($schemaDirective->isRepeatable) {
415+
continue;
416+
}
417+
418+
$existingNodes = $potentiallyDuplicateDirectives[$directiveName] ?? [];
419+
$existingNodes[] = $directive;
420+
$potentiallyDuplicateDirectives[$directiveName] = $existingNodes;
418421
}
419422

420-
foreach ($directivesNamed as $directiveName => $directiveList) {
423+
foreach ($potentiallyDuplicateDirectives as $directiveName => $directiveList) {
421424
if (count($directiveList) <= 1) {
422425
continue;
423426
}
424427

425428
$this->reportError(
426-
sprintf('Directive @%s used twice at the same location.', $directiveName),
429+
sprintf('Non-repeatable directive @%s used more than once at the same location.', $directiveName),
427430
$directiveList
428431
);
429432
}

0 commit comments

Comments
 (0)