Skip to content
Merged
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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@
/composer.lock
/build
/var
/cache
105 changes: 105 additions & 0 deletions Controller/GraphqliteController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
<?php


namespace TheCodingMachine\Graphqlite\Bundle\Controller;


use GraphQL\Error\Debug;
use GraphQL\Executor\ExecutionResult;
use GraphQL\Executor\Promise\Promise;
use GraphQL\Server\StandardServer;
use GraphQL\Upload\UploadMiddleware;
use function json_decode;
use Psr\Http\Message\ServerRequestInterface;
use RuntimeException;
use Symfony\Bridge\PsrHttpMessage\Factory\DiactorosFactory;
use Symfony\Bridge\PsrHttpMessage\HttpMessageFactoryInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\HttpKernel\HttpKernelInterface;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\Routing\Route;
use Symfony\Component\Routing\RouteCollection;

/**
* Listens to every single request and forward Graphql requests to Graphql Webonix standardServer.
*/
class GraphqliteController
{
/**
* @var HttpMessageFactoryInterface
*/
private $httpMessageFactory;
/** @var StandardServer */
private $standardServer;
/** @var bool|int */
private $debug;

public function __construct(StandardServer $standardServer, HttpMessageFactoryInterface $httpMessageFactory = null, ?int $debug = Debug::RETHROW_UNSAFE_EXCEPTIONS)
{
$this->standardServer = $standardServer;
$this->httpMessageFactory = $httpMessageFactory ?: new DiactorosFactory();
$this->debug = $debug ?? false;
}

public function loadRoutes(): RouteCollection
{
$routes = new RouteCollection();

// prepare a new route
$path = '/graphql';
$defaults = [
'_controller' => self::class.'::handleRequest',
];
$route = new Route($path, $defaults);

// add the new route to the route collection
$routeName = 'graphqliteRoute';
$routes->add($routeName, $route);

return $routes;
}

public function handleRequest(Request $request): Response
{
$psr7Request = $this->httpMessageFactory->createRequest($request);

if (strtoupper($request->getMethod()) === "POST" && empty($psr7Request->getParsedBody())) {
$content = $psr7Request->getBody()->getContents();
$parsedBody = json_decode($content, true);
if (json_last_error() !== JSON_ERROR_NONE) {
throw new \RuntimeException('Invalid JSON received in POST body: '.json_last_error_msg());
}
$psr7Request = $psr7Request->withParsedBody($parsedBody);
}

// Let's parse the request and adapt it for file uploads.
$uploadMiddleware = new UploadMiddleware();
$psr7Request = $uploadMiddleware->processRequest($psr7Request);

$result = $this->handlePsr7Request($psr7Request);

return new JsonResponse($result);
}

private function handlePsr7Request(ServerRequestInterface $request): array
{
$result = $this->standardServer->executePsrRequest($request);

if ($result instanceof ExecutionResult) {
return $result->toArray($this->debug);
}
if (is_array($result)) {
return array_map(function (ExecutionResult $executionResult) {
return $executionResult->toArray($this->debug);
}, $result);
}
if ($result instanceof Promise) {
throw new RuntimeException('Only SyncPromiseAdapter is supported');
}
throw new RuntimeException('Unexpected response from StandardServer::executePsrRequest'); // @codeCoverageIgnore
}
}
157 changes: 0 additions & 157 deletions EventListeners/RequestHandler.php

This file was deleted.

6 changes: 2 additions & 4 deletions Resources/config/container/graphqlite.xml
Original file line number Diff line number Diff line change
Expand Up @@ -61,10 +61,6 @@

<service id="TheCodingMachine\GraphQLite\InputTypeUtils" />

<service id="TheCodingMachine\Graphqlite\Bundle\EventListeners\RequestHandler">
<tag name="kernel.event_subscriber" />
</service>

<service id="GraphQL\Server\StandardServer">
<argument type="service" id="GraphQL\Server\ServerConfig" />
</service>
Expand Down Expand Up @@ -101,6 +97,8 @@
<service id="TheCodingMachine\GraphQLite\Types\TypeResolver" />

<service id="TheCodingMachine\GraphQLite\TypeRegistry" />

<service id="TheCodingMachine\Graphqlite\Bundle\Controller\GraphqliteController" public="true" />
</services>

</container>
8 changes: 8 additions & 0 deletions Resources/config/routes.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8" ?>
<routes xmlns="http://symfony.com/schema/routing"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://symfony.com/schema/routing
http://symfony.com/schema/routing/routing-1.0.xsd">

<import resource="TheCodingMachine\Graphqlite\Bundle\Controller\GraphqliteController:loadRoutes" type="service"/>
</routes>
20 changes: 19 additions & 1 deletion Tests/GraphqliteTestingKernel.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,24 @@
namespace TheCodingMachine\Graphqlite\Bundle\Tests;


use Symfony\Bundle\FrameworkBundle\Kernel\MicroKernelTrait;
use Symfony\Component\Config\Loader\LoaderInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\HttpKernel\Kernel;
use Symfony\Component\Routing\RouteCollectionBuilder;
use TheCodingMachine\Graphqlite\Bundle\GraphqliteBundle;

class GraphqliteTestingKernel extends Kernel
{
use MicroKernelTrait;

const CONFIG_EXTS = '.{php,xml,yaml,yml}';

public function __construct()
{
parent::__construct('test', true);
}

public function registerBundles()
{
return [
Expand All @@ -22,7 +30,7 @@ public function registerBundles()
];
}

public function registerContainerConfiguration(LoaderInterface $loader)
public function configureContainer(ContainerBuilder $c, LoaderInterface $loader)
{
$loader->load(function(ContainerBuilder $container) {
$container->loadFromExtension('framework', array(
Expand All @@ -42,4 +50,14 @@ public function registerContainerConfiguration(LoaderInterface $loader)
$loader->load($confDir.'/{services}'.self::CONFIG_EXTS, 'glob');
$loader->load($confDir.'/{services}_'.$this->environment.self::CONFIG_EXTS, 'glob');
}

protected function configureRoutes(RouteCollectionBuilder $routes)
{
$routes->import(__DIR__.'/../Resources/config/routes.xml');
}

public function getCacheDir()
{
return __DIR__.'/../cache/'.spl_object_hash($this);
}
}
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
"beberlei/porpaginas": "^1.2"
},
"scripts": {
"phpstan": "phpstan analyse GraphqliteBundle.php DependencyInjection/ EventListeners/ Mappers/ Resources/ Security/ -c phpstan.neon --level=7 --no-progress"
"phpstan": "phpstan analyse GraphqliteBundle.php DependencyInjection/ Controller/ Mappers/ Resources/ Security/ -c phpstan.neon --level=7 --no-progress"
},
"suggest": {
"symfony/security-bundle": "To use @Logged or @Right annotations"
Expand Down
1 change: 0 additions & 1 deletion phpstan.neon
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
parameters:
ignoreErrors:
- "#Call to an undefined method Symfony\\\\Component\\\\Config\\\\Definition\\\\Builder\\\\NodeDefinition::children\\(\\)#"
- "/Parameter #2 $haystack of function in_array expects array, array<string>|string given./"
- "#Access to an undefined property GraphQL\\\\Type\\\\Definition\\\\NamedType&GraphQL\\\\Type\\\\Definition\\\\OutputType::\\$name.#"
#includes:
# - vendor/thecodingmachine/phpstan-strict-rules/phpstan-strict-rules.neon