Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,5 @@ schema_object/*
!schema_object/.gitkeep
.phpunit.result.cache
/build/
composer.lock
composer.lock
composer.phar
30 changes: 25 additions & 5 deletions bin/generate_schema_objects
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,28 @@
use GraphQL\Client;
use GraphQL\SchemaGenerator\CodeGenerator\ObjectBuilderInterface;
use GraphQL\SchemaGenerator\SchemaClassGenerator;
use GraphQL\SchemaGenerator\SchemaInspector\TypeSubQueryGenerator;

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

function readConfig()
/**
* @return array{
* 0: string,
* 1: string,
* 2: array<string, string>,
* 3: string,
* 4: int,
* }
*/
function readConfig(): array
{
$shortOptions = implode("", [
'u:',
'h:',
'v:',
'd:',
'n:'
'n:',
'D:',
]);

$longOptions = [
Expand All @@ -23,6 +34,7 @@ function readConfig()
'authorization-header-value:',
'directory:',
'namespace:',
'type-of-type-depth:',
];

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

$authHeaders = [];

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

return [$url, empty($customWriteDir) ? "" : $customWriteDir, $authHeaders, empty($namespace) ? ObjectBuilderInterface::DEFAULT_NAMESPACE : $namespace];
return [
$url,
empty($customWriteDir) ? "" : $customWriteDir,
$authHeaders,
empty($namespace) ? ObjectBuilderInterface::DEFAULT_NAMESPACE : $namespace,
$typeOfTypeDepth,
];
}

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

[$endpointUrl, $customWriteDir, $authHeaders, $namespace] = readConfig();
[$endpointUrl, $customWriteDir, $authHeaders, $namespace, $typeOfTypeDepth] = readConfig();

$client = new Client($endpointUrl, $authHeaders);
$scanner = new SchemaClassGenerator($client, $customWriteDir, $namespace);
$scanner = new SchemaClassGenerator($client, $customWriteDir, $namespace, new TypeSubQueryGenerator($typeOfTypeDepth));

print "-------------------------------------------\n";
print "Generating schema objects from schema types\n";
print "Using \"type / ofType\" depth: $typeOfTypeDepth\n";
print "-------------------------------------------\n";

$scanner->generateRootQueryObject();
Expand Down
12 changes: 7 additions & 5 deletions src/SchemaGenerator/SchemaClassGenerator.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
use GraphQL\SchemaGenerator\CodeGenerator\ObjectBuilderInterface;
use GraphQL\SchemaGenerator\CodeGenerator\QueryObjectClassBuilder;
use GraphQL\SchemaGenerator\CodeGenerator\UnionObjectBuilder;
use GraphQL\SchemaGenerator\SchemaInspector\TypeSubQueryGenerator;
use GraphQL\SchemaObject\QueryObject;
use GraphQL\Util\StringLiteralFormatter;
use RuntimeException;
Expand Down Expand Up @@ -49,13 +50,14 @@ class SchemaClassGenerator
/**
* SchemaClassGenerator constructor.
*
* @param Client $client
* @param string $writeDir
* @param string $namespace
* @param Client $client
* @param string $writeDir
* @param string $namespace
* @param TypeSubQueryGenerator|null $typeSubQueryGenerate
*/
public function __construct(Client $client, string $writeDir = '', string $namespace = ObjectBuilderInterface::DEFAULT_NAMESPACE)
public function __construct(Client $client, string $writeDir = '', string $namespace = ObjectBuilderInterface::DEFAULT_NAMESPACE, ?TypeSubQueryGenerator $typeSubQueryGenerate = null)
{
$this->schemaInspector = new SchemaInspector($client);
$this->schemaInspector = new SchemaInspector($client, $typeSubQueryGenerate ?? new TypeSubQueryGenerator(4));
$this->generatedObjects = [];
$this->writeDir = $writeDir;
$this->generationNamespace = $namespace;
Expand Down
85 changes: 50 additions & 35 deletions src/SchemaGenerator/SchemaInspector.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
namespace GraphQL\SchemaGenerator;

use GraphQL\Client;
use GraphQL\SchemaGenerator\SchemaInspector\TypeSubQueryGenerator;

/**
* Class SchemaInspector
Expand All @@ -13,46 +14,44 @@
*/
class SchemaInspector
{
private const TYPE_SUB_QUERY = <<<QUERY
type{
name
kind
description
ofType{
name
kind
ofType{
name
kind
ofType{
name
kind
ofType{
name
kind
}
}
}
}
}
QUERY;


/**
* @var Client
*/
protected $client;

/**
* @var TypeSubQueryGenerator
*/
private $typeSubQueryGenerate;


/**
* SchemaInspector constructor.
*
* @param Client $client
* @param Client $client
* @param TypeSubQueryGenerator|null $typeSubQueryGenerate Generator of sub queries for types
*/
public function __construct(Client $client)
public function __construct(Client $client, ?TypeSubQueryGenerator $typeSubQueryGenerate=null)
{
$this->client = $client;
$this->typeSubQueryGenerate = ($typeSubQueryGenerate ?? new TypeSubQueryGenerator(4));

// End __construct().
}


/**
* @return string
*/
private function getTypeSubQuery(): string
{
return $this->typeSubQueryGenerate->getSubTypeQuery();

// End getTypeSubQuery().
}


/**
* @return array
*/
Expand All @@ -69,12 +68,12 @@ public function getQueryTypeSchema(): array
description
isDeprecated
deprecationReason
" . static::TYPE_SUB_QUERY . "
".$this->getTypeSubQuery()."
args{
name
description
defaultValue
" . static::TYPE_SUB_QUERY . "
".$this->getTypeSubQuery()."
}
}
}
Expand All @@ -83,10 +82,13 @@ public function getQueryTypeSchema(): array
$response = $this->client->runRawQuery($schemaQuery, true);

