Skip to content

Commit

Permalink
Generator for schema class added
Browse files Browse the repository at this point in the history
Dependencies updated
Controller has been updated for the Symfony v3
Additional checks were implemented
GraphQL Schema class was moved to the config file as parameter and is now being used inside the controller
  • Loading branch information
viniychuk committed May 9, 2016
1 parent 62ae4b4 commit 4ccbfcf
Show file tree
Hide file tree
Showing 6 changed files with 168 additions and 31 deletions.
90 changes: 90 additions & 0 deletions Command/GenerateSchemaCommand.php
@@ -0,0 +1,90 @@
<?php

namespace AppBundle\Command;

use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand;
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\Question\ConfirmationQuestion;

class GenerateSchemaCommand extends ContainerAwareCommand
{
protected function configure()
{
$this
->setName('graphql:generate-schema')
->setDescription('Generates GraphQL Schema class')
->addArgument('bundle', InputArgument::REQUIRED, 'Bundle to generate class to');
}

protected function execute(InputInterface $input, OutputInterface $output)
{
$bundleName = $input->getArgument('bundle');
if (strpos($bundleName, -6) != 'Bundle') $bundleName .= 'Bundle';

$srcPath = realpath($this->getContainer()->getParameter('kernel.root_dir') . '/../src');
$activeBundles = $this->getContainer()->getParameter('kernel.bundles');
if (!array_key_exists($bundleName, $activeBundles)) {
$output->writeln('There is no active bundleName: ' . $bundleName);
}

$graphqlPath = $srcPath . '/' . $bundleName . '/GraphQL';
$className = 'Schema';
$classPath = $graphqlPath . '/' . $className . '.php';

$inputHelper = $this->getHelper('question');
$question = new ConfirmationQuestion(sprintf('Confirm creating class at %s ?', $classPath), false);
if (!$inputHelper->ask($input, $output, $question)) {
return;
}

if (!is_dir($graphqlPath)) {
mkdir($graphqlPath, 0777, true);
}
file_put_contents($classPath, $this->getSchemaClassTemplate($bundleName, $className));

$output->writeln('Schema file has been created at');
$output->writeln($classPath . "\n");
$output->writeln('Update your app/config/config.yml with the parameter:');
$output->writeln('graph_ql:');
$output->writeln(sprintf(' schema_class: %s\GraphQL\%s', $bundleName, $className));
}

protected function getSchemaClassTemplate($bundleName, $className = 'Schema')
{
$tpl = <<<TEXT
<?php
/**
* This class was automatically generated by GraphQL Schema generator
*/
namespace $bundleName\GraphQL;
use Youshido\GraphQL\AbstractSchema;
use Youshido\GraphQL\Type\Config\Schema\SchemaConfig;
use Youshido\GraphQL\Type\Scalar\StringType;
class $className extends AbstractSchema
{
public function build(SchemaConfig \$config)
{
\$config->getQuery()->addFields([
'hello' => [
'type' => new StringType(),
'resolve' => function () {
return 'world!';
}
]
]);
}
}
TEXT;

return $tpl;
}

}
21 changes: 13 additions & 8 deletions Controller/GraphQLController.php
Expand Up @@ -10,27 +10,27 @@

use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\Annotation\Route;
use Youshido\GraphQL\Validator\Exception\ConfigurationException;

