Completed
Push — master ( 99dcbb...40d53b )
by Tomáš
05:19
created

RequestProcessor::process()   B

Complexity

Conditions 6
Paths 25

Size

Total Lines 39
Code Lines 21

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 11
CRAP Score 7.5821

Importance

Changes 0
Metric Value
cc 6
eloc 21
nc 25
nop 6
dl 0
loc 39
ccs 11
cts 17
cp 0.6471
crap 7.5821
rs 8.9617
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Portiny\GraphQL\GraphQL;
6
7
use GraphQL\Error\Debug;
8
use GraphQL\Error\FormattedError;
9
use GraphQL\Executor\Promise\Promise;
10
use GraphQL\Executor\Promise\PromiseAdapter;
11
use GraphQL\GraphQL;
12
use GraphQL\Type\Definition\ObjectType;
13
use GraphQL\Type\Schema;
14
use Portiny\GraphQL\Contract\Http\Request\RequestParserInterface;
15
use Portiny\GraphQL\Contract\Provider\MutationFieldsProviderInterface;
16
use Portiny\GraphQL\Contract\Provider\QueryFieldsProviderInterface;
17
use Portiny\GraphQL\GraphQL\Schema\SchemaCacheProvider;
18
use Throwable;
19
use Tracy\ILogger;
20
21
final class RequestProcessor
22
{
23
	/**
24
	 * @var bool
25
	 */
26
	private $debugMode = false;
27
28
	/**
29
	 * @var bool
30
	 */
31
	private $schemaCache = false;
32
33
	/**
34
	 * @var MutationFieldsProviderInterface
35
	 */
36
	private $mutationFieldsProvider;
37
38
	/**
39
	 * @var QueryFieldsProviderInterface
40
	 */
41
	private $queryFieldsProvider;
42
43
	/**
44
	 * @var SchemaCacheProvider
45
	 */
46
	private $schemaCacheProvider;
47
48 2
	public function __construct(
49
		bool $debugMode,
50
		MutationFieldsProviderInterface $mutationFieldsProvider,
51
		QueryFieldsProviderInterface $queryFieldsProvider,
52
		SchemaCacheProvider $schemaCacheProvider
53
	) {
54 2
		$this->debugMode = $debugMode;
55 2
		$this->mutationFieldsProvider = $mutationFieldsProvider;
56 2
		$this->queryFieldsProvider = $queryFieldsProvider;
57 2
		$this->schemaCacheProvider = $schemaCacheProvider;
58 2
	}
59
60 1
	public function setSchemaCache(bool $useSchemaCache): void
61
	{
62 1
		$this->schemaCache = $useSchemaCache;
63 1
	}
64
65
	/**
66
	 * @param mixed|null $context
67
	 * @param array|null $allowedQueries
68
	 * @param array|null $allowedMutations
69
	 */
70 1
	public function process(
71
		RequestParserInterface $requestParser,
72
		array $rootValue = [],
73
		$context = null,
74
		?array $allowedQueries = null,
75
		?array $allowedMutations = null,
76
		?ILogger $logger = null
77
	): array {
78
		try {
79 1
			$cacheKey = $this->schemaCacheProvider->getCacheKey($allowedQueries, $allowedMutations);
80 1
			if ($this->schemaCache && $this->schemaCacheProvider->isCached($cacheKey)) {
81
				$schema = $this->schemaCacheProvider->getSchema($cacheKey);
82
			} else {
83 1
				$schema = $this->createSchema($allowedQueries, $allowedMutations);
84 1
				if ($this->schemaCache) {
85
					$this->schemaCacheProvider->save($cacheKey, $schema);
86
				}
87
			}
88
89 1
			$result = GraphQL::executeQuery(
90 1
				$schema,
91 1
				$requestParser->getQuery(),
92
				$rootValue,
93
				$context,
94 1
				$requestParser->getVariables()
95
			);
96
97 1
			$output = $result->toArray($this->detectDebugLevel($logger));
98
		} catch (Throwable $throwable) {
99
			if ($logger) {
100
				$logger->log($throwable, ILogger::EXCEPTION);
101
			}
102
103
			$output = [
104
				'errors' => [FormattedError::createFromException($throwable, false, 'An error occurred.')],
105
			];
106
		}
107
108 1
		return $output;
109
	}
110
111
	/**
112
	 * @param mixed|null $context
113
	 * @param array|null $allowedQueries
114
	 * @param array|null $allowedMutations
115
	 */
116
	public function processViaPromise(
117
		PromiseAdapter $promiseAdapter,
118
		RequestParserInterface $requestParser,
119
		array $rootValue = [],
120
		$context = null,
121
		?array $allowedQueries = null,
122
		?array $allowedMutations = null,
123
		?ILogger $logger = null
124
	): Promise {
125
		try {
126
			return GraphQL::promiseToExecute(
127
				$promiseAdapter,
128
				$this->createSchema($allowedQueries, $allowedMutations),
129
				$requestParser->getQuery(),
130
				$rootValue,
131
				$context,
132
				$requestParser->getVariables()
133
			);
134
		} catch (Throwable $throwable) {
135
			if ($logger) {
136
				$logger->log($throwable);
137
			}
138
139
			return $promiseAdapter->createRejected($throwable);
140
		}
141
	}
142
143 1
	private function createSchema(?array $allowedQueries = null, ?array $allowedMutations = null): Schema
144
	{
145
		$configuration = [
146 1
			'query' => $this->createQueryObject($allowedQueries),
147
		];
148
149 1
		$mutationObject = $this->createMutationObject($allowedMutations);
150 1
		if ($mutationObject->getFields()) {
151 1
			$configuration['mutation'] = $mutationObject;
152
		}
153
154 1
		return new Schema($configuration);
155
	}
156
157 1
	private function detectDebugLevel(?ILogger $logger): int
158
	{
159 1
		return $this->debugMode
160
			? Debug::INCLUDE_DEBUG_MESSAGE | Debug::INCLUDE_TRACE
161 1
			: ($logger === null ? 0 : Debug::RETHROW_INTERNAL_EXCEPTIONS);
162
	}
163
164 1
	private function createQueryObject(?array $allowedQueries = null): ObjectType
165
	{
166 1
		return new ObjectType([
167 1
			'name' => 'Query',
168 1
			'fields' => $this->queryFieldsProvider->convertFieldsToArray($allowedQueries),
169
		]);
170
	}
171
172 1
	private function createMutationObject(?array $allowedMutations = null): ObjectType
173
	{
174 1
		return new ObjectType([
175 1
			'name' => 'Mutation',
176 1
			'fields' => $this->mutationFieldsProvider->convertFieldsToArray($allowedMutations),
177
		]);
178
	}
179
}
180