From e7dfe8dab563164b4e2c14e4e2132f823e2ceaad Mon Sep 17 00:00:00 2001 From: Tyler Gauch Date: Tue, 31 Mar 2020 17:03:32 -0400 Subject: [PATCH 1/8] Updates to allow printing of Schema Directives --- src/Utils/SchemaPrinter.php | 26 +++++++- tests/Utils/SchemaPrinterTest.php | 100 ++++++++++++++++++++++++++++++ 2 files changed, 124 insertions(+), 2 deletions(-) diff --git a/src/Utils/SchemaPrinter.php b/src/Utils/SchemaPrinter.php index 098912d8c..2e2509dae 100644 --- a/src/Utils/SchemaPrinter.php +++ b/src/Utils/SchemaPrinter.php @@ -317,7 +317,8 @@ public static function printType(Type $type, array $options = []) : string } if ($type instanceof ObjectType) { - return self::printObject($type, $options); + $result= self::printObject($type, $options); + return $result; } if ($type instanceof InterfaceType) { @@ -352,6 +353,27 @@ private static function printScalar(ScalarType $type, array $options) : string */ private static function printObject(ObjectType $type, array $options) : string { + $directives = $type->astNode->directives; + $schemaDirectives = !empty($directives) ? implode(' ', + array_map( + static function ($d) { + $s = " @" . $d->name->value; + if ($d->arguments->count() > 0) { + $s .= "("; + foreach ($d->arguments as $argument) { + $s .= $argument->name->value . ": "; + $s .= Printer::doPrint($argument->value); + } + $s .= ")"; + } + + return $s; + }, + iterator_to_array($directives->getIterator()) + ) + ) : ''; + + $interfaces = $type->getInterfaces(); $implementedInterfaces = ! empty($interfaces) ? ' implements ' . implode( @@ -366,7 +388,7 @@ static function ($i) { : ''; return self::printDescription($options, $type) . - sprintf("type %s%s {\n%s\n}", $type->name, $implementedInterfaces, self::printFields($options, $type)); + sprintf("type %s%s%s {\n%s\n}", $type->name, $implementedInterfaces, $schemaDirectives, self::printFields($options, $type)); } /** diff --git a/tests/Utils/SchemaPrinterTest.php b/tests/Utils/SchemaPrinterTest.php index 7131875f1..63efc78e4 100644 --- a/tests/Utils/SchemaPrinterTest.php +++ b/tests/Utils/SchemaPrinterTest.php @@ -1237,4 +1237,104 @@ enum __TypeKind { EOT; self::assertEquals($introspectionSchema, $output); } + + public function testPrintSchemaDirectiveNoArgs() { + $exceptedSdl = " +directive @sd on OBJECT + +type Bar @sd { + foo: String +} + +type Query { + foo: Bar +} +"; + + $schema = BuildSchema::build($exceptedSdl); + $actual = $this->printForTest($schema); + + self::assertEquals($exceptedSdl, $actual); + } + + public function testPrintSchemaDirectiveWithStringArgs() { + $exceptedSdl = ' +directive @sd(field: String!) on OBJECT + +type Bar @sd(field: "String") { + foo: String +} + +type Query { + foo: Bar +} +'; + + $schema = BuildSchema::build($exceptedSdl); + $actual = $this->printForTest($schema); + + self::assertEquals($exceptedSdl, $actual); + } + + public function testPrintSchemaDirectiveWithNumberArgs() { + $exceptedSdl = ' +directive @sd(field: Int!) on OBJECT + +type Bar @sd(field: 1) { + foo: String +} + +type Query { + foo: Bar +} +'; + + $schema = BuildSchema::build($exceptedSdl); + $actual = $this->printForTest($schema); + + self::assertEquals($exceptedSdl, $actual); + } + + public function testPrintSchemaDirectiveWithArrayArgs() { + $exceptedSdl = ' +directive @sd(field: [Int!]) on OBJECT + +type Bar @sd(field: [1, 2, 3, 4]) { + foo: String +} + +type Query { + foo: Bar +} +'; + + $schema = BuildSchema::build($exceptedSdl); + $actual = $this->printForTest($schema); + + self::assertEquals($exceptedSdl, $actual); + } + + public function testPrintSchemaDirectiveOptionalArgs() { + $exceptedSdl = ' +directive @sd(field: String) on OBJECT + +type Bar @sd(field: "Testing") { + foo: String +} + +type Foo @sd { + bar: String +} + +type Query { + foo: Bar + bar: Foo +} +'; + + $schema = BuildSchema::build($exceptedSdl); + $actual = $this->printForTest($schema); + + self::assertEquals($exceptedSdl, $actual); + } } From f1b16fb0a4b45537a596c67c5f7ffcedfe41656e Mon Sep 17 00:00:00 2001 From: Tyler Gauch Date: Tue, 31 Mar 2020 17:23:00 -0400 Subject: [PATCH 2/8] Updates for added test cases --- src/Utils/SchemaPrinter.php | 57 +++++++++++++++----------- tests/Utils/SchemaPrinterTest.php | 67 +++++++++++++++++++++++++++++++ 2 files changed, 101 insertions(+), 23 deletions(-) diff --git a/src/Utils/SchemaPrinter.php b/src/Utils/SchemaPrinter.php index 2e2509dae..621851404 100644 --- a/src/Utils/SchemaPrinter.php +++ b/src/Utils/SchemaPrinter.php @@ -353,27 +353,6 @@ private static function printScalar(ScalarType $type, array $options) : string */ private static function printObject(ObjectType $type, array $options) : string { - $directives = $type->astNode->directives; - $schemaDirectives = !empty($directives) ? implode(' ', - array_map( - static function ($d) { - $s = " @" . $d->name->value; - if ($d->arguments->count() > 0) { - $s .= "("; - foreach ($d->arguments as $argument) { - $s .= $argument->name->value . ": "; - $s .= Printer::doPrint($argument->value); - } - $s .= ")"; - } - - return $s; - }, - iterator_to_array($directives->getIterator()) - ) - ) : ''; - - $interfaces = $type->getInterfaces(); $implementedInterfaces = ! empty($interfaces) ? ' implements ' . implode( @@ -388,7 +367,7 @@ static function ($i) { : ''; return self::printDescription($options, $type) . - sprintf("type %s%s%s {\n%s\n}", $type->name, $implementedInterfaces, $schemaDirectives, self::printFields($options, $type)); + sprintf("type %s%s%s {\n%s\n}", $type->name, $implementedInterfaces, self::printSchemaDirectives($type), self::printFields($options, $type)); } /** @@ -432,7 +411,7 @@ private static function printDeprecated($fieldOrEnumVal) : string private static function printInterface(InterfaceType $type, array $options) : string { return self::printDescription($options, $type) . - sprintf("interface %s {\n%s\n}", $type->name, self::printFields($options, $type)); + sprintf("interface %s%s {\n%s\n}", $type->name, self::printSchemaDirectives($type), self::printFields($options, $type)); } /** @@ -509,4 +488,36 @@ public static function printIntrospectionSchema(Schema $schema, array $options = $options ); } + + /** + * @param \GraphQL\Type\Definition\Type $type + * + * @return string + */ + public static function printSchemaDirectives(Type $type) : string { + + if (!$type->astNode || !$type->astNode->directives) { + return ''; + } + + $directives = $type->astNode->directives; + return $directives->count() > 0 ? (' ' . implode(' ', + array_map( + static function ($d) { + $s = "@" . $d->name->value; + if ($d->arguments->count() > 0) { + $s .= "("; + foreach ($d->arguments as $argument) { + $s .= $argument->name->value . ": "; + $s .= Printer::doPrint($argument->value); + } + $s .= ")"; + } + + return $s; + }, + iterator_to_array($directives->getIterator()) + ) + )) : ''; + } } diff --git a/tests/Utils/SchemaPrinterTest.php b/tests/Utils/SchemaPrinterTest.php index 63efc78e4..44707ce59 100644 --- a/tests/Utils/SchemaPrinterTest.php +++ b/tests/Utils/SchemaPrinterTest.php @@ -1337,4 +1337,71 @@ public function testPrintSchemaDirectiveOptionalArgs() { self::assertEquals($exceptedSdl, $actual); } + + public function testPrintMultipleSchemaDirectives() { + $exceptedSdl = ' +directive @sd(field: [Int!]) on OBJECT + +directive @sdb on OBJECT + +type Bar @sd(field: [1, 2, 3, 4]) @sdb { + foo: String +} + +type Query { + foo: Bar +} +'; + + $schema = BuildSchema::build($exceptedSdl); + $actual = $this->printForTest($schema); + + self::assertEquals($exceptedSdl, $actual); + } + + public function testPrintSchemaDirectiveOnClassWithInterface() { + $exceptedSdl = ' +directive @sd on OBJECT + +type Bar implements Foo @sd { + foo: String +} + +interface Foo { + bar: String +} + +type Query { + foo: Bar +} +'; + + $schema = BuildSchema::build($exceptedSdl); + $actual = $this->printForTest($schema); + + self::assertEquals($exceptedSdl, $actual); + } + + public function testPrintSchemaDirectiveOnInterface() { + $exceptedSdl = ' +directive @sd on INTERFACE + +type Bar implements Foo { + foo: String +} + +interface Foo @sd { + bar: String +} + +type Query { + foo: Bar +} +'; + + $schema = BuildSchema::build($exceptedSdl); + $actual = $this->printForTest($schema); + + self::assertEquals($exceptedSdl, $actual); + } } From 5741d8e29dc8b3115d41936bf2cd9497045ecb3c Mon Sep 17 00:00:00 2001 From: Tyler Gauch Date: Tue, 31 Mar 2020 17:24:08 -0400 Subject: [PATCH 3/8] Removed set on printType --- src/Utils/SchemaPrinter.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/Utils/SchemaPrinter.php b/src/Utils/SchemaPrinter.php index 621851404..c5c1aee28 100644 --- a/src/Utils/SchemaPrinter.php +++ b/src/Utils/SchemaPrinter.php @@ -317,8 +317,7 @@ public static function printType(Type $type, array $options = []) : string } if ($type instanceof ObjectType) { - $result= self::printObject($type, $options); - return $result; + return self::printObject($type, $options); } if ($type instanceof InterfaceType) { From e590dffe63a9c7ec601fe599ea3dcb81e85e6d25 Mon Sep 17 00:00:00 2001 From: Tyler Gauch Date: Tue, 31 Mar 2020 17:29:30 -0400 Subject: [PATCH 4/8] Added test case for directive with Type args --- tests/Utils/SchemaPrinterTest.php | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/tests/Utils/SchemaPrinterTest.php b/tests/Utils/SchemaPrinterTest.php index 44707ce59..3ab5fc964 100644 --- a/tests/Utils/SchemaPrinterTest.php +++ b/tests/Utils/SchemaPrinterTest.php @@ -1303,6 +1303,29 @@ public function testPrintSchemaDirectiveWithArrayArgs() { foo: String } +type Query { + foo: Bar +} +'; + + $schema = BuildSchema::build($exceptedSdl); + $actual = $this->printForTest($schema); + + self::assertEquals($exceptedSdl, $actual); + } + + public function testPrintSchemaDirectiveWithTypeArgs() { + $exceptedSdl = ' +directive @sd(field: Foo) on OBJECT + +type Bar @sd(field: {bar: "test"}) { + foo: String +} + +type Foo { + bar: String +} + type Query { foo: Bar } From 7acfc93d31928fdc503b2433c55bddb213f53c08 Mon Sep 17 00:00:00 2001 From: Tyler Gauch Date: Tue, 31 Mar 2020 17:43:10 -0400 Subject: [PATCH 5/8] Code Sniffs --- src/Utils/SchemaPrinter.php | 54 ++++++++-------- tests/Utils/SchemaPrinterTest.php | 101 ++++++++++++++++-------------- 2 files changed, 81 insertions(+), 74 deletions(-) diff --git a/src/Utils/SchemaPrinter.php b/src/Utils/SchemaPrinter.php index c5c1aee28..18118ccc0 100644 --- a/src/Utils/SchemaPrinter.php +++ b/src/Utils/SchemaPrinter.php @@ -24,6 +24,7 @@ use function count; use function explode; use function implode; +use function iterator_to_array; use function ksort; use function mb_strlen; use function preg_match_all; @@ -488,35 +489,32 @@ public static function printIntrospectionSchema(Schema $schema, array $options = ); } - /** - * @param \GraphQL\Type\Definition\Type $type - * - * @return string - */ - public static function printSchemaDirectives(Type $type) : string { - - if (!$type->astNode || !$type->astNode->directives) { - return ''; - } - - $directives = $type->astNode->directives; - return $directives->count() > 0 ? (' ' . implode(' ', - array_map( - static function ($d) { - $s = "@" . $d->name->value; - if ($d->arguments->count() > 0) { - $s .= "("; - foreach ($d->arguments as $argument) { - $s .= $argument->name->value . ": "; - $s .= Printer::doPrint($argument->value); - } - $s .= ")"; + public static function printSchemaDirectives(Type $type) : string + { + if (! $type->astNode || ! $type->astNode->directives) { + return ''; + } + + $directives = $type->astNode->directives; + + return $directives->count() > 0 ? (' ' . implode( + ' ', + array_map( + static function ($directive) { + $directiveString = '@' . $directive->name->value; + if ($directive->arguments->count() > 0) { + $directiveString .= '('; + foreach ($directive->arguments as $argument) { + $directiveString .= $argument->name->value . ': '; + $directiveString .= Printer::doPrint($argument->value); + } + $directiveString .= ')'; } - return $s; - }, - iterator_to_array($directives->getIterator()) - ) - )) : ''; + return $directiveString; + }, + iterator_to_array($directives->getIterator()) + ) + )) : ''; } } diff --git a/tests/Utils/SchemaPrinterTest.php b/tests/Utils/SchemaPrinterTest.php index 3ab5fc964..5de96d3b7 100644 --- a/tests/Utils/SchemaPrinterTest.php +++ b/tests/Utils/SchemaPrinterTest.php @@ -1238,8 +1238,9 @@ enum __TypeKind { self::assertEquals($introspectionSchema, $output); } - public function testPrintSchemaDirectiveNoArgs() { - $exceptedSdl = " + public function testPrintSchemaDirectiveNoArgs() + { + $exceptedSdl = ' directive @sd on OBJECT type Bar @sd { @@ -1249,16 +1250,17 @@ public function testPrintSchemaDirectiveNoArgs() { type Query { foo: Bar } -"; +'; - $schema = BuildSchema::build($exceptedSdl); - $actual = $this->printForTest($schema); + $schema = BuildSchema::build($exceptedSdl); + $actual = $this->printForTest($schema); - self::assertEquals($exceptedSdl, $actual); + self::assertEquals($exceptedSdl, $actual); } - public function testPrintSchemaDirectiveWithStringArgs() { - $exceptedSdl = ' + public function testPrintSchemaDirectiveWithStringArgs() + { + $exceptedSdl = ' directive @sd(field: String!) on OBJECT type Bar @sd(field: "String") { @@ -1270,14 +1272,15 @@ public function testPrintSchemaDirectiveWithStringArgs() { } '; - $schema = BuildSchema::build($exceptedSdl); - $actual = $this->printForTest($schema); + $schema = BuildSchema::build($exceptedSdl); + $actual = $this->printForTest($schema); - self::assertEquals($exceptedSdl, $actual); + self::assertEquals($exceptedSdl, $actual); } - public function testPrintSchemaDirectiveWithNumberArgs() { - $exceptedSdl = ' + public function testPrintSchemaDirectiveWithNumberArgs() + { + $exceptedSdl = ' directive @sd(field: Int!) on OBJECT type Bar @sd(field: 1) { @@ -1289,14 +1292,15 @@ public function testPrintSchemaDirectiveWithNumberArgs() { } '; - $schema = BuildSchema::build($exceptedSdl); - $actual = $this->printForTest($schema); + $schema = BuildSchema::build($exceptedSdl); + $actual = $this->printForTest($schema); - self::assertEquals($exceptedSdl, $actual); + self::assertEquals($exceptedSdl, $actual); } - public function testPrintSchemaDirectiveWithArrayArgs() { - $exceptedSdl = ' + public function testPrintSchemaDirectiveWithArrayArgs() + { + $exceptedSdl = ' directive @sd(field: [Int!]) on OBJECT type Bar @sd(field: [1, 2, 3, 4]) { @@ -1308,14 +1312,15 @@ public function testPrintSchemaDirectiveWithArrayArgs() { } '; - $schema = BuildSchema::build($exceptedSdl); - $actual = $this->printForTest($schema); + $schema = BuildSchema::build($exceptedSdl); + $actual = $this->printForTest($schema); - self::assertEquals($exceptedSdl, $actual); + self::assertEquals($exceptedSdl, $actual); } - public function testPrintSchemaDirectiveWithTypeArgs() { - $exceptedSdl = ' + public function testPrintSchemaDirectiveWithTypeArgs() + { + $exceptedSdl = ' directive @sd(field: Foo) on OBJECT type Bar @sd(field: {bar: "test"}) { @@ -1331,14 +1336,15 @@ public function testPrintSchemaDirectiveWithTypeArgs() { } '; - $schema = BuildSchema::build($exceptedSdl); - $actual = $this->printForTest($schema); + $schema = BuildSchema::build($exceptedSdl); + $actual = $this->printForTest($schema); - self::assertEquals($exceptedSdl, $actual); + self::assertEquals($exceptedSdl, $actual); } - public function testPrintSchemaDirectiveOptionalArgs() { - $exceptedSdl = ' + public function testPrintSchemaDirectiveOptionalArgs() + { + $exceptedSdl = ' directive @sd(field: String) on OBJECT type Bar @sd(field: "Testing") { @@ -1355,14 +1361,15 @@ public function testPrintSchemaDirectiveOptionalArgs() { } '; - $schema = BuildSchema::build($exceptedSdl); - $actual = $this->printForTest($schema); + $schema = BuildSchema::build($exceptedSdl); + $actual = $this->printForTest($schema); - self::assertEquals($exceptedSdl, $actual); + self::assertEquals($exceptedSdl, $actual); } - public function testPrintMultipleSchemaDirectives() { - $exceptedSdl = ' + public function testPrintMultipleSchemaDirectives() + { + $exceptedSdl = ' directive @sd(field: [Int!]) on OBJECT directive @sdb on OBJECT @@ -1376,14 +1383,15 @@ public function testPrintMultipleSchemaDirectives() { } '; - $schema = BuildSchema::build($exceptedSdl); - $actual = $this->printForTest($schema); + $schema = BuildSchema::build($exceptedSdl); + $actual = $this->printForTest($schema); - self::assertEquals($exceptedSdl, $actual); + self::assertEquals($exceptedSdl, $actual); } - public function testPrintSchemaDirectiveOnClassWithInterface() { - $exceptedSdl = ' + public function testPrintSchemaDirectiveOnClassWithInterface() + { + $exceptedSdl = ' directive @sd on OBJECT type Bar implements Foo @sd { @@ -1399,14 +1407,15 @@ interface Foo { } '; - $schema = BuildSchema::build($exceptedSdl); - $actual = $this->printForTest($schema); + $schema = BuildSchema::build($exceptedSdl); + $actual = $this->printForTest($schema); - self::assertEquals($exceptedSdl, $actual); + self::assertEquals($exceptedSdl, $actual); } - public function testPrintSchemaDirectiveOnInterface() { - $exceptedSdl = ' + public function testPrintSchemaDirectiveOnInterface() + { + $exceptedSdl = ' directive @sd on INTERFACE type Bar implements Foo { @@ -1422,9 +1431,9 @@ interface Foo @sd { } '; - $schema = BuildSchema::build($exceptedSdl); - $actual = $this->printForTest($schema); + $schema = BuildSchema::build($exceptedSdl); + $actual = $this->printForTest($schema); - self::assertEquals($exceptedSdl, $actual); + self::assertEquals($exceptedSdl, $actual); } } From 0cff146bff08c9d35cddbcf4f53693e342299996 Mon Sep 17 00:00:00 2001 From: Tyler Gauch Date: Tue, 31 Mar 2020 17:52:42 -0400 Subject: [PATCH 6/8] Updates for PHPStan errors --- src/Utils/SchemaPrinter.php | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/src/Utils/SchemaPrinter.php b/src/Utils/SchemaPrinter.php index 18118ccc0..21c9b5b65 100644 --- a/src/Utils/SchemaPrinter.php +++ b/src/Utils/SchemaPrinter.php @@ -5,6 +5,9 @@ namespace GraphQL\Utils; use GraphQL\Error\Error; +use GraphQL\Language\AST\InterfaceTypeDefinitionNode; +use GraphQL\Language\AST\NodeList; +use GraphQL\Language\AST\ObjectTypeDefinitionNode; use GraphQL\Language\Printer; use GraphQL\Type\Definition\Directive; use GraphQL\Type\Definition\EnumType; @@ -491,13 +494,26 @@ public static function printIntrospectionSchema(Schema $schema, array $options = public static function printSchemaDirectives(Type $type) : string { - if (! $type->astNode || ! $type->astNode->directives) { + if ($type->astNode === null) { return ''; } - $directives = $type->astNode->directives; + if ($type->astNode instanceof ObjectTypeDefinitionNode) { + $directives = $type->astNode->directives; + } elseif ($type->astNode instanceof InterfaceTypeDefinitionNode) { + $directives = $type->astNode->directives; + } else { + return ''; + } + + if ($directives instanceof NodeList) { + $count = $directives->count(); + $directives = iterator_to_array($directives->getIterator()); + } else { + $count = count($directives); + } - return $directives->count() > 0 ? (' ' . implode( + return $count > 0 ? (' ' . implode( ' ', array_map( static function ($directive) { @@ -513,7 +529,7 @@ static function ($directive) { return $directiveString; }, - iterator_to_array($directives->getIterator()) + $directives ) )) : ''; } From 4e809bf1842bdd4d6561ee323bb376d2d8f14f7d Mon Sep 17 00:00:00 2001 From: Tyler Gauch Date: Tue, 31 Mar 2020 17:56:21 -0400 Subject: [PATCH 7/8] Updates for changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5500eec86..8ea83af48 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,7 @@ + Cannot return null for non-nullable field "parentType.fieldName". ``` - Simplified Deferred implementation +- Allow SchemaPrinter to print Schema Directives #### v0.13.5 - Fix coroutine executor when using with promise (#486) From 449760621386730ff718833202f05836373b6801 Mon Sep 17 00:00:00 2001 From: Tyler Gauch Date: Tue, 31 Mar 2020 17:57:50 -0400 Subject: [PATCH 8/8] Missed a stan error --- src/Utils/SchemaPrinter.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Utils/SchemaPrinter.php b/src/Utils/SchemaPrinter.php index 21c9b5b65..c66112bd8 100644 --- a/src/Utils/SchemaPrinter.php +++ b/src/Utils/SchemaPrinter.php @@ -516,7 +516,7 @@ public static function printSchemaDirectives(Type $type) : string return $count > 0 ? (' ' . implode( ' ', array_map( - static function ($directive) { + static function ($directive) : string { $directiveString = '@' . $directive->name->value; if ($directive->arguments->count() > 0) { $directiveString .= '(';