Passed
Pull Request — master (#158)
by Christoffer
04:56 queued 02:10
created

ValuesHelper::getArgumentValues()   C

Complexity

Conditions 10
Paths 10

Size

Total Lines 63
Code Lines 37

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 63
rs 6.3636
c 0
b 0
f 0
cc 10
eloc 37
nc 10
nop 3

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
namespace Digia\GraphQL\Execution;
4
5
use Digia\GraphQL\Error\CoercingException;
6
use Digia\GraphQL\Error\ExecutionException;
7
use Digia\GraphQL\Error\InvalidTypeException;
8
use Digia\GraphQL\Error\InvariantException;
9
use Digia\GraphQL\Language\Node\ArgumentNode;
10
use Digia\GraphQL\Language\Node\ArgumentsAwareInterface;
11
use Digia\GraphQL\Language\Node\NameAwareInterface;
12
use Digia\GraphQL\Language\Node\VariableNode;
13
use Digia\GraphQL\Type\Definition\Directive;
14
use Digia\GraphQL\Type\Definition\Field;
15
use Digia\GraphQL\Type\Definition\NonNullType;
16
use Digia\GraphQL\Type\Definition\TypeInterface;
17
use function Digia\GraphQL\Util\find;
18
use function Digia\GraphQL\Util\keyMap;
19
use function Digia\GraphQL\Util\valueFromAST;
20
21
class ValuesHelper
22
{
23
    /**
24
     * @see http://facebook.github.io/graphql/October2016/#CoerceArgumentValues()
25
     *
26
     * @param Field|Directive         $definition
27
     * @param ArgumentsAwareInterface $node
28
     * @param array                   $variableValues
29
     * @return array
30
     * @throws ExecutionException
31
     * @throws InvalidTypeException
32
     * @throws InvariantException
33
     */
34
    public function getArgumentValues($definition, ArgumentsAwareInterface $node, array $variableValues = []): array
35
    {
36
        $coercedValues       = [];
37
        $argumentDefinitions = $definition->getArguments();
38
        $argumentNodes       = $node->getArguments();
39
40
        if (empty($argumentDefinitions) || empty($argumentNodes)) {
41
            return $coercedValues;
42
        }
43
44
        $argumentNodeMap = keyMap($argumentNodes, function (ArgumentNode $value) {
45
            return $value->getNameValue();
46
        });
47
48
        foreach ($argumentDefinitions as $argumentDefinition) {
49
            $argumentName = $argumentDefinition->getName();
50
            $argumentType = $argumentDefinition->getType();
51
            /** @var ArgumentNode $argumentNode */
52
            $argumentNode = $argumentNodeMap[$argumentName];
53
            $defaultValue = $argumentDefinition->getDefaultValue();
54
55
            if (null === $argumentNode) {
56
                if (null === $defaultValue) {
57
                    $coercedValues[$argumentName] = $defaultValue;
58
                } elseif (!$argumentType instanceof NonNullType) {
59
                    throw new ExecutionException(
60
                        sprintf('Argument "%s" of required type "%s" was not provided.', $argumentName, $argumentType),
61
                        [$node]
62
                    );
63
                }
64
            } elseif ($argumentNode instanceof VariableNode) {
65
                $coercedValues[$argumentName] = $this->coerceValueForVariableNode(
66
                    $argumentNode,
67
                    $argumentType,
68
                    $argumentName,
69
                    $variableValues,
70
                    $defaultValue
71
                );
72
            } else {
73
                $coercedValue = null;
0 ignored issues
show
Unused Code introduced by
The assignment to $coercedValue is dead and can be removed.
Loading history...
74
75
                try {
76
                    $coercedValue = valueFromAST($argumentNode->getValue(), $argumentType, $variableValues);
77
                } catch (CoercingException $ex) {
78
                    // Value nodes that cannot be resolved should be treated as invalid values
79
                    // therefore we catch the exception and leave the `$coercedValue` as `null`.
80
                }
81
82
                if (null === $coercedValue) {
83
                    // Note: ValuesOfCorrectType validation should catch this before
84
                    // execution. This is a runtime check to ensure execution does not
85
                    // continue with an invalid argument value.
86
                    throw new ExecutionException(
87
                        sprintf('Argument "%s" has invalid value %s.', $argumentName, $argumentNode),
88
                        [$argumentNode->getValue()]
89
                    );
90
                }
91
92
                $coercedValues[$argumentName] = $coercedValue;
93
            }
94
        }
95
96
        return $coercedValues;
97
    }
98
99
    /**
100
     * @param Directive $directive
101
     * @param mixed     $node
102
     * @param array     $variableValues
103
     * @return array|null
104
     * @throws ExecutionException
105
     * @throws InvalidTypeException
106
     * @throws InvariantException
107
     */
108
    public function getDirectiveValues(
109
        Directive $directive,
110
        $node,
111
        array $variableValues = []
112
    ): ?array {
113
        $directiveNode = $node->hasDirectives()
114
            ? find($node->getDirectives(), function (NameAwareInterface $value) use ($directive) {
115
                return $value->getNameValue() === $directive->getName();
116
            }) : null;
117
118
        if (null !== $directiveNode) {
119
            return $this->getArgumentValues($directive, $directiveNode, $variableValues);
120
        }
121
122
        return null;
123
    }
124
125
    /**
126
     * @param VariableNode  $variableNode
127
     * @param TypeInterface $argumentType
128
     * @param string        $argumentName
129
     * @param array         $variableValues
130
     * @param mixed         $defaultValue
131
     * @return mixed
132
     * @throws ExecutionException
133
     */
134
    protected function coerceValueForVariableNode(
135
        VariableNode $variableNode,
136
        TypeInterface $argumentType,
137
        string $argumentName,
138
        array $variableValues,
139
        $defaultValue
140
    ) {
141
        $variableName = $variableNode->getNameValue();
142
143
        if (!empty($variableValues) && isset($variableValues[$variableName])) {
144
            // Note: this does not check that this variable value is correct.
145
            // This assumes that this query has been validated and the variable
146
            // usage here is of the correct type.
147
            return $variableValues[$variableName];
148
        }
149
150
        if (null !== $defaultValue) {
151
            return $defaultValue;
152
        }
153
154
        if ($argumentType instanceof NonNullType) {
155
            throw new ExecutionException(
156
                \sprintf(
157
                    'Argument "%s" of required type "%s" was provided the variable "%s" which was not provided a runtime value.',
158
                    $argumentName,
159
                    $argumentType,
160
                    $variableName
161
                ),
162
                [$variableNode->getValue()]
0 ignored issues
show
Bug introduced by
The method getValue() does not exist on Digia\GraphQL\Language\Node\VariableNode. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

162
                [$variableNode->/** @scrutinizer ignore-call */ getValue()]

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
163
            );
164
        }
165
    }
166
}
167