Completed
Pull Request — master (#18)
by Quang
03:15
created

Execution::collectFields()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 18
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 18
rs 9.4285
c 0
b 0
f 0
cc 3
eloc 7
nc 3
nop 4
1
<?php
2
3
namespace Digia\GraphQL\Execution;
4
5
use Digia\GraphQL\Error\GraphQLError;
6
use Digia\GraphQL\Language\AST\Node\DocumentNode;
7
use Digia\GraphQL\Language\AST\NodeKindEnum;
8
use Digia\GraphQL\Type\Schema;
9
10
/**
11
 * Class Execution
12
 * @package Digia\GraphQL\Execution
13
 */
14
class Execution
15
{
16
    /**
17
     * @var ExecutionContext
18
     */
19
    protected $context;
20
21
    /**
22
     * Execution constructor.
23
     * @param ExecutionContext $context
24
     */
25
    public function __construct(ExecutionContext $context)
26
    {
27
        $this->context = $context;
28
    }
29
30
    /**
31
     * @param Schema $schema
32
     * @param DocumentNode $documentNode
33
     * @param null $rootValue
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $variableValues is correct as it would always require null to be passed?
Loading history...
Documentation Bug introduced by
Are you sure the doc-type for parameter $contextValue is correct as it would always require null to be passed?
Loading history...
Documentation Bug introduced by
Are you sure the doc-type for parameter $rootValue is correct as it would always require null to be passed?
Loading history...
Documentation Bug introduced by
Are you sure the doc-type for parameter $operationName is correct as it would always require null to be passed?
Loading history...
34
     * @param null $contextValue
35
     * @param null $variableValues
36
     * @param null $operationName
37
     * @param callable|null $fieldResolver
38
     * @return ExecutionResult
39
     */
40
    public static function execute(
41
        Schema $schema,
42
        DocumentNode $documentNode,
43
        $rootValue = null,
44
        $contextValue = null,
45
        $variableValues = null,
46
        $operationName = null,
47
        callable $fieldResolver = null
48
    ) {
49
        try {
50
            $context = self::buildExecutionContext(
51
                $schema,
52
                $documentNode,
53
                $rootValue,
54
                $contextValue,
55
                $variableValues,
56
                $operationName,
57
                $fieldResolver
58
            );
59
        } catch (GraphQLError $error) {
60
            return new ExecutionResult(['data' => null], [$error]);
61
        }
62
63
        $data = $context->getExecutionStrategy()->execute();
64
65
        return new ExecutionResult($data, $context->getErrors());
66
    }
67
68
    /**
69
     * @TODO: Consider to create a ExecutionContextBuilder
70
     * @param Schema $schema
71
     * @param DocumentNode $documentNode
72
     * @param $rootValue
73
     * @param $contextValue
74
     * @param $rawVariableValues
75
     * @param null $operationName
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $operationName is correct as it would always require null to be passed?
Loading history...
76
     * @param callable|null $fieldResolver
77
     * @throws GraphQLError
78
     * @return ExecutionContext
79
     */
80
    private static function buildExecutionContext(
81
        Schema $schema,
82
        DocumentNode $documentNode,
83
        $rootValue,
84
        $contextValue,
85
        $rawVariableValues,
86
        $operationName = null,
87
        callable $fieldResolver = null
88
    ): ExecutionContext {
89
        //TODO: Validate raw variables, operation name etc.
90
        //TODO: Validate document definition
91
92
        $errors    = [];
93
        $fragments = [];
94
        $operation = null;
95
96
        foreach ($documentNode->getDefinitions() as $definition) {
97
            switch ($definition->getKind()) {
98
                case NodeKindEnum::OPERATION_DEFINITION:
99
                    if (!$operationName && $operation) {
100
                        throw new GraphQLError(
101
                            'Must provide operation name if query contains multiple operations.'
102
                        );
103
                    }
104
105
                    if (!$operationName || (!empty($definition->getName()) && $definition->getName()->getValue() === $operationName)) {
106
                        $operation = $definition;
107
                    }
108
                    break;
109
                case NodeKindEnum::FRAGMENT_DEFINITION:
110
                case NodeKindEnum::FRAGMENT_SPREAD:
111
                    $fragments[$definition->getName()->getValue()] = $definition;
112
                    break;
113
                default:
114
                    throw new GraphQLError(
115
                        "GraphQL cannot execute a request containing a {$definition->getKind()}."
116
                    );
117
            }
118
        }
119
120
        $executionContext = new ExecutionContext(
121
            $schema,
122
            $fragments,
123
            $rootValue,
124
            $contextValue,
125
            $rawVariableValues,
126
            $fieldResolver,
127
            $operation,
128
            $errors
129
        );
130
131
        return $executionContext;
132
    }
133
}
134