Skip to content

Commit

Permalink
Validate interface implemented ancestors
Browse files Browse the repository at this point in the history
Part of the work done to implement interfaces implementing interfaces.
This was caught by test and improves on the previously done changes for
the SchemaValidationContext by implementing
`validateTypeImplementsAncestors` which was missing.
  • Loading branch information
Kingdutch committed Nov 27, 2020
1 parent 5e4ab44 commit fde8176
Showing 1 changed file with 38 additions and 6 deletions.
44 changes: 38 additions & 6 deletions src/Type/SchemaValidationContext.php
Original file line number Diff line number Diff line change
Expand Up @@ -307,7 +307,7 @@ public function validateTypes() : void
$this->validateFields($type);

// Ensure objects implement the interfaces they claim to.
$this->validateTypeInterfaces($type);
$this->validateInterfaces($type);

// Ensure directives are valid
$this->validateDirectivesAtLocation(
Expand All @@ -319,7 +319,7 @@ public function validateTypes() : void
$this->validateFields($type);

// Ensure interfaces implement the interfaces they claim to.
$this->validateTypeInterfaces($type);
$this->validateInterfaces($type);

// Ensure directives are valid
$this->validateDirectivesAtLocation(
Expand Down Expand Up @@ -661,9 +661,9 @@ private function getFieldArgNode($type, $fieldName, $argName)
/**
* @param ObjectType|InterfaceType $type
*/
private function validateTypeInterfaces(ImplementingType $type)
private function validateInterfaces(ImplementingType $type)
{
$implementedTypeNames = [];
$ifaceTypeNames = [];
foreach ($type->getInterfaces() as $iface) {
if (! $iface instanceof InterfaceType) {
$this->reportError(
Expand All @@ -676,14 +676,16 @@ private function validateTypeInterfaces(ImplementingType $type)
);
continue;
}
if (isset($implementedTypeNames[$iface->name])) {
if (isset($ifaceTypeNames[$iface->name])) {
$this->reportError(
sprintf('Type %s can only implement %s once.', $type->name, $iface->name),
$this->getAllImplementsInterfaceNodes($type, $iface)
);
continue;
}
$implementedTypeNames[$iface->name] = true;
$ifaceTypeNames[$iface->name] = true;

$this->validateTypeImplementsAncestors($type, $iface);
$this->validateTypeImplementsInterface($type, $iface);
}
}
Expand Down Expand Up @@ -877,6 +879,36 @@ private function validateTypeImplementsInterface($type, $iface)
}
}

/**
* @param ObjectType|InterfaceType $type
* @param InterfaceType $iface
*/
private function validateTypeImplementsAncestors(ImplementingType $type, $iface) {
$typeInterfaces = $type->getInterfaces();
foreach ($iface->getInterfaces() as $transitive) {
if (!in_array($transitive, $typeInterfaces)) {
$this->reportError(
$transitive === $type ?
sprintf(
"Type %s cannot implement %s because it would create a circular reference.",
$type->name,
$iface->name
) :
sprintf(
"Type %s must implement %s because it is implemented by %s.",
$type->name,
$transitive->name,
$iface->name
),
array_merge(
$this->getAllImplementsInterfaceNodes($iface, $transitive),
$this->getAllImplementsInterfaceNodes($type, $iface)
)
);
}
}
}

private function validateUnionMembers(UnionType $union)
{
$memberTypes = $union->getTypes();
Expand Down

0 comments on commit fde8176

Please sign in to comment.