Passed
Push — master ( 60fdc2...e86c97 )
by Christoffer
02:07
created

Printer::printOperationDefinition()   B

Complexity

Conditions 5
Paths 8

Size

Total Lines 17
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 5
eloc 12
nc 8
nop 1
dl 0
loc 17
rs 8.8571
c 0
b 0
f 0
1
<?php
2
3
namespace Digia\GraphQL\Language;
4
5
use Digia\GraphQL\Error\LanguageException;
6
use Digia\GraphQL\Language\Node\ArgumentNode;
7
use Digia\GraphQL\Language\Node\BooleanValueNode;
8
use Digia\GraphQL\Language\Node\DirectiveNode;
9
use Digia\GraphQL\Language\Node\DocumentNode;
10
use Digia\GraphQL\Language\Node\EnumValueNode;
11
use Digia\GraphQL\Language\Node\FieldNode;
12
use Digia\GraphQL\Language\Node\FloatValueNode;
13
use Digia\GraphQL\Language\Node\FragmentDefinitionNode;
14
use Digia\GraphQL\Language\Node\FragmentSpreadNode;
15
use Digia\GraphQL\Language\Node\InlineFragmentNode;
16
use Digia\GraphQL\Language\Node\IntValueNode;
17
use Digia\GraphQL\Language\Node\ListTypeNode;
18
use Digia\GraphQL\Language\Node\ListValueNode;
19
use Digia\GraphQL\Language\Node\NamedTypeNode;
20
use Digia\GraphQL\Language\Node\NameNode;
21
use Digia\GraphQL\Language\Node\NodeInterface;
22
use Digia\GraphQL\Language\Node\NonNullTypeNode;
23
use Digia\GraphQL\Language\Node\NullValueNode;
24
use Digia\GraphQL\Language\Node\ObjectFieldNode;
25
use Digia\GraphQL\Language\Node\ObjectValueNode;
26
use Digia\GraphQL\Language\Node\OperationDefinitionNode;
27
use Digia\GraphQL\Language\Node\SelectionSetNode;
28
use Digia\GraphQL\Language\Node\StringValueNode;
29
use Digia\GraphQL\Language\Node\VariableDefinitionNode;
30
use Digia\GraphQL\Language\Node\VariableNode;
31
use function Digia\GraphQL\Util\toString;
32
33
class Printer implements PrinterInterface
34
{
35
    /**
36
     * @inheritdoc
37
     * @throws LanguageException
38
     */
39
    public function print(NodeInterface $node): string
40
    {
41
        $printMethod = 'print' . $node->getKind();
42
43
        if (\method_exists($this, $printMethod)) {
44
            return $this->{$printMethod}($node);
45
        }
46
47
        throw new LanguageException(\sprintf('Invalid AST Node: %s.', toString($node)));
48
    }
49
50
    /**
51
     * @param NameNode $node
52
     * @return string
53
     */
54
    protected function printName(NameNode $node): string
55
    {
56
        return $node->getValue();
0 ignored issues
show
Bug Best Practice introduced by
The expression return $node->getValue() could return the type null which is incompatible with the type-hinted return string. Consider adding an additional type-check to rule them out.
Loading history...
57
    }
58
59
    /**
60
     * @param VariableNode $node
61
     * @return string
62
     */
63
    protected function printVariable(VariableNode $node): string
64
    {
65
        return '$' . $node->getName();
66
    }
67
68
    // Document
69
70
    /**
71
     * @param DocumentNode $node
72
     * @return string
73
     */
74
    protected function printDocument(DocumentNode $node): string
75
    {
76
        return \implode("\n\n", $node->getDefinitions()) . "\n";
77
    }
78
79
    /**
80
     * @param OperationDefinitionNode $node
81
     * @return string
82
     * @throws LanguageException
83
     */
84
    protected function printOperationDefinition(OperationDefinitionNode $node): string
85
    {
86
        $operation            = $node->getOperation();
87
        $name                 = $this->one($node->getName());
88
        $variablesDefinitions = $this->many($node->getVariableDefinitions());
89
        $directives           = $this->many($node->getDirectives());
90
        $selectionSet         = $this->one($node->getSelectionSet());
91
92
        // Anonymous queries with no directives or variable definitions can use
93
        // the query short form.
94
        return null === $name && empty($directives) && empty($variablesDefinitions) && $operation === 'query'
0 ignored issues
show
introduced by
The condition null === $name is always false.
Loading history...
95
            ? $selectionSet
96
            : \implode(' ', [
97
                $operation,
98
                $name . wrap('(', \implode(', ', $variablesDefinitions), ')'),
99
                \implode(' ', $directives),
100
                $selectionSet,
101
            ]);
102
    }
103
104
    /**
105
     * @param VariableDefinitionNode $node
106
     * @return string
107
     * @throws LanguageException
108
     */
109
    protected function printVariableDefinition(VariableDefinitionNode $node): string
110
    {
111
        $variable     = $this->one($node->getVariable());
112
        $type         = $this->one($node->getType());
113
        $defaultValue = $this->one($node->getDefaultValue());
114
115
        return $variable . ': ' . $type . wrap(' = ', $defaultValue);
116
    }
117
118
    /**
119
     * @param SelectionSetNode $node
120
     * @return string
121
     */
122
    protected function printSelectionSet(SelectionSetNode $node): string
123
    {
124
        return block($this->many($node->getSelections()));
125
    }
126
127
    /**
128
     * @param FieldNode $node
129
     * @return string
130
     * @throws LanguageException
131
     */
132
    protected function printField(FieldNode $node): string
133
    {
134
        $alias        = $this->one($node->getAlias());
135
        $name         = $this->one($node->getName());
136
        $arguments    = $this->many($node->getArguments());
137
        $directives   = $this->many($node->getDirectives());
138
        $selectionSet = $this->one($node->getSelectionSet());
139
140
        return \implode(' ', [
141
            wrap('', $alias, ': ') . $name . wrap('(', \implode(', ', $arguments), ')'),
142
            \implode(' ', $directives),
143
            $selectionSet,
144
        ]);
145
    }
146
147
    /**
148
     * @param ArgumentNode $node
149
     * @return string
150
     * @throws LanguageException
151
     */
152
    protected function printArgument(ArgumentNode $node): string
153
    {
154
        $name  = $this->one($node->getName());
155
        $value = $this->one($node->getValue());
156
157
        return $name . ': ' . $value;
158
    }
159
160
    // Fragments
161
162
    /**
163
     * @param FragmentSpreadNode $node
164
     * @return string
165
     * @throws LanguageException
166
     */
167
    protected function printFragmentSpread(FragmentSpreadNode $node): string
168
    {
169
        $name       = $this->one($node->getName());
170
        $directives = $this->many($node->getDirectives());
171
172
        return '...' . $name . wrap(' ', \implode(' ', $directives));
173
    }
174
175
    /**
176
     * @param InlineFragmentNode $node
177
     * @return string
178
     * @throws LanguageException
179
     */
180
    protected function printInlineFragment(InlineFragmentNode $node): string
181
    {
182
        $typeCondition = $this->one($node->getTypeCondition());
183
        $directives    = $this->many($node->getDirectives());
184
        $selectionSet  = $this->one($node->getSelectionSet());
185
186
        return \implode(' ', [
187
            '...', wrap('on ', $typeCondition),
188
            \implode(' ', $directives),
189
            $selectionSet
190
        ]);
191
    }
192
193
    /**
194
     * @param FragmentDefinitionNode $node
195
     * @return string
196
     * @throws LanguageException
197
     */
198
    protected function printFragmentDefinition(FragmentDefinitionNode $node): string
199
    {
200
        $name                = $this->one($node->getName());
201
        $typeCondition       = $this->one($node->getTypeCondition());
202
        $variableDefinitions = $this->many($node->getVariableDefinitions());
203
        $directives          = $this->many($node->getDirectives());
204
        $selectionSet        = $this->one($node->getSelectionSet());
205
206
        // Note: fragment variable definitions are experimental and may be changed
207
        // or removed in the future.
208
        return \implode(' ', [
209
            'fragment ' . $name . wrap('(', \implode(', ', $variableDefinitions), ')'),
210
            'on ' . $typeCondition . ' ' . \implode(' ', $directives),
211
            $selectionSet
212
        ]);
213
    }
214
215
    // Value
216
217
    /**
218
     * @param IntValueNode $node
219
     * @return string
220
     */
221
    protected function printIntValue(IntValueNode $node): string
222
    {
223
        return $node->getValue();
0 ignored issues
show
Bug Best Practice introduced by
The expression return $node->getValue() could return the type null which is incompatible with the type-hinted return string. Consider adding an additional type-check to rule them out.
Loading history...
224
    }
225
226
    /**
227
     * @param FloatValueNode $node
228
     * @return string
229
     */
230
    protected function printFloatValue(FloatValueNode $node): string
231
    {
232
        return $node->getValue();
0 ignored issues
show
Bug Best Practice introduced by
The expression return $node->getValue() could return the type null which is incompatible with the type-hinted return string. Consider adding an additional type-check to rule them out.
Loading history...
233
    }
234
235
    /**
236
     * @param StringValueNode $node
237
     * @return string
238
     */
239
    protected function printStringValue(StringValueNode $node): string
240
    {
241
        $value = $node->getValue();
242
243
        return $node->isBlock()
0 ignored issues
show
Bug Best Practice introduced by
The expression return $node->isBlock() ...JSON_UNESCAPED_UNICODE) could return the type null|string[] which is incompatible with the type-hinted return string. Consider adding an additional type-check to rule them out.
Loading history...
244
            ? printBlockString($value, false)
245
            : \json_encode($value, JSON_UNESCAPED_UNICODE);
246
    }
