Skip to content

Commit d611cd1

Browse files
committed
[ISSUE-36] Allow to configure how deep the schema inspector should go for type/ofType sub-queries
1 parent 2b451e3 commit d611cd1

File tree

6 files changed

+252
-46
lines changed

6 files changed

+252
-46
lines changed

.gitignore

+2-1
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,5 @@ schema_object/*
55
!schema_object/.gitkeep
66
.phpunit.result.cache
77
/build/
8-
composer.lock
8+
composer.lock
9+
composer.phar

bin/generate_schema_objects

+25-5
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,28 @@
44
use GraphQL\Client;
55
use GraphQL\SchemaGenerator\CodeGenerator\ObjectBuilderInterface;
66
use GraphQL\SchemaGenerator\SchemaClassGenerator;
7+
use GraphQL\SchemaGenerator\SchemaInspector\TypeSubQueryGenerator;
78

89
$autoLoadFiles = [__DIR__ . '/../vendor/autoload.php', __DIR__ . '/../../../autoload.php'];
910

10-
function readConfig()
11+
/**
12+
* @return array{
13+
* 0: string,
14+
* 1: string,
15+
* 2: array<string, string>,
16+
* 3: string,
17+
* 4: int,
18+
* }
19+
*/
20+
function readConfig(): array
1121
{
1222
$shortOptions = implode("", [
1323
'u:',
1424
'h:',
1525
'v:',
1626
'd:',
17-
'n:'
27+
'n:',
28+
'D:',
1829
]);
1930

2031
$longOptions = [
@@ -23,6 +34,7 @@ function readConfig()
2334
'authorization-header-value:',
2435
'directory:',
2536
'namespace:',
37+
'type-of-type-depth:',
2638
];
2739

2840
$options = getopt($shortOptions, $longOptions);
@@ -32,14 +44,21 @@ function readConfig()
3244
$authHeaderName = $options['authorization-header-name'] ?? $options['h'] ?? readline('Authorization header name: ');
3345
$authHeaderValue = $options['authorization-header-value'] ?? $options['v'] ?? readline('Authorization header value: ');
3446
$namespace = $options['n'] ?? $options['namespace'] ?? trim(readline('Custom namespace (optional): '));
47+
$typeOfTypeDepth = $options['type-of-type-depth'] ?? $options['D'] ?? 4;
3548

3649
$authHeaders = [];
3750

3851
if (!empty($authHeaderName)) {
3952
$authHeaders = [$authHeaderName => $authHeaderValue];
4053
}
4154

42-
return [$url, empty($customWriteDir) ? "" : $customWriteDir, $authHeaders, empty($namespace) ? ObjectBuilderInterface::DEFAULT_NAMESPACE : $namespace];
55+
return [
56+
$url,
57+
empty($customWriteDir) ? "" : $customWriteDir,
58+
$authHeaders,
59+
empty($namespace) ? ObjectBuilderInterface::DEFAULT_NAMESPACE : $namespace,
60+
$typeOfTypeDepth,
61+
];
4362
}
4463

4564
// Require autoload.php depending on environment
@@ -55,13 +74,14 @@ if (!$autoLoadFound) {
5574
throw new RuntimeException('Could not find vendor/autoload.php');
5675
}
5776

58-
[$endpointUrl, $customWriteDir, $authHeaders, $namespace] = readConfig();
77+
[$endpointUrl, $customWriteDir, $authHeaders, $namespace, $typeOfTypeDepth] = readConfig();
5978

6079
$client = new Client($endpointUrl, $authHeaders);
61-
$scanner = new SchemaClassGenerator($client, $customWriteDir, $namespace);
80+
$scanner = new SchemaClassGenerator($client, $customWriteDir, $namespace, new TypeSubQueryGenerator($typeOfTypeDepth));
6281

6382
print "-------------------------------------------\n";
6483
print "Generating schema objects from schema types\n";
84+
print "Using \"type / ofType\" depth: $typeOfTypeDepth\n";
6585
print "-------------------------------------------\n";
6686

6787
$scanner->generateRootQueryObject();

src/SchemaGenerator/SchemaClassGenerator.php

