static public doTypesOverlap ( |
||
$schema | ||
$typeA | GraphQL\Type\Definition\CompositeType | |
$typeB | GraphQL\Type\Definition\CompositeType |
static function doTypesOverlap(Schema $schema, CompositeType $typeA, CompositeType $typeB)
{
// Equivalent types overlap
if ($typeA === $typeB) {
return true;
}
if ($typeA instanceof AbstractType) {
if ($typeB instanceof AbstractType) {
// If both types are abstract, then determine if there is any intersection
// between possible concrete types of each.
foreach ($schema->getPossibleTypes($typeA) as $type) {
if ($schema->isPossibleType($typeB, $type)) {
return true;
}
}
return false;
}
/** @var $typeB ObjectType */
// Determine if the latter type is a possible concrete type of the former.
return $schema->isPossibleType($typeA, $typeB);
}
if ($typeB instanceof AbstractType) {
/** @var $typeA ObjectType */
// Determine if the former type is a possible concrete type of the latter.
return $schema->isPossibleType($typeB, $typeA);
}
// Otherwise the types do not overlap.
return false;
}
public function __invoke(ValidationContext $context) { return [NodeKind::INLINE_FRAGMENT => function (InlineFragmentNode $node) use($context) { $fragType = $context->getType(); $parentType = $context->getParentType(); if ($fragType && $parentType && !TypeInfo::doTypesOverlap($context->getSchema(), $fragType, $parentType)) { $context->reportError(new Error(self::typeIncompatibleAnonSpreadMessage($parentType, $fragType), [$node])); } }, NodeKind::FRAGMENT_SPREAD => function (FragmentSpreadNode $node) use($context) { $fragName = $node->name->value; $fragType = $this->getFragmentType($context, $fragName); $parentType = $context->getParentType(); if ($fragType && $parentType && !TypeInfo::doTypesOverlap($context->getSchema(), $fragType, $parentType)) { $context->reportError(new Error(self::typeIncompatibleSpreadMessage($fragName, $parentType, $fragType), [$node])); } }]; }