Skip to content

Commit

Permalink
Support custom directives in SchemaPrinter
Browse files Browse the repository at this point in the history
  • Loading branch information
jbtbnl committed Jun 23, 2021
1 parent bf11070 commit 52864c1
Show file tree
Hide file tree
Showing 2 changed files with 76 additions and 3 deletions.
60 changes: 57 additions & 3 deletions src/Utils/SchemaPrinter.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@
namespace GraphQL\Utils;

use GraphQL\Error\Error;
use GraphQL\Language\AST\ArgumentNode;
use GraphQL\Language\AST\DirectiveNode;
use GraphQL\Language\AST\NodeKind;
use GraphQL\Language\Printer;
use GraphQL\Type\Definition\Directive;
use GraphQL\Type\Definition\EnumType;
Expand All @@ -29,6 +32,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;
Expand Down Expand Up @@ -371,7 +375,7 @@ public static function printType(Type $type, array $options = []): string
*/
protected static function printScalar(ScalarType $type, array $options): string
{
return sprintf('%sscalar %s', static::printDescription($options, $type), $type->name);
return sprintf('%sscalar %s', static::printDescription($options, $type), $type->name) . static::printFieldOrTypeDirectives($type);
}

/**
Expand Down Expand Up @@ -410,14 +414,64 @@ protected static function printFields(array $options, $type): string
static function (FieldDefinition $f, int $i) use ($options): string {
return static::printDescription($options, $f, ' ', $i === 0) . ' ' .
$f->name . static::printArgs($options, $f->args, ' ') . ': ' .
(string) $f->getType() . static::printDeprecated($f);
(string) $f->getType() . static::printFieldOrTypeDirectives($f);
},
$fields,
array_keys($fields)
)
);
}

/**
* @param FieldDefinition|ScalarType|EnumValueDefinition $fieldOrEnumVal
*/
protected static function printFieldOrTypeDirectives($fieldOrEnumVal): string
{
$serialized = '';

if (($fieldOrEnumVal instanceof FieldDefinition || $fieldOrEnumVal instanceof EnumValueDefinition) && $fieldOrEnumVal->deprecationReason !== null) {
$serialized .= static::printDeprecated($fieldOrEnumVal);
}

if ($fieldOrEnumVal->astNode !== null) {
foreach ($fieldOrEnumVal->astNode->directives as $directive) {
/** @var DirectiveNode $directive */
if ($directive->name->value === Directive::DEPRECATED_NAME && $fieldOrEnumVal->deprecationReason !== null) {
continue;
}

$serialized .= ' @' . $directive->name->value;

if ($directive->arguments->count() === 0) {
continue;
}

$serialized .= '(' . implode(',', array_map(static function (ArgumentNode $argument): string {
switch ($argument->value->kind) {
case NodeKind::INT:
$type = Type::int();
break;
case NodeKind::FLOAT:
$type = Type::float();
break;
case NodeKind::STRING:
$type = Type::string();
break;
case NodeKind::BOOLEAN:
$type = Type::boolean();
break;
default:
return '';
}

return $argument->name->value . ': ' . Printer::doPrint(AST::astFromValue($argument->value->value, $type));
}, iterator_to_array($directive->arguments))) . ')';
}
}

return $serialized;
}

/**
* @param FieldArgument|EnumValueDefinition $fieldOrEnumVal
*/
Expand Down Expand Up @@ -487,7 +541,7 @@ protected static function printEnumValues(array $values, array $options): string
array_map(
static function (EnumValueDefinition $value, int $i) use ($options): string {
return static::printDescription($options, $value, ' ', $i === 0) . ' ' .
$value->name . static::printDeprecated($value);
$value->name . static::printFieldOrTypeDirectives($value);
},
$values,
array_keys($values)
Expand Down
19 changes: 19 additions & 0 deletions tests/Utils/SchemaPrinterTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

use Generator;
use GraphQL\Language\DirectiveLocation;
use GraphQL\Language\Parser;
use GraphQL\Type\Definition\CustomScalarType;
use GraphQL\Type\Definition\Directive;
use GraphQL\Type\Definition\EnumType;
Expand Down Expand Up @@ -1370,4 +1371,22 @@ enum __TypeKind {
EOT;
self::assertEquals($introspectionSchema, $output);
}

public function testPrintParsedSDLIncludesCustomDirectives(): void
{
$SDL = <<<'EOT'
directive @customDirective(stringArgument: String!, intArgument: Int!, floatArgument: Float!, booleanArgument: Boolean!) on FIELD_DEFINITION
type Query {
field1: Boolean @customDirective(stringArgument: "test", intArgument: 42, floatArgument: 0.0, booleanArgument: true)
field2: Boolean
}

EOT;
$documentNode = Parser::parse($SDL);
$schema = BuildSchema::build($documentNode);
$output = SchemaPrinter::doPrint($schema);

self::assertEquals($SDL, $output);
}
}

0 comments on commit 52864c1

Please sign in to comment.