Passed
Pull Request — master (#209)
by Christoffer
02:17
created

NodePrinter   A

Complexity

Total Complexity 35

Size/Duplication

Total Lines 341
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
dl 0
loc 341
rs 9
c 0
b 0
f 0
wmc 35

27 Methods

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