class GraphQLController extends Controller
{

/**
* @param Request $request
* @Route("/graphql")
*
* @throws ConfigurationException
* @return JsonResponse
*
* @Route("/graphql")
*/
public function apiAction(Request $request)
public function defaultAction()
{
$request = $this->get('request_stack')->getCurrentRequest();
$query = $request->get('query', null);
$variables = $request->get('variables', null);

$variables = json_decode($variables, true) ?: [];

$content = $this->get("request")->getContent();
$content = $request->getContent();
if (!empty($content)) {
$params = json_decode($content, true);

Expand All @@ -41,8 +41,13 @@ public function apiAction(Request $request)
}

$processor = $this->get('youshido.graphql.processor');

$processor->processQuery($query, $variables);
if ($schemaClass = $this->getParameter('youshido.graphql.schema_class')) {
if (!class_exists($schemaClass)) {
throw new ConfigurationException('Schema class ' . $schemaClass . ' does not exist');
}
$processor->setSchema(new $schemaClass());
}
$processor->processRequest($query, $variables);

return new JsonResponse($processor->getResponseData(), 200, $this->getParameter('youshido.graphql.response_headers'));
}
Expand Down
27 changes: 20 additions & 7 deletions DependencyInjection/GraphQLExtension.php
Expand Up @@ -14,26 +14,39 @@
*/
class GraphQLExtension extends Extension
{
private $config = [];

/**
* {@inheritdoc}
*/
public function load(array $configs, ContainerBuilder $container)
{
$configuration = new Configuration();
$config = $this->processConfiguration($configuration, $configs);
$this->config = $this->processConfiguration($configuration, $configs);

$responseHeaders = [];
if (isset($config['response_headers']) && is_array($config['response_headers'])) {
foreach ($config['response_headers'] as $responseHeader) {
$responseHeaders[$responseHeader['name']] = $responseHeader['value'];
}
foreach ($this->getConfig('response_headers', $this->getDefaultHeaders()) as $responseHeader) {
$responseHeaders[$responseHeader['name']] = $responseHeader['value'];
}

$container->setParameter('youshido.graphql.project_schema', $config['query_schema']);
$container->setParameter('youshido.graphql.project_schema', $this->getConfig('query_schema', null));
$container->setParameter('youshido.graphql.response_headers', $responseHeaders);
$container->setParameter('youshido.graphql.logger', isset($config['logger']) ? $config['logger'] : null);
$container->setParameter('youshido.graphql.logger', $this->getConfig('logger', null));

$loader = new Loader\YamlFileLoader($container, new FileLocator(__DIR__ . '/../Resources/config'));
$loader->load('services.yml');
}

private function getDefaultHeaders()
{
return [
['name' => 'Access-Control-Allow-Origin', 'value' => '*'],
];
}

private function getConfig($key, $default = null)
{
return array_key_exists($key, $this->config) ? $this->config[$key] : $default;
}

}
4 changes: 2 additions & 2 deletions Processor/Processor.php
Expand Up @@ -30,13 +30,13 @@ public function setContainer(ContainerInterface $container = null)
$this->container = $container;
}

public function processQuery($queryString, $variables = [])
public function processRequest($queryString, $variables = [])
{
if ($this->logger) {
$this->logger->debug(sprintf('GraphQL query: %s', $queryString), (array) $variables);
}

parent::processQuery($queryString, $variables);
parent::processRequest($queryString, $variables);
}

/**
Expand Down
52 changes: 43 additions & 9 deletions README.md
Expand Up @@ -14,24 +14,58 @@ This bundle provides you with:
## Installing GraphQL Bundle

We assume you have `composer`, but if you're not – install it from the [official website](https://getcomposer.org/doc/00-intro.md#installation-linux-unix-osx).
After you've done with that, simply run
```
$> composer require youshido/graphql-bundle
Once you have your composer up and running – you're ready to install the GraphQL Bundle
```sh
composer require youshido/graphql-bundle
```

Than add bundle to your `app/AppKernel.php`
```
...
Than enable bundle in your `app/AppKernel.php`
```php
new Youshido\GraphQLBundle\GraphQLBundle(),
...
```

And finally add the routing reference to the `app/config/routing.yml`:
```
Add the routing reference to the `app/config/routing.yml`:
```yaml
graphql:
resource: "@GraphQLBundle/Controller/"
```

Let's check if you've done everything right so far – try to access the `localhost:8000/graphql` url.
You should get a JSON response with the following error:
```js
{"errors":[{"message":"You have to set GraphQL Schema to process"}]}
```

That's because there was no GraphQL Schema specified for the processor yet.
You need to create a GraphQL Schema class and set it inside your `app/config/config.yml` file.

> THere is a way where you can use inline approach, in order to do that you have to define your own GraphQL controller and use a `->setSchema` method of the processor to set the Schema
The fastest way to create a Schema class is to use a generator shipped with this bundle:
```sh
php bin/console graphql:schema:generate App
```
Here *App* is a name of the bundle where the class will be generated in.
You will be requested for a confirmation to create a class and then presented with instructions to update your config file.

```sh
Update your app/config/config.yml with the parameter:
graph_ql:
schema_class: AppBundle\GraphQL\Schema
```

After you've added parameters to config file, try to access the following link in the browser – 'http://localhost:8000/graphql?query={hello}'

> Alternatively, you can execute the same request using CURL client in your console
> `curl http://localhost:8000/graphql --data "query={ hello }"`
Successful response from a test Schema will be displayed:
```js
{"data":{"hello":"world!"}}
```

That means you have GraphQL Bundle for the Symfony Framework configured and now can architect your GraphQL Schema:

## Documentation

Detailed documentation is available on the main GraphQL repository – http://github.com/youshido/graphql/.
5 changes: 0 additions & 5 deletions Resources/config/services.yml
@@ -1,12 +1,10 @@
parameters:
youshido.graphql.processor.class: Youshido\GraphQLBundle\Processor\Processor
youshido.graphql.validator.class: Youshido\GraphQL\Validator\ResolveValidator\ResolveValidator

services:

youshido.graphql.processor:
class: %youshido.graphql.processor.class%
arguments: [ @youshido.graphql.validator ]
calls:
- [ setSchema, [@youshido.graphql.schema]]
- [ setContainer, [@service_container]]
Expand All @@ -15,6 +13,3 @@ services:

youshido.graphql.schema:
class: %youshido.graphql.project_schema%

youshido.graphql.validator:
class: %youshido.graphql.validator.class%

0 comments on commit 4ccbfcf

Please sign in to comment.