247
248
    /**
249
     * @param BooleanValueNode $node
250
     * @return string
251
     */
252
    protected function printBooleanValue(BooleanValueNode $node): string
253
    {
254
        return $node->getValue() ? 'true' : 'false';
255
    }
256
257
    /**
258
     * @param NullValueNode $node
259
     * @return string
260
     */
261
    protected function printNullValue(NullValueNode $node): string
262
    {
263
        return 'null';
264
    }
265
266
    /**
267
     * @param EnumValueNode $node
268
     * @return string
269
     */
270
    protected function printEnumValue(EnumValueNode $node): string
271
    {
272
        return $node->getValue();
0 ignored issues
show
Bug Best Practice introduced by
The expression return $node->getValue() could return the type null which is incompatible with the type-hinted return string. Consider adding an additional type-check to rule them out.
Loading history...
273
    }
274
275
    /**
276
     * @param ListValueNode $node
277
     * @return string
278
     */
279
    protected function printListValue(ListValueNode $node): string
280
    {
281
        $values = $this->many($node->getValues());
282
        return wrap('[', \implode(', ', $values), ']');
283
    }
284
285
    /**
286
     * @param ObjectValueNode $node
287
     * @return string
288
     */
289
    protected function printObjectValue(ObjectValueNode $node): string
