Scrutinizer GitHub App not installed

We could not synchronize checks via GitHub's checks API since Scrutinizer's GitHub App is not installed for this repository.

Install GitHub App

Completed
Pull Request — master (#494)
by Jérémiah
18:56
created

Executor   A

Complexity

Total Complexity 24

Size/Duplication

Total Lines 196
Duplicated Lines 0 %

Test Coverage

Coverage 96.34%

Importance

Changes 0
Metric Value
wmc 24
eloc 70
dl 0
loc 196
ccs 79
cts 82
cp 0.9634
rs 10
c 0
b 0
f 0

14 Methods

Rating   Name   Duplication   Size   Complexity  
A addSchema() 0 5 1
A setMaxQueryComplexity() 0 5 1
A __construct() 0 10 1
A setMaxQueryDepth() 0 5 1
A setPromiseAdapter() 0 5 1
A setExecutor() 0 5 1
A getSchema() 0 16 4
A postExecute() 0 9 2
A execute() 0 25 1
A checkExecutionResult() 0 5 3
A checkPromiseAdapter() 0 8 4
A preExecute() 0 20 2
A enableIntrospectionQuery() 0 3 1
A disableIntrospectionQuery() 0 3 1
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Overblog\GraphQLBundle\Request;
6
7
use GraphQL\Executor\ExecutionResult;
8
use GraphQL\Executor\Promise\Promise;
9
use GraphQL\Executor\Promise\PromiseAdapter;
10
use GraphQL\Type\Schema;
11
use GraphQL\Validator\DocumentValidator;
12
use GraphQL\Validator\Rules\DisableIntrospection;
13
use GraphQL\Validator\Rules\QueryComplexity;
14
use GraphQL\Validator\Rules\QueryDepth;
15
use Overblog\GraphQLBundle\Event\Events;
16
use Overblog\GraphQLBundle\Event\ExecutorArgumentsEvent;
17
use Overblog\GraphQLBundle\Event\ExecutorContextEvent;
18
use Overblog\GraphQLBundle\Event\ExecutorResultEvent;
19
use Overblog\GraphQLBundle\Executor\ExecutorInterface;
20
use Overblog\GraphQLBundle\Executor\Promise\PromiseAdapterInterface;
21
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
22
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
23
24
class Executor
25
{
26
    public const PROMISE_ADAPTER_SERVICE_ID = 'overblog_graphql.promise_adapter';
27
28
    /** @var Schema[] */
29
    private $schemas = [];
30
31
    /** @var EventDispatcherInterface|null */
32
    private $dispatcher;
33
34
    /** @var ExecutorInterface */
35
    private $executor;
36
37
    /** @var PromiseAdapter */
38
    private $promiseAdapter;
39
40
    /** @var callable|null */
41
    private $defaultFieldResolver;
42
43 74
    public function __construct(
44
        ExecutorInterface $executor,
45
        EventDispatcherInterface $dispatcher,
46
        PromiseAdapter $promiseAdapter,
47
        ?callable $defaultFieldResolver = null
48
    ) {
49 74
        $this->executor = $executor;
50 74
        $this->dispatcher = $dispatcher;
51 74
        $this->promiseAdapter = $promiseAdapter;
52 74
        $this->defaultFieldResolver = $defaultFieldResolver;
53 74
    }
54
55 2
    public function setExecutor(ExecutorInterface $executor): self
56
    {
57 2
        $this->executor = $executor;
58
59 2
        return $this;
60
    }
61
62 1
    public function setPromiseAdapter(PromiseAdapter $promiseAdapter): self
63
    {
64 1
        $this->promiseAdapter = $promiseAdapter;
65
66 1
        return $this;
67
    }
68
69
    /**
70
     * @param string $name
71
     * @param Schema $schema
72
     *
73
     * @return self
74
     */
75 67
    public function addSchema(string $name, Schema $schema): self
76
    {
77 67
        $this->schemas[$name] = $schema;
78
79 67
        return $this;
80
    }
81
82
    /**
83
     * @param string|null $name
84
     *
85
     * @return Schema
86
     */
87 61
    public function getSchema(?string $name = null): Schema
88
    {
89 61
        if (empty($this->schemas)) {
90 1
            throw new \RuntimeException('At least one schema should be declare.');
91
        }
92
93 60
        if (null === $name) {
94 54
            $schema = \array_values($this->schemas)[0];
95
        } else {
96 6
            if (!isset($this->schemas[$name])) {
97 1
                throw new NotFoundHttpException(\sprintf('Could not found "%s" schema.', $name));
98
            }
99 5
            $schema = $this->schemas[$name];
100
        }
101
102 59
        return $schema;
103
    }
104
105 70
    public function setMaxQueryDepth($maxQueryDepth): void
106
    {
107
        /** @var QueryDepth $queryDepth */
108 70
        $queryDepth = DocumentValidator::getRule('QueryDepth');
109 70
        $queryDepth->setMaxQueryDepth($maxQueryDepth);
110 70
    }
111
112 70
    public function setMaxQueryComplexity($maxQueryComplexity): void
113
    {
114
        /** @var QueryComplexity $queryComplexity */
115 70
        $queryComplexity = DocumentValidator::getRule('QueryComplexity');
116 70
        $queryComplexity->setMaxQueryComplexity($maxQueryComplexity);
117 70
    }
118
119 70
    public function enableIntrospectionQuery(): void
120
    {
121 70
        DocumentValidator::addRule(new DisableIntrospection(DisableIntrospection::DISABLED));
122 70
    }
123
124
    public function disableIntrospectionQuery(): void
125
    {
126
        DocumentValidator::addRule(new DisableIntrospection());
127
    }
128
129
    /**
130
     * @param string|null                    $schemaName
131
     * @param array                          $request
132
     * @param array|\ArrayObject|object|null $rootValue
133
     *
134
     * @return ExecutionResult
135
     */
136 57
    public function execute(?string $schemaName = null, array $request, $rootValue = null): ExecutionResult
137
    {
138 57
        $executorArgumentsEvent = $this->preExecute(
139 57
            $this->getSchema($schemaName),
140 56
            $request[ParserInterface::PARAM_QUERY] ?? null,
141 56
            new \ArrayObject(),
142 56
            $rootValue,
143 56
            $request[ParserInterface::PARAM_VARIABLES],
144 56
            $request[ParserInterface::PARAM_OPERATION_NAME] ?? null
145
        );
146
147 55
        $executorArgumentsEvent->getSchema()->processExtensions();
148
149 55
        $result = $this->executor->execute(
150 55
            $executorArgumentsEvent->getSchema(),
151 55
            $executorArgumentsEvent->getRequestString(),
152 55
            $executorArgumentsEvent->getRootValue(),
153 55
            $executorArgumentsEvent->getContextValue(),
0 ignored issues
show
Bug introduced by
$executorArgumentsEvent->getContextValue() of type ArrayObject is incompatible with the type array|null expected by parameter $contextValue of Overblog\GraphQLBundle\E...torInterface::execute(). ( Ignorable by Annotation )

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

153
            /** @scrutinizer ignore-type */ $executorArgumentsEvent->getContextValue(),
Loading history...
154 55
            $executorArgumentsEvent->getVariableValue(),
155 55
            $executorArgumentsEvent->getOperationName()
156
        );
157
158 55
        $result = $this->postExecute($result);
159
160 52
        return $result;
161
    }
162
163 56
    private function preExecute(
164
        Schema $schema,
165
        ?string $requestString,
166
        \ArrayObject $contextValue,
167
        $rootValue = null,
168
        ?array $variableValue = null,
169
        ?string $operationName = null
170
    ): ExecutorArgumentsEvent {
171 56
        $this->checkPromiseAdapter();
172
173 55
        $this->executor->setPromiseAdapter($this->promiseAdapter);
174
        // this is needed when not using only generated types
175 55
        if ($this->defaultFieldResolver) {
176 53
            $this->executor->setDefaultFieldResolver($this->defaultFieldResolver);
177
        }
178 55
        $this->dispatcher->dispatch(Events::EXECUTOR_CONTEXT, new ExecutorContextEvent($contextValue));
0 ignored issues
show
Bug introduced by
The method dispatch() does not exist on null. ( Ignorable by Annotation )

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

178
        $this->dispatcher->/** @scrutinizer ignore-call */ 
179
                           dispatch(Events::EXECUTOR_CONTEXT, new ExecutorContextEvent($contextValue));

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...
Bug introduced by
Overblog\GraphQLBundle\E...vents::EXECUTOR_CONTEXT of type string is incompatible with the type object expected by parameter $event of Symfony\Contracts\EventD...erInterface::dispatch(). ( Ignorable by Annotation )

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

178
        $this->dispatcher->dispatch(/** @scrutinizer ignore-type */ Events::EXECUTOR_CONTEXT, new ExecutorContextEvent($contextValue));
Loading history...
Unused Code introduced by
The call to Symfony\Contracts\EventD...erInterface::dispatch() has too many arguments starting with new Overblog\GraphQLBund...extEvent($contextValue). ( Ignorable by Annotation )

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

178
        $this->dispatcher->/** @scrutinizer ignore-call */ 
179
                           dispatch(Events::EXECUTOR_CONTEXT, new ExecutorContextEvent($contextValue));

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
179
180 55
        return $this->dispatcher->dispatch(
181 55
            Events::PRE_EXECUTOR,
182 55
            ExecutorArgumentsEvent::create($schema, $requestString, $contextValue, $rootValue, $variableValue, $operationName)
183
        );
184
    }
185
186
    /**
187
     * @param ExecutionResult|Promise $result
188
     *
189
     * @return ExecutionResult
190
     */
191 55
    private function postExecute($result): ExecutionResult
192
    {
193 55
        if ($result instanceof Promise) {
194 53
            $result = $this->promiseAdapter->wait($result);
0 ignored issues
show
Bug introduced by
The method wait() does not exist on GraphQL\Executor\Promise\PromiseAdapter. It seems like you code against a sub-type of said class. However, the method does not exist in GraphQL\Executor\Promise...ter\ReactPromiseAdapter. Are you sure you never get one of those? ( Ignorable by Annotation )

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

194
            /** @scrutinizer ignore-call */ 
195
            $result = $this->promiseAdapter->wait($result);
Loading history...
195
        }
196
197 55
        $this->checkExecutionResult($result);
198
199 53
        return $this->dispatcher->dispatch(Events::POST_EXECUTOR, new ExecutorResultEvent($result))->getResult();
0 ignored issues
show
Bug introduced by
Overblog\GraphQLBundle\Event\Events::POST_EXECUTOR of type string is incompatible with the type object expected by parameter $event of Symfony\Contracts\EventD...erInterface::dispatch(). ( Ignorable by Annotation )

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

199
        return $this->dispatcher->dispatch(/** @scrutinizer ignore-type */ Events::POST_EXECUTOR, new ExecutorResultEvent($result))->getResult();
Loading history...
Unused Code introduced by
The call to Symfony\Contracts\EventD...erInterface::dispatch() has too many arguments starting with new Overblog\GraphQLBund...torResultEvent($result). ( Ignorable by Annotation )

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

199
        return $this->dispatcher->/** @scrutinizer ignore-call */ dispatch(Events::POST_EXECUTOR, new ExecutorResultEvent($result))->getResult();

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
200
    }
201
202 56
    private function checkPromiseAdapter(): void
203
    {
204 56
        if ($this->promiseAdapter && !$this->promiseAdapter instanceof PromiseAdapterInterface && !\is_callable([$this->promiseAdapter, 'wait'])) {
205 1
            throw new \RuntimeException(
206 1
                \sprintf(
207 1
                    'PromiseAdapter should be an object instantiating "%s" or "%s" with a "wait" method.',
208 1
                    PromiseAdapterInterface::class,
209 1
                    PromiseAdapter::class
210
                )
211
            );
212
        }
213 55
    }
214
215 55
    private function checkExecutionResult($result): void
216
    {
217 55
        if (!\is_object($result) || !$result instanceof ExecutionResult) {
218 2
            throw new \RuntimeException(
219 2
                \sprintf('Execution result should be an object instantiating "%s".', ExecutionResult::class)
220
            );
221
        }
222 53
    }
223
}
224