1 | <?php |
||||
2 | |||||
3 | namespace Fnash\GraphQL; |
||||
4 | |||||
5 | trait QueryTrait |
||||
6 | { |
||||
7 | private static $operationNamePlaceholder = '_operationNamePlaceholder_'; |
||||
8 | |||||
9 | /** |
||||
10 | * @var string |
||||
11 | */ |
||||
12 | public $operationName; |
||||
13 | |||||
14 | /** |
||||
15 | * @var array |
||||
16 | */ |
||||
17 | public $variables = []; |
||||
18 | |||||
19 | /** |
||||
20 | * @var bool |
||||
21 | */ |
||||
22 | public $isRootQuery = true; |
||||
23 | |||||
24 | /** |
||||
25 | * @var array |
||||
26 | */ |
||||
27 | public $type = []; |
||||
28 | |||||
29 | /** |
||||
30 | * @var array |
||||
31 | */ |
||||
32 | public $args = []; |
||||
33 | |||||
34 | /** |
||||
35 | * @var array |
||||
36 | */ |
||||
37 | public $fields = []; |
||||
38 | |||||
39 | /** |
||||
40 | * @var array |
||||
41 | */ |
||||
42 | public $skipIf = []; |
||||
43 | |||||
44 | /** |
||||
45 | * @var array |
||||
46 | */ |
||||
47 | public $includeIf = []; |
||||
48 | |||||
49 | /** |
||||
50 | * @var array |
||||
51 | */ |
||||
52 | public $fragments = []; |
||||
53 | |||||
54 | /** |
||||
55 | * @param null $type |
||||
0 ignored issues
–
show
Documentation
Bug
introduced
by
![]() |
|||||
56 | * @param array $args |
||||
57 | * @param array $fields |
||||
58 | * |
||||
59 | * @return self |
||||
60 | */ |
||||
61 | public static function create($type = null, array $args = [], array $fields = []) |
||||
62 | { |
||||
63 | return new self($type, $args, $fields); |
||||
64 | } |
||||
65 | |||||
66 | /** |
||||
67 | * @param string $operationName |
||||
68 | * |
||||
69 | * @return self |
||||
70 | */ |
||||
71 | public function operationName(string $operationName) |
||||
72 | { |
||||
73 | $this->operationName = $operationName; |
||||
74 | |||||
75 | return $this; |
||||
76 | } |
||||
77 | |||||
78 | /** |
||||
79 | * @param $operationName |
||||
80 | * @param $variables |
||||
81 | * |
||||
82 | * @return string |
||||
83 | */ |
||||
84 | private static function printQuery($operationName, $variables): string |
||||
85 | { |
||||
86 | if (null === $operationName) { |
||||
87 | if (\count($variables)) { |
||||
88 | $operationName = static::$operationNamePlaceholder; |
||||
0 ignored issues
–
show
|
|||||
89 | } else { |
||||
90 | return static::class === Mutation::class ? sprintf('%s', static::KEYWORD) : ''; |
||||
0 ignored issues
–
show
|
|||||
91 | } |
||||
92 | } |
||||
93 | |||||
94 | return sprintf('%s %s %s', static::KEYWORD, $operationName, static::printVariables($variables)); |
||||
0 ignored issues
–
show
|
|||||
95 | } |
||||
96 | |||||
97 | /** |
||||
98 | * @param array $variables |
||||
99 | * |
||||
100 | * @return self |
||||
101 | */ |
||||
102 | public function variables(array $variables = []) |
||||
103 | { |
||||
104 | foreach ($variables as $variableName => $variableType) { |
||||
105 | $this->variables[(string) $variableName] = (string) $variableType; |
||||
106 | } |
||||
107 | |||||
108 | return $this; |
||||
109 | } |
||||
110 | |||||
111 | /** |
||||
112 | * @param array $value |
||||
113 | * |
||||
114 | * @return string |
||||
115 | */ |
||||
116 | private static function printVariables(array $value): string |
||||
117 | { |
||||
118 | if (!\count($value)) { |
||||
119 | return ''; |
||||
120 | } |
||||
121 | |||||
122 | $variables = []; |
||||
123 | |||||
124 | foreach ($value as $variableName => $variableType) { |
||||
125 | $variables[] = sprintf('%s: %s', $variableName, $variableType); |
||||
126 | } |
||||
127 | |||||
128 | return sprintf('(%s)', implode(', ', $variables)); |
||||
129 | } |
||||
130 | |||||
131 | /** |
||||
132 | * @param array $args |
||||
133 | * |
||||
134 | * @return self |
||||
135 | */ |
||||
136 | public function arguments(array $args = []) |
||||
137 | { |
||||
138 | foreach ($args as $name => $value) { |
||||
139 | $this->args[$name] = $value; |
||||
140 | } |
||||
141 | |||||
142 | ksort($this->args); |
||||
143 | |||||
144 | return $this; |
||||
145 | } |
||||
146 | |||||
147 | /** |
||||
148 | * @param array $value |
||||
149 | * |
||||
150 | * @return string |
||||
151 | */ |
||||
152 | private static function printArgs(array $value): string |
||||
153 | { |
||||
154 | if (!count($value)) { |
||||
155 | return ''; |
||||
156 | } |
||||
157 | |||||
158 | $args = []; |
||||
159 | foreach ($value as $argName => $argValue) { |
||||
160 | if (\is_string($argValue) && '$' !== $argValue[0]) { |
||||
161 | if (preg_match_all('/"""/', $argValue) !== 2) { // if not a multi line argument value |
||||
162 | $argValue = sprintf('"%s"', $argValue); |
||||
163 | } |
||||
164 | } |
||||
165 | |||||
166 | if (\is_bool($argValue) || \is_float($argValue)) { |
||||
167 | $argValue = var_export($argValue, true); |
||||
168 | } |
||||
169 | |||||
170 | $args[] = sprintf('%s: %s', $argName, $argValue); |
||||
171 | } |
||||
172 | |||||
173 | return sprintf('(%s)', implode(', ', $args)); |
||||
174 | } |
||||
175 | |||||
176 | /** |
||||
177 | * @param array $fields |
||||
178 | * |
||||
179 | * @return self |
||||
180 | */ |
||||
181 | public function fields(array $fields = []) |
||||
182 | { |
||||
183 | foreach ($fields as $fieldAlias => $field) { |
||||
184 | if (\is_string($field)) { |
||||
185 | if (\is_string($fieldAlias)) { |
||||
186 | $this->fields[$fieldAlias] = $field; |
||||
187 | } else { |
||||
188 | $this->fields[$field] = $field; |
||||
189 | } |
||||
190 | } |
||||
191 | |||||
192 | if ($field instanceof Query) { |
||||
193 | $field->isRootQuery = false; |
||||
194 | $this->fields[$fieldAlias] = $field; |
||||
195 | } |
||||
196 | } |
||||
197 | |||||
198 | ksort($this->fields); |
||||
199 | |||||
200 | return $this; |
||||
201 | } |
||||
202 | |||||
203 | /** |
||||
204 | * @param array $fields |
||||
205 | * |
||||
206 | * @return self |
||||
207 | */ |
||||
208 | public function removeFields(array $fields = []): Query |
||||
209 | { |
||||
210 | foreach ($fields as $field) { |
||||
211 | unset($this->fields[$field]); |
||||
212 | } |
||||
213 | |||||
214 | return $this; |
||||
215 | } |
||||
216 | |||||
217 | /** |
||||
218 | * @param array $value |
||||
219 | * @param array $skipIf |
||||
220 | * @param array $includeIf |
||||
221 | * |
||||
222 | * @return string |
||||
223 | */ |
||||
224 | private static function printFields(array $value, array $skipIf = [], array $includeIf = []): string |
||||
225 | { |
||||
226 | $fields = []; |
||||
227 | |||||
228 | foreach ($value as $fieldAlias => $field) { |
||||
229 | $directive = ''; |
||||
230 | |||||
231 | if (\is_string($field)) { |
||||
232 | if ($fieldAlias !== $field) { |
||||
233 | if (array_key_exists($fieldAlias, $skipIf)) { |
||||
234 | $directive = sprintf('@skip(if: %s)', $skipIf[$fieldAlias]); |
||||
235 | } elseif (array_key_exists($fieldAlias, $includeIf)) { |
||||
236 | $directive = sprintf('@include(if: %s)', $includeIf[$fieldAlias]); |
||||
237 | } |
||||
238 | |||||
239 | $fields[] = sprintf('%s: %s %s', $fieldAlias, $field, $directive); |
||||
240 | } else { |
||||
241 | if (array_key_exists($field, $skipIf)) { |
||||
242 | $directive = sprintf('@skip(if: %s)', $skipIf[$field]); |
||||
243 | } elseif (array_key_exists($field, $includeIf)) { |
||||
244 | $directive = sprintf('@include(if: %s)', $includeIf[$field]); |
||||
245 | } |
||||
246 | |||||
247 | $fields[] = sprintf('%s %s', $field, $directive); |
||||
248 | } |
||||
249 | } |
||||
250 | |||||
251 | if ($field instanceof Query) { |
||||
252 | $field->isRootQuery = false; |
||||
253 | |||||
254 | if (array_key_exists($fieldAlias, $skipIf)) { |
||||
255 | $directive = sprintf('@skip(if: %s)', $skipIf[$fieldAlias]); |
||||
256 | } elseif (array_key_exists($fieldAlias, $includeIf)) { |
||||
257 | $directive = sprintf('@include(if: %s)', $includeIf[$fieldAlias]); |
||||
258 | } |
||||
259 | |||||
260 | if (null !== $field->type) { |
||||
261 | $fieldAlias = sprintf('%s: %s', $fieldAlias, $field->type); |
||||
0 ignored issues
–
show
$field->type of type array is incompatible with the type string expected by parameter $args of sprintf() .
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
262 | } |
||||
263 | |||||
264 | $fields[] = sprintf('%s %s { %s }', $fieldAlias, $directive, static::printFields($field->fields)); |
||||
265 | } |
||||
266 | } |
||||
267 | |||||
268 | return implode(', ', $fields); |
||||
269 | } |
||||
270 | |||||
271 | /** |
||||
272 | * @param array $values |
||||
273 | * |
||||
274 | * @return self |
||||
275 | */ |
||||
276 | public function skipIf(array $values = []) |
||||
277 | { |
||||
278 | foreach ($values as $field => $argument) { |
||||
279 | $this->skipIf[$field] = $argument; |
||||
280 | } |
||||
281 | |||||
282 | return $this; |
||||
283 | } |
||||
284 | |||||
285 | /** |
||||
286 | * @param array $values |
||||
287 | * |
||||
288 | * @return self |
||||
289 | */ |
||||
290 | public function includeIf(array $values = []) |
||||
291 | { |
||||
292 | foreach ($values as $field => $argument) { |
||||
293 | $this->includeIf[$field] = $argument; |
||||
294 | } |
||||
295 | |||||
296 | return $this; |
||||
297 | } |
||||
298 | |||||
299 | public function __toString() |
||||
300 | { |
||||
301 | if ($this->isRootQuery) { |
||||
302 | $query = sprintf('%s { %s %s { %s } } %s', static::printQuery($this->operationName, $this->variables), static::printType($this->type), static::printArgs($this->args), static::printFields($this->fields, $this->skipIf, $this->includeIf), static::printFragments($this->fragments)); |
||||
0 ignored issues
–
show
The method
Fnash\GraphQL\QueryTrait::printFragments() is not static, but was called statically.
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
303 | } else { |
||||
304 | $query = sprintf('%s { %s }', static::printType($this->type), static::printFields($this->fields, $this->skipIf, $this->includeIf)); |
||||
305 | } |
||||
306 | |||||
307 | $query = \GraphQL\Language\Printer::doPrint(\GraphQL\Language\Parser::parse((string) $query)); |
||||
308 | |||||
309 | $query = str_replace(static::$operationNamePlaceholder, static::GENERATED_NAME_PREFIX.sha1($query), $query); |
||||
0 ignored issues
–
show
|
|||||
310 | |||||
311 | return $query; |
||||
312 | } |
||||
313 | |||||
314 | /** |
||||
315 | * @param Fragment $fragment |
||||
316 | * |
||||
317 | * @return $this |
||||
318 | */ |
||||
319 | public function addFragment(Fragment $fragment) |
||||
320 | { |
||||
321 | $this->fragments[$fragment->name] = $fragment; |
||||
322 | |||||
323 | return $this; |
||||
324 | } |
||||
325 | |||||
326 | /** |
||||
327 | * @param $value |
||||
328 | * |
||||
329 | * @return string |
||||
330 | */ |
||||
331 | private function printFragments($value) |
||||
332 | { |
||||
333 | $fragments = ''; |
||||
334 | foreach ($value as $fragment) { |
||||
335 | $fragments .= (string) $fragment; |
||||
336 | } |
||||
337 | |||||
338 | return $fragments; |
||||
339 | } |
||||
340 | |||||
341 | /** |
||||
342 | * @param null $type |
||||
0 ignored issues
–
show
|
|||||
343 | * @param array $args |
||||
344 | * @param array $fields |
||||
345 | */ |
||||
346 | private function __construct($type = null, array $args = [], array $fields = []) |
||||
347 | { |
||||
348 | $this->type = $type; |
||||
349 | |||||
350 | $this->arguments($args); |
||||
351 | |||||
352 | $this->fields($fields); |
||||
353 | } |
||||
354 | |||||
355 | private static function printType($value): string |
||||
356 | { |
||||
357 | if (\is_string($value)) { |
||||
358 | return $value; |
||||
359 | } |
||||
360 | |||||
361 | if (\is_array($value) && \count($value)) { |
||||
362 | foreach ($value as $alias => $type) { |
||||
363 | return sprintf('%s: %s', $alias, $type); |
||||
364 | } |
||||
365 | } |
||||
366 | } |
||||
367 | } |
||||
368 |