290
    {
291
        $fields = $this->many($node->getFields());
292
        return wrap('{', \implode(', ', $fields), '}');
293
    }
294
295
    /**
296
     * @param ObjectFieldNode $node
297
     * @return string
298
     * @throws LanguageException
299
     */
300
    protected function printObjectField(ObjectFieldNode $node): string
301
    {
302
        $name  = $this->one($node->getName());
303
        $value = $this->one($node->getValue());
304
305
        return $name . ': ' . $value;
306
    }
307
308
    // Directive
309
310
    /**
311
     * @param DirectiveNode $node
312
     * @return string
313
     * @throws LanguageException
314
     */
315
    protected function printDirective(DirectiveNode $node): string
316
    {
317
        $name      = $this->one($node->getName());
318
        $arguments = $this->many($node->getArguments());
319
320
        return '@' . $name . wrap('(', \implode(', ', $arguments), ')');
321
    }
322
323
    // Type
324
325
    /**
326
     * @param NamedTypeNode $node
327
     * @return string
328
     * @throws LanguageException
329
     */
330
    protected function printNamedType(NamedTypeNode $node): string
331
    {
332
        return $this->one($node->getName());
333
    }
334
335
    /**
336
     * @param ListTypeNode $node
337
     * @return string
338
     * @throws LanguageException
339
     */
340
    protected function printListType(ListTypeNode $node): string
341
    {
342
        return wrap('[', $this->one($node->getType()), ']');
343
    }
344
345
    /**
346
     * @param NonNullTypeNode $node
347
     * @return string
348
     * @throws LanguageException
349
     */
350
    protected function printNonNullType(NonNullTypeNode $node): string
351
    {
352
        return $this->one($node->getType()) . '!';
353
    }
354
355
    /**
356
     * @param NodeInterface|null $node
357
     * @return string
358
     * @throws LanguageException
359
     */
360
    protected function one(?NodeInterface $node): string
361
    {
362
        return null !== $node ? $this->print($node) : '';
363
    }
364
365
    /**
366
     * @param array $nodes
367
     * @return array
368
     */
369
    protected function many(array $nodes): array
370
    {
371
        return \array_map(function ($node) {
372
            return $this->print($node);
373
        }, $nodes);
374
    }
375
}
376