return $response->getData()['__schema']['queryType'];

// End getQueryTypeSchema().
}


/**
* @param string $objectName
* @param string $objectName The name of the object
*
* @return array
*/
Expand All @@ -101,23 +103,26 @@ public function getObjectSchema(string $objectName): array
description
isDeprecated
deprecationReason
" . static::TYPE_SUB_QUERY . "
".$this->getTypeSubQuery()."
args{
name
description
defaultValue
" . static::TYPE_SUB_QUERY . "
".$this->getTypeSubQuery()."
}
}
}
}";
$response = $this->client->runRawQuery($schemaQuery, true);

return $response->getData()['__type'];

// End getObjectSchema().
}


/**
* @param string $objectName
* @param string $objectName The name of the object
*
* @return array
*/
Expand All @@ -131,17 +136,20 @@ public function getInputObjectSchema(string $objectName): array
name
description
defaultValue
" . static::TYPE_SUB_QUERY . "
".$this->getTypeSubQuery()."
}
}
}";
$response = $this->client->runRawQuery($schemaQuery, true);

return $response->getData()['__type'];

// End getInputObjectSchema().
}


/**
* @param string $objectName
* @param string $objectName The name of the enum object
*
* @return array
*/
Expand All @@ -160,10 +168,13 @@ enumValues {
$response = $this->client->runRawQuery($schemaQuery, true);

return $response->getData()['__type'];

// End getEnumObjectSchema().
}


/**
* @param string $objectName
* @param string $objectName The name of the union object
*
* @return array
*/
Expand All @@ -182,5 +193,9 @@ public function getUnionObjectSchema(string $objectName): array
$response = $this->client->runRawQuery($schemaQuery, true);

return $response->getData()['__type'];

// End getUnionObjectSchema().
}


}
90 changes: 90 additions & 0 deletions src/SchemaGenerator/SchemaInspector/TypeSubQueryGenerator.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
<?php

namespace GraphQL\SchemaGenerator\SchemaInspector;

class TypeSubQueryGenerator
{

/**
* @var integer
*/
private $depth;

/**
* Cache the sub-queries to not rebuild them everytime
*
* @var array<integer, string>
*/
private static $ofTypes = [];


/**
* @param integer $depth How many levels of `ofType` to generate
*/
public function __construct(int $depth=4)
{
$this->depth = $depth;

// End __construct().
}


/**
* @return string
*/
public function getSubTypeQuery(): string
{
$ofType = $this->getOfTypeSubQuery($this->depth);

return "type{
name
kind
description{$ofType}
}";

// End getSubTypeQuery().
}


/**
* @param integer $depth How many levels of `ofType` to generate
*
* @return string
*/
private function getOfTypeSubQuery($depth): string
{
if (isset(self::$ofTypes[$depth]) === false) {
self::$ofTypes[$depth] = $this->generateOfTypeSubQuery($depth, ' ');
}

return self::$ofTypes[$depth];

// End getOfTypeSubQuery().
}


/**
* @param integer $depth How many levels of `ofType` to generate
* @param string $indent Indentation for the sub-query
*
* @return string
*/
private function generateOfTypeSubQuery(int $depth, string $indent): string
{
if ($depth <= 0) {
return '';
}

$subQuery = $this->generateOfTypeSubQuery(($depth - 1), $indent.' ');

return "
{$indent}ofType{
{$indent} name
{$indent} kind{$subQuery}
{$indent}}";

// End generateOfTypeSubQuery().
}


}
Loading