/** * Provided a type and a super type, return true if the first type is either * equal or a subset of the second super type (covariant). */ static function isTypeSubTypeOf(Schema $schema, Type $maybeSubType, Type $superType) { // Equivalent type is a valid subtype if ($maybeSubType === $superType) { return true; } // If superType is non-null, maybeSubType must also be nullable. if ($superType instanceof NonNull) { if ($maybeSubType instanceof NonNull) { return self::isTypeSubTypeOf($schema, $maybeSubType->getWrappedType(), $superType->getWrappedType()); } return false; } else { if ($maybeSubType instanceof NonNull) { // If superType is nullable, maybeSubType may be non-null. return self::isTypeSubTypeOf($schema, $maybeSubType->getWrappedType(), $superType); } } // If superType type is a list, maybeSubType type must also be a list. if ($superType instanceof ListOfType) { if ($maybeSubType instanceof ListOfType) { return self::isTypeSubTypeOf($schema, $maybeSubType->getWrappedType(), $superType->getWrappedType()); } return false; } else { if ($maybeSubType instanceof ListOfType) { // If superType is not a list, maybeSubType must also be not a list. return false; } } // If superType type is an abstract type, maybeSubType type may be a currently // possible object type. if (Type::isAbstractType($superType) && $maybeSubType instanceof ObjectType && $schema->isPossibleType($superType, $maybeSubType)) { return true; } // Otherwise, the child type is not a valid subtype of the parent type. return false; }