Passed
Pull Request — master (#3)
by
unknown
05:56 queued 02:23
created

AbstractQuery::printArgs()   B

Complexity

Conditions 7
Paths 6

Size

Total Lines 20
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 7
eloc 10
nc 6
nop 1
dl 0
loc 20
rs 8.8333
c 0
b 0
f 0
1
<?php
2
3
namespace Commadore\GraphQL;
4
5
use Commadore\GraphQL\Interfaces\QueryInterface;
6
7
abstract class AbstractQuery implements QueryInterface
8
{
9
    public static $operationNamePlaceholder = '_operationNamePlaceholder_';
10
11
    abstract function getKeyword(): string;
12
    abstract function getPrefix(): string;
13
14
    /**
15
     * @var string
16
     */
17
    public $operationName;
18
19
    /**
20
     * @var array
21
     */
22
    public $variables = [];
23
24
    /**
25
     * @var bool
26
     */
27
    public $isRootQuery = true;
28
29
    /**
30
     * @var array
31
     */
32
    public $type = [];
33
34
    /**
35
     * @var array
36
     */
37
    public $args = [];
38
39
    /**
40
     * @var array
41
     */
42
    public $fields = [];
43
44
    /**
45
     * @var array
46
     */
47
    public $skipIf = [];
48
49
    /**
50
     * @var array
51
     */
52
    public $includeIf = [];
53
54
    /**
55
     * @var array
56
     */
57
    public $fragments = [];
58
59
    /**
60
     * @param null $type
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $type is correct as it would always require null to be passed?
Loading history...
61
     * @param array $args
62
     * @param array $fields
63
     */
64
    public function __construct($type = null, array $args = [], array $fields = [])
65
    {
66
        $this->type = $type;
67
68
        $this->arguments($args);
69
70
        $this->fields($fields);
71
    }
72
73
    /**
74
     * @param string $operationName
75
     *
76
     * @return QueryInterface
77
     */
78
    public function operationName(string $operationName): QueryInterface
79
    {
80
        $this->operationName = $operationName;
81
82
        return $this;
83
    }
84
85
    /**
86
     * @param $operationName
87
     * @param $variables
88
     *
89
     * @return string
90
     */
91
    private function printQuery($operationName, $variables): string
92
    {
93
        if (null === $operationName) {
94
            if (\count($variables)) {
95
                $operationName = static::$operationNamePlaceholder;
96
            } else {
97
                return '';
98
            }
99
        }
100
101
        return sprintf('%s %s %s', $this->getKeyword(), $operationName, $this->printVariables($variables));
102
    }
103
104
    /**
105
     * @param array $variables
106
     *
107
     * @return self
108
     */
109
    public function variables(array $variables = []): QueryInterface
110
    {
111
        foreach ($variables as $variableName => $variableType) {
112
            $this->variables[(string) $variableName] = (string) $variableType;
113
        }
114
115
        return $this;
116
    }
117
118
    /**
119
     * @param array $value
120
     *
121
     * @return string
122
     */
123
    private function printVariables(array $value): string
124
    {
125
        if (!\count($value)) {
126
            return '';
127
        }
128
129
        $variables = [];
130
131
        foreach ($value as $variableName => $variableType) {
132
            $variables[] = sprintf('%s: %s', $variableName, $variableType);
133
        }
134
135
        return sprintf('(%s)', implode(', ', $variables));
136
    }
137
138
    /**
139
     * @param array $args
140
     *
141
     * @return self
142
     */
143
    public function arguments(array $args = []): QueryInterface
144
    {
145
        foreach ($args as $name => $value) {
146
            $this->args[$name] = $value;
147
        }
148
149
        ksort($this->args);
150
151
        return $this;
152
    }
153
154
155
    /**
156
     * @param array $value
157
     *
158
     * @return string
159
     */
160
    private function printArgs(array $value): string
161
    {
162
        if (!count($value)) {
163
            return '';
164
        }
165
166
        $args = [];
167
        foreach ($value as $argName => $argValue) {
168
            if (\is_string($argValue) && '$' !== $argValue[0]) {
169
                $argValue = sprintf('"%s"', $argValue);
170
            }
171
172
            if (\is_bool($argValue) || \is_float($argValue)) {
173
                $argValue = var_export($argValue, true);
174
            }
175
176
            $args[] = sprintf('%s: %s', $argName, $argValue);
177
        }
178
179
        return sprintf('(%s)', implode(', ', $args));
180
    }
181
182
    /**
183
     * @param array $fields
184
     *
185
     * @return self
186
     */
187
    public function fields(array $fields = []): QueryInterface
188
    {
189
        foreach ($fields as $fieldAlias => $field) {
190
            if (\is_string($field)) {
191
                if (\is_string($fieldAlias)) {
192
                    $this->fields[$fieldAlias] = $field;
193
                } else {
194
                    $this->fields[$field] = $field;
195
                }
196
            }
197
198
            if ($field instanceof self) {
199
                $field->isRootQuery = false;
200
                $this->fields[$fieldAlias] = $field;
201
            }
202
        }
203
204
        ksort($this->fields);
205
206
        return $this;
207
    }
208
209
    /**
210
     * @param array $fields
211
     *
212
     * @return self
213
     */
214
    public function removeFields(array $fields = []): QueryInterface
215
    {
216
        foreach ($fields as $field) {
217
            unset($this->fields[$field]);
218
        }
219
220
        return $this;
221
    }
222
223
    /**
224
     * @param array $value
225
     * @param array $skipIf
226
     * @param array $includeIf
227
     *
228
     * @return string
229
     */
230
    private function printFields(array $value, array $skipIf = [], array $includeIf = []): string
231
    {
232
        $fields = [];
233
234
        foreach ($value as $fieldAlias => $field) {
235
            $directive = '';
236
237
            if (\is_string($field)) {
238
                if ($fieldAlias !== $field) {
239
                    if (array_key_exists($fieldAlias, $skipIf)) {
240
                        $directive = sprintf('@skip(if: %s)', $skipIf[$fieldAlias]);
241
                    } elseif (array_key_exists($fieldAlias, $includeIf)) {
242
                        $directive = sprintf('@include(if: %s)', $includeIf[$fieldAlias]);
243
                    }
244
245
                    $fields[] = sprintf('%s: %s %s', $fieldAlias, $field, $directive);
246
                } else {
247
                    if (array_key_exists($field, $skipIf)) {
248
                        $directive = sprintf('@skip(if: %s)', $skipIf[$field]);
249
                    } elseif (array_key_exists($field, $includeIf)) {
250
                        $directive = sprintf('@include(if: %s)', $includeIf[$field]);
251
                    }
252
253
                    $fields[] = sprintf('%s %s', $field, $directive);
254
                }
255
            }
256
257
            if ($field instanceof self) {
258
                $field->isRootQuery = false;
259
260
                if (array_key_exists($fieldAlias, $skipIf)) {
261
                    $directive = sprintf('@skip(if: %s)', $skipIf[$fieldAlias]);
262
                } elseif (array_key_exists($fieldAlias, $includeIf)) {
263
                    $directive = sprintf('@include(if: %s)', $includeIf[$fieldAlias]);
264
                }
265
266
                if (null !== $field->type) {
267
                    $fieldAlias = sprintf('%s: %s', $fieldAlias, $field->type);
0 ignored issues
show
Bug introduced by
$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 ignore-type  annotation

267
                    $fieldAlias = sprintf('%s: %s', $fieldAlias, /** @scrutinizer ignore-type */ $field->type);
Loading history...
268
                }
269
270
                $fields[] = sprintf('%s %s { %s }', $fieldAlias, $directive, static::printFields($field->fields));
0 ignored issues
show
Bug Best Practice introduced by
The method Commadore\GraphQL\AbstractQuery::printFields() 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 ignore-call  annotation

270
                $fields[] = sprintf('%s %s { %s }', $fieldAlias, $directive, static::/** @scrutinizer ignore-call */ printFields($field->fields));
Loading history...
271
            }
272
        }
273
274
        return implode(', ', $fields);
275
    }
276
277
    /**
278
     * @param array $values
279
     *
280
     * @return self
281
     */
282
    public function skipIf(array $values = []): QueryInterface
283
    {
284
        foreach ($values as $field => $argument) {
285
            $this->skipIf[$field] = $argument;
286
        }
287
288
        return $this;
289
    }
290
291
    /**
292
     * @param array $values
293
     *
294
     * @return self
295
     */
296
    public function includeIf(array $values = []): QueryInterface
297
    {
298
        foreach ($values as $field => $argument) {
299
            $this->includeIf[$field] = $argument;
300
        }
301
302
        return $this;
303
    }
304
305
    public function __toString()
306
    {
307
        if ($this->isRootQuery) {
308
            $query = sprintf('%s { %s %s { %s } } %s',
309
                $this->printQuery($this->operationName, $this->variables),
310
                $this->printType($this->type), $this->printArgs($this->args),
311
                $this->printFields($this->fields, $this->skipIf, $this->includeIf),
312
                $this->printFragments($this->fragments));
313
        } else {
314
            $query = sprintf('%s { %s }',
315
                $this->printType($this->type),
316
                $this->printFields($this->fields, $this->skipIf, $this->includeIf));
317
        }
318
319
        $query = \GraphQL\Language\Printer::doPrint(\GraphQL\Language\Parser::parse((string) $query));
320
321
        $query = str_replace(static::$operationNamePlaceholder, $this->getPrefix().sha1($query), $query);
322
323
        return $query;
324
    }
325
326
    /**
327
     * @param Fragment $fragment
328
     *
329
     * @return $this
330
     */
331
    public function addFragment(Fragment $fragment): QueryInterface
332
    {
333
        $this->fragments[$fragment->name] = $fragment;
334
335
        return $this;
336
    }
337
338
    /**
339
     * @param $value
340
     *
341
     * @return string
342
     */
343
    private function printFragments($value)
344
    {
345
        $fragments = '';
346
        foreach ($value as $fragment) {
347
            $fragments .= (string) $fragment;
348
        }
349
350
        return $fragments;
351
    }
352
353
354
    private function printType($value): string
355
    {
356
        if (\is_string($value)) {
357
            return $value;
358
        }
359
360
        if (\is_array($value) && \count($value)) {
361
            foreach ($value as $alias => $type) {
362
                return sprintf('%s: %s', $alias, $type);
363
            }
364
        }
365
    }
366
}
367