+7-5
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
use GraphQL\SchemaGenerator\CodeGenerator\ObjectBuilderInterface;
1111
use GraphQL\SchemaGenerator\CodeGenerator\QueryObjectClassBuilder;
1212
use GraphQL\SchemaGenerator\CodeGenerator\UnionObjectBuilder;
13+
use GraphQL\SchemaGenerator\SchemaInspector\TypeSubQueryGenerator;
1314
use GraphQL\SchemaObject\QueryObject;
1415
use GraphQL\Util\StringLiteralFormatter;
1516
use RuntimeException;
@@ -49,13 +50,14 @@ class SchemaClassGenerator
4950
/**
5051
* SchemaClassGenerator constructor.
5152
*
52-
* @param Client $client
53-
* @param string $writeDir
54-
* @param string $namespace
53+
* @param Client $client
54+
* @param string $writeDir
55+
* @param string $namespace
56+
* @param TypeSubQueryGenerator|null $typeSubQueryGenerate
5557
*/
56-
public function __construct(Client $client, string $writeDir = '', string $namespace = ObjectBuilderInterface::DEFAULT_NAMESPACE)
58+
public function __construct(Client $client, string $writeDir = '', string $namespace = ObjectBuilderInterface::DEFAULT_NAMESPACE, ?TypeSubQueryGenerator $typeSubQueryGenerate = null)
5759
{
58-
$this->schemaInspector = new SchemaInspector($client);
60+
$this->schemaInspector = new SchemaInspector($client, $typeSubQueryGenerate ?? new TypeSubQueryGenerator(4));
5961
$this->generatedObjects = [];
6062
$this->writeDir = $writeDir;
6163
$this->generationNamespace = $namespace;

src/SchemaGenerator/SchemaInspector.php

+50-35
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
namespace GraphQL\SchemaGenerator;
44

55
use GraphQL\Client;
6+
use GraphQL\SchemaGenerator\SchemaInspector\TypeSubQueryGenerator;
67

78
/**
89
* Class SchemaInspector
@@ -13,45 +14,43 @@
1314
*/
1415
class SchemaInspector
1516
{
16-
private const TYPE_SUB_QUERY = <<<QUERY
17-
type{
18-
name
19-
kind
20-
description
21-
ofType{
22-
name
23-
kind
24-
ofType{
25-
name
26-
kind
27-
ofType{
28-
name
29-
kind
30-
ofType{
31-
name
32-
kind
33-
}
34-
}
35-
}
36-
}
37-
}
38-
QUERY;
39-
4017

4118
/**
4219
* @var Client
4320
*/
4421
protected $client;
4522

23+
/**
24+
* @var TypeSubQueryGenerator
25+
*/
26+
private $typeSubQueryGenerate;
27+
28+
4629
/**
4730
* SchemaInspector constructor.
4831
*
49-
* @param Client $client
32+
* @param Client $client
33+
* @param TypeSubQueryGenerator|null $typeSubQueryGenerate Generator of sub queries for types
5034
*/
51-
public function __construct(Client $client)
35+
public function __construct(Client $client, ?TypeSubQueryGenerator $typeSubQueryGenerate=null)
5236
{
5337
$this->client = $client;
38+
$this->typeSubQueryGenerate = ($typeSubQueryGenerate ?? new TypeSubQueryGenerator(4));
39+
40+
}
41+
// End __construct()
42+
43+
44+
/**
45+
* @return string
46+
*/
47+
private function getTypeSubQuery(): string
48+
{
49+
return $this->typeSubQueryGenerate->getSubTypeQuery();
50+
5451
}
52+
// End getTypeSubQuery()
53+
5554

5655
/**
5756
* @return array
@@ -69,12 +68,12 @@ public function getQueryTypeSchema(): array
6968
description
7069
isDeprecated
7170
deprecationReason
72-
" . static::TYPE_SUB_QUERY . "
71+
".$this->getTypeSubQuery()."
7372
args{
7473
name
7574
description
7675
defaultValue
77-
" . static::TYPE_SUB_QUERY . "
76+
".$this->getTypeSubQuery()."
7877
}
7978
}
8079
}
@@ -83,10 +82,13 @@ public function getQueryTypeSchema(): array
8382
$response = $this->client->runRawQuery($schemaQuery, true);
8483

8584
return $response->getData()['__schema']['queryType'];
85+
8686
}
87+
// End getQueryTypeSchema()
88+
8789

8890
/**
89-
* @param string $objectName
91+
* @param string $objectName The name of the object
9092
*
9193
* @return array
9294
*/
@@ -101,23 +103,26 @@ public function getObjectSchema(string $objectName): array
101103
description
102104
isDeprecated
103105
deprecationReason
104-
" . static::TYPE_SUB_QUERY . "
106+
".$this->getTypeSubQuery()."
105107
args{
106108
name
107109
description
108110
defaultValue
109-
" . static::TYPE_SUB_QUERY . "
111+
".$this->getTypeSubQuery()."
110112
}
111113
}
112114
}
113115
}";
114116
$response = $this->client->runRawQuery($schemaQuery, true);
115117

