some functions converted over

This commit is contained in:
Ben Roberts 2017-11-16 13:53:01 -05:00
parent 7aebf2dbf7
commit 3811181f49

View File

@ -5,8 +5,19 @@
namespace GraphQL\Utils;
use GraphQL\Type\Definition\EnumType;
use GraphQL\Type\Definition\InputObjectType;
use GraphQL\Type\Definition\InterfaceType;
use GraphQL\Type\Definition\ListOfType;
use GraphQL\Type\Definition\NonNull;
use GraphQL\Type\Definition\ObjectType;
use GraphQL\Type\Definition\ScalarType;
use GraphQL\Type\Definition\Type;
use GraphQL\Type\Definition\UnionType;
use GraphQL\Type\Schema;
class FindBreakingChanges {
class FindBreakingChanges
{
const BREAKING_CHANGE_FIELD_CHANGED = 'FIELD_CHANGED_KIND';
const BREAKING_CHANGE_FIELD_REMOVED = 'FIELD_REMOVED';
@ -26,6 +37,24 @@ class FindBreakingChanges {
TYPE_ADDED_TO_UNION: 'TYPE_ADDED_TO_UNION',
};*/
/**
* Given two schemas, returns an Array containing descriptions of all the types
* of potentially dangerous changes covered by the other functions down below.
*
* @return array
*/
public function findDangerousChanges(
Schema $oldSchema, Schema $newSchema
)
{
return [
/* ...findArgChanges(oldSchema, newSchema).dangerousChanges,
...findValuesAddedToEnums(oldSchema, newSchema),
...findTypesAddedToUnions(oldSchema, newSchema)
*/
];
}
/**
* Given two schemas, returns an Array containing descriptions of all the types
* of breaking changes covered by the other functions down below.
@ -34,7 +63,8 @@ class FindBreakingChanges {
*/
public function findBreakingChanges(
$oldSchema, $newSchema
) {
)
{
return [
/*...findRemovedTypes(oldSchema, newSchema),
...findTypesThatChangedKind(oldSchema, newSchema),
@ -47,43 +77,35 @@ class FindBreakingChanges {
];
}
/**
* Given two schemas, returns an Array containing descriptions of all the types
* of potentially dangerous changes covered by the other functions down below.
*
* @return array
*/
public function findDangerousChanges(
$oldSchema, $newSchema
) {
return [
/* ...findArgChanges(oldSchema, newSchema).dangerousChanges,
...findValuesAddedToEnums(oldSchema, newSchema),
...findTypesAddedToUnions(oldSchema, newSchema)
*/
];
}
/**
* Given two schemas, returns an Array containing descriptions of any breaking
* changes in the newSchema related to removing an entire type.
*/
public function findRemovedTypes(
$oldSchema, $newSchema
) {
/*const oldTypeMap = oldSchema.getTypeMap();
const newTypeMap = newSchema.getTypeMap();
Schema $oldSchema, Schema $newSchema
)
{
$oldTypeMap = $oldSchema->getTypeMap();
$newTypeMap = $newSchema->getTypeMap();
const breakingChanges = [];
Object.keys(oldTypeMap).forEach(typeName => {
$breakingChanges = [];
foreach ($oldTypeMap as $typeName => $typeDefinition) {
if (!isset($newTypeMap[$typeName])) {
$breakingChanges[] =
['type' => self::BREAKING_CHANGE_TYPE_REMOVED, 'description' => "${$typeName} was removed."];
}
}
/*Object.keys(oldTypeMap).forEach(typeName => {
if (!newTypeMap[typeName]) {
breakingChanges.push({
type: BreakingChangeType.TYPE_REMOVED,
description: `${typeName} was removed.`,
});
}
});
return breakingChanges;*/
});*/
return $breakingChanges;
}
/**
@ -91,12 +113,29 @@ class FindBreakingChanges {
* changes in the newSchema related to changing the type of a type.
*/
public function findTypesThatChangedKind(
$oldSchema, $newSchema
) {
/*const oldTypeMap = oldSchema.getTypeMap();
const newTypeMap = newSchema.getTypeMap();
Schema $oldSchema, Schema $newSchema
)
{
$oldTypeMap = $oldSchema->getTypeMap();
$newTypeMap = $newSchema->getTypeMap();
const breakingChanges = [];
$breakingChanges = [];
foreach ($oldTypeMap as $typeName => $typeDefinition) {
if (!isset($newTypeMap[$typeName])) {
continue;
}
$newTypeDefinition = $newTypeMap[$typeName];
if (!($typeDefinition instanceof $newTypeDefinition)) {
$oldTypeKindName = self::typeKindName($typeDefinition);
$newTypeKindName = self::typeKindName($newTypeDefinition);
$breakingChanges[] = [
'type' => self::BREAKING_CHANGE_TYPE_CHANGED,
'description' => "${$typeName} changed from ${oldTypeKindName} to ${newTypeKindName}."
];
}
}
/*
Object.keys(oldTypeMap).forEach(typeName => {
if (!newTypeMap[typeName]) {
return;
@ -110,9 +149,9 @@ class FindBreakingChanges {
`${typeKindName(oldType)} to ${typeKindName(newType)}.`
});
}
});
return breakingChanges;
*/
});*/
return $breakingChanges;
}
/**
@ -122,14 +161,77 @@ class FindBreakingChanges {
* argument's default value).
*/
public function findArgChanges(
$oldSchema, $newSchema
) {
/* const oldTypeMap = oldSchema.getTypeMap();
const newTypeMap = newSchema.getTypeMap();
Schema $oldSchema, Schema $newSchema
)
{
$oldTypeMap = $oldSchema->getTypeMap();
$newTypeMap = $newSchema->getTypeMap();
const breakingChanges = [];
const dangerousChanges = [];
$breakingChanges = [];
$dangerousChanges = [];
foreach ($oldTypeMap as $oldTypeName => $oldTypeDefinition) {
$newTypeDefinition = isset($newTypeMap[$oldTypeName]) ? $newTypeMap[$oldTypeName] : null;
if (!($oldTypeDefinition instanceof ObjectType || $oldTypeDefinition instanceof InterfaceType) ||
!($newTypeDefinition instanceof $oldTypeDefinition)) {
continue;
}
$oldTypeFields = $oldTypeDefinition->getFields();
$newTypeFields = $newTypeDefinition->getFields();
foreach ($oldTypeFields as $fieldName => $fieldDefinition) {
if (!isset($newTypeFields[$fieldName])) {
continue;
}
foreach ($fieldDefinition->args as $oldArgName => $oldArgDef) {
$newArgs = $newTypeFields[$fieldName]->args;
$newArgDef = Utils::find(
$newArgs, function ($arg) use ($oldArgDef) {
return $arg->name === $oldArgDef->name;
}
);
if (!$newArgDef) {
$breakingChanges[] = [
'type' => self::BREAKING_CHANGE_ARG_REMOVED,
'description' => "${$oldTypeName}->${$fieldName} arg ${oldArgName} was removed"
];
} else {
$isSafe = self::isChangeSafeForInputObjectFieldOrFieldArg($oldArgDef->getType(), $newArgDef->getType());
if (!$isSafe) {
$oldArgType = $oldArgDef->getType();
$newArgType = $newArgDef->getType();
$breakingChanges[] = [
'type' => self::BREAKING_CHANGE_ARG_CHANGED,
'description' => "${oldTypeName}->${fieldName} arg ${oldArgName} has changed type from ${oldArgType} to ${newArgType}"
];
} elseif ($oldArgDef->defaultValueExists() && $oldArgDef->defaultValue !== $newArgDef->defaultValue) {
$dangerousChanges[] = []; // TODO
}
}
// Check if a non-null arg was added to the field
foreach ($newTypeFields[$fieldName]->args as $newArgName => $newArgDef) {
$oldArgs = $oldTypeFields[$fieldName]->args;
$oldArgDef = Utils::find(
$oldArgs, function ($arg) use ($newArgDef) {
return $arg->name === $newArgDef->name;
}
);
if (!$oldArgDef && $newArgDef->getType() instanceof NonNull) {
$newTypeName = $newTypeDefinition->name;
$breakingChanges[] = [
'type' => self::BREAKING_CHANGE_NON_NULL_ARG_ADDED,
'description' => "A non-null arg ${$newArgName} on ${newTypeName}->${fieldName} was added."
];
}
}
}
}
}
return ['breakingChanges' => $breakingChanges, 'dangerousChanges' => $dangerousChanges];
/*
Object.keys(oldTypeMap).forEach(typeName => {
const oldType = oldTypeMap[typeName];
const newType = newTypeMap[typeName];
@ -207,26 +309,29 @@ class FindBreakingChanges {
};*/
}
private static function typeKindName($type) {
/* if (type instanceof GraphQLScalarType) {
/**
* @param Type $type
* @return string
*
* @throws \TypeError
*/
private static function typeKindName(Type $type)
{
if ($type instanceof ScalarType) {
return 'a Scalar type';
}
if (type instanceof GraphQLObjectType) {
} elseif($type instanceof ObjectType) {
return 'an Object type';
}
if (type instanceof GraphQLInterfaceType) {
} elseif ($type instanceof InterfaceType) {
return 'an Interface type';
}
if (type instanceof GraphQLUnionType) {
} elseif ($type instanceof UnionType) {
return 'a Union type';
}
if (type instanceof GraphQLEnumType) {
} elseif ($type instanceof EnumType) {
return 'an Enum type';
}
if (type instanceof GraphQLInputObjectType) {
} elseif ($type instanceof InputObjectType) {
return 'an Input type';
}
throw new TypeError('Unknown type ' + type.constructor.name);*/
throw new \TypeError('unknown type ' . $type->name);
}
/**
@ -236,8 +341,9 @@ class FindBreakingChanges {
* a non-null field is added to an input type.
*/
public static function findFieldsThatChangedType(
$oldSchema, $newSchema
) {
Schema $oldSchema, Schema $newSchema
)
{
/*return [
...findFieldsThatChangedTypeOnObjectOrInterfaceTypes(oldSchema, newSchema),
...findFieldsThatChangedTypeOnInputObjectTypes(oldSchema, newSchema),
@ -246,7 +352,8 @@ class FindBreakingChanges {
private static function findFieldsThatChangedTypeOnObjectOrInterfaceTypes(
$oldSchema, $newSchema
) {
)
{
/*const oldTypeMap = oldSchema.getTypeMap();
const newTypeMap = newSchema.getTypeMap();
@ -296,8 +403,9 @@ class FindBreakingChanges {
}
public static function findFieldsThatChangedTypeOnInputObjectTypes(
$oldSchema, $newSchema
) {
Schema $oldSchema, Schema $newSchema
)
{
/* const oldTypeMap = oldSchema.getTypeMap();
const newTypeMap = newSchema.getTypeMap();
@ -360,8 +468,31 @@ class FindBreakingChanges {
}
private static function isChangeSafeForObjectOrInterfaceField(
$oldType, $newType
) {
Type $oldType, Type $newType
)
{
if (self::isNamedType($oldType)) {
// if they're both named types, see if their names are equivalent
return (self::isNamedType($newType) && $oldType->name === $newType->name)
// moving from nullable to non-null of the same underlying type is safe
|| ($newType instanceof NonNull
&& self::isChangeSafeForObjectOrInterfaceField(
$oldType, $newType->getWrappedType()
));
} elseif ($oldType instanceof ListOfType) {
// if they're both lists, make sure the underlying types are compatible
return ($newType instanceof ListOfType &&
self::isChangeSafeForObjectOrInterfaceField($oldType->getWrappedType(), $newType->getWrappedType())) ||
// moving from nullable to non-null of the same underlying type is safe
($newType instanceof NonNull &&
self::isChangeSafeForObjectOrInterfaceField($oldType, $newType->getWrappedType()));
} elseif ($oldType instanceof NonNull) {
// if they're both non-null, make sure the underlying types are compatible
return $newType instanceof NonNull &&
self::isChangeSafeForObjectOrInterfaceField($oldType->getWrappedType(), $newType->getWrappedType());
}
return false;
/*if (isNamedType(oldType)) {
return (
// if they're both named types, see if their names are equivalent
@ -404,8 +535,9 @@ class FindBreakingChanges {
}
private static function isChangeSafeForInputObjectFieldOrFieldArg(
$oldType, $newType
) {
Schema $oldSchema, Schema $newSchema
)
{
/* if (isNamedType(oldType)) {
// if they're both named types, see if their names are equivalent
return isNamedType(newType) && oldType.name === newType.name;
@ -443,8 +575,9 @@ class FindBreakingChanges {
* changes in the newSchema related to removing types from a union type.
*/
public static function findTypesRemovedFromUnions(
$oldSchema, $newSchema
) {
Schema $oldSchema, Schema $newSchema
)
{
/* const oldTypeMap = oldSchema.getTypeMap();
const newTypeMap = newSchema.getTypeMap();
@ -477,8 +610,9 @@ class FindBreakingChanges {
* changes in the newSchema related to adding types to a union type.
*/
public static function findTypesAddedToUnions(
$oldSchema, $newSchema
) {
Schema $oldSchema, Schema $newSchema
)
{
/* const oldTypeMap = oldSchema.getTypeMap();
const newTypeMap = newSchema.getTypeMap();
@ -511,8 +645,9 @@ class FindBreakingChanges {
* changes in the newSchema related to removing values from an enum type.
*/
public static function findValuesRemovedFromEnums(
$oldSchema, $newSchema
) {
Schema $oldSchema, Schema $newSchema
)
{
/* const oldTypeMap = oldSchema.getTypeMap();
const newTypeMap = newSchema.getTypeMap();
@ -545,8 +680,9 @@ class FindBreakingChanges {
* changes in the newSchema related to adding values to an enum type.
*/
public static function findValuesAddedToEnums(
$oldSchema, $newSchema
) {
Schema $oldSchema, Schema $newSchema
)
{
/* const oldTypeMap = oldSchema.getTypeMap();
const newTypeMap = newSchema.getTypeMap();
@ -576,8 +712,9 @@ class FindBreakingChanges {
}
public static function findInterfacesRemovedFromObjectTypes(
$oldSchema, $newSchema
) {
Schema $oldSchema, Schema $newSchema
)
{
/* const oldTypeMap = oldSchema.getTypeMap();
const newTypeMap = newSchema.getTypeMap();
const breakingChanges = [];
@ -606,4 +743,21 @@ class FindBreakingChanges {
});
return breakingChanges;*/
}
/**
* @param Type $type
*
* @return bool
*/
private static function isNamedType(Type $type)
{
return (
$type instanceof ScalarType ||
$type instanceof ObjectType ||
$type instanceof InterfaceType ||
$type instanceof UnionType ||
$type instanceof EnumType ||
$type instanceof InputObjectType
);
}
}