|
4 | 4 |
|
5 | 5 | namespace GraphQL\Utils;
|
6 | 6 |
|
| 7 | +use Closure; |
7 | 8 | use GraphQL\Error\Error;
|
| 9 | +use GraphQL\Language\AST\DirectiveNode; |
| 10 | +use GraphQL\Language\AST\ScalarTypeDefinitionNode; |
8 | 11 | use GraphQL\Language\BlockString;
|
9 | 12 | use GraphQL\Language\Printer;
|
10 | 13 | use GraphQL\Type\Definition\Directive;
|
|
30 | 33 | use function count;
|
31 | 34 | use function explode;
|
32 | 35 | use function implode;
|
| 36 | +use function is_callable; |
33 | 37 | use function ksort;
|
34 | 38 | use function mb_strlen;
|
| 39 | +use function self; |
35 | 40 | use function sprintf;
|
36 | 41 | use function str_replace;
|
37 | 42 | use function strlen;
|
38 | 43 |
|
39 | 44 | /**
|
40 | 45 | * Prints the contents of a Schema in schema definition language.
|
41 | 46 | *
|
42 |
| - * @phpstan-type Options array{commentDescriptions?: bool} |
| 47 | + * @phpstan-type Options array{commentDescriptions?: bool, printDirectives?: callable(DirectiveNode): bool} |
43 | 48 | *
|
44 | 49 | * - commentDescriptions:
|
45 | 50 | * Provide true to use preceding comments as the description.
|
46 | 51 | * This option is provided to ease adoption and will be removed in v16.
|
| 52 | + * - printDirectives |
| 53 | + * Callable used to determine should be directive printed or not. |
47 | 54 | */
|
48 | 55 | class SchemaPrinter
|
49 | 56 | {
|
| 57 | + protected const LINE_LENGTH = 80; |
| 58 | + |
50 | 59 | /**
|
51 | 60 | * @param array<string, bool> $options
|
52 | 61 | * @phpstan-param Options $options
|
@@ -308,7 +317,9 @@ protected static function printInputValue($arg): string
|
308 | 317 | */
|
309 | 318 | protected static function printScalar(ScalarType $type, array $options): string
|
310 | 319 | {
|
311 |
| - return sprintf('%sscalar %s', static::printDescription($options, $type), $type->name); |
| 320 | + return static::printDescription($options, $type) . |
| 321 | + sprintf('scalar %s', $type->name) . |
| 322 | + static::printTypeDirectives($type, $options); |
312 | 323 | }
|
313 | 324 |
|
314 | 325 | /**
|
@@ -459,4 +470,53 @@ protected static function printBlock(array $items): string
|
459 | 470 | ? " {\n" . implode("\n", $items) . "\n}"
|
460 | 471 | : '';
|
461 | 472 | }
|
| 473 | + |
| 474 | + /** |
| 475 | + * @param array<string, bool> $options |
| 476 | + * @phpstan-param Options $options |
| 477 | + */ |
| 478 | + protected static function printTypeDirectives(Type $type, array $options, string $indentation = ''): string { |
| 479 | + // Enabled? |
| 480 | + $filter = $options['printDirectives'] ?? null; |
| 481 | + |
| 482 | + if (!$filter || !is_callable($filter)) { |
| 483 | + return ''; |
| 484 | + } |
| 485 | + |
| 486 | + // AST Node available and has directives? |
| 487 | + $node = $type->astNode; |
| 488 | + |
| 489 | + if (!($node instanceof ScalarTypeDefinitionNode)) { |
| 490 | + return ''; |
| 491 | + } |
| 492 | + |
| 493 | + // Print |
| 494 | + /** @var array<string> $directives */ |
| 495 | + $length = 0; |
| 496 | + $directives = []; |
| 497 | + |
| 498 | + foreach ($node->directives as $directive) { |
| 499 | + if ($filter($directive)) { |
| 500 | + $string = static::printTypeDirective($directive, $options, $indentation); |
| 501 | + $length = $length + mb_strlen($string); |
| 502 | + $directives[] = $string; |
| 503 | + } |
| 504 | + } |
| 505 | + |
| 506 | + // Multiline? |
| 507 | + $delimiter = $length > static::LINE_LENGTH ? "\n{$indentation}" : ' '; |
| 508 | + $serialized = $delimiter.implode($delimiter, $directives); |
| 509 | + |
| 510 | + // Return |
| 511 | + return $serialized; |
| 512 | + } |
| 513 | + |
| 514 | + /** |
| 515 | + * @param array<string, bool> $options |
| 516 | + * @phpstan-param Options $options |
| 517 | + */ |
| 518 | + protected static function printTypeDirective(DirectiveNode $directive, array $options, string $indentation): string |
| 519 | + { |
| 520 | + return Printer::doPrint($directive); |
| 521 | + } |
462 | 522 | }
|
0 commit comments