116118
return $response->getData()['__type'];
119+
117120
}
121+
// End getObjectSchema()
122+
118123

119124
/**
120-
* @param string $objectName
125+
* @param string $objectName The name of the object
121126
*
122127
* @return array
123128
*/
@@ -131,17 +136,20 @@ public function getInputObjectSchema(string $objectName): array
131136
name
132137
description
133138
defaultValue
134-
" . static::TYPE_SUB_QUERY . "
139+
".$this->getTypeSubQuery()."
135140
}
136141
}
137142
}";
138143
$response = $this->client->runRawQuery($schemaQuery, true);
139144

140145
return $response->getData()['__type'];
146+
141147
}
148+
// End getInputObjectSchema()
149+
142150

143151
/**
144-
* @param string $objectName
152+
* @param string $objectName The name of the enum object
145153
*
146154
* @return array
147155
*/
@@ -160,10 +168,13 @@ enumValues {
160168
$response = $this->client->runRawQuery($schemaQuery, true);
161169

162170
return $response->getData()['__type'];
171+
163172
}
173+
//end getEnumObjectSchema()
174+
164175

165176
/**
166-
* @param string $objectName
177+
* @param string $objectName The name of the union object
167178
*
168179
* @return array
169180
*/
@@ -182,5 +193,9 @@ public function getUnionObjectSchema(string $objectName): array
182193
$response = $this->client->runRawQuery($schemaQuery, true);
183194

184195
return $response->getData()['__type'];
196+
185197
}
198+
//end getUnionObjectSchema()
199+
200+
186201
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
<?php
2+
3+
namespace GraphQL\SchemaGenerator\SchemaInspector;
4+
5+
class TypeSubQueryGenerator
6+
{
7+
8+
/**
9+
* @var integer
10+
*/
11+
private $depth;
12+
13+
/**
14+
* Cache the sub-queries to not rebuild them everytime
15+
*
16+
* @var array<integer, string>
17+
*/
18+
private static $ofTypes = [];
19+
20+
21+
/**
22+
* @param integer $depth How many levels of `ofType` to generate
23+
*/
24+
public function __construct(int $depth=4)
25+
{
26+
$this->depth = $depth;
27+
28+
}
29+
// End __construct()
30+
31+
32+
/**
33+
* @return string
34+
*/
35+
public function getSubTypeQuery(): string
36+
{
37+
$ofType = $this->getOfTypeSubQuery($this->depth);
38+
39+
return "type{
40+
name
41+
kind
42+
description{$ofType}
43+
}";
44+
45+
}
46+
// End getSubTypeQuery()
47+
48+
49+
/**
50+
* @param integer $depth How many levels of `ofType` to generate
51+
*
52+
* @return string
53+
*/
54+
private function getOfTypeSubQuery($depth): string
55+
{
56+
if (isset(self::$ofTypes[$depth]) === false) {
57+
self::$ofTypes[$depth] = $this->generateOfTypeSubQuery($depth, ' ');
58+
}
59+
60+
return self::$ofTypes[$depth];
61+
62+
}
63+
// End getOfTypeSubQuery()
64+
65+
66+
/**
67+
* @param integer $depth How many levels of `ofType` to generate
68+
* @param string $indent Indentation for the sub-query
69+
*
70+
* @return string
71+
*/
72+
private function generateOfTypeSubQuery(int $depth, string $indent): string
73+
{
74+
if ($depth <= 0) {
75+
return '';
76+
}
77+
78+
$subQuery = $this->generateOfTypeSubQuery(($depth - 1), $indent.' ');
79+
80+
return "
81+
{$indent}ofType{
82+
{$indent} name
83+
{$indent} kind{$subQuery}
84+
{$indent}}";
85+
86+
}
87+
// End generateOfTypeSubQuery()
88+
89+
90+
}

0 commit comments

Comments
 (0)