|
1
|
|
|
<?php |
|
2
|
|
|
|
|
3
|
|
|
namespace Overblog\GraphQLBundle\Request; |
|
4
|
|
|
|
|
5
|
|
|
use Symfony\Component\HttpFoundation\Request; |
|
6
|
|
|
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException; |
|
7
|
|
|
|
|
8
|
|
|
class Parser implements ParserInterface |
|
9
|
|
|
{ |
|
10
|
|
|
use UploadParserTrait; |
|
11
|
|
|
|
|
12
|
|
|
/** |
|
13
|
|
|
* @param Request $request |
|
14
|
|
|
* |
|
15
|
|
|
* @return array |
|
16
|
|
|
*/ |
|
17
|
29 |
|
public function parse(Request $request) |
|
18
|
|
|
{ |
|
19
|
|
|
// Extracts the GraphQL request parameters |
|
20
|
29 |
|
$parsedBody = $this->getParsedBody($request); |
|
21
|
29 |
|
$data = $this->getParams($request, $parsedBody); |
|
22
|
|
|
|
|
23
|
29 |
|
return $data; |
|
24
|
|
|
} |
|
25
|
|
|
|
|
26
|
|
|
/** |
|
27
|
|
|
* Gets the body from the request based on Content-Type header. |
|
28
|
|
|
* |
|
29
|
|
|
* @param Request $request |
|
30
|
|
|
* |
|
31
|
|
|
* @return array |
|
32
|
|
|
*/ |
|
33
|
29 |
|
private function getParsedBody(Request $request) |
|
34
|
|
|
{ |
|
35
|
29 |
|
$body = $request->getContent(); |
|
36
|
29 |
|
$type = explode(';', $request->headers->get('content-type'), 2)[0]; |
|
37
|
|
|
|
|
38
|
|
|
switch ($type) { |
|
39
|
|
|
// Plain string |
|
40
|
29 |
|
case static::CONTENT_TYPE_GRAPHQL: |
|
41
|
|
|
$parsedBody = [static::PARAM_QUERY => $body]; |
|
42
|
|
|
break; |
|
43
|
|
|
|
|
44
|
|
|
// JSON object |
|
45
|
29 |
View Code Duplication |
case static::CONTENT_TYPE_JSON: |
|
|
|
|
|
|
46
|
|
|
if (empty($body)) { |
|
47
|
|
|
throw new BadRequestHttpException('The request content body must not be empty when using json content type request.'); |
|
48
|
|
|
} |
|
49
|
|
|
|
|
50
|
|
|
$parsedBody = json_decode($body, true); |
|
51
|
|
|
|
|
52
|
|
|
if (JSON_ERROR_NONE !== json_last_error()) { |
|
53
|
|
|
throw new BadRequestHttpException('POST body sent invalid JSON'); |
|
54
|
|
|
} |
|
55
|
|
|
break; |
|
56
|
|
|
|
|
57
|
|
|
// URL-encoded query-string |
|
58
|
29 |
|
case static::CONTENT_TYPE_FORM: |
|
59
|
|
|
$parsedBody = $request->request->all(); |
|
60
|
|
|
break; |
|
61
|
|
|
|
|
62
|
29 |
|
case static::CONTENT_TYPE_FORM_DATA: |
|
63
|
|
|
$parsedBody = $this->handleUploadedFiles($request->request->all(), $request->files->all()); |
|
64
|
|
|
break; |
|
65
|
|
|
|
|
66
|
|
|
default: |
|
67
|
29 |
|
$parsedBody = []; |
|
68
|
29 |
|
break; |
|
69
|
|
|
} |
|
70
|
|
|
|
|
71
|
29 |
|
return $parsedBody; |
|
72
|
|
|
} |
|
73
|
|
|
|
|
74
|
|
|
/** |
|
75
|
|
|
* Gets the GraphQL parameters from the request. |
|
76
|
|
|
* |
|
77
|
|
|
* @param Request $request |
|
78
|
|
|
* @param array $data |
|
79
|
|
|
* |
|
80
|
|
|
* @return array |
|
81
|
|
|
*/ |
|
82
|
29 |
|
private function getParams(Request $request, array $data = []) |
|
83
|
|
|
{ |
|
84
|
|
|
// Add default request parameters |
|
85
|
29 |
|
$data = array_filter($data) + [ |
|
86
|
29 |
|
static::PARAM_QUERY => null, |
|
87
|
29 |
|
static::PARAM_VARIABLES => null, |
|
88
|
29 |
|
static::PARAM_OPERATION_NAME => null, |
|
89
|
|
|
]; |
|
90
|
|
|
|
|
91
|
|
|
// Keep a reference to the query-string |
|
92
|
29 |
|
$qs = $request->query; |
|
93
|
|
|
|
|
94
|
|
|
// Override request using query-string parameters |
|
95
|
29 |
|
$query = $qs->has(static::PARAM_QUERY) ? $qs->get(static::PARAM_QUERY) : $data[static::PARAM_QUERY]; |
|
96
|
29 |
|
$variables = $qs->has(static::PARAM_VARIABLES) ? $qs->get(static::PARAM_VARIABLES) : $data[static::PARAM_VARIABLES]; |
|
97
|
29 |
|
$operationName = $qs->has(static::PARAM_OPERATION_NAME) ? $qs->get(static::PARAM_OPERATION_NAME) : $data[static::PARAM_OPERATION_NAME]; |
|
98
|
|
|
|
|
99
|
|
|
// `query` parameter is mandatory. |
|
100
|
29 |
|
if (empty($query)) { |
|
101
|
|
|
throw new BadRequestHttpException('Must provide query parameter'); |
|
102
|
|
|
} |
|
103
|
|
|
|
|
104
|
|
|
// Variables can be defined using a JSON-encoded object. |
|
105
|
|
|
// If the parsing fails, an exception will be thrown. |
|
106
|
29 |
|
if (is_string($variables)) { |
|
107
|
|
|
$variables = json_decode($variables, true); |
|
108
|
|
|
|
|
109
|
|
|
if (JSON_ERROR_NONE !== json_last_error()) { |
|
110
|
|
|
throw new BadRequestHttpException('Variables are invalid JSON'); |
|
111
|
|
|
} |
|
112
|
|
|
} |
|
113
|
|
|
|
|
114
|
|
|
return [ |
|
115
|
29 |
|
static::PARAM_QUERY => $query, |
|
116
|
29 |
|
static::PARAM_VARIABLES => $variables, |
|
117
|
29 |
|
static::PARAM_OPERATION_NAME => $operationName, |
|
118
|
|
|
]; |
|
119
|
|
|
} |
|
120
|
|
|
} |
|
121
|
|
|
|
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.