Skip to content
This repository was archived by the owner on Mar 29, 2020. It is now read-only.

Commit 70faa7e

Browse files
committed
created relay middleware trait
1 parent d23e5db commit 70faa7e

File tree

2 files changed

+200
-0
lines changed

2 files changed

+200
-0
lines changed

src/Context.php

Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
<?php
2+
3+
namespace Nuwave\Relay;
4+
5+
use GraphQL\Executor\Executor;
6+
use GraphQL\Error;
7+
use GraphQL\Language\AST\Document;
8+
use GraphQL\Language\AST\Field;
9+
use GraphQL\Language\AST\FragmentDefinition;
10+
use GraphQL\Language\AST\Node;
11+
use GraphQL\Language\AST\OperationDefinition;
12+
use GraphQL\Language\AST\SelectionSet;
13+
use GraphQL\Schema;
14+
use GraphQL\Type\Definition\AbstractType;
15+
use GraphQL\Type\Definition\Directive;
16+
use GraphQL\Type\Definition\EnumType;
17+
use GraphQL\Type\Definition\FieldDefinition;
18+
use GraphQL\Type\Definition\InterfaceType;
19+
use GraphQL\Type\Definition\ListOfType;
20+
use GraphQL\Type\Definition\NonNull;
21+
use GraphQL\Type\Definition\ObjectType;
22+
use GraphQL\Type\Definition\ResolveInfo;
23+
use GraphQL\Type\Definition\ScalarType;
24+
use GraphQL\Type\Definition\Type;
25+
use GraphQL\Type\Definition\UnionType;
26+
use GraphQL\Type\Introspection;
27+
use GraphQL\Utils;
28+
use GraphQL\Language\Parser;
29+
use GraphQL\Language\Source;
30+
use GraphQL\Validator\DocumentValidator;
31+
use GraphQL\Executor\ExecutionResult;
32+
use GraphQL\Executor\Values;
33+
use GraphQL\Executor\ExecutionContext;
34+
35+
class Context extends Executor
36+
{
37+
private static $UNDEFINED;
38+
39+
/**
40+
* Constructs a ExecutionContext object from the arguments passed to
41+
* execute.
42+
*
43+
* (https://github.com/webonyx/graphql-php/blob/master/src/Executor/Executor.php)
44+
*
45+
* @param Schema $schema [description]
46+
* @param $requestString
47+
* @param $rootValue
48+
* @param $variableValues
49+
* @param $operationName
50+
* @return ExecutionContext
51+
*/
52+
public static function get(Schema $schema, $requestString, $rootValue = null, $variableValues = null, $operationName = null)
53+
{
54+
try {
55+
$source = new Source($requestString ?: '', 'GraphQL request');
56+
$documentAST = Parser::parse($source);
57+
$validationErrors = DocumentValidator::validate($schema, $documentAST);
58+
59+
if (!empty($validationErrors)) {
60+
return null;
61+
} else {
62+
return self::generate($schema, $documentAST, $rootValue, $variableValues, $operationName);
63+
}
64+
} catch (Error $e) {
65+
return null;
66+
}
67+
}
68+
69+
/**
70+
* @param Schema $schema
71+
* @param Document $ast
72+
* @param $rootValue
73+
* @param $variableValues
74+
* @param $operationName
75+
* @return ExecutionContext
76+
*/
77+
protected static function generate(Schema $schema, Document $ast, $rootValue = null, $variableValues = null, $operationName = null)
78+
{
79+
if (!self::$UNDEFINED) {
80+
self::$UNDEFINED = new \stdClass();
81+
}
82+
83+
if (null !== $variableValues) {
84+
Utils::invariant(
85+
is_array($variableValues) || $variableValues instanceof \ArrayAccess,
86+
"Variable values are expected to be array or instance of ArrayAccess, got " . Utils::getVariableType($variableValues)
87+
);
88+
}
89+
90+
if (null !== $operationName) {
91+
Utils::invariant(
92+
is_string($operationName),
93+
"Operation name is supposed to be string, got " . Utils::getVariableType($operationName)
94+
);
95+
}
96+
97+
return self::buildExecutionContext($schema, $ast, $rootValue, $variableValues, $operationName);
98+
}
99+
100+
/**
101+
* @param Schema $schema
102+
* @param Document $documentAst
103+
* @param $rootValue
104+
* @param $rawVariableValues
105+
* @param $operationName
106+
* @return ExecutionContext
107+
*/
108+
protected static function buildExecutionContext(Schema $schema, Document $documentAst, $rootValue, $rawVariableValues, $operationName = null)
109+
{
110+
$errors = [];
111+
$operations = [];
112+
$fragments = [];
113+
114+
foreach ($documentAst->definitions as $statement) {
115+
switch ($statement->kind) {
116+
case Node::OPERATION_DEFINITION:
117+
$operations[$statement->name ? $statement->name->value : ''] = $statement;
118+
break;
119+
case Node::FRAGMENT_DEFINITION:
120+
$fragments[$statement->name->value] = $statement;
121+
break;
122+
}
123+
}
124+
125+
if (!$operationName && count($operations) !== 1) {
126+
throw new Error(
127+
'Must provide operation name if query contains multiple operations.'
128+
);
129+
}
130+
131+
$opName = $operationName ?: key($operations);
132+
133+
if (empty($operations[$opName])) {
134+
throw new Error('Unknown operation named ' . $opName);
135+
}
136+
137+
$operation = $operations[$opName];
138+
$variableValues = Values::getVariableValues($schema, $operation->variableDefinitions ?: [], $rawVariableValues ?: []);
139+
$exeContext = new ExecutionContext($schema, $fragments, $rootValue, $operation, $variableValues, $errors);
140+
141+
return $exeContext;
142+
}
143+
}

src/Traits/RelayMiddleware.php

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
<?php
2+
3+
namespace Nuwave\Relay\Traits;
4+
5+
use Illuminate\Http\Request;
6+
use Nuwave\Relay\Context;
7+
8+
trait RelayMiddleware
9+
{
10+
/**
11+
* Middleware to be attached to GraphQL query.
12+
*
13+
* @var array
14+
*/
15+
protected $relayMiddleware = [];
16+
17+
/**
18+
* Genarate middleware to be run on query.
19+
*
20+
* @param Request $request
21+
* @return array
22+
*/
23+
public function queryMiddleware(Request $request)
24+
{
25+
$relay = app('relay');
26+
$schema = app('graphql')->schema();
27+
$query = $request->get('query');
28+
$params = $request->get('variables');
29+
30+
if (is_string($params)) {
31+
$params = json_decode($params, true);
32+
}
33+
34+
$context = Context::get($schema, $query, null, $params);
35+
$operation = $context->operation->operation;
36+
$selectionSet = $context->operation->selectionSet->selections;
37+
38+
foreach ($selectionSet as $selection) {
39+
if (is_object($selection) && $selection instanceof \GraphQL\Language\AST\Field) {
40+
try {
41+
$schema = $relay->find(
42+
$selection->name->value,
43+
$context->operation->operation
44+
);
45+
46+
if (isset($schema['middleware']) && !empty($schema['middleware'])) {
47+
$this->relayMiddleware = array_merge($this->relayMiddleware, $schema['middleware']);
48+
}
49+
} catch (\Exception $e) {
50+
continue;
51+
}
52+
}
53+
}
54+
55+
return array_unique($this->relayMiddleware);
56+
}
57+
}

0 commit comments

Comments
 (0)