From 49f34d3243819703b42aae7c03cf9998c805cfe8 Mon Sep 17 00:00:00 2001
From: Simon Podlipsky
Date: Wed, 22 Aug 2018 01:20:49 +0200
Subject: [PATCH] Fix CS in Utils
---
.scrutinizer.yml | 2 +-
CHANGELOG.md | 1 +
src/Utils/AST.php | 29 +-
src/Utils/ASTDefinitionBuilder.php | 338 ++--
src/Utils/BlockString.php | 50 +-
...gChanges.php => BreakingChangesFinder.php} | 1476 +++++++++--------
src/Utils/BuildSchema.php | 167 +-
src/Utils/MixedStore.php | 164 +-
src/Utils/PairSet.php | 21 +-
src/Utils/SchemaPrinter.php | 504 +++---
src/Utils/TypeComparators.php | 38 +-
src/Utils/TypeInfo.php | 541 +++---
src/Utils/Utils.php | 283 ++--
src/Utils/Value.php | 194 ++-
...Test.php => BreakingChangesFinderTest.php} | 211 +--
15 files changed, 2216 insertions(+), 1803 deletions(-)
rename src/Utils/{FindBreakingChanges.php => BreakingChangesFinder.php} (54%)
rename tests/Utils/{FindBreakingChangesTest.php => BreakingChangesFinderTest.php} (84%)
diff --git a/.scrutinizer.yml b/.scrutinizer.yml
index 4e4a5c1..a211422 100644
--- a/.scrutinizer.yml
+++ b/.scrutinizer.yml
@@ -3,7 +3,7 @@ build:
analysis:
environment:
php:
- version: 5.6
+ version: 7.1
cache:
disabled: false
directories:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 3a6599e..1941edf 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -3,6 +3,7 @@
- Spec compliance: error extensions are displayed under `extensions` key
- `AbstractValidationRule` renamed to `ValidationRule` (NS `GraphQL\Validator\Rules`)
- `AbstractQuerySecurity` renamed to `QuerySecurityRule` (NS `GraphQL\Validator\Rules`)
+- `FindBreakingChanges` renamed to `BreakingChangesFinder` (NS `GraphQL\Utils`)
#### v0.12.5
- Execution performance optimization for lists
diff --git a/src/Utils/AST.php b/src/Utils/AST.php
index faa60f1..1f3082a 100644
--- a/src/Utils/AST.php
+++ b/src/Utils/AST.php
@@ -81,9 +81,8 @@ class AST
*
* @api
* @param mixed[] $node
- * @return Node
*/
- public static function fromArray(array $node)
+ public static function fromArray(array $node) : Node
{
if (! isset($node['kind']) || ! isset(NodeKind::$classMap[$node['kind']])) {
throw new InvariantViolation('Unexpected node structure: ' . Utils::printSafeJson($node));
@@ -457,6 +456,19 @@ class AST
throw new Error('Unknown type: ' . Utils::printSafe($type) . '.');
}
+ /**
+ * Returns true if the provided valueNode is a variable which is not defined
+ * in the set of variables.
+ * @param ValueNode $valueNode
+ * @param mixed[] $variables
+ * @return bool
+ */
+ private static function isMissingVariable($valueNode, $variables)
+ {
+ return $valueNode instanceof VariableNode &&
+ (count($variables) === 0 || ! array_key_exists($valueNode->name->value, $variables));
+ }
+
/**
* Produces a PHP value given a GraphQL Value AST.
*
@@ -552,19 +564,6 @@ class AST
throw new Error('Unexpected type kind: ' . $inputTypeNode->kind . '.');
}
- /**
- * Returns true if the provided valueNode is a variable which is not defined
- * in the set of variables.
- * @param ValueNode $valueNode
- * @param mixed[] $variables
- * @return bool
- */
- private static function isMissingVariable($valueNode, $variables)
- {
- return $valueNode instanceof VariableNode &&
- (count($variables) === 0 || ! array_key_exists($valueNode->name->value, $variables));
- }
-
/**
* Returns operation type ("query", "mutation" or "subscription") given a document and operation name
*
diff --git a/src/Utils/ASTDefinitionBuilder.php b/src/Utils/ASTDefinitionBuilder.php
index 8ca7d16..5112851 100644
--- a/src/Utils/ASTDefinitionBuilder.php
+++ b/src/Utils/ASTDefinitionBuilder.php
@@ -75,36 +75,112 @@ class ASTDefinitionBuilder
$this->cache = Type::getAllBuiltInTypes();
}
- /**
- * @param TypeNode|ListTypeNode|NonNullTypeNode $inputTypeNode
- * @return Type
- */
- private function buildWrappedType(Type $innerType, TypeNode $inputTypeNode)
+ public function buildDirective(DirectiveDefinitionNode $directiveNode)
{
- if ($inputTypeNode->kind === NodeKind::LIST_TYPE) {
- return Type::listOf($this->buildWrappedType($innerType, $inputTypeNode->type));
- }
- if ($inputTypeNode->kind === NodeKind::NON_NULL_TYPE) {
- $wrappedType = $this->buildWrappedType($innerType, $inputTypeNode->type);
-
- return Type::nonNull(NonNull::assertNullableType($wrappedType));
- }
-
- return $innerType;
+ return new Directive([
+ 'name' => $directiveNode->name->value,
+ 'description' => $this->getDescription($directiveNode),
+ 'locations' => Utils::map(
+ $directiveNode->locations,
+ function ($node) {
+ return $node->value;
+ }
+ ),
+ 'args' => $directiveNode->arguments ? FieldArgument::createMap($this->makeInputValues($directiveNode->arguments)) : null,
+ 'astNode' => $directiveNode,
+ ]);
}
/**
- * @param TypeNode|ListTypeNode|NonNullTypeNode $typeNode
- * @return TypeNode
+ * Given an ast node, returns its string description.
*/
- private function getNamedTypeNode(TypeNode $typeNode)
+ private function getDescription($node)
{
- $namedType = $typeNode;
- while ($namedType->kind === NodeKind::LIST_TYPE || $namedType->kind === NodeKind::NON_NULL_TYPE) {
- $namedType = $namedType->type;
+ if ($node->description) {
+ return $node->description->value;
+ }
+ if (isset($this->options['commentDescriptions'])) {
+ $rawValue = $this->getLeadingCommentBlock($node);
+ if ($rawValue !== null) {
+ return BlockString::value("\n" . $rawValue);
+ }
}
- return $namedType;
+ return null;
+ }
+
+ private function getLeadingCommentBlock($node)
+ {
+ $loc = $node->loc;
+ if (! $loc || ! $loc->startToken) {
+ return null;
+ }
+ $comments = [];
+ $token = $loc->startToken->prev;
+ while ($token &&
+ $token->kind === Token::COMMENT &&
+ $token->next && $token->prev &&
+ $token->line + 1 === $token->next->line &&
+ $token->line !== $token->prev->line
+ ) {
+ $value = $token->value;
+ $comments[] = $value;
+ $token = $token->prev;
+ }
+
+ return implode("\n", array_reverse($comments));
+ }
+
+ private function makeInputValues($values)
+ {
+ return Utils::keyValMap(
+ $values,
+ function ($value) {
+ return $value->name->value;
+ },
+ function ($value) {
+ // Note: While this could make assertions to get the correctly typed
+ // value, that would throw immediately while type system validation
+ // with validateSchema() will produce more actionable results.
+ $type = $this->internalBuildWrappedType($value->type);
+ $config = [
+ 'name' => $value->name->value,
+ 'type' => $type,
+ 'description' => $this->getDescription($value),
+ 'astNode' => $value,
+ ];
+ if (isset($value->defaultValue)) {
+ $config['defaultValue'] = AST::valueFromAST($value->defaultValue, $type);
+ }
+
+ return $config;
+ }
+ );
+ }
+
+ /**
+ * @return Type|InputType
+ * @throws Error
+ */
+ private function internalBuildWrappedType(TypeNode $typeNode)
+ {
+ $typeDef = $this->buildType($this->getNamedTypeNode($typeNode));
+
+ return $this->buildWrappedType($typeDef, $typeNode);
+ }
+
+ /**
+ * @param string|NamedTypeNode $ref
+ * @return Type
+ * @throws Error
+ */
+ public function buildType($ref)
+ {
+ if (is_string($ref)) {
+ return $this->internalBuildType($ref);
+ }
+
+ return $this->internalBuildType($ref->name->value, $ref);
}
/**
@@ -154,61 +230,6 @@ class ASTDefinitionBuilder
return $this->cache[$typeName];
}
- /**
- * @param string|NamedTypeNode $ref
- * @return Type
- * @throws Error
- */
- public function buildType($ref)
- {
- if (is_string($ref)) {
- return $this->internalBuildType($ref);
- }
-
- return $this->internalBuildType($ref->name->value, $ref);
- }
-
- /**
- * @return Type|InputType
- * @throws Error
- */
- private function internalBuildWrappedType(TypeNode $typeNode)
- {
- $typeDef = $this->buildType($this->getNamedTypeNode($typeNode));
-
- return $this->buildWrappedType($typeDef, $typeNode);
- }
-
- public function buildDirective(DirectiveDefinitionNode $directiveNode)
- {
- return new Directive([
- 'name' => $directiveNode->name->value,
- 'description' => $this->getDescription($directiveNode),
- 'locations' => Utils::map(
- $directiveNode->locations,
- function ($node) {
- return $node->value;
- }
- ),
- 'args' => $directiveNode->arguments ? FieldArgument::createMap($this->makeInputValues($directiveNode->arguments)) : null,
- 'astNode' => $directiveNode,
- ]);
- }
-
- public function buildField(FieldDefinitionNode $field)
- {
- return [
- // Note: While this could make assertions to get the correctly typed
- // value, that would throw immediately while type system validation
- // with validateSchema() will produce more actionable results.
- 'type' => $this->internalBuildWrappedType($field->type),
- 'description' => $this->getDescription($field),
- 'args' => $field->arguments ? $this->makeInputValues($field->arguments) : null,
- 'deprecationReason' => $this->getDeprecationReason($field),
- 'astNode' => $field,
- ];
- }
-
/**
* @param ObjectTypeDefinitionNode|InterfaceTypeDefinitionNode|EnumTypeDefinitionNode|ScalarTypeDefinitionNode|InputObjectTypeDefinitionNode|UnionTypeDefinitionNode $def
* @return CustomScalarType|EnumType|InputObjectType|InterfaceType|ObjectType|UnionType
@@ -237,35 +258,6 @@ class ASTDefinitionBuilder
}
}
- /**
- * @param ObjectTypeDefinitionNode|InterfaceTypeDefinitionNode|EnumTypeExtensionNode|ScalarTypeDefinitionNode|InputObjectTypeDefinitionNode $def
- * @param mixed[] $config
- * @return CustomScalarType|EnumType|InputObjectType|InterfaceType|ObjectType|UnionType
- * @throws Error
- */
- private function makeSchemaDefFromConfig($def, array $config)
- {
- if (! $def) {
- throw new Error('def must be defined.');
- }
- switch ($def->kind) {
- case NodeKind::OBJECT_TYPE_DEFINITION:
- return new ObjectType($config);
- case NodeKind::INTERFACE_TYPE_DEFINITION:
- return new InterfaceType($config);
- case NodeKind::ENUM_TYPE_DEFINITION:
- return new EnumType($config);
- case NodeKind::UNION_TYPE_DEFINITION:
- return new UnionType($config);
- case NodeKind::SCALAR_TYPE_DEFINITION:
- return new CustomScalarType($config);
- case NodeKind::INPUT_OBJECT_TYPE_DEFINITION:
- return new InputObjectType($config);
- default:
- throw new Error(sprintf('Type kind of %s not supported.', $def->kind));
- }
- }
-
private function makeTypeDef(ObjectTypeDefinitionNode $def)
{
$typeName = $def->name->value;
@@ -298,6 +290,34 @@ class ASTDefinitionBuilder
: [];
}
+ public function buildField(FieldDefinitionNode $field)
+ {
+ return [
+ // Note: While this could make assertions to get the correctly typed
+ // value, that would throw immediately while type system validation
+ // with validateSchema() will produce more actionable results.
+ 'type' => $this->internalBuildWrappedType($field->type),
+ 'description' => $this->getDescription($field),
+ 'args' => $field->arguments ? $this->makeInputValues($field->arguments) : null,
+ 'deprecationReason' => $this->getDeprecationReason($field),
+ 'astNode' => $field,
+ ];
+ }
+
+ /**
+ * Given a collection of directives, returns the string value for the
+ * deprecation reason.
+ *
+ * @param EnumValueDefinitionNode | FieldDefinitionNode $node
+ * @return string
+ */
+ private function getDeprecationReason($node)
+ {
+ $deprecated = Values::getDirectiveValues(Directive::deprecatedDirective(), $node);
+
+ return $deprecated['reason'] ?? null;
+ }
+
private function makeImplementedInterfaces(ObjectTypeDefinitionNode $def)
{
if ($def->interfaces) {
@@ -315,33 +335,6 @@ class ASTDefinitionBuilder
return null;
}
- private function makeInputValues($values)
- {
- return Utils::keyValMap(
- $values,
- function ($value) {
- return $value->name->value;
- },
- function ($value) {
- // Note: While this could make assertions to get the correctly typed
- // value, that would throw immediately while type system validation
- // with validateSchema() will produce more actionable results.
- $type = $this->internalBuildWrappedType($value->type);
- $config = [
- 'name' => $value->name->value,
- 'type' => $type,
- 'description' => $this->getDescription($value),
- 'astNode' => $value,
- ];
- if (isset($value->defaultValue)) {
- $config['defaultValue'] = AST::valueFromAST($value->defaultValue, $type);
- }
-
- return $config;
- }
- );
- }
-
private function makeInterfaceDef(InterfaceTypeDefinitionNode $def)
{
$typeName = $def->name->value;
@@ -427,56 +420,63 @@ class ASTDefinitionBuilder
}
/**
- * Given a collection of directives, returns the string value for the
- * deprecation reason.
- *
- * @param EnumValueDefinitionNode | FieldDefinitionNode $node
- * @return string
+ * @param ObjectTypeDefinitionNode|InterfaceTypeDefinitionNode|EnumTypeExtensionNode|ScalarTypeDefinitionNode|InputObjectTypeDefinitionNode $def
+ * @param mixed[] $config
+ * @return CustomScalarType|EnumType|InputObjectType|InterfaceType|ObjectType|UnionType
+ * @throws Error
*/
- private function getDeprecationReason($node)
+ private function makeSchemaDefFromConfig($def, array $config)
{
- $deprecated = Values::getDirectiveValues(Directive::deprecatedDirective(), $node);
-
- return $deprecated['reason'] ?? null;
+ if (! $def) {
+ throw new Error('def must be defined.');
+ }
+ switch ($def->kind) {
+ case NodeKind::OBJECT_TYPE_DEFINITION:
+ return new ObjectType($config);
+ case NodeKind::INTERFACE_TYPE_DEFINITION:
+ return new InterfaceType($config);
+ case NodeKind::ENUM_TYPE_DEFINITION:
+ return new EnumType($config);
+ case NodeKind::UNION_TYPE_DEFINITION:
+ return new UnionType($config);
+ case NodeKind::SCALAR_TYPE_DEFINITION:
+ return new CustomScalarType($config);
+ case NodeKind::INPUT_OBJECT_TYPE_DEFINITION:
+ return new InputObjectType($config);
+ default:
+ throw new Error(sprintf('Type kind of %s not supported.', $def->kind));
+ }
}
/**
- * Given an ast node, returns its string description.
+ * @param TypeNode|ListTypeNode|NonNullTypeNode $typeNode
+ * @return TypeNode
*/
- private function getDescription($node)
+ private function getNamedTypeNode(TypeNode $typeNode)
{
- if ($node->description) {
- return $node->description->value;
- }
- if (isset($this->options['commentDescriptions'])) {
- $rawValue = $this->getLeadingCommentBlock($node);
- if ($rawValue !== null) {
- return BlockString::value("\n" . $rawValue);
- }
+ $namedType = $typeNode;
+ while ($namedType->kind === NodeKind::LIST_TYPE || $namedType->kind === NodeKind::NON_NULL_TYPE) {
+ $namedType = $namedType->type;
}
- return null;
+ return $namedType;
}
- private function getLeadingCommentBlock($node)
+ /**
+ * @param TypeNode|ListTypeNode|NonNullTypeNode $inputTypeNode
+ * @return Type
+ */
+ private function buildWrappedType(Type $innerType, TypeNode $inputTypeNode)
{
- $loc = $node->loc;
- if (! $loc || ! $loc->startToken) {
- return null;
+ if ($inputTypeNode->kind === NodeKind::LIST_TYPE) {
+ return Type::listOf($this->buildWrappedType($innerType, $inputTypeNode->type));
}
- $comments = [];
- $token = $loc->startToken->prev;
- while ($token &&
- $token->kind === Token::COMMENT &&
- $token->next && $token->prev &&
- $token->line + 1 === $token->next->line &&
- $token->line !== $token->prev->line
- ) {
- $value = $token->value;
- $comments[] = $value;
- $token = $token->prev;
+ if ($inputTypeNode->kind === NodeKind::NON_NULL_TYPE) {
+ $wrappedType = $this->buildWrappedType($innerType, $inputTypeNode->type);
+
+ return Type::nonNull(NonNull::assertNullableType($wrappedType));
}
- return implode("\n", array_reverse($comments));
+ return $innerType;
}
}
diff --git a/src/Utils/BlockString.php b/src/Utils/BlockString.php
index 5bc40e4..a81760c 100644
--- a/src/Utils/BlockString.php
+++ b/src/Utils/BlockString.php
@@ -1,43 +1,58 @@
= mb_strlen($line) ||
+ ($commonIndent !== null && $indent >= $commonIndent)
) {
- $commonIndent = $indent;
- if ($commonIndent === 0) {
- break;
- }
+ continue;
+ }
+
+ $commonIndent = $indent;
+ if ($commonIndent === 0) {
+ break;
}
}
-
+
if ($commonIndent) {
for ($i = 1; $i < $linesLength; $i++) {
- $line = $lines[$i];
+ $line = $lines[$i];
$lines[$i] = mb_substr($line, $commonIndent);
}
}
-
+
// Remove leading and trailing blank lines.
while (count($lines) > 0 && trim($lines[0], " \t") === '') {
array_shift($lines);
@@ -50,7 +65,8 @@ class BlockString {
return implode("\n", $lines);
}
- private static function leadingWhitespace($str) {
+ private static function leadingWhitespace($str)
+ {
$i = 0;
while ($i < mb_strlen($str) && ($str[$i] === ' ' || $str[$i] === '\t')) {
$i++;
diff --git a/src/Utils/FindBreakingChanges.php b/src/Utils/BreakingChangesFinder.php
similarity index 54%
rename from src/Utils/FindBreakingChanges.php
rename to src/Utils/BreakingChangesFinder.php
index ecad9f8..5e17e23 100644
--- a/src/Utils/FindBreakingChanges.php
+++ b/src/Utils/BreakingChangesFinder.php
@@ -1,4 +1,7 @@
getTypeMap();
+ $newTypeMap = $newSchema->getTypeMap();
+
+ $breakingChanges = [];
+ foreach (array_keys($oldTypeMap) as $typeName) {
+ if (isset($newTypeMap[$typeName])) {
+ continue;
+ }
+
+ $breakingChanges[] = [
+ 'type' => self::BREAKING_CHANGE_TYPE_REMOVED,
+ 'description' => "${typeName} was removed.",
+ ];
+ }
+
+ return $breakingChanges;
+ }
+
+ /**
+ * Given two schemas, returns an Array containing descriptions of any breaking
+ * changes in the newSchema related to changing the type of a type.
+ *
+ * @return string[][]
+ */
+ public static function findTypesThatChangedKind(
+ Schema $oldSchema,
+ Schema $newSchema
+ ) {
+ $oldTypeMap = $oldSchema->getTypeMap();
+ $newTypeMap = $newSchema->getTypeMap();
+
+ $breakingChanges = [];
+ foreach ($oldTypeMap as $typeName => $oldType) {
+ if (! isset($newTypeMap[$typeName])) {
+ continue;
+ }
+ $newType = $newTypeMap[$typeName];
+ if ($oldType instanceof $newType) {
+ continue;
+ }
+
+ $oldTypeKindName = self::typeKindName($oldType);
+ $newTypeKindName = self::typeKindName($newType);
+ $breakingChanges[] = [
+ 'type' => self::BREAKING_CHANGE_TYPE_CHANGED_KIND,
+ 'description' => "${typeName} changed from ${oldTypeKindName} to ${newTypeKindName}.",
+ ];
+ }
+
+ return $breakingChanges;
+ }
+
+ /**
+ * @return string
+ *
+ * @throws \TypeError
+ */
+ private static function typeKindName(Type $type)
+ {
+ if ($type instanceof ScalarType) {
+ return 'a Scalar type';
+ }
+
+ if ($type instanceof ObjectType) {
+ return 'an Object type';
+ }
+
+ if ($type instanceof InterfaceType) {
+ return 'an Interface type';
+ }
+
+ if ($type instanceof UnionType) {
+ return 'a Union type';
+ }
+
+ if ($type instanceof EnumType) {
+ return 'an Enum type';
+ }
+
+ if ($type instanceof InputObjectType) {
+ return 'an Input type';
+ }
+
+ throw new \TypeError('unknown type ' . $type->name);
+ }
+
+ /**
+ * @return string[][]
+ */
+ public static function findFieldsThatChangedTypeOnObjectOrInterfaceTypes(
+ Schema $oldSchema,
+ Schema $newSchema
+ ) {
+ $oldTypeMap = $oldSchema->getTypeMap();
+ $newTypeMap = $newSchema->getTypeMap();
+
+ $breakingChanges = [];
+ foreach ($oldTypeMap as $typeName => $oldType) {
+ $newType = $newTypeMap[$typeName] ?? null;
+ if (! ($oldType instanceof ObjectType || $oldType instanceof InterfaceType) ||
+ ! ($newType instanceof ObjectType || $newType instanceof InterfaceType) ||
+ ! ($newType instanceof $oldType)
+ ) {
+ continue;
+ }
+
+ $oldTypeFieldsDef = $oldType->getFields();
+ $newTypeFieldsDef = $newType->getFields();
+ foreach ($oldTypeFieldsDef as $fieldName => $fieldDefinition) {
+ // Check if the field is missing on the type in the new schema.
+ if (! isset($newTypeFieldsDef[$fieldName])) {
+ $breakingChanges[] = [
+ 'type' => self::BREAKING_CHANGE_FIELD_REMOVED,
+ 'description' => "${typeName}.${fieldName} was removed.",
+ ];
+ } else {
+ $oldFieldType = $oldTypeFieldsDef[$fieldName]->getType();
+ $newFieldType = $newTypeFieldsDef[$fieldName]->getType();
+ $isSafe = self::isChangeSafeForObjectOrInterfaceField(
+ $oldFieldType,
+ $newFieldType
+ );
+ if (! $isSafe) {
+ $oldFieldTypeString = $oldFieldType instanceof NamedType
+ ? $oldFieldType->name
+ : $oldFieldType;
+ $newFieldTypeString = $newFieldType instanceof NamedType
+ ? $newFieldType->name
+ : $newFieldType;
+ $breakingChanges[] = [
+ 'type' => self::BREAKING_CHANGE_FIELD_CHANGED_KIND,
+ 'description' => "${typeName}.${fieldName} changed type from ${oldFieldTypeString} to ${newFieldTypeString}.",
+ ];
+ }
+ }
+ }
+ }
+
+ return $breakingChanges;
+ }
+
+ /**
+ * @return bool
+ */
+ private static function isChangeSafeForObjectOrInterfaceField(
+ Type $oldType,
+ Type $newType
+ ) {
+ if ($oldType instanceof NamedType) {
+ return // if they're both named types, see if their names are equivalent
+ ($newType instanceof NamedType && $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())
+ );
+ }
+
+ if ($oldType instanceof ListOfType) {
+ return // if they're both lists, make sure the underlying types are compatible
+ ($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()));
+ }
+
+ if ($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;
+ }
+
+ /**
+ * @return string[][]
+ */
+ public static function findFieldsThatChangedTypeOnInputObjectTypes(
+ Schema $oldSchema,
+ Schema $newSchema
+ ) {
+ $oldTypeMap = $oldSchema->getTypeMap();
+ $newTypeMap = $newSchema->getTypeMap();
+
+ $breakingChanges = [];
+ $dangerousChanges = [];
+ foreach ($oldTypeMap as $typeName => $oldType) {
+ $newType = $newTypeMap[$typeName] ?? null;
+ if (! ($oldType instanceof InputObjectType) || ! ($newType instanceof InputObjectType)) {
+ continue;
+ }
+
+ $oldTypeFieldsDef = $oldType->getFields();
+ $newTypeFieldsDef = $newType->getFields();
+ foreach (array_keys($oldTypeFieldsDef) as $fieldName) {
+ if (! isset($newTypeFieldsDef[$fieldName])) {
+ $breakingChanges[] = [
+ 'type' => self::BREAKING_CHANGE_FIELD_REMOVED,
+ 'description' => "${typeName}.${fieldName} was removed.",
+ ];
+ } else {
+ $oldFieldType = $oldTypeFieldsDef[$fieldName]->getType();
+ $newFieldType = $newTypeFieldsDef[$fieldName]->getType();
+
+ $isSafe = self::isChangeSafeForInputObjectFieldOrFieldArg(
+ $oldFieldType,
+ $newFieldType
+ );
+ if (! $isSafe) {
+ $oldFieldTypeString = $oldFieldType instanceof NamedType
+ ? $oldFieldType->name
+ : $oldFieldType;
+ $newFieldTypeString = $newFieldType instanceof NamedType
+ ? $newFieldType->name
+ : $newFieldType;
+ $breakingChanges[] = [
+ 'type' => self::BREAKING_CHANGE_FIELD_CHANGED_KIND,
+ 'description' => "${typeName}.${fieldName} changed type from ${oldFieldTypeString} to ${newFieldTypeString}.",
+ ];
+ }
+ }
+ }
+ // Check if a field was added to the input object type
+ foreach ($newTypeFieldsDef as $fieldName => $fieldDef) {
+ if (isset($oldTypeFieldsDef[$fieldName])) {
+ continue;
+ }
+
+ $newTypeName = $newType->name;
+ if ($fieldDef->getType() instanceof NonNull) {
+ $breakingChanges[] = [
+ 'type' => self::BREAKING_CHANGE_NON_NULL_INPUT_FIELD_ADDED,
+ 'description' => "A non-null field ${fieldName} on input type ${newTypeName} was added.",
+ ];
+ } else {
+ $dangerousChanges[] = [
+ 'type' => self::DANGEROUS_CHANGE_NULLABLE_INPUT_FIELD_ADDED,
+ 'description' => "A nullable field ${fieldName} on input type ${newTypeName} was added.",
+ ];
+ }
+ }
+ }
+
+ return [
+ 'breakingChanges' => $breakingChanges,
+ 'dangerousChanges' => $dangerousChanges,
+ ];
+ }
+
+ /**
+ *
+ * @return bool
+ */
+ private static function isChangeSafeForInputObjectFieldOrFieldArg(
+ Type $oldType,
+ Type $newType
+ ) {
+ if ($oldType instanceof NamedType) {
+ // if they're both named types, see if their names are equivalent
+ return $newType instanceof NamedType && $oldType->name === $newType->name;
+ }
+
+ if ($oldType instanceof ListOfType) {
+ // if they're both lists, make sure the underlying types are compatible
+ return $newType instanceof ListOfType &&
+ self::isChangeSafeForInputObjectFieldOrFieldArg(
+ $oldType->getWrappedType(),
+ $newType->getWrappedType()
+ );
+ }
+
+ if ($oldType instanceof NonNull) {
+ return // if they're both non-null, make sure the underlying types are
+ // compatible
+ ($newType instanceof NonNull &&
+ self::isChangeSafeForInputObjectFieldOrFieldArg(
+ $oldType->getWrappedType(),
+ $newType->getWrappedType()
+ )) ||
+ // moving from non-null to nullable of the same underlying type is safe
+ (! ($newType instanceof NonNull) &&
+ self::isChangeSafeForInputObjectFieldOrFieldArg($oldType->getWrappedType(), $newType));
+ }
+
+ return false;
+ }
+
+ /**
+ * Given two schemas, returns an Array containing descriptions of any breaking
+ * changes in the newSchema related to removing types from a union type.
+ *
+ * @return string[][]
+ */
+ public static function findTypesRemovedFromUnions(
+ Schema $oldSchema,
+ Schema $newSchema
+ ) {
+ $oldTypeMap = $oldSchema->getTypeMap();
+ $newTypeMap = $newSchema->getTypeMap();
+
+ $typesRemovedFromUnion = [];
+ foreach ($oldTypeMap as $typeName => $oldType) {
+ $newType = $newTypeMap[$typeName] ?? null;
+ if (! ($oldType instanceof UnionType) || ! ($newType instanceof UnionType)) {
+ continue;
+ }
+ $typeNamesInNewUnion = [];
+ foreach ($newType->getTypes() as $type) {
+ $typeNamesInNewUnion[$type->name] = true;
+ }
+ foreach ($oldType->getTypes() as $type) {
+ if (isset($typeNamesInNewUnion[$type->name])) {
+ continue;
+ }
+
+ $typesRemovedFromUnion[] = [
+ 'type' => self::BREAKING_CHANGE_TYPE_REMOVED_FROM_UNION,
+ 'description' => sprintf('%s was removed from union type %s.', $type->name, $typeName),
+ ];
+ }
+ }
+
+ return $typesRemovedFromUnion;
+ }
+
+ /**
+ * Given two schemas, returns an Array containing descriptions of any breaking
+ * changes in the newSchema related to removing values from an enum type.
+ *
+ * @return string[][]
+ */
+ public static function findValuesRemovedFromEnums(
+ Schema $oldSchema,
+ Schema $newSchema
+ ) {
+ $oldTypeMap = $oldSchema->getTypeMap();
+ $newTypeMap = $newSchema->getTypeMap();
+
+ $valuesRemovedFromEnums = [];
+ foreach ($oldTypeMap as $typeName => $oldType) {
+ $newType = $newTypeMap[$typeName] ?? null;
+ if (! ($oldType instanceof EnumType) || ! ($newType instanceof EnumType)) {
+ continue;
+ }
+ $valuesInNewEnum = [];
+ foreach ($newType->getValues() as $value) {
+ $valuesInNewEnum[$value->name] = true;
+ }
+ foreach ($oldType->getValues() as $value) {
+ if (isset($valuesInNewEnum[$value->name])) {
+ continue;
+ }
+
+ $valuesRemovedFromEnums[] = [
+ 'type' => self::BREAKING_CHANGE_VALUE_REMOVED_FROM_ENUM,
+ 'description' => sprintf('%s was removed from enum type %s.', $value->name, $typeName),
+ ];
+ }
+ }
+
+ return $valuesRemovedFromEnums;
+ }
+
+ /**
+ * Given two schemas, returns an Array containing descriptions of any
+ * breaking or dangerous changes in the newSchema related to arguments
+ * (such as removal or change of type of an argument, or a change in an
+ * argument's default value).
+ *
+ * @return string[][]
+ */
+ public static function findArgChanges(
+ Schema $oldSchema,
+ Schema $newSchema
+ ) {
+ $oldTypeMap = $oldSchema->getTypeMap();
+ $newTypeMap = $newSchema->getTypeMap();
+
+ $breakingChanges = [];
+ $dangerousChanges = [];
+
+ foreach ($oldTypeMap as $typeName => $oldType) {
+ $newType = $newTypeMap[$typeName] ?? null;
+ if (! ($oldType instanceof ObjectType || $oldType instanceof InterfaceType) ||
+ ! ($newType instanceof ObjectType || $newType instanceof InterfaceType) ||
+ ! ($newType instanceof $oldType)
+ ) {
+ continue;
+ }
+
+ $oldTypeFields = $oldType->getFields();
+ $newTypeFields = $newType->getFields();
+
+ foreach ($oldTypeFields as $fieldName => $oldField) {
+ if (! isset($newTypeFields[$fieldName])) {
+ continue;
+ }
+
+ foreach ($oldField->args as $oldArgDef) {
+ $newArgs = $newTypeFields[$fieldName]->args;
+ $newArgDef = Utils::find(
+ $newArgs,
+ function ($arg) use ($oldArgDef) {
+ return $arg->name === $oldArgDef->name;
+ }
+ );
+ if ($newArgDef) {
+ $isSafe = self::isChangeSafeForInputObjectFieldOrFieldArg(
+ $oldArgDef->getType(),
+ $newArgDef->getType()
+ );
+ $oldArgType = $oldArgDef->getType();
+ $oldArgName = $oldArgDef->name;
+ if (! $isSafe) {
+ $newArgType = $newArgDef->getType();
+ $breakingChanges[] = [
+ 'type' => self::BREAKING_CHANGE_ARG_CHANGED_KIND,
+ 'description' => "${typeName}.${fieldName} arg ${oldArgName} has changed type from ${oldArgType} to ${newArgType}",
+ ];
+ } elseif ($oldArgDef->defaultValueExists() && $oldArgDef->defaultValue !== $newArgDef->defaultValue) {
+ $dangerousChanges[] = [
+ 'type' => self::DANGEROUS_CHANGE_ARG_DEFAULT_VALUE_CHANGED,
+ 'description' => "${typeName}.${fieldName} arg ${oldArgName} has changed defaultValue",
+ ];
+ }
+ } else {
+ $breakingChanges[] = [
+ 'type' => self::BREAKING_CHANGE_ARG_REMOVED,
+ 'description' => sprintf(
+ '%s.%s arg %s was removed',
+ $typeName,
+ $fieldName,
+ $oldArgDef->name
+ ),
+ ];
+ }
+ // Check if a non-null arg was added to the field
+ foreach ($newTypeFields[$fieldName]->args as $newArgDef) {
+ $oldArgs = $oldTypeFields[$fieldName]->args;
+ $oldArgDef = Utils::find(
+ $oldArgs,
+ function ($arg) use ($newArgDef) {
+ return $arg->name === $newArgDef->name;
+ }
+ );
+
+ if ($oldArgDef) {
+ continue;
+ }
+
+ $newTypeName = $newType->name;
+ $newArgName = $newArgDef->name;
+ if ($newArgDef->getType() instanceof NonNull) {
+ $breakingChanges[] = [
+ 'type' => self::BREAKING_CHANGE_NON_NULL_ARG_ADDED,
+ 'description' => "A non-null arg ${newArgName} on ${newTypeName}.${fieldName} was added",
+ ];
+ } else {
+ $dangerousChanges[] = [
+ 'type' => self::DANGEROUS_CHANGE_NULLABLE_ARG_ADDED,
+ 'description' => "A nullable arg ${newArgName} on ${newTypeName}.${fieldName} was added",
+ ];
+ }
+ }
+ }
+ }
+ }
+
+ return [
+ 'breakingChanges' => $breakingChanges,
+ 'dangerousChanges' => $dangerousChanges,
+ ];
+ }
+
+ /**
+ * @return string[][]
+ */
+ public static function findInterfacesRemovedFromObjectTypes(
+ Schema $oldSchema,
+ Schema $newSchema
+ ) {
+ $oldTypeMap = $oldSchema->getTypeMap();
+ $newTypeMap = $newSchema->getTypeMap();
+ $breakingChanges = [];
+
+ foreach ($oldTypeMap as $typeName => $oldType) {
+ $newType = $newTypeMap[$typeName] ?? null;
+ if (! ($oldType instanceof ObjectType) || ! ($newType instanceof ObjectType)) {
+ continue;
+ }
+
+ $oldInterfaces = $oldType->getInterfaces();
+ $newInterfaces = $newType->getInterfaces();
+ foreach ($oldInterfaces as $oldInterface) {
+ if (Utils::find(
+ $newInterfaces,
+ function (InterfaceType $interface) use ($oldInterface) {
+ return $interface->name === $oldInterface->name;
+ }
+ )) {
+ continue;
+ }
+
+ $breakingChanges[] = [
+ 'type' => self::BREAKING_CHANGE_INTERFACE_REMOVED_FROM_OBJECT,
+ 'description' => sprintf('%s no longer implements interface %s.', $typeName, $oldInterface->name),
+ ];
+ }
+ }
+
+ return $breakingChanges;
+ }
+
+ /**
+ * @return string[][]
+ */
+ public static function findRemovedDirectives(Schema $oldSchema, Schema $newSchema)
+ {
+ $removedDirectives = [];
+
+ $newSchemaDirectiveMap = self::getDirectiveMapForSchema($newSchema);
+ foreach ($oldSchema->getDirectives() as $directive) {
+ if (isset($newSchemaDirectiveMap[$directive->name])) {
+ continue;
+ }
+
+ $removedDirectives[] = [
+ 'type' => self::BREAKING_CHANGE_DIRECTIVE_REMOVED,
+ 'description' => sprintf('%s was removed', $directive->name),
+ ];
+ }
+
+ return $removedDirectives;
+ }
+
+ private static function getDirectiveMapForSchema(Schema $schema)
+ {
+ return Utils::keyMap(
+ $schema->getDirectives(),
+ function ($dir) {
+ return $dir->name;
+ }
+ );
+ }
+
+ public static function findRemovedDirectiveArgs(Schema $oldSchema, Schema $newSchema)
+ {
+ $removedDirectiveArgs = [];
+ $oldSchemaDirectiveMap = self::getDirectiveMapForSchema($oldSchema);
+
+ foreach ($newSchema->getDirectives() as $newDirective) {
+ if (! isset($oldSchemaDirectiveMap[$newDirective->name])) {
+ continue;
+ }
+
+ foreach (self::findRemovedArgsForDirectives(
+ $oldSchemaDirectiveMap[$newDirective->name],
+ $newDirective
+ ) as $arg) {
+ $removedDirectiveArgs[] = [
+ 'type' => self::BREAKING_CHANGE_DIRECTIVE_ARG_REMOVED,
+ 'description' => sprintf('%s was removed from %s', $arg->name, $newDirective->name),
+ ];
+ }
+ }
+
+ return $removedDirectiveArgs;
+ }
+
+ public static function findRemovedArgsForDirectives(Directive $oldDirective, Directive $newDirective)
+ {
+ $removedArgs = [];
+ $newArgMap = self::getArgumentMapForDirective($newDirective);
+ foreach ((array) $oldDirective->args as $arg) {
+ if (isset($newArgMap[$arg->name])) {
+ continue;
+ }
+
+ $removedArgs[] = $arg;
+ }
+
+ return $removedArgs;
+ }
+
+ private static function getArgumentMapForDirective(Directive $directive)
+ {
+ return Utils::keyMap(
+ $directive->args ?: [],
+ function ($arg) {
+ return $arg->name;
+ }
+ );
+ }
+
+ public static function findAddedNonNullDirectiveArgs(Schema $oldSchema, Schema $newSchema)
+ {
+ $addedNonNullableArgs = [];
+ $oldSchemaDirectiveMap = self::getDirectiveMapForSchema($oldSchema);
+
+ foreach ($newSchema->getDirectives() as $newDirective) {
+ if (! isset($oldSchemaDirectiveMap[$newDirective->name])) {
+ continue;
+ }
+
+ foreach (self::findAddedArgsForDirective(
+ $oldSchemaDirectiveMap[$newDirective->name],
+ $newDirective
+ ) as $arg) {
+ if (! $arg->getType() instanceof NonNull) {
+ continue;
+ }
+ $addedNonNullableArgs[] = [
+ 'type' => self::BREAKING_CHANGE_NON_NULL_DIRECTIVE_ARG_ADDED,
+ 'description' => sprintf(
+ 'A non-null arg %s on directive %s was added',
+ $arg->name,
+ $newDirective->name
+ ),
+ ];
+ }
+ }
+
+ return $addedNonNullableArgs;
+ }
+
+ /**
+ * @return FieldArgument[]
+ */
+ public static function findAddedArgsForDirective(Directive $oldDirective, Directive $newDirective)
+ {
+ $addedArgs = [];
+ $oldArgMap = self::getArgumentMapForDirective($oldDirective);
+ foreach ((array) $newDirective->args as $arg) {
+ if (isset($oldArgMap[$arg->name])) {
+ continue;
+ }
+
+ $addedArgs[] = $arg;
+ }
+
+ return $addedArgs;
+ }
+
+ /**
+ * @return string[][]
+ */
+ public static function findRemovedDirectiveLocations(Schema $oldSchema, Schema $newSchema)
+ {
+ $removedLocations = [];
+ $oldSchemaDirectiveMap = self::getDirectiveMapForSchema($oldSchema);
+
+ foreach ($newSchema->getDirectives() as $newDirective) {
+ if (! isset($oldSchemaDirectiveMap[$newDirective->name])) {
+ continue;
+ }
+
+ foreach (self::findRemovedLocationsForDirective(
+ $oldSchemaDirectiveMap[$newDirective->name],
+ $newDirective
+ ) as $location) {
+ $removedLocations[] = [
+ 'type' => self::BREAKING_CHANGE_DIRECTIVE_LOCATION_REMOVED,
+ 'description' => sprintf('%s was removed from %s', $location, $newDirective->name),
+ ];
+ }
+ }
+
+ return $removedLocations;
+ }
+
+ public static function findRemovedLocationsForDirective(Directive $oldDirective, Directive $newDirective)
+ {
+ $removedLocations = [];
+ $newLocationSet = array_flip($newDirective->locations);
+ foreach ($oldDirective->locations as $oldLocation) {
+ if (array_key_exists($oldLocation, $newLocationSet)) {
+ continue;
+ }
+
+ $removedLocations[] = $oldLocation;
+ }
+
+ return $removedLocations;
+ }
+
/**
* 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
+ * @return string[][]
*/
public static function findDangerousChanges(Schema $oldSchema, Schema $newSchema)
{
@@ -85,490 +792,11 @@ class FindBreakingChanges
);
}
- /**
- * Given two schemas, returns an Array containing descriptions of any breaking
- * changes in the newSchema related to removing an entire type.
- *
- * @return array
- */
- public static function findRemovedTypes(
- Schema $oldSchema,
- Schema $newSchema
- ) {
- $oldTypeMap = $oldSchema->getTypeMap();
- $newTypeMap = $newSchema->getTypeMap();
-
- $breakingChanges = [];
- foreach (array_keys($oldTypeMap) as $typeName) {
- if (!isset($newTypeMap[$typeName])) {
- $breakingChanges[] = [
- 'type' => self::BREAKING_CHANGE_TYPE_REMOVED,
- 'description' => "${typeName} was removed."
- ];
- }
- }
- return $breakingChanges;
- }
-
- /**
- * Given two schemas, returns an Array containing descriptions of any breaking
- * changes in the newSchema related to changing the type of a type.
- *
- * @return array
- */
- public static function findTypesThatChangedKind(
- Schema $oldSchema,
- Schema $newSchema
- ) {
- $oldTypeMap = $oldSchema->getTypeMap();
- $newTypeMap = $newSchema->getTypeMap();
-
- $breakingChanges = [];
- foreach ($oldTypeMap as $typeName => $oldType) {
- if (!isset($newTypeMap[$typeName])) {
- continue;
- }
- $newType = $newTypeMap[$typeName];
- if (!($oldType instanceof $newType)) {
- $oldTypeKindName = self::typeKindName($oldType);
- $newTypeKindName = self::typeKindName($newType);
- $breakingChanges[] = [
- 'type' => self::BREAKING_CHANGE_TYPE_CHANGED_KIND,
- 'description' => "${typeName} changed from ${oldTypeKindName} to ${newTypeKindName}."
- ];
- }
- }
- return $breakingChanges;
- }
-
- /**
- * Given two schemas, returns an Array containing descriptions of any
- * breaking or dangerous changes in the newSchema related to arguments
- * (such as removal or change of type of an argument, or a change in an
- * argument's default value).
- *
- * @return array
- */
- public static function findArgChanges(
- Schema $oldSchema,
- Schema $newSchema
- ) {
- $oldTypeMap = $oldSchema->getTypeMap();
- $newTypeMap = $newSchema->getTypeMap();
-
- $breakingChanges = [];
- $dangerousChanges = [];
-
- foreach ($oldTypeMap as $typeName => $oldType) {
- $newType = isset($newTypeMap[$typeName]) ? $newTypeMap[$typeName] : null;
- if (
- !($oldType instanceof ObjectType || $oldType instanceof InterfaceType) ||
- !($newType instanceof ObjectType || $newType instanceof InterfaceType) ||
- !($newType instanceof $oldType)
- ) {
- continue;
- }
-
- $oldTypeFields = $oldType->getFields();
- $newTypeFields = $newType->getFields();
-
- foreach ($oldTypeFields as $fieldName => $oldField) {
- if (!isset($newTypeFields[$fieldName])) {
- continue;
- }
-
- foreach ($oldField->args as $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' => "${typeName}.${fieldName} arg {$oldArgDef->name} was removed"
- ];
- } else {
- $isSafe = self::isChangeSafeForInputObjectFieldOrFieldArg(
- $oldArgDef->getType(),
- $newArgDef->getType()
- );
- $oldArgType = $oldArgDef->getType();
- $oldArgName = $oldArgDef->name;
- if (!$isSafe) {
- $newArgType = $newArgDef->getType();
- $breakingChanges[] = [
- 'type' => self::BREAKING_CHANGE_ARG_CHANGED_KIND,
- 'description' => "${typeName}.${fieldName} arg ${oldArgName} has changed type from ${oldArgType} to ${newArgType}"
- ];
- } elseif ($oldArgDef->defaultValueExists() && $oldArgDef->defaultValue !== $newArgDef->defaultValue) {
- $dangerousChanges[] = [
- 'type' => FindBreakingChanges::DANGEROUS_CHANGE_ARG_DEFAULT_VALUE_CHANGED,
- 'description' => "${typeName}.${fieldName} arg ${oldArgName} has changed defaultValue"
- ];
- }
- }
- // Check if a non-null arg was added to the field
- foreach ($newTypeFields[$fieldName]->args as $newArgDef) {
- $oldArgs = $oldTypeFields[$fieldName]->args;
- $oldArgDef = Utils::find(
- $oldArgs,
- function ($arg) use ($newArgDef) {
- return $arg->name === $newArgDef->name;
- }
- );
-
- if (!$oldArgDef) {
- $newTypeName = $newType->name;
- $newArgName = $newArgDef->name;
- if ($newArgDef->getType() instanceof NonNull) {
- $breakingChanges[] = [
- 'type' => self::BREAKING_CHANGE_NON_NULL_ARG_ADDED,
- 'description' => "A non-null arg ${newArgName} on ${newTypeName}.${fieldName} was added"
- ];
- } else {
- $dangerousChanges[] = [
- 'type' => self::DANGEROUS_CHANGE_NULLABLE_ARG_ADDED,
- 'description' => "A nullable arg ${newArgName} on ${newTypeName}.${fieldName} was added"
- ];
- }
- }
- }
- }
- }
- }
-
- return [
- 'breakingChanges' => $breakingChanges,
- 'dangerousChanges' => $dangerousChanges,
- ];
- }
-
- /**
- * @param Type $type
- * @return string
- *
- * @throws \TypeError
- */
- private static function typeKindName(Type $type)
- {
- if ($type instanceof ScalarType) {
- return 'a Scalar type';
- } elseif ($type instanceof ObjectType) {
- return 'an Object type';
- } elseif ($type instanceof InterfaceType) {
- return 'an Interface type';
- } elseif ($type instanceof UnionType) {
- return 'a Union type';
- } elseif ($type instanceof EnumType) {
- return 'an Enum type';
- } elseif ($type instanceof InputObjectType) {
- return 'an Input type';
- }
-
- throw new \TypeError('unknown type ' . $type->name);
- }
-
- public static function findFieldsThatChangedTypeOnObjectOrInterfaceTypes(
- Schema $oldSchema,
- Schema $newSchema
- ) {
- $oldTypeMap = $oldSchema->getTypeMap();
- $newTypeMap = $newSchema->getTypeMap();
-
- $breakingChanges = [];
- foreach ($oldTypeMap as $typeName => $oldType) {
- $newType = isset($newTypeMap[$typeName]) ? $newTypeMap[$typeName] : null;
- if (
- !($oldType instanceof ObjectType || $oldType instanceof InterfaceType) ||
- !($newType instanceof ObjectType || $newType instanceof InterfaceType) ||
- !($newType instanceof $oldType)
- ) {
- continue;
- }
-
- $oldTypeFieldsDef = $oldType->getFields();
- $newTypeFieldsDef = $newType->getFields();
- foreach ($oldTypeFieldsDef as $fieldName => $fieldDefinition) {
- // Check if the field is missing on the type in the new schema.
- if (!isset($newTypeFieldsDef[$fieldName])) {
- $breakingChanges[] = [
- 'type' => self::BREAKING_CHANGE_FIELD_REMOVED,
- 'description' => "${typeName}.${fieldName} was removed."
- ];
- } else {
- $oldFieldType = $oldTypeFieldsDef[$fieldName]->getType();
- $newFieldType = $newTypeFieldsDef[$fieldName]->getType();
- $isSafe = self::isChangeSafeForObjectOrInterfaceField(
- $oldFieldType,
- $newFieldType
- );
- if (!$isSafe) {
- $oldFieldTypeString = $oldFieldType instanceof NamedType
- ? $oldFieldType->name
- : $oldFieldType;
- $newFieldTypeString = $newFieldType instanceof NamedType
- ? $newFieldType->name
- : $newFieldType;
- $breakingChanges[] = [
- 'type' => self::BREAKING_CHANGE_FIELD_CHANGED_KIND,
- 'description' => "${typeName}.${fieldName} changed type from ${oldFieldTypeString} to ${newFieldTypeString}."
- ];
- }
- }
- }
- }
- return $breakingChanges;
- }
-
- public static function findFieldsThatChangedTypeOnInputObjectTypes(
- Schema $oldSchema,
- Schema $newSchema
- ) {
- $oldTypeMap = $oldSchema->getTypeMap();
- $newTypeMap = $newSchema->getTypeMap();
-
- $breakingChanges = [];
- $dangerousChanges = [];
- foreach ($oldTypeMap as $typeName => $oldType) {
- $newType = isset($newTypeMap[$typeName]) ? $newTypeMap[$typeName] : null;
- if (!($oldType instanceof InputObjectType) || !($newType instanceof InputObjectType)) {
- continue;
- }
-
- $oldTypeFieldsDef = $oldType->getFields();
- $newTypeFieldsDef = $newType->getFields();
- foreach (array_keys($oldTypeFieldsDef) as $fieldName) {
- if (!isset($newTypeFieldsDef[$fieldName])) {
- $breakingChanges[] = [
- 'type' => self::BREAKING_CHANGE_FIELD_REMOVED,
- 'description' => "${typeName}.${fieldName} was removed."
- ];
- } else {
- $oldFieldType = $oldTypeFieldsDef[$fieldName]->getType();
- $newFieldType = $newTypeFieldsDef[$fieldName]->getType();
-
- $isSafe = self::isChangeSafeForInputObjectFieldOrFieldArg(
- $oldFieldType,
- $newFieldType
- );
- if (!$isSafe) {
- $oldFieldTypeString = $oldFieldType instanceof NamedType
- ? $oldFieldType->name
- : $oldFieldType;
- $newFieldTypeString = $newFieldType instanceof NamedType
- ? $newFieldType->name
- : $newFieldType;
- $breakingChanges[] = [
- 'type' => self::BREAKING_CHANGE_FIELD_CHANGED_KIND,
- 'description' => "${typeName}.${fieldName} changed type from ${oldFieldTypeString} to ${newFieldTypeString}."];
- }
- }
- }
- // Check if a field was added to the input object type
- foreach ($newTypeFieldsDef as $fieldName => $fieldDef) {
- if (!isset($oldTypeFieldsDef[$fieldName])) {
- $newTypeName = $newType->name;
- if ($fieldDef->getType() instanceof NonNull) {
- $breakingChanges[] = [
- 'type' => self::BREAKING_CHANGE_NON_NULL_INPUT_FIELD_ADDED,
- 'description' => "A non-null field ${fieldName} on input type ${newTypeName} was added."
- ];
- } else {
- $dangerousChanges[] = [
- 'type' => self::DANGEROUS_CHANGE_NULLABLE_INPUT_FIELD_ADDED,
- 'description' => "A nullable field ${fieldName} on input type ${newTypeName} was added."
- ];
- }
- }
- }
- }
-
- return [
- 'breakingChanges' => $breakingChanges,
- 'dangerousChanges' => $dangerousChanges,
- ];
-
- }
-
- private static function isChangeSafeForObjectOrInterfaceField(
- Type $oldType,
- Type $newType
- ) {
- if ($oldType instanceof NamedType) {
- return (
- // if they're both named types, see if their names are equivalent
- ($newType instanceof NamedType && $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) {
- return (
- // if they're both lists, make sure the underlying types are compatible
- ($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;
- }
-
- /**
- * @param Type $oldType
- * @param Type $newType
- *
- * @return bool
- */
- private static function isChangeSafeForInputObjectFieldOrFieldArg(
- Type $oldType,
- Type $newType
- ) {
- if ($oldType instanceof NamedType) {
- // if they're both named types, see if their names are equivalent
- return $newType instanceof NamedType && $oldType->name === $newType->name;
- } elseif ($oldType instanceof ListOfType) {
- // if they're both lists, make sure the underlying types are compatible
- return $newType instanceof ListOfType && self::isChangeSafeForInputObjectFieldOrFieldArg($oldType->getWrappedType(), $newType->getWrappedType());
- } elseif ($oldType instanceof NonNull) {
- return (
- // if they're both non-null, make sure the underlying types are
- // compatible
- ($newType instanceof NonNull &&
- self::isChangeSafeForInputObjectFieldOrFieldArg(
- $oldType->getWrappedType(),
- $newType->getWrappedType()
- )) ||
- // moving from non-null to nullable of the same underlying type is safe
- (!($newType instanceof NonNull) &&
- self::isChangeSafeForInputObjectFieldOrFieldArg($oldType->getWrappedType(), $newType))
- );
- }
- return false;
- }
-
- /**
- * Given two schemas, returns an Array containing descriptions of any breaking
- * changes in the newSchema related to removing types from a union type.
- *
- * @return array
- */
- public static function findTypesRemovedFromUnions(
- Schema $oldSchema,
- Schema $newSchema
- ) {
- $oldTypeMap = $oldSchema->getTypeMap();
- $newTypeMap = $newSchema->getTypeMap();
-
- $typesRemovedFromUnion = [];
- foreach ($oldTypeMap as $typeName => $oldType) {
- $newType = isset($newTypeMap[$typeName]) ? $newTypeMap[$typeName] : null;
- if (!($oldType instanceof UnionType) || !($newType instanceof UnionType)) {
- continue;
- }
- $typeNamesInNewUnion = [];
- foreach ($newType->getTypes() as $type) {
- $typeNamesInNewUnion[$type->name] = true;
- }
- foreach ($oldType->getTypes() as $type) {
- if (!isset($typeNamesInNewUnion[$type->name])) {
- $typesRemovedFromUnion[] = [
- 'type' => self::BREAKING_CHANGE_TYPE_REMOVED_FROM_UNION,
- 'description' => "{$type->name} was removed from union type ${typeName}.",
- ];
- }
- }
- }
- return $typesRemovedFromUnion;
- }
-
- /**
- * Given two schemas, returns an Array containing descriptions of any dangerous
- * changes in the newSchema related to adding types to a union type.
- *
- * @return array
- */
- public static function findTypesAddedToUnions(
- Schema $oldSchema,
- Schema $newSchema
- ) {
- $oldTypeMap = $oldSchema->getTypeMap();
- $newTypeMap = $newSchema->getTypeMap();
-
- $typesAddedToUnion = [];
- foreach ($newTypeMap as $typeName => $newType) {
- $oldType = isset($oldTypeMap[$typeName]) ? $oldTypeMap[$typeName] : null;
- if (!($oldType instanceof UnionType) || !($newType instanceof UnionType)) {
- continue;
- }
-
- $typeNamesInOldUnion = [];
- foreach ($oldType->getTypes() as $type) {
- $typeNamesInOldUnion[$type->name] = true;
- }
- foreach ($newType->getTypes() as $type) {
- if (!isset($typeNamesInOldUnion[$type->name])) {
- $typesAddedToUnion[] = [
- 'type' => self::DANGEROUS_CHANGE_TYPE_ADDED_TO_UNION,
- 'description' => "{$type->name} was added to union type ${typeName}.",
- ];
- }
- }
- }
- return $typesAddedToUnion;
- }
-
- /**
- * Given two schemas, returns an Array containing descriptions of any breaking
- * changes in the newSchema related to removing values from an enum type.
- *
- * @return array
- */
- public static function findValuesRemovedFromEnums(
- Schema $oldSchema,
- Schema $newSchema
- ) {
- $oldTypeMap = $oldSchema->getTypeMap();
- $newTypeMap = $newSchema->getTypeMap();
-
- $valuesRemovedFromEnums = [];
- foreach ($oldTypeMap as $typeName => $oldType) {
- $newType = isset($newTypeMap[$typeName]) ? $newTypeMap[$typeName] : null;
- if (!($oldType instanceof EnumType) || !($newType instanceof EnumType)) {
- continue;
- }
- $valuesInNewEnum = [];
- foreach ($newType->getValues() as $value) {
- $valuesInNewEnum[$value->name] = true;
- }
- foreach ($oldType->getValues() as $value) {
- if (!isset($valuesInNewEnum[$value->name])) {
- $valuesRemovedFromEnums[] = [
- 'type' => self::BREAKING_CHANGE_VALUE_REMOVED_FROM_ENUM,
- 'description' => "{$value->name} was removed from enum type ${typeName}.",
- ];
- }
- }
- }
- return $valuesRemovedFromEnums;
- }
-
/**
* Given two schemas, returns an Array containing descriptions of any dangerous
* changes in the newSchema related to adding values to an enum type.
*
- * @return array
+ * @return string[][]
*/
public static function findValuesAddedToEnums(
Schema $oldSchema,
@@ -579,8 +807,8 @@ class FindBreakingChanges
$valuesAddedToEnums = [];
foreach ($oldTypeMap as $typeName => $oldType) {
- $newType = isset($newTypeMap[$typeName]) ? $newTypeMap[$typeName] : null;
- if (!($oldType instanceof EnumType) || !($newType instanceof EnumType)) {
+ $newType = $newTypeMap[$typeName] ?? null;
+ if (! ($oldType instanceof EnumType) || ! ($newType instanceof EnumType)) {
continue;
}
$valuesInOldEnum = [];
@@ -588,218 +816,102 @@ class FindBreakingChanges
$valuesInOldEnum[$value->name] = true;
}
foreach ($newType->getValues() as $value) {
- if (!isset($valuesInOldEnum[$value->name])) {
- $valuesAddedToEnums[] = [
- 'type' => self::DANGEROUS_CHANGE_VALUE_ADDED_TO_ENUM,
- 'description' => "{$value->name} was added to enum type ${typeName}.",
- ];
+ if (isset($valuesInOldEnum[$value->name])) {
+ continue;
}
+
+ $valuesAddedToEnums[] = [
+ 'type' => self::DANGEROUS_CHANGE_VALUE_ADDED_TO_ENUM,
+ 'description' => sprintf('%s was added to enum type %s.', $value->name, $typeName),
+ ];
}
}
+
return $valuesAddedToEnums;
}
/**
- * @param Schema $oldSchema
- * @param Schema $newSchema
*
- * @return array
- */
- public static function findInterfacesRemovedFromObjectTypes(
- Schema $oldSchema,
- Schema $newSchema
- ) {
- $oldTypeMap = $oldSchema->getTypeMap();
- $newTypeMap = $newSchema->getTypeMap();
- $breakingChanges = [];
-
- foreach ($oldTypeMap as $typeName => $oldType) {
- $newType = isset($newTypeMap[$typeName]) ? $newTypeMap[$typeName] : null;
- if (!($oldType instanceof ObjectType) || !($newType instanceof ObjectType)) {
- continue;
- }
-
- $oldInterfaces = $oldType->getInterfaces();
- $newInterfaces = $newType->getInterfaces();
- foreach ($oldInterfaces as $oldInterface) {
- if (!Utils::find($newInterfaces, function (InterfaceType $interface) use ($oldInterface) {
- return $interface->name === $oldInterface->name;
- })) {
- $breakingChanges[] = [
- 'type' => self::BREAKING_CHANGE_INTERFACE_REMOVED_FROM_OBJECT,
- 'description' => "${typeName} no longer implements interface {$oldInterface->name}."
- ];
- }
- }
- }
- return $breakingChanges;
- }
-
- /**
- * @param Schema $oldSchema
- * @param Schema $newSchema
- *
- * @return array
+ * @return string[][]
*/
public static function findInterfacesAddedToObjectTypes(
Schema $oldSchema,
Schema $newSchema
) {
- $oldTypeMap = $oldSchema->getTypeMap();
- $newTypeMap = $newSchema->getTypeMap();
+ $oldTypeMap = $oldSchema->getTypeMap();
+ $newTypeMap = $newSchema->getTypeMap();
$interfacesAddedToObjectTypes = [];
foreach ($newTypeMap as $typeName => $newType) {
- $oldType = isset($oldTypeMap[$typeName]) ? $oldTypeMap[$typeName] : null;
- if (!($oldType instanceof ObjectType) || !($newType instanceof ObjectType)) {
+ $oldType = $oldTypeMap[$typeName] ?? null;
+ if (! ($oldType instanceof ObjectType) || ! ($newType instanceof ObjectType)) {
continue;
}
$oldInterfaces = $oldType->getInterfaces();
$newInterfaces = $newType->getInterfaces();
foreach ($newInterfaces as $newInterface) {
- if (!Utils::find($oldInterfaces, function (InterfaceType $interface) use ($newInterface) {
- return $interface->name === $newInterface->name;
- })) {
- $interfacesAddedToObjectTypes[] = [
- 'type' => self::DANGEROUS_CHANGE_INTERFACE_ADDED_TO_OBJECT,
- 'description' => "{$newInterface->name} added to interfaces implemented by {$typeName}.",
- ];
+ if (Utils::find(
+ $oldInterfaces,
+ function (InterfaceType $interface) use ($newInterface) {
+ return $interface->name === $newInterface->name;
+ }
+ )) {
+ continue;
}
+
+ $interfacesAddedToObjectTypes[] = [
+ 'type' => self::DANGEROUS_CHANGE_INTERFACE_ADDED_TO_OBJECT,
+ 'description' => sprintf(
+ '%s added to interfaces implemented by %s.',
+ $newInterface->name,
+ $typeName
+ ),
+ ];
}
}
+
return $interfacesAddedToObjectTypes;
}
- public static function findRemovedDirectives(Schema $oldSchema, Schema $newSchema)
- {
- $removedDirectives = [];
+ /**
+ * Given two schemas, returns an Array containing descriptions of any dangerous
+ * changes in the newSchema related to adding types to a union type.
+ *
+ * @return string[][]
+ */
+ public static function findTypesAddedToUnions(
+ Schema $oldSchema,
+ Schema $newSchema
+ ) {
+ $oldTypeMap = $oldSchema->getTypeMap();
+ $newTypeMap = $newSchema->getTypeMap();
- $newSchemaDirectiveMap = self::getDirectiveMapForSchema($newSchema);
- foreach($oldSchema->getDirectives() as $directive) {
- if (!isset($newSchemaDirectiveMap[$directive->name])) {
- $removedDirectives[] = [
- 'type' => self::BREAKING_CHANGE_DIRECTIVE_REMOVED,
- 'description' => "{$directive->name} was removed",
- ];
- }
- }
-
- return $removedDirectives;
- }
-
- public static function findRemovedArgsForDirectives(Directive $oldDirective, Directive $newDirective)
- {
- $removedArgs = [];
- $newArgMap = self::getArgumentMapForDirective($newDirective);
- foreach((array) $oldDirective->args as $arg) {
- if (!isset($newArgMap[$arg->name])) {
- $removedArgs[] = $arg;
- }
- }
-
- return $removedArgs;
- }
-
- public static function findRemovedDirectiveArgs(Schema $oldSchema, Schema $newSchema)
- {
- $removedDirectiveArgs = [];
- $oldSchemaDirectiveMap = self::getDirectiveMapForSchema($oldSchema);
-
- foreach($newSchema->getDirectives() as $newDirective) {
- if (!isset($oldSchemaDirectiveMap[$newDirective->name])) {
+ $typesAddedToUnion = [];
+ foreach ($newTypeMap as $typeName => $newType) {
+ $oldType = $oldTypeMap[$typeName] ?? null;
+ if (! ($oldType instanceof UnionType) || ! ($newType instanceof UnionType)) {
continue;
}
- foreach(self::findRemovedArgsForDirectives($oldSchemaDirectiveMap[$newDirective->name], $newDirective) as $arg) {
- $removedDirectiveArgs[] = [
- 'type' => self::BREAKING_CHANGE_DIRECTIVE_ARG_REMOVED,
- 'description' => "{$arg->name} was removed from {$newDirective->name}",
- ];
+ $typeNamesInOldUnion = [];
+ foreach ($oldType->getTypes() as $type) {
+ $typeNamesInOldUnion[$type->name] = true;
}
- }
-
- return $removedDirectiveArgs;
- }
-
- public static function findAddedArgsForDirective(Directive $oldDirective, Directive $newDirective)
- {
- $addedArgs = [];
- $oldArgMap = self::getArgumentMapForDirective($oldDirective);
- foreach((array) $newDirective->args as $arg) {
- if (!isset($oldArgMap[$arg->name])) {
- $addedArgs[] = $arg;
- }
- }
-
- return $addedArgs;
- }
-
- public static function findAddedNonNullDirectiveArgs(Schema $oldSchema, Schema $newSchema)
- {
- $addedNonNullableArgs = [];
- $oldSchemaDirectiveMap = self::getDirectiveMapForSchema($oldSchema);
-
- foreach($newSchema->getDirectives() as $newDirective) {
- if (!isset($oldSchemaDirectiveMap[$newDirective->name])) {
- continue;
- }
-
- foreach(self::findAddedArgsForDirective($oldSchemaDirectiveMap[$newDirective->name], $newDirective) as $arg) {
- if (!$arg->getType() instanceof NonNull) {
+ foreach ($newType->getTypes() as $type) {
+ if (isset($typeNamesInOldUnion[$type->name])) {
continue;
}
- $addedNonNullableArgs[] = [
- 'type' => self::BREAKING_CHANGE_NON_NULL_DIRECTIVE_ARG_ADDED,
- 'description' => "A non-null arg {$arg->name} on directive {$newDirective->name} was added",
+
+ $typesAddedToUnion[] = [
+ 'type' => self::DANGEROUS_CHANGE_TYPE_ADDED_TO_UNION,
+ 'description' => sprintf('%s was added to union type %s.', $type->name, $typeName),
];
}
}
- return $addedNonNullableArgs;
- }
-
- public static function findRemovedLocationsForDirective(Directive $oldDirective, Directive $newDirective)
- {
- $removedLocations = [];
- $newLocationSet = array_flip($newDirective->locations);
- foreach($oldDirective->locations as $oldLocation) {
- if (!array_key_exists($oldLocation, $newLocationSet)) {
- $removedLocations[] = $oldLocation;
- }
- }
-
- return $removedLocations;
- }
-
- public static function findRemovedDirectiveLocations(Schema $oldSchema, Schema $newSchema)
- {
- $removedLocations = [];
- $oldSchemaDirectiveMap = self::getDirectiveMapForSchema($oldSchema);
-
- foreach($newSchema->getDirectives() as $newDirective) {
- if (!isset($oldSchemaDirectiveMap[$newDirective->name])) {
- continue;
- }
-
- foreach(self::findRemovedLocationsForDirective($oldSchemaDirectiveMap[$newDirective->name], $newDirective) as $location) {
- $removedLocations[] = [
- 'type' => self::BREAKING_CHANGE_DIRECTIVE_LOCATION_REMOVED,
- 'description' => "{$location} was removed from {$newDirective->name}",
- ];
- }
- }
-
- return $removedLocations;
- }
-
- private static function getDirectiveMapForSchema(Schema $schema)
- {
- return Utils::keyMap($schema->getDirectives(), function ($dir) { return $dir->name; });
- }
-
- private static function getArgumentMapForDirective(Directive $directive)
- {
- return Utils::keyMap($directive->args ?: [], function ($arg) { return $arg->name; });
+ return $typesAddedToUnion;
}
}
+
+class_alias(BreakingChangesFinder::class, 'GraphQL\Utils\FindBreakingChanges');
diff --git a/src/Utils/BuildSchema.php b/src/Utils/BuildSchema.php
index 18e169d..94d4dcf 100644
--- a/src/Utils/BuildSchema.php
+++ b/src/Utils/BuildSchema.php
@@ -1,14 +1,21 @@
ast = $ast;
+ $this->typeConfigDecorator = $typeConfigDecorator;
+ $this->options = $options;
+ }
+
+ /**
+ * A helper function to build a GraphQLSchema directly from a source
+ * document.
+ *
+ * @api
+ * @param DocumentNode|Source|string $source
+ * @param bool[] $options
+ * @return Schema
+ */
+ public static function build($source, ?callable $typeConfigDecorator = null, array $options = [])
+ {
+ $doc = $source instanceof DocumentNode ? $source : Parser::parse($source);
+
+ return self::buildAST($doc, $typeConfigDecorator, $options);
+ }
+
/**
* This takes the ast of a schema document produced by the parse function in
* GraphQL\Language\Parser.
@@ -33,35 +78,22 @@ class BuildSchema
*
*
* @api
- * @param DocumentNode $ast
- * @param callable $typeConfigDecorator
- * @param array $options
+ * @param bool[] $options
* @return Schema
* @throws Error
*/
- public static function buildAST(DocumentNode $ast, callable $typeConfigDecorator = null, array $options = [])
+ public static function buildAST(DocumentNode $ast, ?callable $typeConfigDecorator = null, array $options = [])
{
$builder = new self($ast, $typeConfigDecorator, $options);
+
return $builder->buildSchema();
}
- private $ast;
- private $nodeMap;
- private $typeConfigDecorator;
- private $options;
-
- public function __construct(DocumentNode $ast, callable $typeConfigDecorator = null, array $options = [])
- {
- $this->ast = $ast;
- $this->typeConfigDecorator = $typeConfigDecorator;
- $this->options = $options;
- }
-
public function buildSchema()
{
/** @var SchemaDefinitionNode $schemaDef */
- $schemaDef = null;
- $typeDefs = [];
+ $schemaDef = null;
+ $typeDefs = [];
$this->nodeMap = [];
$directiveDefs = [];
foreach ($this->ast->definitions as $d) {
@@ -79,10 +111,10 @@ class BuildSchema
case NodeKind::UNION_TYPE_DEFINITION:
case NodeKind::INPUT_OBJECT_TYPE_DEFINITION:
$typeName = $d->name->value;
- if (!empty($this->nodeMap[$typeName])) {
- throw new Error("Type \"$typeName\" was defined more than once.");
+ if (! empty($this->nodeMap[$typeName])) {
+ throw new Error(sprintf('Type "%s" was defined more than once.', $typeName));
}
- $typeDefs[] = $d;
+ $typeDefs[] = $d;
$this->nodeMap[$typeName] = $d;
break;
case NodeKind::DIRECTIVE_DEFINITION:
@@ -94,41 +126,55 @@ class BuildSchema
$operationTypes = $schemaDef
? $this->getOperationTypes($schemaDef)
: [
- 'query' => isset($this->nodeMap['Query']) ? 'Query' : null,
- 'mutation' => isset($this->nodeMap['Mutation']) ? 'Mutation' : null,
+ 'query' => isset($this->nodeMap['Query']) ? 'Query' : null,
+ 'mutation' => isset($this->nodeMap['Mutation']) ? 'Mutation' : null,
'subscription' => isset($this->nodeMap['Subscription']) ? 'Subscription' : null,
];
$defintionBuilder = new ASTDefinitionBuilder(
$this->nodeMap,
$this->options,
- function($typeName) { throw new Error('Type "'. $typeName . '" not found in document.'); },
+ function ($typeName) {
+ throw new Error('Type "' . $typeName . '" not found in document.');
+ },
$this->typeConfigDecorator
);
- $directives = array_map(function($def) use ($defintionBuilder) {
- return $defintionBuilder->buildDirective($def);
- }, $directiveDefs);
+ $directives = array_map(
+ function ($def) use ($defintionBuilder) {
+ return $defintionBuilder->buildDirective($def);
+ },
+ $directiveDefs
+ );
// If specified directives were not explicitly declared, add them.
- $skip = array_reduce($directives, function ($hasSkip, $directive) {
- return $hasSkip || $directive->name == 'skip';
- });
- if (!$skip) {
+ $skip = array_reduce(
+ $directives,
+ function ($hasSkip, $directive) {
+ return $hasSkip || $directive->name === 'skip';
+ }
+ );
+ if (! $skip) {
$directives[] = Directive::skipDirective();
}
- $include = array_reduce($directives, function ($hasInclude, $directive) {
- return $hasInclude || $directive->name == 'include';
- });
- if (!$include) {
+ $include = array_reduce(
+ $directives,
+ function ($hasInclude, $directive) {
+ return $hasInclude || $directive->name === 'include';
+ }
+ );
+ if (! $include) {
$directives[] = Directive::includeDirective();
}
- $deprecated = array_reduce($directives, function ($hasDeprecated, $directive) {
- return $hasDeprecated || $directive->name == 'deprecated';
- });
- if (!$deprecated) {
+ $deprecated = array_reduce(
+ $directives,
+ function ($hasDeprecated, $directive) {
+ return $hasDeprecated || $directive->name === 'deprecated';
+ }
+ );
+ if (! $deprecated) {
$directives[] = Directive::deprecatedDirective();
}
@@ -137,27 +183,28 @@ class BuildSchema
// validation with validateSchema() will produce more actionable results.
$schema = new Schema([
- 'query' => isset($operationTypes['query'])
+ 'query' => isset($operationTypes['query'])
? $defintionBuilder->buildType($operationTypes['query'])
: null,
- 'mutation' => isset($operationTypes['mutation'])
+ 'mutation' => isset($operationTypes['mutation'])
? $defintionBuilder->buildType($operationTypes['mutation'])
: null,
'subscription' => isset($operationTypes['subscription'])
? $defintionBuilder->buildType($operationTypes['subscription'])
: null,
- 'typeLoader' => function ($name) use ($defintionBuilder) {
+ 'typeLoader' => function ($name) use ($defintionBuilder) {
return $defintionBuilder->buildType($name);
},
- 'directives' => $directives,
- 'astNode' => $schemaDef,
- 'types' => function () use ($defintionBuilder) {
+ 'directives' => $directives,
+ 'astNode' => $schemaDef,
+ 'types' => function () use ($defintionBuilder) {
$types = [];
foreach ($this->nodeMap as $name => $def) {
$types[] = $defintionBuilder->buildType($def->name->value);
}
+
return $types;
- }
+ },
]);
return $schema;
@@ -165,7 +212,7 @@ class BuildSchema
/**
* @param SchemaDefinitionNode $schemaDef
- * @return array
+ * @return string[]
* @throws Error
*/
private function getOperationTypes($schemaDef)
@@ -173,15 +220,15 @@ class BuildSchema
$opTypes = [];
foreach ($schemaDef->operationTypes as $operationType) {
- $typeName = $operationType->type->name->value;
+ $typeName = $operationType->type->name->value;
$operation = $operationType->operation;
if (isset($opTypes[$operation])) {
- throw new Error("Must provide only one $operation type in schema.");
+ throw new Error(sprintf('Must provide only one %s type in schema.', $operation));
}
- if (!isset($this->nodeMap[$typeName])) {
- throw new Error("Specified $operation type \"$typeName\" not found in document.");
+ if (! isset($this->nodeMap[$typeName])) {
+ throw new Error(sprintf('Specified %s type "%s" not found in document.', $operation, $typeName));
}
$opTypes[$operation] = $typeName;
@@ -189,20 +236,4 @@ class BuildSchema
return $opTypes;
}
-
- /**
- * A helper function to build a GraphQLSchema directly from a source
- * document.
- *
- * @api
- * @param DocumentNode|Source|string $source
- * @param callable $typeConfigDecorator
- * @param array $options
- * @return Schema
- */
- public static function build($source, callable $typeConfigDecorator = null, array $options = [])
- {
- $doc = $source instanceof DocumentNode ? $source : Parser::parse($source);
- return self::buildAST($doc, $typeConfigDecorator, $options);
- }
}
diff --git a/src/Utils/MixedStore.php b/src/Utils/MixedStore.php
index 89f183f..a3201a3 100644
--- a/src/Utils/MixedStore.php
+++ b/src/Utils/MixedStore.php
@@ -1,6 +1,19 @@
standardStore = [];
- $this->floatStore = [];
- $this->objectStore = new \SplObjectStorage();
- $this->arrayKeys = [];
- $this->arrayValues = [];
- $this->nullValueIsSet = false;
- $this->trueValueIsSet = false;
+ $this->standardStore = [];
+ $this->floatStore = [];
+ $this->objectStore = new \SplObjectStorage();
+ $this->arrayKeys = [];
+ $this->arrayValues = [];
+ $this->nullValueIsSet = false;
+ $this->trueValueIsSet = false;
$this->falseValueIsSet = false;
}
@@ -98,18 +81,17 @@ class MixedStore implements \ArrayAccess
* @param mixed $offset
* An offset to check for.
*
- * @return boolean true on success or false on failure.
+ * @return bool true on success or false on failure.
*
*
* The return value will be casted to boolean if non-boolean was returned.
- * @since 5.0.0
*/
public function offsetExists($offset)
{
- if (false === $offset) {
+ if ($offset === false) {
return $this->falseValueIsSet;
}
- if (true === $offset) {
+ if ($offset === true) {
return $this->trueValueIsSet;
}
if (is_int($offset) || is_string($offset)) {
@@ -124,15 +106,17 @@ class MixedStore implements \ArrayAccess
if (is_array($offset)) {
foreach ($this->arrayKeys as $index => $entry) {
if ($entry === $offset) {
- $this->lastArrayKey = $offset;
+ $this->lastArrayKey = $offset;
$this->lastArrayValue = $this->arrayValues[$index];
+
return true;
}
}
}
- if (null === $offset) {
+ if ($offset === null) {
return $this->nullValueIsSet;
}
+
return false;
}
@@ -143,21 +127,20 @@ class MixedStore implements \ArrayAccess
* The offset to retrieve.
*
* @return mixed Can return all value types.
- * @since 5.0.0
*/
public function offsetGet($offset)
{
- if (true === $offset) {
+ if ($offset === true) {
return $this->trueValue;
}
- if (false === $offset) {
+ if ($offset === false) {
return $this->falseValue;
}
if (is_int($offset) || is_string($offset)) {
return $this->standardStore[$offset];
}
if (is_float($offset)) {
- return $this->floatStore[(string)$offset];
+ return $this->floatStore[(string) $offset];
}
if (is_object($offset)) {
return $this->objectStore->offsetGet($offset);
@@ -173,9 +156,10 @@ class MixedStore implements \ArrayAccess
}
}
}
- if (null === $offset) {
+ if ($offset === null) {
return $this->nullValue;
}
+
return null;
}
@@ -185,34 +169,33 @@ class MixedStore implements \ArrayAccess
* @param mixed $offset
* The offset to assign the value to.
*
- * @param mixed $value
- * The value to set.
- *
+ * @param mixed $value
+ * The value to set.
+ *
* @return void
- * @since 5.0.0
*/
public function offsetSet($offset, $value)
{
- if (false === $offset) {
- $this->falseValue = $value;
+ if ($offset === false) {
+ $this->falseValue = $value;
$this->falseValueIsSet = true;
- } else if (true === $offset) {
- $this->trueValue = $value;
+ } elseif ($offset === true) {
+ $this->trueValue = $value;
$this->trueValueIsSet = true;
- } else if (is_int($offset) || is_string($offset)) {
+ } elseif (is_int($offset) || is_string($offset)) {
$this->standardStore[$offset] = $value;
- } else if (is_float($offset)) {
- $this->floatStore[(string)$offset] = $value;
- } else if (is_object($offset)) {
+ } elseif (is_float($offset)) {
+ $this->floatStore[(string) $offset] = $value;
+ } elseif (is_object($offset)) {
$this->objectStore[$offset] = $value;
- } else if (is_array($offset)) {
- $this->arrayKeys[] = $offset;
+ } elseif (is_array($offset)) {
+ $this->arrayKeys[] = $offset;
$this->arrayValues[] = $value;
- } else if (null === $offset) {
- $this->nullValue = $value;
+ } elseif ($offset === null) {
+ $this->nullValue = $value;
$this->nullValueIsSet = true;
} else {
- throw new \InvalidArgumentException("Unexpected offset type: " . Utils::printSafe($offset));
+ throw new \InvalidArgumentException('Unexpected offset type: ' . Utils::printSafe($offset));
}
}
@@ -223,31 +206,30 @@ class MixedStore implements \ArrayAccess
* The offset to unset.
*
* @return void
- * @since 5.0.0
*/
public function offsetUnset($offset)
{
- if (true === $offset) {
- $this->trueValue = null;
+ if ($offset === true) {
+ $this->trueValue = null;
$this->trueValueIsSet = false;
- } else if (false === $offset) {
- $this->falseValue = null;
+ } elseif ($offset === false) {
+ $this->falseValue = null;
$this->falseValueIsSet = false;
- } else if (is_int($offset) || is_string($offset)) {
+ } elseif (is_int($offset) || is_string($offset)) {
unset($this->standardStore[$offset]);
- } else if (is_float($offset)) {
- unset($this->floatStore[(string)$offset]);
- } else if (is_object($offset)) {
+ } elseif (is_float($offset)) {
+ unset($this->floatStore[(string) $offset]);
+ } elseif (is_object($offset)) {
$this->objectStore->offsetUnset($offset);
- } else if (is_array($offset)) {
+ } elseif (is_array($offset)) {
$index = array_search($offset, $this->arrayKeys, true);
- if (false !== $index) {
+ if ($index !== false) {
array_splice($this->arrayKeys, $index, 1);
array_splice($this->arrayValues, $index, 1);
}
- } else if (null === $offset) {
- $this->nullValue = null;
+ } elseif ($offset === null) {
+ $this->nullValue = null;
$this->nullValueIsSet = false;
}
}
diff --git a/src/Utils/PairSet.php b/src/Utils/PairSet.php
index d00161d..e910a4b 100644
--- a/src/Utils/PairSet.php
+++ b/src/Utils/PairSet.php
@@ -1,4 +1,7 @@
data = [];
@@ -23,12 +21,12 @@ class PairSet
/**
* @param string $a
* @param string $b
- * @param bool $areMutuallyExclusive
+ * @param bool $areMutuallyExclusive
* @return bool
*/
public function has($a, $b, $areMutuallyExclusive)
{
- $first = isset($this->data[$a]) ? $this->data[$a] : null;
+ $first = $this->data[$a] ?? null;
$result = ($first && isset($first[$b])) ? $first[$b] : null;
if ($result === null) {
return false;
@@ -39,13 +37,14 @@ class PairSet
if ($areMutuallyExclusive === false) {
return $result === false;
}
+
return true;
}
/**
* @param string $a
* @param string $b
- * @param bool $areMutuallyExclusive
+ * @param bool $areMutuallyExclusive
*/
public function add($a, $b, $areMutuallyExclusive)
{
@@ -56,11 +55,11 @@ class PairSet
/**
* @param string $a
* @param string $b
- * @param bool $areMutuallyExclusive
+ * @param bool $areMutuallyExclusive
*/
private function pairSetAdd($a, $b, $areMutuallyExclusive)
{
- $this->data[$a] = isset($this->data[$a]) ? $this->data[$a] : [];
+ $this->data[$a] = $this->data[$a] ?? [];
$this->data[$a][$b] = $areMutuallyExclusive;
}
}
diff --git a/src/Utils/SchemaPrinter.php b/src/Utils/SchemaPrinter.php
index 1c56648..7b547dd 100644
--- a/src/Utils/SchemaPrinter.php
+++ b/src/Utils/SchemaPrinter.php
@@ -1,10 +1,12 @@
getDirectives(), function($directive) use ($directiveFilter) {
- return $directiveFilter($directive);
- });
+ $directives = array_filter(
+ $schema->getDirectives(),
+ function ($directive) use ($directiveFilter) {
+ return $directiveFilter($directive);
+ }
+ );
+
$types = $schema->getTypeMap();
ksort($types);
$types = array_filter($types, $typeFilter);
- return implode("\n\n", array_filter(array_merge(
- [self::printSchemaDefinition($schema)],
- array_map(function($directive) use ($options) { return self::printDirective($directive, $options); }, $directives),
- array_map(function($type) use ($options) { return self::printType($type, $options); }, $types)
- ))) . "\n";
+ return sprintf(
+ "%s\n",
+ implode(
+ "\n\n",
+ array_filter(
+ array_merge(
+ [self::printSchemaDefinition($schema)],
+ array_map(
+ function ($directive) use ($options) {
+ return self::printDirective($directive, $options);
+ },
+ $directives
+ ),
+ array_map(
+ function ($type) use ($options) {
+ return self::printType($type, $options);
+ },
+ $types
+ )
+ )
+ )
+ )
+ );
}
private static function printSchemaDefinition(Schema $schema)
@@ -83,20 +111,20 @@ class SchemaPrinter
$queryType = $schema->getQueryType();
if ($queryType) {
- $operationTypes[] = " query: {$queryType->name}";
+ $operationTypes[] = sprintf(' query: %s', $queryType->name);
}
$mutationType = $schema->getMutationType();
if ($mutationType) {
- $operationTypes[] = " mutation: {$mutationType->name}";
+ $operationTypes[] = sprintf(' mutation: %s', $mutationType->name);
}
$subscriptionType = $schema->getSubscriptionType();
if ($subscriptionType) {
- $operationTypes[] = " subscription: {$subscriptionType->name}";
+ $operationTypes[] = sprintf(' subscription: %s', $subscriptionType->name);
}
- return "schema {\n" . implode("\n", $operationTypes) . "\n}";
+ return sprintf("schema {\n%s\n}", implode("\n", $operationTypes));
}
/**
@@ -131,120 +159,6 @@ class SchemaPrinter
return true;
}
- public static function printType(Type $type, array $options = [])
- {
- if ($type instanceof ScalarType) {
- return self::printScalar($type, $options);
- } else if ($type instanceof ObjectType) {
- return self::printObject($type, $options);
- } else if ($type instanceof InterfaceType) {
- return self::printInterface($type, $options);
- } else if ($type instanceof UnionType) {
- return self::printUnion($type, $options);
- } else if ($type instanceof EnumType) {
- return self::printEnum($type, $options);
- } else if ($type instanceof InputObjectType) {
- return self::printInputObject($type, $options);
- }
-
- throw new Error('Unknown type: ' . Utils::printSafe($type) . '.');
- }
-
- private static function printScalar(ScalarType $type, array $options)
- {
- return self::printDescription($options, $type) . "scalar {$type->name}";
- }
-
- private static function printObject(ObjectType $type, array $options)
- {
- $interfaces = $type->getInterfaces();
- $implementedInterfaces = !empty($interfaces) ?
- ' implements ' . implode(', ', array_map(function($i) {
- return $i->name;
- }, $interfaces)) : '';
- return self::printDescription($options, $type) .
- "type {$type->name}$implementedInterfaces {\n" .
- self::printFields($options, $type) . "\n" .
- "}";
- }
-
- private static function printInterface(InterfaceType $type, array $options)
- {
- return self::printDescription($options, $type) .
- "interface {$type->name} {\n" .
- self::printFields($options, $type) . "\n" .
- "}";
- }
-
- private static function printUnion(UnionType $type, array $options)
- {
- return self::printDescription($options, $type) .
- "union {$type->name} = " . implode(" | ", $type->getTypes());
- }
-
- private static function printEnum(EnumType $type, array $options)
- {
- return self::printDescription($options, $type) .
- "enum {$type->name} {\n" .
- self::printEnumValues($type->getValues(), $options) . "\n" .
- "}";
- }
-
- private static function printEnumValues($values, $options)
- {
- return implode("\n", array_map(function($value, $i) use ($options) {
- return self::printDescription($options, $value, ' ', !$i) . ' ' .
- $value->name . self::printDeprecated($value);
- }, $values, array_keys($values)));
- }
-
- private static function printInputObject(InputObjectType $type, array $options)
- {
- $fields = array_values($type->getFields());
- return self::printDescription($options, $type) .
- "input {$type->name} {\n" .
- implode("\n", array_map(function($f, $i) use ($options) {
- return self::printDescription($options, $f, ' ', !$i) . ' ' . self::printInputValue($f);
- }, $fields, array_keys($fields))) . "\n" .
- "}";
- }
-
- private static function printFields($options, $type)
- {
- $fields = array_values($type->getFields());
- return implode("\n", array_map(function($f, $i) use ($options) {
- return self::printDescription($options, $f, ' ', !$i) . ' ' .
- $f->name . self::printArgs($options, $f->args, ' ') . ': ' .
- (string) $f->getType() . self::printDeprecated($f);
- }, $fields, array_keys($fields)));
- }
-
- private static function printArgs($options, $args, $indentation = '')
- {
- if (!$args) {
- return '';
- }
-
- // If every arg does not have a description, print them on one line.
- if (Utils::every($args, function($arg) { return empty($arg->description); })) {
- return '(' . implode(', ', array_map('self::printInputValue', $args)) . ')';
- }
-
- return "(\n" . implode("\n", array_map(function($arg, $i) use ($indentation, $options) {
- return self::printDescription($options, $arg, ' ' . $indentation, !$i) . ' ' . $indentation .
- self::printInputValue($arg);
- }, $args, array_keys($args))) . "\n" . $indentation . ')';
- }
-
- private static function printInputValue($arg)
- {
- $argDecl = $arg->name . ': ' . (string) $arg->getType();
- if ($arg->defaultValueExists()) {
- $argDecl .= ' = ' . Printer::doPrint(AST::astFromValue($arg->defaultValue, $arg->getType()));
- }
- return $argDecl;
- }
-
private static function printDirective($directive, $options)
{
return self::printDescription($options, $directive) .
@@ -252,22 +166,9 @@ class SchemaPrinter
' on ' . implode(' | ', $directive->locations);
}
- private static function printDeprecated($fieldOrEnumVal)
- {
- $reason = $fieldOrEnumVal->deprecationReason;
- if (empty($reason)) {
- return '';
- }
- if ($reason === '' || $reason === Directive::DEFAULT_DEPRECATION_REASON) {
- return ' @deprecated';
- }
- return ' @deprecated(reason: ' .
- Printer::doPrint(AST::astFromValue($reason, Type::string())) . ')';
- }
-
private static function printDescription($options, $def, $indentation = '', $firstInBlock = true)
{
- if (!$def->description) {
+ if (! $def->description) {
return '';
}
$lines = self::descriptionLines($def->description, 120 - strlen($indentation));
@@ -275,13 +176,12 @@ class SchemaPrinter
return self::printDescriptionWithComments($lines, $indentation, $firstInBlock);
}
- $description = ($indentation && !$firstInBlock)
+ $description = ($indentation && ! $firstInBlock)
? "\n" . $indentation . '"""'
: $indentation . '"""';
// In some circumstances, a single line can be used for the description.
- if (
- count($lines) === 1 &&
+ if (count($lines) === 1 &&
mb_strlen($lines[0]) < 70 &&
substr($lines[0], -1) !== '"'
) {
@@ -294,13 +194,13 @@ class SchemaPrinter
substr($lines[0], 0, 1) === ' ' ||
substr($lines[0], 0, 1) === '\t'
);
- if (!$hasLeadingSpace) {
+ if (! $hasLeadingSpace) {
$description .= "\n";
}
$lineLength = count($lines);
for ($i = 0; $i < $lineLength; $i++) {
- if ($i !== 0 || !$hasLeadingSpace) {
+ if ($i !== 0 || ! $hasLeadingSpace) {
$description .= $indentation;
}
$description .= self::escapeQuote($lines[$i]) . "\n";
@@ -310,29 +210,11 @@ class SchemaPrinter
return $description;
}
- private static function escapeQuote($line)
+ private static function descriptionLines($description, $maxLen)
{
- return str_replace('"""', '\\"""', $line);
- }
-
- private static function printDescriptionWithComments($lines, $indentation, $firstInBlock)
- {
- $description = $indentation && !$firstInBlock ? "\n" : '';
- foreach ($lines as $line) {
- if ($line === '') {
- $description .= $indentation . "#\n";
- } else {
- $description .= $indentation . '# ' . $line . "\n";
- }
- }
-
- return $description;
- }
-
- private static function descriptionLines($description, $maxLen) {
- $lines = [];
+ $lines = [];
$rawLines = explode("\n", $description);
- foreach($rawLines as $line) {
+ foreach ($rawLines as $line) {
if ($line === '') {
$lines[] = $line;
} else {
@@ -344,6 +226,7 @@ class SchemaPrinter
}
}
}
+
return $lines;
}
@@ -352,10 +235,251 @@ class SchemaPrinter
if (strlen($line) < $maxLen + 5) {
return [$line];
}
- preg_match_all("/((?: |^).{15," . ($maxLen - 40) . "}(?= |$))/", $line, $parts);
+ preg_match_all('/((?: |^).{15,' . ($maxLen - 40) . '}(?= |$))/', $line, $parts);
$parts = $parts[0];
- return array_map(function($part) {
- return trim($part);
- }, $parts);
+
+ return array_map('trim', $parts);
+ }
+
+ private static function printDescriptionWithComments($lines, $indentation, $firstInBlock)
+ {
+ $description = $indentation && ! $firstInBlock ? "\n" : '';
+ foreach ($lines as $line) {
+ if ($line === '') {
+ $description .= $indentation . "#\n";
+ } else {
+ $description .= $indentation . '# ' . $line . "\n";
+ }
+ }
+
+ return $description;
+ }
+
+ private static function escapeQuote($line)
+ {
+ return str_replace('"""', '\\"""', $line);
+ }
+
+ private static function printArgs($options, $args, $indentation = '')
+ {
+ if (! $args) {
+ return '';
+ }
+
+ // If every arg does not have a description, print them on one line.
+ if (Utils::every(
+ $args,
+ function ($arg) {
+ return empty($arg->description);
+ }
+ )) {
+ return '(' . implode(', ', array_map('self::printInputValue', $args)) . ')';
+ }
+
+ return sprintf(
+ "(\n%s\n%s)",
+ implode(
+ "\n",
+ array_map(
+ function ($arg, $i) use ($indentation, $options) {
+ return self::printDescription($options, $arg, ' ' . $indentation, ! $i) . ' ' . $indentation .
+ self::printInputValue($arg);
+ },
+ $args,
+ array_keys($args)
+ )
+ ),
+ $indentation
+ );
+ }
+
+ private static function printInputValue($arg)
+ {
+ $argDecl = $arg->name . ': ' . (string) $arg->getType();
+ if ($arg->defaultValueExists()) {
+ $argDecl .= ' = ' . Printer::doPrint(AST::astFromValue($arg->defaultValue, $arg->getType()));
+ }
+
+ return $argDecl;
+ }
+
+ /**
+ * @param bool[] $options
+ */
+ public static function printType(Type $type, array $options = [])
+ {
+ if ($type instanceof ScalarType) {
+ return self::printScalar($type, $options);
+ }
+
+ if ($type instanceof ObjectType) {
+ return self::printObject($type, $options);
+ }
+
+ if ($type instanceof InterfaceType) {
+ return self::printInterface($type, $options);
+ }
+
+ if ($type instanceof UnionType) {
+ return self::printUnion($type, $options);
+ }
+
+ if ($type instanceof EnumType) {
+ return self::printEnum($type, $options);
+ }
+
+ if ($type instanceof InputObjectType) {
+ return self::printInputObject($type, $options);
+ }
+
+ throw new Error(sprintf('Unknown type: %s.', Utils::printSafe($type)));
+ }
+
+ /**
+ * @param bool[] $options
+ */
+ private static function printScalar(ScalarType $type, array $options)
+ {
+ return sprintf('%sscalar %s', self::printDescription($options, $type), $type->name);
+ }
+
+ /**
+ * @param bool[] $options
+ */
+ private static function printObject(ObjectType $type, array $options)
+ {
+ $interfaces = $type->getInterfaces();
+ $implementedInterfaces = ! empty($interfaces) ?
+ ' implements ' . implode(
+ ', ',
+ array_map(
+ function ($i) {
+ return $i->name;
+ },
+ $interfaces
+ )
+ ) : '';
+
+ return self::printDescription($options, $type) .
+ sprintf("type %s%s {\n%s\n}", $type->name, $implementedInterfaces, self::printFields($options, $type));
+ }
+
+ /**
+ * @param bool[] $options
+ */
+ private static function printFields($options, $type)
+ {
+ $fields = array_values($type->getFields());
+
+ return implode(
+ "\n",
+ array_map(
+ function ($f, $i) use ($options) {
+ return self::printDescription($options, $f, ' ', ! $i) . ' ' .
+ $f->name . self::printArgs($options, $f->args, ' ') . ': ' .
+ (string) $f->getType() . self::printDeprecated($f);
+ },
+ $fields,
+ array_keys($fields)
+ )
+ );
+ }
+
+ private static function printDeprecated($fieldOrEnumVal)
+ {
+ $reason = $fieldOrEnumVal->deprecationReason;
+ if (empty($reason)) {
+ return '';
+ }
+ if ($reason === '' || $reason === Directive::DEFAULT_DEPRECATION_REASON) {
+ return ' @deprecated';
+ }
+
+ return ' @deprecated(reason: ' .
+ Printer::doPrint(AST::astFromValue($reason, Type::string())) . ')';
+ }
+
+ /**
+ * @param bool[] $options
+ */
+ private static function printInterface(InterfaceType $type, array $options)
+ {
+ return self::printDescription($options, $type) .
+ sprintf("interface %s {\n%s\n}", $type->name, self::printFields($options, $type));
+ }
+
+ /**
+ * @param bool[] $options
+ */
+ private static function printUnion(UnionType $type, array $options)
+ {
+ return self::printDescription($options, $type) .
+ sprintf('union %s = %s', $type->name, implode(' | ', $type->getTypes()));
+ }
+
+ /**
+ * @param bool[] $options
+ */
+ private static function printEnum(EnumType $type, array $options)
+ {
+ return self::printDescription($options, $type) .
+ sprintf("enum %s {\n%s\n}", $type->name, self::printEnumValues($type->getValues(), $options));
+ }
+
+ /**
+ * @param bool[] $options
+ */
+ private static function printEnumValues($values, $options)
+ {
+ return implode(
+ "\n",
+ array_map(
+ function ($value, $i) use ($options) {
+ return self::printDescription($options, $value, ' ', ! $i) . ' ' .
+ $value->name . self::printDeprecated($value);
+ },
+ $values,
+ array_keys($values)
+ )
+ );
+ }
+
+ /**
+ * @param bool[] $options
+ */
+ private static function printInputObject(InputObjectType $type, array $options)
+ {
+ $fields = array_values($type->getFields());
+
+ return self::printDescription($options, $type) .
+ sprintf(
+ "input %s {\n%s\n}",
+ $type->name,
+ implode(
+ "\n",
+ array_map(
+ function ($f, $i) use ($options) {
+ return self::printDescription($options, $f, ' ', ! $i) . ' ' . self::printInputValue($f);
+ },
+ $fields,
+ array_keys($fields)
+ )
+ )
+ );
+ }
+
+ /**
+ * @api
+ * @param bool[] $options
+ * @return string
+ */
+ public static function printIntrosepctionSchema(Schema $schema, array $options = [])
+ {
+ return self::printFilteredSchema(
+ $schema,
+ [Directive::class, 'isSpecifiedDirective'],
+ [Introspection::class, 'isIntrospectionType'],
+ $options
+ );
}
}
diff --git a/src/Utils/TypeComparators.php b/src/Utils/TypeComparators.php
index 0ddcbaf..c66b266 100644
--- a/src/Utils/TypeComparators.php
+++ b/src/Utils/TypeComparators.php
@@ -1,21 +1,22 @@
getWrappedType(), $superType->getWrappedType());
}
+
return false;
- } else if ($maybeSubType instanceof NonNull) {
+ }
+
+ if ($maybeSubType instanceof NonNull) {
// If superType is nullable, maybeSubType may be non-null.
return self::isTypeSubTypeOf($schema, $maybeSubType->getWrappedType(), $superType);
}
@@ -71,15 +74,24 @@ class TypeComparators
if ($maybeSubType instanceof ListOfType) {
return self::isTypeSubTypeOf($schema, $maybeSubType->getWrappedType(), $superType->getWrappedType());
}
+
return false;
- } else if ($maybeSubType instanceof ListOfType) {
+ }
+
+ 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)) {
+ if (Type::isAbstractType($superType) &&
+ $maybeSubType instanceof ObjectType &&
+ $schema->isPossibleType(
+ $superType,
+ $maybeSubType
+ )
+ ) {
return true;
}
@@ -96,12 +108,9 @@ class TypeComparators
*
* This function is commutative.
*
- * @param Schema $schema
- * @param CompositeType $typeA
- * @param CompositeType $typeB
* @return bool
*/
- static function doTypesOverlap(Schema $schema, CompositeType $typeA, CompositeType $typeB)
+ public static function doTypesOverlap(Schema $schema, CompositeType $typeA, CompositeType $typeB)
{
// Equivalent types overlap
if ($typeA === $typeB) {
@@ -117,6 +126,7 @@ class TypeComparators
return true;
}
}
+
return false;
}
diff --git a/src/Utils/TypeInfo.php b/src/Utils/TypeInfo.php
index 7d93ee2..616c754 100644
--- a/src/Utils/TypeInfo.php
+++ b/src/Utils/TypeInfo.php
@@ -1,4 +1,7 @@
*/
+ private $typeStack;
+
+ /** @var \SplStack */
+ private $parentTypeStack;
+
+ /** @var \SplStack */
+ private $inputTypeStack;
+
+ /** @var \SplStack */
+ private $fieldDefStack;
+
+ /** @var Directive */
+ private $directive;
+
+ /** @var FieldArgument */
+ private $argument;
+
+ /** @var mixed */
+ private $enumValue;
+
+ /**
+ *
+ * @param Type|null $initialType
+ */
+ public function __construct(Schema $schema, $initialType = null)
+ {
+ $this->schema = $schema;
+ $this->typeStack = [];
+ $this->parentTypeStack = [];
+ $this->inputTypeStack = [];
+ $this->fieldDefStack = [];
+ if (! $initialType) {
+ return;
+ }
+
+ if (Type::isInputType($initialType)) {
+ $this->inputTypeStack[] = $initialType;
+ }
+ if (Type::isCompositeType($initialType)) {
+ $this->parentTypeStack[] = $initialType;
+ }
+ if (! Type::isOutputType($initialType)) {
+ return;
+ }
+
+ $this->typeStack[] = $initialType;
+ }
+
/**
* @deprecated moved to GraphQL\Utils\TypeComparators
*/
@@ -42,7 +101,7 @@ class TypeInfo
/**
* @deprecated moved to GraphQL\Utils\TypeComparators
*/
- static function isTypeSubTypeOf(Schema $schema, Type $maybeSubType, Type $superType)
+ public static function isTypeSubTypeOf(Schema $schema, Type $maybeSubType, Type $superType)
{
return TypeComparators::isTypeSubTypeOf($schema, $maybeSubType, $superType);
}
@@ -50,22 +109,11 @@ class TypeInfo
/**
* @deprecated moved to GraphQL\Utils\TypeComparators
*/
- static function doTypesOverlap(Schema $schema, CompositeType $typeA, CompositeType $typeB)
+ public static function doTypesOverlap(Schema $schema, CompositeType $typeA, CompositeType $typeB)
{
return TypeComparators::doTypesOverlap($schema, $typeA, $typeB);
}
- /**
- * @param Schema $schema
- * @param NamedTypeNode|ListTypeNode|NonNullTypeNode $inputTypeNode
- * @return Type|null
- * @throws InvariantViolation
- */
- public static function typeFromAST(Schema $schema, $inputTypeNode)
- {
- return AST::typeFromAST($schema, $inputTypeNode);
- }
-
/**
* Given root type scans through all fields to find nested types. Returns array where keys are for type name
* and value contains corresponding type instance.
@@ -77,37 +125,39 @@ class TypeInfo
* ...
* ]
*
- * @param Type $type
- * @param array|null $typeMap
- * @return array
+ * @param Type|null $type
+ * @param Type[]|null $typeMap
+ * @return Type[]|null
*/
- public static function extractTypes($type, array $typeMap = null)
+ public static function extractTypes($type, ?array $typeMap = null)
{
- if (!$typeMap) {
+ if (! $typeMap) {
$typeMap = [];
}
- if (!$type) {
+ if (! $type) {
return $typeMap;
}
if ($type instanceof WrappingType) {
return self::extractTypes($type->getWrappedType(true), $typeMap);
}
- if (!$type instanceof Type) {
+ if (! $type instanceof Type) {
Warning::warnOnce(
- 'One of the schema types is not a valid type definition instance. '.
+ 'One of the schema types is not a valid type definition instance. ' .
'Try running $schema->assertValid() to find out the cause of this warning.',
Warning::WARNING_NOT_A_TYPE
);
+
return $typeMap;
}
- if (!empty($typeMap[$type->name])) {
+ if (! empty($typeMap[$type->name])) {
Utils::invariant(
$typeMap[$type->name] === $type,
- "Schema must contain unique named types but contains multiple types named \"$type\" ".
- "(see http://webonyx.github.io/graphql-php/type-system/#type-registry)."
+ sprintf('Schema must contain unique named types but contains multiple types named "%s" ', $type) .
+ '(see http://webonyx.github.io/graphql-php/type-system/#type-registry).'
);
+
return $typeMap;
}
$typeMap[$type->name] = $type;
@@ -122,8 +172,14 @@ class TypeInfo
}
if ($type instanceof ObjectType || $type instanceof InterfaceType) {
foreach ((array) $type->getFields() as $fieldName => $field) {
- if (!empty($field->args)) {
- $fieldArgTypes = array_map(function(FieldArgument $arg) { return $arg->getType(); }, $field->args);
+ if (! empty($field->args)) {
+ $fieldArgTypes = array_map(
+ function (FieldArgument $arg) {
+ return $arg->getType();
+ },
+ $field->args
+ );
+
$nestedTypes = array_merge($nestedTypes, $fieldArgTypes);
}
$nestedTypes[] = $field->getType();
@@ -137,9 +193,169 @@ class TypeInfo
foreach ($nestedTypes as $type) {
$typeMap = self::extractTypes($type, $typeMap);
}
+
return $typeMap;
}
+ /**
+ * @return InputType|null
+ */
+ public function getParentInputType()
+ {
+ $inputTypeStackLength = count($this->inputTypeStack);
+ if ($inputTypeStackLength > 1) {
+ return $this->inputTypeStack[$inputTypeStackLength - 2];
+ }
+ }
+
+ /**
+ * @return FieldArgument|null
+ */
+ public function getArgument()
+ {
+ return $this->argument;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getEnumValue()
+ {
+ return $this->enumValue;
+ }
+
+ public function enter(Node $node)
+ {
+ $schema = $this->schema;
+
+ // Note: many of the types below are explicitly typed as "mixed" to drop
+ // any assumptions of a valid schema to ensure runtime types are properly
+ // checked before continuing since TypeInfo is used as part of validation
+ // which occurs before guarantees of schema and document validity.
+ switch ($node->kind) {
+ case NodeKind::SELECTION_SET:
+ $namedType = Type::getNamedType($this->getType());
+ $this->parentTypeStack[] = Type::isCompositeType($namedType) ? $namedType : null;
+ break;
+
+ case NodeKind::FIELD:
+ $parentType = $this->getParentType();
+ $fieldDef = null;
+ if ($parentType) {
+ $fieldDef = self::getFieldDefinition($schema, $parentType, $node);
+ }
+ $fieldType = null;
+ if ($fieldDef) {
+ $fieldType = $fieldDef->getType();
+ }
+ $this->fieldDefStack[] = $fieldDef;
+ $this->typeStack[] = Type::isOutputType($fieldType) ? $fieldType : null;
+ break;
+
+ case NodeKind::DIRECTIVE:
+ $this->directive = $schema->getDirective($node->name->value);
+ break;
+
+ case NodeKind::OPERATION_DEFINITION:
+ $type = null;
+ if ($node->operation === 'query') {
+ $type = $schema->getQueryType();
+ } elseif ($node->operation === 'mutation') {
+ $type = $schema->getMutationType();
+ } elseif ($node->operation === 'subscription') {
+ $type = $schema->getSubscriptionType();
+ }
+ $this->typeStack[] = Type::isOutputType($type) ? $type : null;
+ break;
+
+ case NodeKind::INLINE_FRAGMENT:
+ case NodeKind::FRAGMENT_DEFINITION:
+ $typeConditionNode = $node->typeCondition;
+ $outputType = $typeConditionNode ? self::typeFromAST(
+ $schema,
+ $typeConditionNode
+ ) : Type::getNamedType($this->getType());
+ $this->typeStack[] = Type::isOutputType($outputType) ? $outputType : null;
+ break;
+
+ case NodeKind::VARIABLE_DEFINITION:
+ $inputType = self::typeFromAST($schema, $node->type);
+ $this->inputTypeStack[] = Type::isInputType($inputType) ? $inputType : null; // push
+ break;
+
+ case NodeKind::ARGUMENT:
+ $fieldOrDirective = $this->getDirective() ?: $this->getFieldDef();
+ $argDef = $argType = null;
+ if ($fieldOrDirective) {
+ $argDef = Utils::find(
+ $fieldOrDirective->args,
+ function ($arg) use ($node) {
+ return $arg->name === $node->name->value;
+ }
+ );
+ if ($argDef) {
+ $argType = $argDef->getType();
+ }
+ }
+ $this->argument = $argDef;
+ $this->inputTypeStack[] = Type::isInputType($argType) ? $argType : null;
+ break;
+
+ case NodeKind::LST:
+ $listType = Type::getNullableType($this->getInputType());
+ $itemType = $listType instanceof ListOfType
+ ? $listType->getWrappedType()
+ : $listType;
+ $this->inputTypeStack[] = Type::isInputType($itemType) ? $itemType : null;
+ break;
+
+ case NodeKind::OBJECT_FIELD:
+ $objectType = Type::getNamedType($this->getInputType());
+ $fieldType = null;
+ $inputFieldType = null;
+ if ($objectType instanceof InputObjectType) {
+ $tmp = $objectType->getFields();
+ $inputField = $tmp[$node->name->value] ?? null;
+ $inputFieldType = $inputField ? $inputField->getType() : null;
+ }
+ $this->inputTypeStack[] = Type::isInputType($inputFieldType) ? $inputFieldType : null;
+ break;
+
+ case NodeKind::ENUM:
+ $enumType = Type::getNamedType($this->getInputType());
+ $enumValue = null;
+ if ($enumType instanceof EnumType) {
+ $enumValue = $enumType->getValue($node->value);
+ }
+ $this->enumValue = $enumValue;
+ break;
+ }
+ }
+
+ /**
+ * @return Type
+ */
+ public function getType()
+ {
+ if (! empty($this->typeStack)) {
+ return $this->typeStack[count($this->typeStack) - 1];
+ }
+
+ return null;
+ }
+
+ /**
+ * @return Type
+ */
+ public function getParentType()
+ {
+ if (! empty($this->parentTypeStack)) {
+ return $this->parentTypeStack[count($this->parentTypeStack) - 1];
+ }
+
+ return null;
+ }
+
/**
* Not exactly the same as the executor's definition of getFieldDef, in this
* statically evaluated environment we do not always have an Object type,
@@ -147,9 +363,9 @@ class TypeInfo
*
* @return FieldDefinition
*/
- static private function getFieldDefinition(Schema $schema, Type $parentType, FieldNode $fieldNode)
+ private static function getFieldDefinition(Schema $schema, Type $parentType, FieldNode $fieldNode)
{
- $name = $fieldNode->name->value;
+ $name = $fieldNode->name->value;
$schemaMeta = Introspection::schemaMetaFieldDef();
if ($name === $schemaMeta->name && $schema->getQueryType() === $parentType) {
return $schemaMeta;
@@ -166,263 +382,56 @@ class TypeInfo
if ($parentType instanceof ObjectType ||
$parentType instanceof InterfaceType) {
$fields = $parentType->getFields();
- return isset($fields[$name]) ? $fields[$name] : null;
+
+ return $fields[$name] ?? null;
}
- return null;
- }
-
- /**
- * @var Schema
- */
- private $schema;
-
- /**
- * @var \SplStack
- */
- private $typeStack;
-
- /**
- * @var \SplStack
- */
- private $parentTypeStack;
-
- /**
- * @var \SplStack
- */
- private $inputTypeStack;
-
- /**
- * @var \SplStack
- */
- private $fieldDefStack;
-
- /**
- * @var Directive
- */
- private $directive;
-
- /**
- * @var FieldArgument
- */
- private $argument;
-
- /**
- * @var mixed
- */
- private $enumValue;
-
- /**
- * TypeInfo constructor.
- * @param Schema $schema
- * @param Type|null $initialType
- */
- public function __construct(Schema $schema, $initialType = null)
- {
- $this->schema = $schema;
- $this->typeStack = [];
- $this->parentTypeStack = [];
- $this->inputTypeStack = [];
- $this->fieldDefStack = [];
- if ($initialType) {
- if (Type::isInputType($initialType)) {
- $this->inputTypeStack[] = $initialType;
- }
- if (Type::isCompositeType($initialType)) {
- $this->parentTypeStack[] = $initialType;
- }
- if (Type::isOutputType($initialType)) {
- $this->typeStack[] = $initialType;
- }
- }
- }
-
- /**
- * @return Type
- */
- function getType()
- {
- if (!empty($this->typeStack)) {
- return $this->typeStack[count($this->typeStack) - 1];
- }
return null;
}
/**
- * @return Type
+ * @param NamedTypeNode|ListTypeNode|NonNullTypeNode $inputTypeNode
+ * @return Type|null
+ * @throws InvariantViolation
*/
- function getParentType()
+ public static function typeFromAST(Schema $schema, $inputTypeNode)
{
- if (!empty($this->parentTypeStack)) {
- return $this->parentTypeStack[count($this->parentTypeStack) - 1];
+ return AST::typeFromAST($schema, $inputTypeNode);
+ }
+
+ /**
+ * @return Directive|null
+ */
+ public function getDirective()
+ {
+ return $this->directive;
+ }
+
+ /**
+ * @return FieldDefinition
+ */
+ public function getFieldDef()
+ {
+ if (! empty($this->fieldDefStack)) {
+ return $this->fieldDefStack[count($this->fieldDefStack) - 1];
}
+
return null;
}
/**
* @return InputType
*/
- function getInputType()
+ public function getInputType()
{
- if (!empty($this->inputTypeStack)) {
+ if (! empty($this->inputTypeStack)) {
return $this->inputTypeStack[count($this->inputTypeStack) - 1];
}
+
return null;
}
- /**
- * @return InputType|null
- */
- public function getParentInputType()
- {
- $inputTypeStackLength = count($this->inputTypeStack);
- if ($inputTypeStackLength > 1) {
- return $this->inputTypeStack[$inputTypeStackLength - 2];
- }
- }
-
- /**
- * @return FieldDefinition
- */
- function getFieldDef()
- {
- if (!empty($this->fieldDefStack)) {
- return $this->fieldDefStack[count($this->fieldDefStack) - 1];
- }
- return null;
- }
-
- /**
- * @return Directive|null
- */
- function getDirective()
- {
- return $this->directive;
- }
-
- /**
- * @return FieldArgument|null
- */
- function getArgument()
- {
- return $this->argument;
- }
-
- /**
- * @return mixed
- */
- function getEnumValue()
- {
- return $this->enumValue;
- }
-
- /**
- * @param Node $node
- */
- function enter(Node $node)
- {
- $schema = $this->schema;
-
- // Note: many of the types below are explicitly typed as "mixed" to drop
- // any assumptions of a valid schema to ensure runtime types are properly
- // checked before continuing since TypeInfo is used as part of validation
- // which occurs before guarantees of schema and document validity.
- switch ($node->kind) {
- case NodeKind::SELECTION_SET:
- $namedType = Type::getNamedType($this->getType());
- $this->parentTypeStack[] = Type::isCompositeType($namedType) ? $namedType : null;
- break;
-
- case NodeKind::FIELD:
- $parentType = $this->getParentType();
- $fieldDef = null;
- if ($parentType) {
- $fieldDef = self::getFieldDefinition($schema, $parentType, $node);
- }
- $fieldType = null;
- if ($fieldDef) {
- $fieldType = $fieldDef->getType();
- }
- $this->fieldDefStack[] = $fieldDef;
- $this->typeStack[] = Type::isOutputType($fieldType) ? $fieldType : null;
- break;
-
- case NodeKind::DIRECTIVE:
- $this->directive = $schema->getDirective($node->name->value);
- break;
-
- case NodeKind::OPERATION_DEFINITION:
- $type = null;
- if ($node->operation === 'query') {
- $type = $schema->getQueryType();
- } else if ($node->operation === 'mutation') {
- $type = $schema->getMutationType();
- } else if ($node->operation === 'subscription') {
- $type = $schema->getSubscriptionType();
- }
- $this->typeStack[] = Type::isOutputType($type) ? $type : null;
- break;
-
- case NodeKind::INLINE_FRAGMENT:
- case NodeKind::FRAGMENT_DEFINITION:
- $typeConditionNode = $node->typeCondition;
- $outputType = $typeConditionNode ? self::typeFromAST($schema, $typeConditionNode) : Type::getNamedType($this->getType());
- $this->typeStack[] = Type::isOutputType($outputType) ? $outputType : null;
- break;
-
- case NodeKind::VARIABLE_DEFINITION:
- $inputType = self::typeFromAST($schema, $node->type);
- $this->inputTypeStack[] = Type::isInputType($inputType) ? $inputType : null; // push
- break;
-
- case NodeKind::ARGUMENT:
- $fieldOrDirective = $this->getDirective() ?: $this->getFieldDef();
- $argDef = $argType = null;
- if ($fieldOrDirective) {
- $argDef = Utils::find($fieldOrDirective->args, function($arg) use ($node) {return $arg->name === $node->name->value;});
- if ($argDef) {
- $argType = $argDef->getType();
- }
- }
- $this->argument = $argDef;
- $this->inputTypeStack[] = Type::isInputType($argType) ? $argType : null;
- break;
-
- case NodeKind::LST:
- $listType = Type::getNullableType($this->getInputType());
- $itemType = $listType instanceof ListOfType
- ? $listType->getWrappedType()
- : $listType;
- $this->inputTypeStack[] = Type::isInputType($itemType) ? $itemType : null;
- break;
-
- case NodeKind::OBJECT_FIELD:
- $objectType = Type::getNamedType($this->getInputType());
- $fieldType = null;
- $inputFieldType = null;
- if ($objectType instanceof InputObjectType) {
- $tmp = $objectType->getFields();
- $inputField = isset($tmp[$node->name->value]) ? $tmp[$node->name->value] : null;
- $inputFieldType = $inputField ? $inputField->getType() : null;
- }
- $this->inputTypeStack[] = Type::isInputType($inputFieldType) ? $inputFieldType : null;
- break;
-
- case NodeKind::ENUM:
- $enumType = Type::getNamedType($this->getInputType());
- $enumValue = null;
- if ($enumType instanceof EnumType) {
- $enumValue = $enumType->getValue($node->value);
- }
- $this->enumValue = $enumValue;
- break;
- }
- }
-
- /**
- * @param Node $node
- */
- function leave(Node $node)
+ public function leave(Node $node)
{
switch ($node->kind) {
case NodeKind::SELECTION_SET:
diff --git a/src/Utils/Utils.php b/src/Utils/Utils.php
index 1d9c0f4..a4f5884 100644
--- a/src/Utils/Utils.php
+++ b/src/Utils/Utils.php
@@ -1,4 +1,7 @@
$value) {
- if (!property_exists($obj, $key)) {
+ if (! property_exists($obj, $key)) {
$cls = get_class($obj);
Warning::warn(
- "Trying to set non-existing property '$key' on class '$cls'",
+ sprintf("Trying to set non-existing property '%s' on class '%s'", $key, $cls),
Warning::WARNING_ASSIGN
);
}
$obj->{$key} = $value;
}
+
return $obj;
}
/**
- * @param array|Traversable $traversable
- * @param callable $predicate
+ * @param mixed|Traversable $traversable
* @return mixed|null
*/
public static function find($traversable, callable $predicate)
{
- self::invariant(is_array($traversable) || $traversable instanceof \Traversable, __METHOD__ . ' expects array or Traversable');
+ self::invariant(
+ is_array($traversable) || $traversable instanceof \Traversable,
+ __METHOD__ . ' expects array or Traversable'
+ );
foreach ($traversable as $key => $value) {
if ($predicate($value, $key)) {
return $value;
}
}
+
return null;
}
/**
- * @param $traversable
- * @param callable $predicate
- * @return array
+ * @param mixed|Traversable $traversable
+ * @return mixed[]
* @throws \Exception
*/
public static function filter($traversable, callable $predicate)
{
- self::invariant(is_array($traversable) || $traversable instanceof \Traversable, __METHOD__ . ' expects array or Traversable');
+ self::invariant(
+ is_array($traversable) || $traversable instanceof \Traversable,
+ __METHOD__ . ' expects array or Traversable'
+ );
$result = [];
- $assoc = false;
+ $assoc = false;
foreach ($traversable as $key => $value) {
- if (!$assoc && !is_int($key)) {
+ if (! $assoc && ! is_int($key)) {
$assoc = true;
}
- if ($predicate($value, $key)) {
- $result[$key] = $value;
+ if (! $predicate($value, $key)) {
+ continue;
}
+
+ $result[$key] = $value;
}
return $assoc ? $result : array_values($result);
}
/**
- * @param array|\Traversable $traversable
- * @param callable $fn function($value, $key) => $newValue
- * @return array
+ * @param mixed|\Traversable $traversable
+ * @return int[][]
* @throws \Exception
*/
public static function map($traversable, callable $fn)
{
- self::invariant(is_array($traversable) || $traversable instanceof \Traversable, __METHOD__ . ' expects array or Traversable');
+ self::invariant(
+ is_array($traversable) || $traversable instanceof \Traversable,
+ __METHOD__ . ' expects array or Traversable'
+ );
$map = [];
foreach ($traversable as $key => $value) {
$map[$key] = $fn($value, $key);
}
+
return $map;
}
/**
- * @param $traversable
- * @param callable $fn
- * @return array
+ * @param mixed|Traversable $traversable
+ * @return mixed[]
* @throws \Exception
*/
public static function mapKeyValue($traversable, callable $fn)
{
- self::invariant(is_array($traversable) || $traversable instanceof \Traversable, __METHOD__ . ' expects array or Traversable');
+ self::invariant(
+ is_array($traversable) || $traversable instanceof \Traversable,
+ __METHOD__ . ' expects array or Traversable'
+ );
$map = [];
foreach ($traversable as $key => $value) {
list($newKey, $newValue) = $fn($value, $key);
$map[$newKey] = $newValue;
}
+
return $map;
}
/**
- * @param $traversable
- * @param callable $keyFn function($value, $key) => $newKey
- * @return array
+ * @param mixed|Traversable $traversable
+ * @return mixed[]
* @throws \Exception
*/
public static function keyMap($traversable, callable $keyFn)
{
- self::invariant(is_array($traversable) || $traversable instanceof \Traversable, __METHOD__ . ' expects array or Traversable');
+ self::invariant(
+ is_array($traversable) || $traversable instanceof \Traversable,
+ __METHOD__ . ' expects array or Traversable'
+ );
$map = [];
foreach ($traversable as $key => $value) {
$newKey = $keyFn($value, $key);
- if (is_scalar($newKey)) {
- $map[$newKey] = $value;
+ if (! is_scalar($newKey)) {
+ continue;
}
+
+ $map[$newKey] = $value;
}
+
return $map;
}
- /**
- * @param $traversable
- * @param callable $fn
- */
public static function each($traversable, callable $fn)
{
- self::invariant(is_array($traversable) || $traversable instanceof \Traversable, __METHOD__ . ' expects array or Traversable');
+ self::invariant(
+ is_array($traversable) || $traversable instanceof \Traversable,
+ __METHOD__ . ' expects array or Traversable'
+ );
foreach ($traversable as $key => $item) {
$fn($item, $key);
@@ -177,13 +236,15 @@ class Utils
*
* $keyFn is also allowed to return array of keys. Then value will be added to all arrays with given keys
*
- * @param $traversable
- * @param callable $keyFn function($value, $key) => $newKey(s)
- * @return array
+ * @param mixed[]|Traversable $traversable
+ * @return mixed[]
*/
public static function groupBy($traversable, callable $keyFn)
{
- self::invariant(is_array($traversable) || $traversable instanceof \Traversable, __METHOD__ . ' expects array or Traversable');
+ self::invariant(
+ is_array($traversable) || $traversable instanceof \Traversable,
+ __METHOD__ . ' expects array or Traversable'
+ );
$grouped = [];
foreach ($traversable as $key => $value) {
@@ -197,10 +258,8 @@ class Utils
}
/**
- * @param array|Traversable $traversable
- * @param callable $keyFn
- * @param callable $valFn
- * @return array
+ * @param mixed[]|Traversable $traversable
+ * @return mixed[][]
*/
public static function keyValMap($traversable, callable $keyFn, callable $valFn)
{
@@ -208,38 +267,36 @@ class Utils
foreach ($traversable as $item) {
$map[$keyFn($item)] = $valFn($item);
}
+
return $map;
}
/**
- * @param $traversable
- * @param callable $predicate
+ * @param mixed[] $traversable
* @return bool
*/
public static function every($traversable, callable $predicate)
{
foreach ($traversable as $key => $value) {
- if (!$predicate($value, $key)) {
+ if (! $predicate($value, $key)) {
return false;
}
}
+
return true;
}
/**
- * @param $test
+ * @param bool $test
* @param string $message
- * @param mixed $sprintfParam1
- * @param mixed $sprintfParam2 ...
- * @throws Error
*/
public static function invariant($test, $message = '')
{
- if (!$test) {
+ if (! $test) {
if (func_num_args() > 2) {
$args = func_get_args();
array_shift($args);
- $message = call_user_func_array('sprintf', $args);
+ $message = sprintf(...$args);
}
// TODO switch to Error here
throw new InvariantViolation($message);
@@ -247,7 +304,7 @@ class Utils
}
/**
- * @param $var
+ * @param Type|mixed $var
* @return string
*/
public static function getVariableType($var)
@@ -257,8 +314,10 @@ class Utils
if ($var instanceof WrappingType) {
$var = $var->getWrappedType(true);
}
+
return $var->name;
}
+
return is_object($var) ? get_class($var) : gettype($var);
}
@@ -274,29 +333,30 @@ class Utils
if (is_array($var)) {
return json_encode($var);
}
- if ('' === $var) {
+ if ($var === '') {
return '(empty string)';
}
- if (null === $var) {
+ if ($var === null) {
return 'null';
}
- if (false === $var) {
+ if ($var === false) {
return 'false';
}
- if (true === $var) {
+ if ($var === true) {
return 'true';
}
if (is_string($var)) {
- return "\"$var\"";
+ return sprintf('"%s"', $var);
}
if (is_scalar($var)) {
return (string) $var;
}
+
return gettype($var);
}
/**
- * @param $var
+ * @param Type|mixed $var
* @return string
*/
public static function printSafe($var)
@@ -307,23 +367,23 @@ class Utils
if (is_object($var)) {
if (method_exists($var, '__toString')) {
return (string) $var;
- } else {
- return 'instance of ' . get_class($var);
}
+
+ return 'instance of ' . get_class($var);
}
if (is_array($var)) {
return json_encode($var);
}
- if ('' === $var) {
+ if ($var === '') {
return '(empty string)';
}
- if (null === $var) {
+ if ($var === null) {
return 'null';
}
- if (false === $var) {
+ if ($var === false) {
return 'false';
}
- if (true === $var) {
+ if ($var === true) {
return 'true';
}
if (is_string($var)) {
@@ -332,6 +392,7 @@ class Utils
if (is_scalar($var)) {
return (string) $var;
}
+
return gettype($var);
}
@@ -348,10 +409,10 @@ class Utils
return chr($ord);
}
if ($encoding === 'UCS-4BE') {
- return pack("N", $ord);
- } else {
- return mb_convert_encoding(self::chr($ord, 'UCS-4BE'), $encoding, 'UCS-4BE');
+ return pack('N', $ord);
}
+
+ return mb_convert_encoding(self::chr($ord, 'UCS-4BE'), $encoding, 'UCS-4BE');
}
/**
@@ -363,44 +424,46 @@ class Utils
*/
public static function ord($char, $encoding = 'UTF-8')
{
- if (!$char && '0' !== $char) {
+ if (! $char && $char !== '0') {
return 0;
}
- if (!isset($char[1])) {
+ if (! isset($char[1])) {
return ord($char);
}
if ($encoding !== 'UCS-4BE') {
$char = mb_convert_encoding($char, 'UCS-4BE', $encoding);
}
- list(, $ord) = unpack('N', $char);
- return $ord;
+
+ return unpack('N', $char)[1];
}
/**
* Returns UTF-8 char code at given $positing of the $string
*
- * @param $string
- * @param $position
+ * @param string $string
+ * @param int $position
* @return mixed
*/
public static function charCodeAt($string, $position)
{
$char = mb_substr($string, $position, 1, 'UTF-8');
+
return self::ord($char);
}
/**
- * @param $code
+ * @param int|null $code
* @return string
*/
public static function printCharCode($code)
{
- if (null === $code) {
+ if ($code === null) {
return '';
}
+
return $code < 0x007F
// Trust JSON for ASCII.
- ? json_encode(Utils::chr($code))
+ ? json_encode(self::chr($code))
// Otherwise print the escaped form.
: '"\\u' . dechex($code) . '"';
}
@@ -408,7 +471,7 @@ class Utils
/**
* Upholds the spec rules about naming.
*
- * @param $name
+ * @param string $name
* @throws Error
*/
public static function assertValidName($name)
@@ -422,25 +485,25 @@ class Utils
/**
* Returns an Error if a name is invalid.
*
- * @param string $name
+ * @param string $name
* @param Node|null $node
* @return Error|null
*/
public static function isValidNameError($name, $node = null)
{
- Utils::invariant(is_string($name), 'Expected string');
+ self::invariant(is_string($name), 'Expected string');
if (isset($name[1]) && $name[0] === '_' && $name[1] === '_') {
return new Error(
- "Name \"{$name}\" must not begin with \"__\", which is reserved by " .
- "GraphQL introspection.",
+ sprintf('Name "%s" must not begin with "__", which is reserved by ', $name) .
+ 'GraphQL introspection.',
$node
);
}
- if (!preg_match('/^[_a-zA-Z][_a-zA-Z0-9]*$/', $name)) {
+ if (! preg_match('/^[_a-zA-Z][_a-zA-Z0-9]*$/', $name)) {
return new Error(
- "Names must match /^[_a-zA-Z][_a-zA-Z0-9]*\$/ but \"{$name}\" does not.",
+ sprintf('Names must match /^[_a-zA-Z][_a-zA-Z0-9]*$/ but "%s" does not.', $name),
$node
);
}
@@ -452,13 +515,12 @@ class Utils
* Wraps original closure with PHP error handling (using set_error_handler).
* Resulting closure will collect all PHP errors that occur during the call in $errors array.
*
- * @param callable $fn
* @param \ErrorException[] $errors
* @return \Closure
*/
public static function withErrorHandling(callable $fn, array &$errors)
{
- return function() use ($fn, &$errors) {
+ return function () use ($fn, &$errors) {
// Catch custom errors (to report them in query results)
set_error_handler(function ($severity, $message, $file, $line) use (&$errors) {
$errors[] = new \ErrorException($message, 0, $severity, $file, $line);
@@ -472,25 +534,34 @@ class Utils
};
}
-
/**
* @param string[] $items
* @return string
*/
public static function quotedOrList(array $items)
{
- $items = array_map(function($item) { return "\"$item\""; }, $items);
+ $items = array_map(
+ function ($item) {
+ return sprintf('"%s"', $item);
+ },
+ $items
+ );
+
return self::orList($items);
}
+ /**
+ * @param string[] $items
+ * @return string
+ */
public static function orList(array $items)
{
- if (!$items) {
+ if (count($items) === 0) {
throw new \LogicException('items must not need to be empty.');
}
- $selected = array_slice($items, 0, 5);
+ $selected = array_slice($items, 0, 5);
$selectedLength = count($selected);
- $firstSelected = $selected[0];
+ $firstSelected = $selected[0];
if ($selectedLength === 1) {
return $firstSelected;
@@ -499,7 +570,7 @@ class Utils
return array_reduce(
range(1, $selectedLength - 1),
function ($list, $index) use ($selected, $selectedLength) {
- return $list.
+ return $list .
($selectedLength > 2 ? ', ' : ' ') .
($index === $selectedLength - 1 ? 'or ' : '') .
$selected[$index];
@@ -515,24 +586,28 @@ class Utils
* Includes a custom alteration from Damerau-Levenshtein to treat case changes
* as a single edit which helps identify mis-cased values with an edit distance
* of 1
- * @param string $input
- * @param array $options
+ * @param string $input
+ * @param string[] $options
* @return string[]
*/
public static function suggestionList($input, array $options)
{
$optionsByDistance = [];
- $inputThreshold = mb_strlen($input) / 2;
+ $inputThreshold = mb_strlen($input) / 2;
foreach ($options as $option) {
- $distance = $input === $option
- ? 0
- : (strtolower($input) === strtolower($option)
+ if ($input === $option) {
+ $distance = 0;
+ } else {
+ $distance = (strtolower($input) === strtolower($option)
? 1
: levenshtein($input, $option));
- $threshold = max($inputThreshold, mb_strlen($option) / 2, 1);
- if ($distance <= $threshold) {
- $optionsByDistance[$option] = $distance;
}
+ $threshold = max($inputThreshold, mb_strlen($option) / 2, 1);
+ if ($distance > $threshold) {
+ continue;
+ }
+
+ $optionsByDistance[$option] = $distance;
}
asort($optionsByDistance);
diff --git a/src/Utils/Value.php b/src/Utils/Value.php
index bf01018..9541291 100644
--- a/src/Utils/Value.php
+++ b/src/Utils/Value.php
@@ -1,4 +1,7 @@
getWrappedType(), $blameNode, $path);
}
- if (null === $value) {
+ if ($value === null) {
// Explicitly return the value null.
return self::ofValue(null);
}
@@ -50,7 +64,7 @@ class Value
} catch (\Exception $error) {
return self::ofErrors([
self::coercionError(
- "Expected type {$type->name}",
+ sprintf('Expected type %s', $type->name),
$blameNode,
$path,
$error->getMessage(),
@@ -60,7 +74,7 @@ class Value
} catch (\Throwable $error) {
return self::ofErrors([
self::coercionError(
- "Expected type {$type->name}",
+ sprintf('Expected type %s', $type->name),
$blameNode,
$path,
$error->getMessage(),
@@ -80,15 +94,21 @@ class Value
$suggestions = Utils::suggestionList(
Utils::printSafe($value),
- array_map(function($enumValue) { return $enumValue->name; }, $type->getValues())
+ array_map(
+ function ($enumValue) {
+ return $enumValue->name;
+ },
+ $type->getValues()
+ )
);
+
$didYouMean = $suggestions
- ? "did you mean " . Utils::orList($suggestions) . "?"
+ ? 'did you mean ' . Utils::orList($suggestions) . '?'
: null;
return self::ofErrors([
self::coercionError(
- "Expected type {$type->name}",
+ sprintf('Expected type %s', $type->name),
$blameNode,
$path,
$didYouMean
@@ -99,7 +119,7 @@ class Value
if ($type instanceof ListOfType) {
$itemType = $type->getWrappedType();
if (is_array($value) || $value instanceof \Traversable) {
- $errors = [];
+ $errors = [];
$coercedValue = [];
foreach ($value as $index => $itemValue) {
$coercedItem = self::coerceValue(
@@ -114,44 +134,32 @@ class Value
$coercedValue[] = $coercedItem['value'];
}
}
+
return $errors ? self::ofErrors($errors) : self::ofValue($coercedValue);
}
// Lists accept a non-list value as a list of one.
$coercedItem = self::coerceValue($value, $itemType, $blameNode);
+
return $coercedItem['errors'] ? $coercedItem : self::ofValue([$coercedItem['value']]);
}
if ($type instanceof InputObjectType) {
- if (!is_object($value) && !is_array($value) && !$value instanceof \Traversable) {
+ if (! is_object($value) && ! is_array($value) && ! $value instanceof \Traversable) {
return self::ofErrors([
self::coercionError(
- "Expected type {$type->name} to be an object",
+ sprintf('Expected type %s to be an object', $type->name),
$blameNode,
$path
),
]);
}
- $errors = [];
+ $errors = [];
$coercedValue = [];
- $fields = $type->getFields();
+ $fields = $type->getFields();
foreach ($fields as $fieldName => $field) {
- if (!array_key_exists($fieldName, $value)) {
- if ($field->defaultValueExists()) {
- $coercedValue[$fieldName] = $field->defaultValue;
- } else if ($field->getType() instanceof NonNull) {
- $fieldPath = self::printPath(self::atPath($path, $fieldName));
- $errors = self::add(
- $errors,
- self::coercionError(
- "Field {$fieldPath} of required " .
- "type {$field->type} was not provided",
- $blameNode
- )
- );
- }
- } else {
- $fieldValue = $value[$fieldName];
+ if (array_key_exists($fieldName, $value)) {
+ $fieldValue = $value[$fieldName];
$coercedField = self::coerceValue(
$fieldValue,
$field->getType(),
@@ -163,63 +171,76 @@ class Value
} else {
$coercedValue[$fieldName] = $coercedField['value'];
}
- }
- }
-
- // Ensure every provided field is defined.
- foreach ($value as $fieldName => $field) {
- if (!array_key_exists($fieldName, $fields)) {
- $suggestions = Utils::suggestionList(
- $fieldName,
- array_keys($fields)
- );
- $didYouMean = $suggestions
- ? "did you mean " . Utils::orList($suggestions) . "?"
- : null;
- $errors = self::add(
+ } elseif ($field->defaultValueExists()) {
+ $coercedValue[$fieldName] = $field->defaultValue;
+ } elseif ($field->getType() instanceof NonNull) {
+ $fieldPath = self::printPath(self::atPath($path, $fieldName));
+ $errors = self::add(
$errors,
self::coercionError(
- "Field \"{$fieldName}\" is not defined by type {$type->name}",
- $blameNode,
- $path,
- $didYouMean
+ sprintf(
+ 'Field %s of required type %s was not provided',
+ $fieldPath,
+ $field->type->toString()
+ ),
+ $blameNode
)
);
}
}
+ // Ensure every provided field is defined.
+ foreach ($value as $fieldName => $field) {
+ if (array_key_exists($fieldName, $fields)) {
+ continue;
+ }
+
+ $suggestions = Utils::suggestionList(
+ $fieldName,
+ array_keys($fields)
+ );
+ $didYouMean = $suggestions
+ ? 'did you mean ' . Utils::orList($suggestions) . '?'
+ : null;
+ $errors = self::add(
+ $errors,
+ self::coercionError(
+ sprintf('Field "%s" is not defined by type %s', $fieldName, $type->name),
+ $blameNode,
+ $path,
+ $didYouMean
+ )
+ );
+ }
+
return $errors ? self::ofErrors($errors) : self::ofValue($coercedValue);
}
- throw new Error("Unexpected type {$type}");
+ throw new Error(sprintf('Unexpected type %s', $type->name));
}
- private static function ofValue($value) {
- return ['errors' => null, 'value' => $value];
- }
-
- private static function ofErrors($errors) {
+ private static function ofErrors($errors)
+ {
return ['errors' => $errors, 'value' => Utils::undefined()];
}
- private static function add($errors, $moreErrors) {
- return array_merge($errors, is_array($moreErrors) ? $moreErrors : [$moreErrors]);
- }
-
- private static function atPath($prev, $key) {
- return ['prev' => $prev, 'key' => $key];
- }
-
/**
- * @param string $message
- * @param Node $blameNode
- * @param array|null $path
- * @param string $subMessage
+ * @param string $message
+ * @param Node $blameNode
+ * @param mixed[]|null $path
+ * @param string $subMessage
* @param \Exception|\Throwable|null $originalError
* @return Error
*/
- private static function coercionError($message, $blameNode, array $path = null, $subMessage = null, $originalError = null) {
+ private static function coercionError(
+ $message,
+ $blameNode,
+ ?array $path = null,
+ $subMessage = null,
+ $originalError = null
+ ) {
$pathStr = self::printPath($path);
+
// Return a GraphQLError instance
return new Error(
$message .
@@ -236,19 +257,50 @@ class Value
/**
* Build a string describing the path into the value where the error was found
*
- * @param $path
+ * @param mixed[]|null $path
* @return string
*/
- private static function printPath(array $path = null) {
- $pathStr = '';
+ private static function printPath(?array $path = null)
+ {
+ $pathStr = '';
$currentPath = $path;
- while($currentPath) {
- $pathStr =
+ while ($currentPath) {
+ $pathStr =
(is_string($currentPath['key'])
? '.' . $currentPath['key']
: '[' . $currentPath['key'] . ']') . $pathStr;
$currentPath = $currentPath['prev'];
}
+
return $pathStr ? 'value' . $pathStr : '';
}
+
+ /**
+ * @param mixed $value
+ * @return (mixed|null)[]
+ */
+ private static function ofValue($value)
+ {
+ return ['errors' => null, 'value' => $value];
+ }
+
+ /**
+ * @param mixed|null $prev
+ * @param mixed|null $key
+ * @return (mixed|null)[]
+ */
+ private static function atPath($prev, $key)
+ {
+ return ['prev' => $prev, 'key' => $key];
+ }
+
+ /**
+ * @param Error[] $errors
+ * @param Error|Error[] $moreErrors
+ * @return Error[]
+ */
+ private static function add($errors, $moreErrors)
+ {
+ return array_merge($errors, is_array($moreErrors) ? $moreErrors : [$moreErrors]);
+ }
}
diff --git a/tests/Utils/FindBreakingChangesTest.php b/tests/Utils/BreakingChangesFinderTest.php
similarity index 84%
rename from tests/Utils/FindBreakingChangesTest.php
rename to tests/Utils/BreakingChangesFinderTest.php
index fb8ae57..978733a 100644
--- a/tests/Utils/FindBreakingChangesTest.php
+++ b/tests/Utils/BreakingChangesFinderTest.php
@@ -1,4 +1,5 @@
FindBreakingChanges::BREAKING_CHANGE_TYPE_REMOVED,
+ 'type' => BreakingChangesFinder::BREAKING_CHANGE_TYPE_REMOVED,
'description' => 'Type1 was removed.'
]
];
$this->assertEquals(
$expected,
- FindBreakingChanges::findRemovedTypes($oldSchema, $newSchema)
+ BreakingChangesFinder::findRemovedTypes($oldSchema, $newSchema)
);
- $this->assertEquals([], FindBreakingChanges::findRemovedTypes($oldSchema, $oldSchema));
+ $this->assertEquals([], BreakingChangesFinder::findRemovedTypes($oldSchema, $oldSchema));
}
/**
@@ -109,14 +110,14 @@ class FindBreakingChangesTest extends TestCase
$expected = [
[
- 'type' => FindBreakingChanges::BREAKING_CHANGE_TYPE_CHANGED_KIND,
+ 'type' => BreakingChangesFinder::BREAKING_CHANGE_TYPE_CHANGED_KIND,
'description' => 'Type1 changed from an Interface type to a Union type.'
]
];
$this->assertEquals(
$expected,
- FindBreakingChanges::findTypesThatChangedKind($oldSchema, $newSchema)
+ BreakingChangesFinder::findTypesThatChangedKind($oldSchema, $newSchema)
);
}
@@ -208,60 +209,60 @@ class FindBreakingChangesTest extends TestCase
$expectedFieldChanges = [
[
- 'type' => FindBreakingChanges::BREAKING_CHANGE_FIELD_REMOVED,
+ 'type' => BreakingChangesFinder::BREAKING_CHANGE_FIELD_REMOVED,
'description' => 'Type1.field2 was removed.',
],
[
- 'type' => FindBreakingChanges::BREAKING_CHANGE_FIELD_CHANGED_KIND,
+ 'type' => BreakingChangesFinder::BREAKING_CHANGE_FIELD_CHANGED_KIND,
'description' => 'Type1.field3 changed type from String to Boolean.',
],
[
- 'type' => FindBreakingChanges::BREAKING_CHANGE_FIELD_CHANGED_KIND,
+ 'type' => BreakingChangesFinder::BREAKING_CHANGE_FIELD_CHANGED_KIND,
'description' => 'Type1.field4 changed type from TypeA to TypeB.',
],
[
- 'type' => FindBreakingChanges::BREAKING_CHANGE_FIELD_CHANGED_KIND,
+ 'type' => BreakingChangesFinder::BREAKING_CHANGE_FIELD_CHANGED_KIND,
'description' => 'Type1.field6 changed type from String to [String].',
],
[
- 'type' => FindBreakingChanges::BREAKING_CHANGE_FIELD_CHANGED_KIND,
+ 'type' => BreakingChangesFinder::BREAKING_CHANGE_FIELD_CHANGED_KIND,
'description' => 'Type1.field7 changed type from [String] to String.',
],
[
- 'type' => FindBreakingChanges::BREAKING_CHANGE_FIELD_CHANGED_KIND,
+ 'type' => BreakingChangesFinder::BREAKING_CHANGE_FIELD_CHANGED_KIND,
'description' => 'Type1.field9 changed type from Int! to Int.',
],
[
- 'type' => FindBreakingChanges::BREAKING_CHANGE_FIELD_CHANGED_KIND,
+ 'type' => BreakingChangesFinder::BREAKING_CHANGE_FIELD_CHANGED_KIND,
'description' => 'Type1.field10 changed type from [Int]! to [Int].',
],
[
- 'type' => FindBreakingChanges::BREAKING_CHANGE_FIELD_CHANGED_KIND,
+ 'type' => BreakingChangesFinder::BREAKING_CHANGE_FIELD_CHANGED_KIND,
'description' => 'Type1.field11 changed type from Int to [Int]!.',
],
[
- 'type' => FindBreakingChanges::BREAKING_CHANGE_FIELD_CHANGED_KIND,
+ 'type' => BreakingChangesFinder::BREAKING_CHANGE_FIELD_CHANGED_KIND,
'description' => 'Type1.field13 changed type from [Int!] to [Int].',
],
[
- 'type' => FindBreakingChanges::BREAKING_CHANGE_FIELD_CHANGED_KIND,
+ 'type' => BreakingChangesFinder::BREAKING_CHANGE_FIELD_CHANGED_KIND,
'description' => 'Type1.field14 changed type from [Int] to [[Int]].',
],
[
- 'type' => FindBreakingChanges::BREAKING_CHANGE_FIELD_CHANGED_KIND,
+ 'type' => BreakingChangesFinder::BREAKING_CHANGE_FIELD_CHANGED_KIND,
'description' => 'Type1.field15 changed type from [[Int]] to [Int].',
],
[
- 'type' => FindBreakingChanges::BREAKING_CHANGE_FIELD_CHANGED_KIND,
+ 'type' => BreakingChangesFinder::BREAKING_CHANGE_FIELD_CHANGED_KIND,
'description' => 'Type1.field16 changed type from Int! to [Int]!.',
],
[
- 'type' => FindBreakingChanges::BREAKING_CHANGE_FIELD_CHANGED_KIND,
+ 'type' => BreakingChangesFinder::BREAKING_CHANGE_FIELD_CHANGED_KIND,
'description' => 'Type1.field18 changed type from [[Int!]!] to [[Int!]].',
],
];
- $this->assertEquals($expectedFieldChanges, FindBreakingChanges::findFieldsThatChangedTypeOnObjectOrInterfaceTypes($oldSchema, $newSchema));
+ $this->assertEquals($expectedFieldChanges, BreakingChangesFinder::findFieldsThatChangedTypeOnObjectOrInterfaceTypes($oldSchema, $newSchema));
}
/**
@@ -380,52 +381,52 @@ class FindBreakingChangesTest extends TestCase
$expectedFieldChanges = [
[
- 'type' => FindBreakingChanges::BREAKING_CHANGE_FIELD_CHANGED_KIND,
+ 'type' => BreakingChangesFinder::BREAKING_CHANGE_FIELD_CHANGED_KIND,
'description' => 'InputType1.field1 changed type from String to Int.',
],
[
- 'type' => FindBreakingChanges::BREAKING_CHANGE_FIELD_REMOVED,
+ 'type' => BreakingChangesFinder::BREAKING_CHANGE_FIELD_REMOVED,
'description' => 'InputType1.field2 was removed.',
],
[
- 'type' => FindBreakingChanges::BREAKING_CHANGE_FIELD_CHANGED_KIND,
+ 'type' => BreakingChangesFinder::BREAKING_CHANGE_FIELD_CHANGED_KIND,
'description' => 'InputType1.field3 changed type from [String] to String.',
],
[
- 'type' => FindBreakingChanges::BREAKING_CHANGE_FIELD_CHANGED_KIND,
+ 'type' => BreakingChangesFinder::BREAKING_CHANGE_FIELD_CHANGED_KIND,
'description' => 'InputType1.field5 changed type from String to String!.',
],
[
- 'type' => FindBreakingChanges::BREAKING_CHANGE_FIELD_CHANGED_KIND,
+ 'type' => BreakingChangesFinder::BREAKING_CHANGE_FIELD_CHANGED_KIND,
'description' => 'InputType1.field6 changed type from [Int] to [Int]!.',
],
[
- 'type' => FindBreakingChanges::BREAKING_CHANGE_FIELD_CHANGED_KIND,
+ 'type' => BreakingChangesFinder::BREAKING_CHANGE_FIELD_CHANGED_KIND,
'description' => 'InputType1.field8 changed type from Int to [Int]!.',
],
[
- 'type' => FindBreakingChanges::BREAKING_CHANGE_FIELD_CHANGED_KIND,
+ 'type' => BreakingChangesFinder::BREAKING_CHANGE_FIELD_CHANGED_KIND,
'description' => 'InputType1.field9 changed type from [Int] to [Int!].',
],
[
- 'type' => FindBreakingChanges::BREAKING_CHANGE_FIELD_CHANGED_KIND,
+ 'type' => BreakingChangesFinder::BREAKING_CHANGE_FIELD_CHANGED_KIND,
'description' => 'InputType1.field11 changed type from [Int] to [[Int]].',
],
[
- 'type' => FindBreakingChanges::BREAKING_CHANGE_FIELD_CHANGED_KIND,
+ 'type' => BreakingChangesFinder::BREAKING_CHANGE_FIELD_CHANGED_KIND,
'description' => 'InputType1.field12 changed type from [[Int]] to [Int].',
],
[
- 'type' => FindBreakingChanges::BREAKING_CHANGE_FIELD_CHANGED_KIND,
+ 'type' => BreakingChangesFinder::BREAKING_CHANGE_FIELD_CHANGED_KIND,
'description' => 'InputType1.field13 changed type from Int! to [Int]!.',
],
[
- 'type' => FindBreakingChanges::BREAKING_CHANGE_FIELD_CHANGED_KIND,
+ 'type' => BreakingChangesFinder::BREAKING_CHANGE_FIELD_CHANGED_KIND,
'description' => 'InputType1.field15 changed type from [[Int]!] to [[Int!]!].',
],
];
- $this->assertEquals($expectedFieldChanges, FindBreakingChanges::findFieldsThatChangedTypeOnInputObjectTypes($oldSchema, $newSchema)['breakingChanges']);
+ $this->assertEquals($expectedFieldChanges, BreakingChangesFinder::findFieldsThatChangedTypeOnInputObjectTypes($oldSchema, $newSchema)['breakingChanges']);
}
/**
@@ -461,14 +462,14 @@ class FindBreakingChangesTest extends TestCase
$expected = [
[
- 'type' => FindBreakingChanges::BREAKING_CHANGE_NON_NULL_INPUT_FIELD_ADDED,
+ 'type' => BreakingChangesFinder::BREAKING_CHANGE_NON_NULL_INPUT_FIELD_ADDED,
'description' => 'A non-null field requiredField on input type InputType1 was added.'
],
];
$this->assertEquals(
$expected,
- FindBreakingChanges::findFieldsThatChangedTypeOnInputObjectTypes($oldSchema, $newSchema)['breakingChanges']
+ BreakingChangesFinder::findFieldsThatChangedTypeOnInputObjectTypes($oldSchema, $newSchema)['breakingChanges']
);
}
@@ -524,14 +525,14 @@ class FindBreakingChangesTest extends TestCase
$expected = [
[
- 'type' => FindBreakingChanges::BREAKING_CHANGE_TYPE_REMOVED_FROM_UNION,
+ 'type' => BreakingChangesFinder::BREAKING_CHANGE_TYPE_REMOVED_FROM_UNION,
'description' => 'Type2 was removed from union type UnionType1.'
]
];
$this->assertEquals(
$expected,
- FindBreakingChanges::findTypesRemovedFromUnions($oldSchema, $newSchema)
+ BreakingChangesFinder::findTypesRemovedFromUnions($oldSchema, $newSchema)
);
}
@@ -569,14 +570,14 @@ class FindBreakingChangesTest extends TestCase
$expected = [
[
- 'type' => FindBreakingChanges::BREAKING_CHANGE_VALUE_REMOVED_FROM_ENUM,
+ 'type' => BreakingChangesFinder::BREAKING_CHANGE_VALUE_REMOVED_FROM_ENUM,
'description' => 'VALUE1 was removed from enum type EnumType1.'
]
];
$this->assertEquals(
$expected,
- FindBreakingChanges::findValuesRemovedFromEnums($oldSchema, $newSchema)
+ BreakingChangesFinder::findValuesRemovedFromEnums($oldSchema, $newSchema)
);
}
@@ -646,20 +647,20 @@ class FindBreakingChangesTest extends TestCase
$expectedChanges = [
[
- 'type' => FindBreakingChanges::BREAKING_CHANGE_ARG_REMOVED,
+ 'type' => BreakingChangesFinder::BREAKING_CHANGE_ARG_REMOVED,
'description' => 'Type1.field1 arg name was removed',
],
[
- 'type' => FindBreakingChanges::BREAKING_CHANGE_ARG_REMOVED,
+ 'type' => BreakingChangesFinder::BREAKING_CHANGE_ARG_REMOVED,
'description' => 'Interface1.field1 arg arg1 was removed',
],
[
- 'type' => FindBreakingChanges::BREAKING_CHANGE_ARG_REMOVED,
+ 'type' => BreakingChangesFinder::BREAKING_CHANGE_ARG_REMOVED,
'description' => 'Interface1.field1 arg objectArg was removed',
]
];
- $this->assertEquals($expectedChanges, FindBreakingChanges::findArgChanges($oldSchema, $newSchema)['breakingChanges']);
+ $this->assertEquals($expectedChanges, BreakingChangesFinder::findArgChanges($oldSchema, $newSchema)['breakingChanges']);
}
/**
@@ -731,56 +732,56 @@ class FindBreakingChangesTest extends TestCase
$expectedChanges = [
[
- 'type' => FindBreakingChanges::BREAKING_CHANGE_ARG_CHANGED_KIND,
+ 'type' => BreakingChangesFinder::BREAKING_CHANGE_ARG_CHANGED_KIND,
'description' => 'Type1.field1 arg arg1 has changed type from String to Int',
],
[
- 'type' => FindBreakingChanges::BREAKING_CHANGE_ARG_CHANGED_KIND,
+ 'type' => BreakingChangesFinder::BREAKING_CHANGE_ARG_CHANGED_KIND,
'description' => 'Type1.field1 arg arg2 has changed type from String to [String]'
],
[
- 'type' => FindBreakingChanges::BREAKING_CHANGE_ARG_CHANGED_KIND,
+ 'type' => BreakingChangesFinder::BREAKING_CHANGE_ARG_CHANGED_KIND,
'description' => 'Type1.field1 arg arg3 has changed type from [String] to String',
],
[
- 'type' => FindBreakingChanges::BREAKING_CHANGE_ARG_CHANGED_KIND,
+ 'type' => BreakingChangesFinder::BREAKING_CHANGE_ARG_CHANGED_KIND,
'description' => 'Type1.field1 arg arg4 has changed type from String to String!',
],
[
- 'type' => FindBreakingChanges::BREAKING_CHANGE_ARG_CHANGED_KIND,
+ 'type' => BreakingChangesFinder::BREAKING_CHANGE_ARG_CHANGED_KIND,
'description' => 'Type1.field1 arg arg5 has changed type from String! to Int',
],
[
- 'type' => FindBreakingChanges::BREAKING_CHANGE_ARG_CHANGED_KIND,
+ 'type' => BreakingChangesFinder::BREAKING_CHANGE_ARG_CHANGED_KIND,
'description' => 'Type1.field1 arg arg6 has changed type from String! to Int!',
],
[
- 'type' => FindBreakingChanges::BREAKING_CHANGE_ARG_CHANGED_KIND,
+ 'type' => BreakingChangesFinder::BREAKING_CHANGE_ARG_CHANGED_KIND,
'description' => 'Type1.field1 arg arg8 has changed type from Int to [Int]!',
],
[
- 'type' => FindBreakingChanges::BREAKING_CHANGE_ARG_CHANGED_KIND,
+ 'type' => BreakingChangesFinder::BREAKING_CHANGE_ARG_CHANGED_KIND,
'description' => 'Type1.field1 arg arg9 has changed type from [Int] to [Int!]',
],
[
- 'type' => FindBreakingChanges::BREAKING_CHANGE_ARG_CHANGED_KIND,
+ 'type' => BreakingChangesFinder::BREAKING_CHANGE_ARG_CHANGED_KIND,
'description' => 'Type1.field1 arg arg11 has changed type from [Int] to [[Int]]',
],
[
- 'type' => FindBreakingChanges::BREAKING_CHANGE_ARG_CHANGED_KIND,
+ 'type' => BreakingChangesFinder::BREAKING_CHANGE_ARG_CHANGED_KIND,
'description' => 'Type1.field1 arg arg12 has changed type from [[Int]] to [Int]',
],
[
- 'type' => FindBreakingChanges::BREAKING_CHANGE_ARG_CHANGED_KIND,
+ 'type' => BreakingChangesFinder::BREAKING_CHANGE_ARG_CHANGED_KIND,
'description' => 'Type1.field1 arg arg13 has changed type from Int! to [Int]!',
],
[
- 'type' => FindBreakingChanges::BREAKING_CHANGE_ARG_CHANGED_KIND,
+ 'type' => BreakingChangesFinder::BREAKING_CHANGE_ARG_CHANGED_KIND,
'description' => 'Type1.field1 arg arg15 has changed type from [[Int]!] to [[Int!]!]',
],
];
- $this->assertEquals($expectedChanges, FindBreakingChanges::findArgChanges($oldSchema, $newSchema)['breakingChanges']);
+ $this->assertEquals($expectedChanges, BreakingChangesFinder::findArgChanges($oldSchema, $newSchema)['breakingChanges']);
}
/**
@@ -821,14 +822,15 @@ class FindBreakingChangesTest extends TestCase
$expected = [
[
- 'type' => FindBreakingChanges::BREAKING_CHANGE_NON_NULL_ARG_ADDED,
+ 'type' => BreakingChangesFinder::BREAKING_CHANGE_NON_NULL_ARG_ADDED,
'description' => 'A non-null arg newRequiredArg on Type1.field1 was added'
]
];
$this->assertEquals(
$expected,
- FindBreakingChanges::findArgChanges($oldSchema, $newSchema)['breakingChanges']);
+ BreakingChangesFinder::findArgChanges($oldSchema, $newSchema)['breakingChanges']
+ );
}
/**
@@ -885,7 +887,7 @@ class FindBreakingChangesTest extends TestCase
'types' => [$newType],
]);
- $this->assertEquals([], FindBreakingChanges::findArgChanges($oldSchema, $newSchema)['breakingChanges']);
+ $this->assertEquals([], BreakingChangesFinder::findArgChanges($oldSchema, $newSchema)['breakingChanges']);
}
/**
@@ -925,7 +927,7 @@ class FindBreakingChangesTest extends TestCase
'types' => [$newType],
]);
- $this->assertEquals([], FindBreakingChanges::findArgChanges($oldSchema, $newSchema)['breakingChanges']);
+ $this->assertEquals([], BreakingChangesFinder::findArgChanges($oldSchema, $newSchema)['breakingChanges']);
}
/**
@@ -964,14 +966,15 @@ class FindBreakingChangesTest extends TestCase
$expected = [
[
- 'type' => FindBreakingChanges::BREAKING_CHANGE_INTERFACE_REMOVED_FROM_OBJECT,
+ 'type' => BreakingChangesFinder::BREAKING_CHANGE_INTERFACE_REMOVED_FROM_OBJECT,
'description' => 'Type1 no longer implements interface Interface1.'
],
];
$this->assertEquals(
$expected,
- FindBreakingChanges::findInterfacesRemovedFromObjectTypes($oldSchema, $newSchema));
+ BreakingChangesFinder::findInterfacesRemovedFromObjectTypes($oldSchema, $newSchema)
+ );
}
/**
@@ -1178,11 +1181,11 @@ class FindBreakingChangesTest extends TestCase
$expectedBreakingChanges = [
[
- 'type' => FindBreakingChanges::BREAKING_CHANGE_TYPE_REMOVED,
+ 'type' => BreakingChangesFinder::BREAKING_CHANGE_TYPE_REMOVED,
'description' => 'TypeThatGetsRemoved was removed.',
],
[
- 'type' => FindBreakingChanges::BREAKING_CHANGE_TYPE_REMOVED,
+ 'type' => BreakingChangesFinder::BREAKING_CHANGE_TYPE_REMOVED,
'description' => 'TypeInUnion2 was removed.',
],
/* This is reported in the js version because builtin sclar types are added on demand
@@ -1192,52 +1195,52 @@ class FindBreakingChangesTest extends TestCase
'description' => 'Int was removed.'
],*/
[
- 'type' => FindBreakingChanges::BREAKING_CHANGE_TYPE_CHANGED_KIND,
+ 'type' => BreakingChangesFinder::BREAKING_CHANGE_TYPE_CHANGED_KIND,
'description' => 'TypeThatChangesType changed from an Object type to an Interface type.',
],
[
- 'type' => FindBreakingChanges::BREAKING_CHANGE_FIELD_REMOVED,
+ 'type' => BreakingChangesFinder::BREAKING_CHANGE_FIELD_REMOVED,
'description' => 'TypeThatHasBreakingFieldChanges.field1 was removed.',
],
[
- 'type' => FindBreakingChanges::BREAKING_CHANGE_FIELD_CHANGED_KIND,
+ 'type' => BreakingChangesFinder::BREAKING_CHANGE_FIELD_CHANGED_KIND,
'description' => 'TypeThatHasBreakingFieldChanges.field2 changed type from String to Boolean.',
],
[
- 'type' => FindBreakingChanges::BREAKING_CHANGE_TYPE_REMOVED_FROM_UNION,
+ 'type' => BreakingChangesFinder::BREAKING_CHANGE_TYPE_REMOVED_FROM_UNION,
'description' => 'TypeInUnion2 was removed from union type UnionTypeThatLosesAType.',
],
[
- 'type' => FindBreakingChanges::BREAKING_CHANGE_VALUE_REMOVED_FROM_ENUM,
+ 'type' => BreakingChangesFinder::BREAKING_CHANGE_VALUE_REMOVED_FROM_ENUM,
'description' => 'VALUE0 was removed from enum type EnumTypeThatLosesAValue.',
],
[
- 'type' => FindBreakingChanges::BREAKING_CHANGE_ARG_CHANGED_KIND,
+ 'type' => BreakingChangesFinder::BREAKING_CHANGE_ARG_CHANGED_KIND,
'description' => 'ArgThatChanges.field1 arg id has changed type from Int to String',
],
[
- 'type' => FindBreakingChanges::BREAKING_CHANGE_INTERFACE_REMOVED_FROM_OBJECT,
+ 'type' => BreakingChangesFinder::BREAKING_CHANGE_INTERFACE_REMOVED_FROM_OBJECT,
'description' => 'TypeThatLosesInterface1 no longer implements interface Interface1.',
],
[
- 'type' => FindBreakingChanges::BREAKING_CHANGE_DIRECTIVE_REMOVED,
+ 'type' => BreakingChangesFinder::BREAKING_CHANGE_DIRECTIVE_REMOVED,
'description' => 'skip was removed',
],
[
- 'type' => FindBreakingChanges::BREAKING_CHANGE_DIRECTIVE_ARG_REMOVED,
+ 'type' => BreakingChangesFinder::BREAKING_CHANGE_DIRECTIVE_ARG_REMOVED,
'description' => 'arg1 was removed from DirectiveThatRemovesArg',
],
[
- 'type' => FindBreakingChanges::BREAKING_CHANGE_NON_NULL_DIRECTIVE_ARG_ADDED,
+ 'type' => BreakingChangesFinder::BREAKING_CHANGE_NON_NULL_DIRECTIVE_ARG_ADDED,
'description' => 'A non-null arg arg1 on directive NonNullDirectiveAdded was added',
],
[
- 'type' => FindBreakingChanges::BREAKING_CHANGE_DIRECTIVE_LOCATION_REMOVED,
+ 'type' => BreakingChangesFinder::BREAKING_CHANGE_DIRECTIVE_LOCATION_REMOVED,
'description' => 'QUERY was removed from Directive Name',
]
];
- $this->assertEquals($expectedBreakingChanges, FindBreakingChanges::findBreakingChanges($oldSchema, $newSchema));
+ $this->assertEquals($expectedBreakingChanges, BreakingChangesFinder::findBreakingChanges($oldSchema, $newSchema));
}
/**
@@ -1257,12 +1260,12 @@ class FindBreakingChangesTest extends TestCase
$expectedBreakingChanges = [
[
- 'type' => FindBreakingChanges::BREAKING_CHANGE_DIRECTIVE_REMOVED,
+ 'type' => BreakingChangesFinder::BREAKING_CHANGE_DIRECTIVE_REMOVED,
'description' => "{$includeDirective->name} was removed",
]
];
- $this->assertEquals($expectedBreakingChanges, FindBreakingChanges::findRemovedDirectives($oldSchema, $newSchema));
+ $this->assertEquals($expectedBreakingChanges, BreakingChangesFinder::findRemovedDirectives($oldSchema, $newSchema));
}
/**
@@ -1280,12 +1283,12 @@ class FindBreakingChangesTest extends TestCase
$expectedBreakingChanges = [
[
- 'type' => FindBreakingChanges::BREAKING_CHANGE_DIRECTIVE_REMOVED,
+ 'type' => BreakingChangesFinder::BREAKING_CHANGE_DIRECTIVE_REMOVED,
'description' => "{$deprecatedDirective->name} was removed",
]
];
- $this->assertEquals($expectedBreakingChanges, FindBreakingChanges::findRemovedDirectives($oldSchema, $newSchema));
+ $this->assertEquals($expectedBreakingChanges, BreakingChangesFinder::findRemovedDirectives($oldSchema, $newSchema));
}
/**
@@ -1318,12 +1321,12 @@ class FindBreakingChangesTest extends TestCase
$expectedBreakingChanges = [
[
- 'type' => FindBreakingChanges::BREAKING_CHANGE_DIRECTIVE_ARG_REMOVED,
+ 'type' => BreakingChangesFinder::BREAKING_CHANGE_DIRECTIVE_ARG_REMOVED,
'description' => "arg1 was removed from DirectiveWithArg",
]
];
- $this->assertEquals($expectedBreakingChanges, FindBreakingChanges::findRemovedDirectiveArgs($oldSchema, $newSchema));
+ $this->assertEquals($expectedBreakingChanges, BreakingChangesFinder::findRemovedDirectiveArgs($oldSchema, $newSchema));
}
/**
@@ -1357,12 +1360,12 @@ class FindBreakingChangesTest extends TestCase
$expectedBreakingChanges = [
[
- 'type' => FindBreakingChanges::BREAKING_CHANGE_NON_NULL_DIRECTIVE_ARG_ADDED,
+ 'type' => BreakingChangesFinder::BREAKING_CHANGE_NON_NULL_DIRECTIVE_ARG_ADDED,
'description' => "A non-null arg arg1 on directive DirectiveName was added",
]
];
- $this->assertEquals($expectedBreakingChanges, FindBreakingChanges::findAddedNonNullDirectiveArgs($oldSchema, $newSchema));
+ $this->assertEquals($expectedBreakingChanges, BreakingChangesFinder::findAddedNonNullDirectiveArgs($oldSchema, $newSchema));
}
/**
@@ -1380,7 +1383,7 @@ class FindBreakingChangesTest extends TestCase
'locations' => [DirectiveLocation::FIELD_DEFINITION],
]);
- $this->assertEquals([DirectiveLocation::QUERY], FindBreakingChanges::findRemovedLocationsForDirective($d1, $d2));
+ $this->assertEquals([DirectiveLocation::QUERY], BreakingChangesFinder::findRemovedLocationsForDirective($d1, $d2));
}
/**
@@ -1411,12 +1414,12 @@ class FindBreakingChangesTest extends TestCase
$expectedBreakingChanges = [
[
- 'type' => FindBreakingChanges::BREAKING_CHANGE_DIRECTIVE_LOCATION_REMOVED,
+ 'type' => BreakingChangesFinder::BREAKING_CHANGE_DIRECTIVE_LOCATION_REMOVED,
'description' => "QUERY was removed from Directive Name",
]
];
- $this->assertEquals($expectedBreakingChanges, FindBreakingChanges::findRemovedDirectiveLocations($oldSchema, $newSchema));
+ $this->assertEquals($expectedBreakingChanges, BreakingChangesFinder::findRemovedDirectiveLocations($oldSchema, $newSchema));
}
// DESCRIBE: findDangerousChanges
@@ -1469,14 +1472,14 @@ class FindBreakingChangesTest extends TestCase
$expected = [
[
- 'type' => FindBreakingChanges::DANGEROUS_CHANGE_ARG_DEFAULT_VALUE_CHANGED,
+ 'type' => BreakingChangesFinder::DANGEROUS_CHANGE_ARG_DEFAULT_VALUE_CHANGED,
'description' => 'Type1.field1 arg name has changed defaultValue'
]
];
$this->assertEquals(
$expected,
- FindBreakingChanges::findArgChanges($oldSchema, $newSchema)['dangerousChanges']
+ BreakingChangesFinder::findArgChanges($oldSchema, $newSchema)['dangerousChanges']
);
}
@@ -1513,14 +1516,14 @@ class FindBreakingChangesTest extends TestCase
$expected = [
[
- 'type' => FindBreakingChanges::DANGEROUS_CHANGE_VALUE_ADDED_TO_ENUM,
+ 'type' => BreakingChangesFinder::DANGEROUS_CHANGE_VALUE_ADDED_TO_ENUM,
'description' => 'VALUE2 was added to enum type EnumType1.'
]
];
$this->assertEquals(
$expected,
- FindBreakingChanges::findValuesAddedToEnums($oldSchema, $newSchema)
+ BreakingChangesFinder::findValuesAddedToEnums($oldSchema, $newSchema)
);
}
@@ -1562,14 +1565,14 @@ class FindBreakingChangesTest extends TestCase
$expected = [
[
- 'type' => FindBreakingChanges::DANGEROUS_CHANGE_INTERFACE_ADDED_TO_OBJECT,
+ 'type' => BreakingChangesFinder::DANGEROUS_CHANGE_INTERFACE_ADDED_TO_OBJECT,
'description' => 'Interface1 added to interfaces implemented by Type1.'
]
];
$this->assertEquals(
$expected,
- FindBreakingChanges::findInterfacesAddedToObjectTypes($oldSchema, $newSchema)
+ BreakingChangesFinder::findInterfacesAddedToObjectTypes($oldSchema, $newSchema)
);
}
@@ -1620,14 +1623,14 @@ class FindBreakingChangesTest extends TestCase
$expected = [
[
- 'type' => FindBreakingChanges::DANGEROUS_CHANGE_TYPE_ADDED_TO_UNION,
+ 'type' => BreakingChangesFinder::DANGEROUS_CHANGE_TYPE_ADDED_TO_UNION,
'description' => 'Type2 was added to union type UnionType1.'
]
];
$this->assertEquals(
$expected,
- FindBreakingChanges::findTypesAddedToUnions($oldSchema, $newSchema)
+ BreakingChangesFinder::findTypesAddedToUnions($oldSchema, $newSchema)
);
}
@@ -1673,11 +1676,11 @@ class FindBreakingChangesTest extends TestCase
$expectedFieldChanges = [
[
'description' => 'A nullable field field2 on input type InputType1 was added.',
- 'type' => FindBreakingChanges::DANGEROUS_CHANGE_NULLABLE_INPUT_FIELD_ADDED
+ 'type' => BreakingChangesFinder::DANGEROUS_CHANGE_NULLABLE_INPUT_FIELD_ADDED,
],
];
- $this->assertEquals($expectedFieldChanges, FindBreakingChanges::findFieldsThatChangedTypeOnInputObjectTypes($oldSchema, $newSchema)['dangerousChanges']);
+ $this->assertEquals($expectedFieldChanges, BreakingChangesFinder::findFieldsThatChangedTypeOnInputObjectTypes($oldSchema, $newSchema)['dangerousChanges']);
}
/**
@@ -1797,23 +1800,23 @@ class FindBreakingChangesTest extends TestCase
$expectedDangerousChanges = [
[
'description' => 'Type1.field1 arg name has changed defaultValue',
- 'type' => FindBreakingChanges::DANGEROUS_CHANGE_ARG_DEFAULT_VALUE_CHANGED
+ 'type' => BreakingChangesFinder::DANGEROUS_CHANGE_ARG_DEFAULT_VALUE_CHANGED,
],
[
'description' => 'VALUE2 was added to enum type EnumType1.',
- 'type' => FindBreakingChanges::DANGEROUS_CHANGE_VALUE_ADDED_TO_ENUM
+ 'type' => BreakingChangesFinder::DANGEROUS_CHANGE_VALUE_ADDED_TO_ENUM,
],
[
- 'type' => FindBreakingChanges::DANGEROUS_CHANGE_INTERFACE_ADDED_TO_OBJECT,
+ 'type' => BreakingChangesFinder::DANGEROUS_CHANGE_INTERFACE_ADDED_TO_OBJECT,
'description' => 'Interface1 added to interfaces implemented by TypeThatGainsInterface1.',
],
[
- 'type' => FindBreakingChanges::DANGEROUS_CHANGE_TYPE_ADDED_TO_UNION,
+ 'type' => BreakingChangesFinder::DANGEROUS_CHANGE_TYPE_ADDED_TO_UNION,
'description' => 'TypeInUnion2 was added to union type UnionTypeThatGainsAType.',
]
];
- $this->assertEquals($expectedDangerousChanges, FindBreakingChanges::findDangerousChanges($oldSchema, $newSchema));
+ $this->assertEquals($expectedDangerousChanges, BreakingChangesFinder::findDangerousChanges($oldSchema, $newSchema));
}
/**
@@ -1865,10 +1868,10 @@ class FindBreakingChangesTest extends TestCase
$expectedFieldChanges = [
[
'description' => 'A nullable arg arg2 on Type1.field1 was added',
- 'type' => FindBreakingChanges::DANGEROUS_CHANGE_NULLABLE_ARG_ADDED
+ 'type' => BreakingChangesFinder::DANGEROUS_CHANGE_NULLABLE_ARG_ADDED,
],
];
- $this->assertEquals($expectedFieldChanges, FindBreakingChanges::findArgChanges($oldSchema, $newSchema)['dangerousChanges']);
+ $this->assertEquals($expectedFieldChanges, BreakingChangesFinder::findArgChanges($oldSchema, $newSchema)['dangerousChanges']);
}
}