Completed
Push — master ( 93ccd7...3b27ab )
by Vladimir
27s queued 13s
created

Executor::promiseToExecute()   A

Complexity

Conditions 2
Paths 1

Size

Total Lines 25
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 12
CRAP Score 2

Importance

Changes 0
Metric Value
eloc 11
dl 0
loc 25
ccs 12
cts 12
cp 1
rs 9.9
c 0
b 0
f 0
cc 2
nc 1
nop 8
crap 2

How to fix   Many Parameters   

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

1
<?php
2
3
declare(strict_types=1);
4
5
namespace GraphQL\Executor;
6
7
use ArrayAccess;
8
use Closure;
9
use GraphQL\Executor\Promise\Adapter\SyncPromiseAdapter;
10
use GraphQL\Executor\Promise\Promise;
11
use GraphQL\Executor\Promise\PromiseAdapter;
12
use GraphQL\Language\AST\DocumentNode;
13
use GraphQL\Type\Definition\ResolveInfo;
14
use GraphQL\Type\Schema;
15
use function is_array;
16
use function is_object;
17
18
/**
19
 * Implements the "Evaluating requests" section of the GraphQL specification.
20
 */
21
class Executor
22
{
23
    /** @var callable|string[] */
24
    private static $defaultFieldResolver = [self::class, 'defaultFieldResolver'];
25
26
    /** @var PromiseAdapter */
27
    private static $defaultPromiseAdapter;
28
29
    /** @var callable */
30
    private static $implementationFactory = [ReferenceExecutor::class, 'create'];
31
32
    public static function getDefaultFieldResolver() : callable
33
    {
34
        return self::$defaultFieldResolver;
35
    }
36
37
    /**
38
     * Custom default resolve function.
39
     */
40
    public static function setDefaultFieldResolver(callable $fieldResolver)
41
    {
42
        self::$defaultFieldResolver = $fieldResolver;
43
    }
44
45 144
    public static function getPromiseAdapter() : PromiseAdapter
46
    {
47 144
        return self::$defaultPromiseAdapter ?: (self::$defaultPromiseAdapter = new SyncPromiseAdapter());
48
    }
49
50 24
    public static function setPromiseAdapter(?PromiseAdapter $defaultPromiseAdapter = null)
51
    {
52 24
        self::$defaultPromiseAdapter = $defaultPromiseAdapter;
53 24
    }
54
55
    public static function getImplementationFactory() : callable
56
    {
57
        return self::$implementationFactory;
58
    }
59
60
    /**
61
     * Custom executor implementation factory.
62
     *
63
     * Will be called with as
64
     */
65
    public static function setImplementationFactory(callable $implementationFactory)
66
    {
67
        self::$implementationFactory = $implementationFactory;
68
    }
69
70
    /**
71
     * Executes DocumentNode against given $schema.
72
     *
73
     * Always returns ExecutionResult and never throws. All errors which occur during operation
74
     * execution are collected in `$result->errors`.
75
     *
76
     * @param mixed|null               $rootValue
77
     * @param mixed|null               $contextValue
78
     * @param mixed[]|ArrayAccess|null $variableValues
79
     * @param string|null              $operationName
80
     *
81
     * @return ExecutionResult|Promise
82
     *
83
     * @api
84
     */
85 116
    public static function execute(
86
        Schema $schema,
87
        DocumentNode $documentNode,
88
        $rootValue = null,
89
        $contextValue = null,
90
        $variableValues = null,
91
        $operationName = null,
92
        ?callable $fieldResolver = null
93
    ) {
94
        // TODO: deprecate (just always use SyncAdapter here) and have `promiseToExecute()` for other cases
95
96 116
        $promiseAdapter = static::getPromiseAdapter();
97
98 116
        $result = static::promiseToExecute(
99 116
            $promiseAdapter,
100 116
            $schema,
101 116
            $documentNode,
102 116
            $rootValue,
103 116
            $contextValue,
104 116
            $variableValues,
0 ignored issues
show
Bug introduced by
It seems like $variableValues can also be of type ArrayAccess; however, parameter $variableValues of GraphQL\Executor\Executor::promiseToExecute() does only seem to accept array<mixed,mixed>|null, maybe add an additional type check? ( Ignorable by Annotation )

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

104
            /** @scrutinizer ignore-type */ $variableValues,
Loading history...
105 116
            $operationName,
106 116
            $fieldResolver
107
        );
108
109 116
        if ($promiseAdapter instanceof SyncPromiseAdapter) {
110 116
            $result = $promiseAdapter->wait($result);
111
        }
112
113 116
        return $result;
114
    }
115
116
    /**
117
     * Same as execute(), but requires promise adapter and returns a promise which is always
118
     * fulfilled with an instance of ExecutionResult and never rejected.
119
     *
120
     * Useful for async PHP platforms.
121
     *
122
     * @param mixed|null   $rootValue
123
     * @param mixed|null   $contextValue
124
     * @param mixed[]|null $variableValues
125
     * @param string|null  $operationName
126
     *
127
     * @return Promise
128
     *
129
     * @api
130
     */
131 216
    public static function promiseToExecute(
132
        PromiseAdapter $promiseAdapter,
133
        Schema $schema,
134
        DocumentNode $documentNode,
135
        $rootValue = null,
136
        $contextValue = null,
137
        $variableValues = null,
138
        $operationName = null,
139
        ?callable $fieldResolver = null
140
    ) {
141 216
        $factory = self::$implementationFactory;
142
143
        /** @var ExecutorImplementation $executor */
144 216
        $executor = $factory(
145 216
            $promiseAdapter,
146 216
            $schema,
147 216
            $documentNode,
148 216
            $rootValue,
149 216
            $contextValue,
150 216
            $variableValues,
151 216
            $operationName,
152 216
            $fieldResolver ?: self::$defaultFieldResolver
153
        );
154
155 216
        return $executor->doExecute();
156
    }
157
158
    /**
159
     * If a resolve function is not given, then a default resolve behavior is used
160
     * which takes the property of the source object of the same name as the field
161
     * and returns it as the result, or if it's a function, returns the result
162
     * of calling that function while passing along args and context.
163
     *
164
     * @param mixed      $source
165
     * @param mixed[]    $args
166
     * @param mixed|null $context
167
     *
168
     * @return mixed|null
169
     */
170 118
    public static function defaultFieldResolver($source, $args, $context, ResolveInfo $info)
171
    {
172 118
        $fieldName = $info->fieldName;
173 118
        $property  = null;
174
175 118
        if (is_array($source) || $source instanceof ArrayAccess) {
176 76
            if (isset($source[$fieldName])) {
177 76
                $property = $source[$fieldName];
178
            }
179 42
        } elseif (is_object($source)) {
180 41
            if (isset($source->{$fieldName})) {
181 41
                $property = $source->{$fieldName};
182
            }
183
        }
184
185 118
        return $property instanceof Closure
186 34
            ? $property($source, $args, $context, $info)
187 116
            : $property;
188
    }
189
}
190