RequestProcessor::createSchema()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 12
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 2

Importance

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