Skip to content

WIP Enhancement #31

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
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
/.php-cs-fixer.cache
17 changes: 17 additions & 0 deletions .php-cs-fixer.dist.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?php

$finder = (new PhpCsFixer\Finder())
->in(__DIR__ . '/src')
->in(__DIR__ . '/tests')
;

return (new PhpCsFixer\Config())
->setRiskyAllowed(true)
->setRules([
'@Symfony' => true, // should be last of rules set to avoid override its rules
// here we override some rules
'yoda_style' => false,
'declare_strict_types' => true,
])
->setFinder($finder)
;
99 changes: 67 additions & 32 deletions bin/generate_schema_objects
Original file line number Diff line number Diff line change
@@ -1,45 +1,80 @@
#!/usr/bin/env php
<?php

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

// Require autoload.php depending on environment
$autoLoadFound = false;
foreach ($autoLoadFiles as $autoLoadFile) {
if (file_exists($autoLoadFile)) {
require $autoLoadFile;
$autoLoadFound = true;
}
}
// Exit if autoload.php is not required
if (!$autoLoadFound) {
throw new RuntimeException('Could not find vendor/autoload.php');
foreach ([__DIR__.'/../vendor/autoload.php', __DIR__.'/../autoload.php', __DIR__.'/../../../autoload.php'] as $autoload) {
if (file_exists($autoload)) {
require_once $autoload;
break;
}
}

use GraphQL\Client;
use GraphQL\Client as GraphQLClient;
use GraphQL\SchemaGenerator\SchemaClassGenerator;
use GraphQL\Util\GuzzleAdapter;
use GuzzleHttp\Client as HttpClient;
use GuzzleHttp\HandlerStack;
use Kevinrob\GuzzleCache\CacheMiddleware;
use Kevinrob\GuzzleCache\KeyValueHttpHeader;
use Kevinrob\GuzzleCache\Storage\Psr6CacheStorage;
use Kevinrob\GuzzleCache\Strategy\PrivateCacheStrategy;
use Psr\Http\Message\RequestInterface;
use Symfony\Component\Cache\Adapter\FilesystemAdapter;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\SingleCommandApplication;
use Symfony\Component\Console\Style\SymfonyStyle;

$endpointUrl = readline('GraphlQL endpoint URL: ');
(new SingleCommandApplication())
->addArgument('graphql-endpoint', InputArgument::REQUIRED, 'GraphQL endpoint URL')
->addOption('auth-header', null, InputOption::VALUE_REQUIRED, 'Authorization Header Name')
->addOption('auth-header-value', null, InputOption::VALUE_REQUIRED, 'Authorization Header Name')
->addOption('dir', null, InputOption::VALUE_REQUIRED, 'Custom classes writing dir', '')
->setCode(function (InputInterface $input, OutputInterface $output) {
$io = new SymfonyStyle($input, $output);
$endpoint = $input->getArgument('graphql-endpoint');
$dir = '';
$authHeaders = [];

$authHeaders = [];
$authHeaderName = readline('Authorization header name: ');
if (!empty($authHeaderName)) {
$authHeaderValue = readline('Authorization header value: ');
$authHeaders = [$authHeaderName => $authHeaderValue];
}
if ($input->getOption('dir')) {
$dir = $input->getOption('dir');
}

if ($input->getOption('auth-header')) {
$authHeaders = [$input->getOption('auth-header') => $input->getOption('auth-header-value')];
}

// Create default HandlerStack
$stack = HandlerStack::create();

// Add this middleware to the top with `push`
$cacheStorage = new Psr6CacheStorage(new FilesystemAdapter(directory: __DIR__.'/../cache'));
$cacheStrategy = new class($cacheStorage) extends PrivateCacheStrategy {
protected function getCacheKey(RequestInterface $request, KeyValueHttpHeader $varyHeaders = null)
{
return hash('sha256', $request->getMethod().$request->getUri().$request->getBody());
}
};
$cacheMiddleware = new CacheMiddleware($cacheStrategy);
$cacheMiddleware->setHttpMethods(['GET' => true, 'POST' => true]);
$stack->push($cacheMiddleware, 'cache');

// Initialize the client with the handler option
$guzzle = new HttpClient(['handler' => $stack]);

$customWriteDir = readline('Custom classes writing dir (optional): ');
if (empty($customWriteDir)) $customWriteDir = '';
$client = new GraphQLClient(
endpointUrl: $endpoint,
authorizationHeaders: $authHeaders,
httpClient: new GuzzleAdapter($guzzle)
);

$client = new Client($endpointUrl, $authHeaders);
$scanner = new SchemaClassGenerator($client, $customWriteDir);
$scanner = new SchemaClassGenerator($client, $dir);

print "-------------------------------------------\n";
print "Generating schema objects from schema types\n";
print "-------------------------------------------\n";
$io->block('Generating schema objects from schema types');

$scanner->generateRootQueryObject();
$scanner->generateRootQueryObject();

print "-------------------------------------------\n";
print "Schema objects generation complete\n";
print "-------------------------------------------\n";
$io->block('Schema objects generation complete');
})
->run();
12 changes: 9 additions & 3 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,13 +34,19 @@
},
"bin": ["bin/generate_schema_objects"],
"require": {
"php": "^7.1 || ^8.0",
"gmostafa/php-graphql-client": "^1.12"
"php": "^8.1",
"gmostafa/php-graphql-client": "^1.12",
"nette/php-generator": "^4.0",
"guzzlehttp/guzzle": "^7.4",
"kevinrob/guzzle-cache-middleware": "^4.0",
"symfony/cache": "^6.0"
},
"require-dev": {
"phpunit/phpunit": "^7.5|^8.0",
"codacy/coverage": "^1.4",
"ext-json": "*"
"ext-readline": "*",
"ext-json": "*",
"friendsofphp/php-cs-fixer": "^3.7"
},
"scripts": {
"test": "phpunit tests/ --whitelist src/ --coverage-clover build/coverage/xml"
Expand Down
Empty file removed schema_object/.gitkeep
Empty file.
23 changes: 12 additions & 11 deletions src/Enumeration/FieldTypeKindEnum.php
Original file line number Diff line number Diff line change
@@ -1,19 +1,20 @@
<?php

declare(strict_types=1);

namespace GraphQL\Enumeration;

/**
* Class FieldTypeKindEnum
*
* @package GraphQL\Enumeration
* Class FieldTypeKindEnum.
*/
class FieldTypeKindEnum
enum FieldTypeKindEnum: string
{
const SCALAR = 'SCALAR';
const LIST = 'LIST';
const NON_NULL = 'NON_NULL';
const OBJECT = 'OBJECT';
const INPUT_OBJECT = 'INPUT_OBJECT';
const ENUM_OBJECT = 'ENUM';
const UNION_OBJECT = 'UNION';
case SCALAR = 'SCALAR';
case LIST = 'LIST';
case NON_NULL = 'NON_NULL';
case OBJECT = 'OBJECT';
case INPUT_OBJECT = 'INPUT_OBJECT';
case ENUM_OBJECT = 'ENUM';
case UNION_OBJECT = 'UNION';
case INTERFACE_OBJECT = 'INTERFACE';
}
17 changes: 17 additions & 0 deletions src/SchemaGenerator/CodeGenerator/AbstractObjectBuilder.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?php

declare(strict_types=1);

namespace GraphQL\SchemaGenerator\CodeGenerator;

use GraphQL\SchemaGenerator\CodeGenerator\CodeFile\ClassFile;

abstract class AbstractObjectBuilder implements ObjectBuilderInterface
{
protected ClassFile $classFile;

public function build(): void
{
$this->classFile->writeFile();
}
}
78 changes: 37 additions & 41 deletions src/SchemaGenerator/CodeGenerator/ArgumentsObjectClassBuilder.php
Original file line number Diff line number Diff line change
@@ -1,83 +1,79 @@
<?php

declare(strict_types=1);

namespace GraphQL\SchemaGenerator\CodeGenerator;

use GraphQL\SchemaGenerator\CodeGenerator\CodeFile\ClassFile;
use GraphQL\SchemaObject\ArgumentsObject;
use GraphQL\Util\StringLiteralFormatter;

/**
* Class ArgumentsObjectClassBuilder
*
* @package GraphQL\SchemaGenerator\CodeGenerator
* Class ArgumentsObjectClassBuilder.
*/
class ArgumentsObjectClassBuilder extends ObjectClassBuilder
{
/**
* ArgumentsObjectClassBuilder constructor.
*
* @param string $writeDir
* @param string $objectName
* @param string $namespace
*/
public function __construct(string $writeDir, string $objectName, string $namespace = self::DEFAULT_NAMESPACE)
{
$this->classFile = new ClassFile($writeDir, $objectName);
$this->classFile->setNamespace($namespace);
if ($namespace !== self::DEFAULT_NAMESPACE) {
$this->classFile->addImport('GraphQL\\SchemaObject\\ArgumentsObject');
}
$this->classFile->extendsClass('ArgumentsObject');
$this->classFile = new ClassFile($writeDir, $objectName, $namespace);
$this->classFile->extendsClass(ArgumentsObject::class);
}

/**
* @param string $argumentName
*/
public function addScalarArgument(string $argumentName)
public function addScalarArgument(string $argumentName, ?string $typeName = ''): void
{
$lowerTypeName = strtolower($typeName);
if ($lowerTypeName === 'boolean') {
$lowerTypeName = 'bool';
}

if ($lowerTypeName === 'id') {
$lowerTypeName = 'string';
}

if ($lowerTypeName === 'money') {
$lowerTypeName = 'string';
}

if ($lowerTypeName === 'url') {
$lowerTypeName = 'string';
}

if ($lowerTypeName) {
assert(in_array($lowerTypeName, ['bool', 'int', 'float', 'string']), $lowerTypeName);
}

$upperCamelCaseArg = StringLiteralFormatter::formatUpperCamelCase($argumentName);
$this->addProperty($argumentName);
$this->addProperty($argumentName, null, $lowerTypeName);
$this->addScalarSetter($argumentName, $upperCamelCaseArg);
}

/**
* @param string string $argumentName
* @param string string $typeName
*/
public function addListArgument(string $argumentName, string $typeName)
public function addListArgument(string $argumentName, string $typeName): void
{
$upperCamelCaseArg = StringLiteralFormatter::formatUpperCamelCase($argumentName);
$this->addProperty($argumentName);
$this->addProperty($argumentName, null, 'array');
$this->addListSetter($argumentName, $upperCamelCaseArg, $typeName);
}

/**
* @param string $argumentName
* @param string $typeName
*/
public function addInputEnumArgument(string $argumentName, string $typeName)
public function addInputEnumArgument(string $argumentName, string $typeName): void
{
$typeName .= 'EnumObject';
$upperCamelCaseArg = StringLiteralFormatter::formatUpperCamelCase($argumentName);
$this->addProperty($argumentName);
$this->addProperty($argumentName, null, $typeName);
$this->addEnumSetter($argumentName, $upperCamelCaseArg, $typeName);
}

/**
* @param string $argumentName
* @param string $typeName
*/
public function addInputObjectArgument(string $argumentName, string $typeName)
public function addInputObjectArgument(string $argumentName, string $typeName): void
{
$typeName .= 'InputObject';
$upperCamelCaseArg = StringLiteralFormatter::formatUpperCamelCase($argumentName);
$this->addProperty($argumentName);
$this->addProperty($argumentName, null, $typeName);
$this->addObjectSetter($argumentName, $upperCamelCaseArg, $typeName);
}

/**
* @return void
*/
public function build(): void
{
$this->classFile->writeFile();
}
}
}
Loading